Compare commits

...

121 Commits

Author SHA1 Message Date
Ani 0064976c43 Bump version to 0.0.4 2017-11-12 18:13:22 +00:00
Ani 4bdb6674eb GUI: Style fix for Kuroi (Dark)
Small style fix for Kuroi (Dark) Theme
2017-11-12 18:13:22 +00:00
Ani c7f7d7ef5b Fixes commit count on GIT-VERSION
AppVeyor: Fetches commit count from unshallowed upstream instead of fetching from HEAD (will always be 3 since we clone with depth of 3)
2017-11-12 18:13:22 +00:00
Robbie 2c19fdf092 Fix off by one error in trophies (#3715) 2017-11-12 17:36:13 +00:00
Ofek 8fc9862614 Fix cellGameGet(Set)Param (#3690)
* Fix cellGameGet(Set)Param
2017-11-11 22:22:38 +00:00
Talkashie 55d84414ee Stub sceNpSnsFbCheckConfig (#3720) 2017-11-11 22:18:32 +04:00
Talkashie 8c0bdd71d9 Correct two typos and a couple of other nitpicky things (#3721)
Correct two typos and a couple of other nitpicky things
2017-11-11 12:56:59 +00:00
kd-11 3c9126d91f rsx: Ignore FENCE instruction as it seems like its ignored on realhw
- This is likely a compiler hint for performance reasons and not a mandate
2017-11-09 14:39:50 +03:00
kd-11 8b4836a12f rsx: Fix shader cache version check 2017-11-09 14:39:50 +03:00
kd-11 b2a7eee1ec rsx: Bump shader cache ver and fix blit engine crash
- Disables blit operations if the target will have a size of 0 in any dimension
- Bumps shader cache ver to 1.1
2017-11-09 14:39:50 +03:00
kd-11 ed21bb309f rsx: Minor fixups
- Fix texture cache blit behaviour when src has AA enabled and dst is a blit dst texture with or without AA
-- This requires handling AA resolve by removing a half downscale on multisampled axes

- Return all ones when a vertex attribute is disabled.
-- Some games forget to enable vertex attributes actually needed by the fs
2017-11-08 13:15:34 +03:00
kd-11 7b3e4f5e3d vk: Hotfix
- facepalm: Do not enable depth comparison mode if masquerading as RGBA color!
2017-11-08 13:15:34 +03:00
kd-11 30b3af0d12 vk: Cleanup, simplify renderpass management 2017-11-08 13:15:34 +03:00
kd-11 541cb4062b vk: Fix shader logging
- Do not overwrite logged programs
2017-11-08 13:15:34 +03:00
kd-11 4e9160104a rsx/vk/gl: Cleanup and refector glsl::getFunctionImpl
- Both backends now generate very similar code
2017-11-08 13:15:34 +03:00
kd-11 86fa379c78 rsx/vk: Fix unnormalized converted textures 2017-11-08 13:15:34 +03:00
kd-11 8733505d0a rsx: Minor fixes
- texture_cache: Fix internal size calculation for subresources
- vk: Delay dynamic state updates until just about to draw to ensure no flush has discarded the cb state
2017-11-08 13:15:34 +03:00
kd-11 242611aa46 gl/qt: Catch segfaults in wglDeleteContext with SEH (AMD windows driver)
- In rare cases the driver derefs a nullptr and dies, taking the emulator with it
- From testing, it seems the vram is indeed freed when this happens so its "safe" to continue
2017-11-08 13:15:34 +03:00
kd-11 baa5a261a5 rsx: Rewrite invalidate_range_impl_base in a way that makes sense. Fixes wcb hanging 2017-11-08 13:15:34 +03:00
kd-11 3730b9d1da rsx: More fixes
- Support for raster offsets in surface descriptors (looks to be unused)
- Do not tag disabled render targets when using MRT (pitch = 64)
- Add missing notify_surface_changed() call for openGL
2017-11-08 13:15:34 +03:00
kd-11 0d35363ea0 rsx: Minor optimization - dont update sampler state if texture state registers have not changed 2017-11-08 13:15:34 +03:00
kd-11 75504b3f5e rsx: Rework context handling and stop leaking the GL ccontext
- GL contexts are external handles that require manual lifecycle management
2017-11-08 13:15:34 +03:00
kd-11 4ca98e53a6 rsx: Fix for unnormalized texture access 2017-11-08 13:15:34 +03:00
kd-11 300a36d3d6 rsx: Fixes for cubemap reconstruction
- Do not abort generation if sides are missing, replace with blank surfaces instead
- Make cubemaps scale with res scaling
2017-11-08 13:15:34 +03:00
kd-11 60c7a508a7 rsx: Refactor create_subresource_view(deferred_subresource&) and implement a subresource cache
- This limits the number of times an image is copied and improves performance
2017-11-08 13:15:34 +03:00
kd-11 1fa18757fc rsx: Implement render-to-cubemap; Also simplify unnormalized samplers [WIP, DELETE SHADER CACHE, VERY SLOW]
- Enables real-time cubemap reflections
- TODO: Vulkan is broke; rsx is very slow with this feature
2017-11-08 13:15:34 +03:00
kd-11 fbb7186e66 rsx/gl: Addendum - Fix fragment shader to consume texture scale parameters 2017-11-08 13:15:34 +03:00
kd-11 0961a43997 rsx: Implement 1D<->2D image type casts 2017-11-08 13:15:34 +03:00
kd-11 7037504dcf rsx: Workaround for missing AA flags on some surfaces
- This just doesnt work right yet. It looks like AA is being used dynamically? (RDR)
- TODO: Try to locate flags to set AA if AA mode is not changed
2017-11-08 13:15:34 +03:00
kd-11 2385029eab gl: Shift code around to increase work done after memory transfer operations
- The current code is slower because memory operations are too close to their draw calls
-- This is mainly an issue with proprietary AMD drivers
2017-11-08 13:15:34 +03:00
kd-11 eed55a446c rsx: Minor optimization
- Defer resolving image copy operations to the binding step
2017-11-08 13:15:34 +03:00
kd-11 bbcb6b6851 rsx: Fbo fixes 2
- Use AA mode to predict surface compression. Compression mode is useless without AA activated
- Rewrites most image subresource fetch routines to use the new heuristic
- Fix rsx::thread::find_tile. FEED000(X) can be substituted for (X) in the code
-- Fixes alot of failures when looking for tiled regions

rsx: Fix antialiased unnormalized coords
- scaling factors are inverse to allow proper coordinates to be computed in fs
2017-11-08 13:15:34 +03:00
kd-11 b95630d84a rsx: Minor fixups
- Optimize framebuffer memory invalidate conditions
- Fix texture sampling of AA textures (wider by 2x surfaces)
2017-11-08 13:15:34 +03:00
kd-11 af1d3c2aa6 rsx: Improve surface store resource management
- vk: Use frame testing to determine invalidated resources that can be safely deleted
2017-11-08 13:15:34 +03:00
kd-11 ec3e5c547f rsx: More fixes
- Tag surface store to help determine when contents have been invalidated
- Crop framebuffer textures if they are not the requested dimensions!
2017-11-08 13:15:34 +03:00
kd-11 963a87fed5 rsx: Critical fixes
- Remove generic throws from the rsx pipeline. Stops the rsx thread from silently dying leaving the emulator in a hung state
- Hackplement add_signed and reverse_subtract_signed blend modes
2017-11-08 13:15:34 +03:00
kd-11 173d05b54f rsx: Optimizations
- Reimplement fragment program fetch and rewrite texture upload mechanism
-- All of these steps should only be done at most once per draw call
-- Eliminates continously checking the surface store for overlapping addresses as well

addenda - critical fixes
- gl: Bind TIU before starting texture operations as they will affect the currently bound texture
- vk: Reuse sampler objects if possible
- rsx: Support for depth resampling for depth textures obtained via blit engine

vk/rsx: Minor fixes
- Fix accidental imageview dereference when using WCB if texture memory occupies FB memory
- Invalidate dirty framebuffers (strict mode only)
- Normalize line endings because VS is dumb
2017-11-08 13:15:34 +03:00
Zion Nimchuk 865bb47462 HEAD or master will no longer show up in the titlebar 2017-11-08 12:49:22 +04:00
scribam 3e7ed8a831 PPUTranslator minor changes 2017-11-08 08:34:00 +04:00
Zion 3a49a77c07 Fix git-branch in title... again (#3704)
Fix git-branch in title... again
2017-11-08 01:22:41 +00:00
Zion Nimchuk 6782b22637 Make cellMouseGetDataList return CELL_MOUSE_ERROR_NO_DEVICE if mouse handler is set to null 2017-11-04 19:55:32 +00:00
scribam 4600094829 [RSX] Fix uninitialized value before usage 2017-11-04 01:28:53 +03:00
kd-11 daaa83b9ca rsx: Fix for framebuffer validation 2017-11-04 00:08:30 +03:00
Robbie 3288050680 Have trophy manager reject games that have invalid usr data rather than dying. 2017-11-03 21:15:43 +03:00
Robbie b8c29ae957 Make it so that TROPUSR doesn't crash on "bad" imput. 2017-11-03 21:15:43 +03:00
Robbie 47bacc0ef0 Make trophy dialog smarter and not need the silly file. Can load all games by default now. 2017-11-03 21:15:43 +03:00
Tahir Akhlaq 3d0dced4bd change CryptAcquireContextW to try CRYPT_NEWKEYSET flag if key container doesnt exist already < https://msdn.microsoft.com/en-us/library/windows/desktop/aa379886(v=vs.85).aspx > 2017-11-03 14:17:37 +03:00
kd-11 30bba09fed disable fb testing for partial framebuffer resources 2017-11-02 14:35:19 +03:00
kd-11 31b07f2c5c rsx: Tweaks
- Optimize get_surface_subresource
- Add check_program_status time to draw call setup statistics. It can slow down games significantly
2017-11-02 14:35:19 +03:00
kd-11 f7063bb57b vk: Improved handling of swap_bytes behaviour when using WCB 2017-11-02 14:35:19 +03:00
kd-11 e4ef85b6e0 rsx: Experimental; Try to calculate pixel offset using nv3062 pitch register since we know the target block is defined with 3062 registers 2017-11-02 14:35:19 +03:00
Nekotekina b7c2088489 Add supporters 2017-11-01 05:07:12 +03:00
Nekotekina 59cd0a9c7f Implement set_native_priority (posix) 2017-11-01 05:07:12 +03:00
Nekotekina af107df0b4 Fix NPDRM exitspawn 2017-11-01 05:07:12 +03:00
Nekotekina 0e7e40f2cb Fix /dev_bdvd/ for exitspawn 2017-11-01 05:07:11 +03:00
Nekotekina 0b788f5b43 Add Delete LLVM Cache option 2017-11-01 05:07:11 +03:00
scribam db5c2500c2 Update PPA urls to the latest version of Qt 2017-10-31 09:29:12 +00:00
scribam a1496eb1f1 Revert Qt requirements to version 5.7 for Linux 2017-10-31 09:29:12 +00:00
Robbie 4aa89132d7 Implement Trophy Manager. 2017-10-29 18:48:33 +03:00
Ani 9b8eb089b1 Handle device not ready in fs::error. Solves #3592 2017-10-29 16:52:12 +03:00
MRG95 c1f08ce58d Added breakpoint list
Added a list widget that displays all the currently active breakpoints. You can rename each one for convenience, delete them in bulk, or double click to jump to that address.
2017-10-29 16:17:05 +03:00
MRG95 09a0d046f4 Repositioned current instruction to middle
As soon as I tried the debugger, i wanted to move it to the middle almost instantly. Checked the code and found it sitting right here but commented out. Why? This is awesome.
2017-10-29 16:17:05 +03:00
Unknown 0741698f13 Qt: Fix Save Data Dialog initial size 2017-10-29 15:52:46 +03:00
kd-11 c2ac05f734 rsx: Fix for rsx thread lockup due to nested access violations when WCB is enabled 2017-10-29 15:25:17 +03:00
kd-11 f8f5f9f418 vk: Allow swapchain create to fail with an error 2017-10-29 15:25:17 +03:00
kd-11 7e6d6b45d4 nvidia facepalm 2017-10-29 15:25:17 +03:00
kd-11 361e80f7dc rsx: Tag cache blocks returned on access violation to validate data passed
to flush_all is up to date. Should prevent recursive exceptions

Partially revert Jarves' fix to invalidate cache on tile unbind. This will
need alot more work. Fixes hangs
2017-10-29 15:25:17 +03:00
kd-11 395b4bfa45 gsframe: Break waiting is emulator is stopped suddenly
- Keeps the queue from hanging the GUI
2017-10-29 15:25:17 +03:00
kd-11 ce2b790d8f rsx/qt: GsFrame improvements
- Identify minimize/restore events as separate from regular resize and do not react to them
- Enable message queue consumption after loading the shaders cache. Also hides the frame in this step
-- This fixes the 'start fullscreen' bug when running vulkan
2017-10-29 15:25:17 +03:00
Nekotekina 1ffc1e82b0 fixup 2017-10-28 23:39:10 +03:00
Nekotekina 8520ca7ef7 Audio: add Buffer Count setting 2017-10-28 23:24:08 +03:00
Nekotekina 89fba1c385 ppu_acontext draft 2017-10-28 23:24:08 +03:00
Nekotekina 00a0d37455 Add cmdline support 2017-10-28 23:24:08 +03:00
scribam dbb2251f93 [Qt] Fix uninitialised values before usage 2017-10-28 13:56:32 +03:00
kd-11 7abf755a57 rsx: Avoid false positives by early rejection. Should keep cache thashing to a minimum 2017-10-28 13:26:16 +03:00
kd-11 055f0e2e4a rsx: Export more information about affected cache sections when handling violations
- This allows for better handling of deferred flushes.
-- There's still no guarantee that cache contents will have changed between the set acquisition and following flush operation
-- Hopefully this is rare enough that it doesnt cause serious issues for now
2017-10-28 13:26:16 +03:00
kd-11 49f4da3016 rsx: Fixes
- vk: Always reopen primary command buffers. They should only be closed in flush_command_queue
- If uploading a texture and there are collisions with protected buffers, do not rebuild the cache
- Perform writes via flush before reprotecting pages that were not trampled
- Only flush no pages once
2017-10-28 13:26:16 +03:00
kd-11 bf234dc668 rsx: Implement memory tags for strict mode to validate render target memory 2017-10-28 13:26:16 +03:00
kd-11 11bd65c2b5 vulkan: Flush queue before attempting to copy texture memory! 2017-10-28 13:26:16 +03:00
Jake e0d1ac676e rsx: invalidate surface store address when tile is unbound 2017-10-28 12:46:20 +03:00
Jake 494cbac78b spu: save and restore mfc cmd after processing 2017-10-28 12:46:20 +03:00
Jake 0d46a8e786 spu: Implement readch(mfc_cmd) 2017-10-28 12:46:20 +03:00
Jake 626b9f93c4 rsx: make dmactrl get 'readonly' 2017-10-28 12:46:20 +03:00
Zangetsu38 53f9defb07 Trophy: use system language setting 2017-10-27 14:09:50 +01:00
Robbie 4bf8d1e41f Fix off by one error. Sigh. 2017-10-26 20:31:55 +01:00
Robbie 936c817bd8 Fix focus issue in trophies. 2017-10-26 20:31:55 +01:00
kd-11 9c9495621c rsx: Fix critical bug concerning transient data layout in memory 2017-10-26 00:35:45 +03:00
kd-11 d53673c6f7 rsx: Disable draw call batching when strict mode is enabled
- Minor bugs have been observed with it always enabled
2017-10-26 00:35:45 +03:00
kd-11 882e949f80 vk: Fix for infinite hanging in the access violation handler 2017-10-24 22:59:09 +03:00
kd-11 e6849a59a2 rsx: Better detection of framebuffer memory copy operations
- Still requires texture stitching to work correctly, but matching dimensions works well for now
2017-10-24 22:59:09 +03:00
kd-11 6918e265ec rsx/vk: Be a little more frugal with texture memory to avoid running out of VRAM on 1GB cards 2017-10-24 22:59:09 +03:00
kd-11 e9f293f522 rsx: Improve separate treatment of write exceptions vs read exceptions
- Optimizes search functionality and avoids thrashing valid sections
2017-10-24 22:59:09 +03:00
kd-11 5fc36d64b6 fix build 2017-10-24 22:59:09 +03:00
kd-11 95e6d78689 rsx: Workaround for 0 pitch textures.
- Should these be ignored? Needs investigation
2017-10-24 22:59:09 +03:00
kd-11 f4a666345a rsx: Even more texture cache fixes
- Fix subresource sampling
- Invalidate memory range before uploading textures to prevent hangs
2017-10-24 22:59:09 +03:00
kd-11 7a5c88a8d1 rsx: Only transfer framebuffer contents if memory contents are compatible 2017-10-24 22:59:09 +03:00
kd-11 0de0dded53 rsx: Texture fixes continued
- Fix buffer invalidate behaviour (wcb)
- Disable auto rebuild with only framebuffer storage getting rebuilt
- Fix vulkan subresource sampling
2017-10-24 22:59:09 +03:00
kd-11 5e58cf6079 rsx: Restructuring [WIP]
- Refactor invalidate memory functions into one function
- Add cached object rebuilding functionality to avoid throwing away useful memory on an invalidate
- Added debug monitoring of texture unit VRAM usage
2017-10-24 22:59:09 +03:00
Robbie b0737d1c90 Make a basic trophy notification dialog (#3204)
* Make trophy notification dialog.

* Fix bug where trophy state doesn't persist with game reboot.
2017-10-24 18:43:05 +03:00
Robbie 779ed75a19 Save manager improvements (#3631)
* Make size of manager only 60% of screen height initially at most.

* Add ability to delete/select multiple entries.

* Add ability to open up save dir and fix how it's done in
game_list_frame.

* Make delete much cleaner.
2017-10-24 18:09:38 +03:00
Unknown dbf1573e89 Update Readme to Qt 5.8 2017-10-24 15:11:37 +01:00
kd-11 96fd8556f2 Silence annoying experimental build warning
- Compiling locally on VS defines BRANCH to "" (empty $BRANCH envvar) and defines _MSC_VER. The pdb check is useless since it will never be reached
2017-10-22 00:14:40 +03:00
kd-11 8f324dfc0a vk: Enable primitive restart workaround for polaris and vega on linux as well
- Looks like it might be a hardware erratum
2017-10-22 00:14:40 +03:00
Unknown 34a6085cc0 Qt: add "clear" option to tty log contextmenu 2017-10-19 15:13:17 +01:00
Megamouse b3efa75206 [Qt] UI improvements (#3558)
* Qt: Show tooltips in description box

* Qt: implement description subscription

* Qt: add gamelist resize for ctrl-+/-/wheel (simple zoom)

* Qt: handle strict mode in gui tab

* Qt: more highdpi stuff

* Qt: remove old tooltips from settings_dialog

* Qt: conform cpublit tooltip to new subscription model
2017-10-19 14:29:48 +03:00
toccata10 b90a7dc66a evdev: add analog to dpad option (#3551)
* evdev Analog to digital option

* rewrite conditions on axis rotation

* a bit of cleanup
2017-10-19 13:41:02 +03:00
Megamouse 200557c036 [Qt] Add syntax highlighter (#3550)
* Qt: Add syntax highlighter

* Qt: add syntax highlighter to cg_disasm

The glsl part is pretty much finished.
The asm is still missing a few rules.
Colors are not yet fully decided

* Qt: add filter for syntax highlighter
2017-10-19 12:58:39 +03:00
kd-11 472cb3b1c2 gl: Check for vendor_string ATI for AMD cards. It seems AMD is still using the ATI openGL stack 2017-10-19 12:22:52 +03:00
kd-11 d8ee6a2edb add RX 550 to AMD vulkan cards with restart bug 2017-10-19 12:22:52 +03:00
kd-11 ddcacb8258 general fixes; Force u32 return type for index_count and add RX Vega to primitive restart blacklist 2017-10-19 12:22:52 +03:00
kd-11 a8e1754fa4 rsx: Allow clear_surface command for depth-only passes. Removes invalidate cache hack 2017-10-19 12:22:52 +03:00
kd-11 5db45c3699 rsx: More fixes
- Workaround for AMD glMultiDrawArrays bug
- Disable disjoint command submission when multidraw support is disabled
2017-10-19 12:22:52 +03:00
kd-11 89dcafbe41 rsx: Reimplement index buffer generation
- Emulate primitive restart in software whenever we get the chance
- Ensure PRIMITIVE_RESTART is never active when LIST topologies are active
- Reimplement TRIANGLE_FAN, POLYGON and QUAD expansion
2017-10-19 12:22:52 +03:00
kd-11 3d05e61f7e rsx/vk: Workaround for polaris primitive restart bug 2017-10-19 12:22:52 +03:00
Zangetsu38 5146f3ec47 Fix compile VS 2017-10-16 18:42:03 +03:00
scribam 170a95f5df Add BRANCH as a preprocessor definition taken from an environment variable 2017-10-15 18:20:02 +01:00
scribam c661578906 Bump Qt version to 5.9.2 for Travis 2017-10-15 14:23:48 +01:00
scribam f20e0c2898 rpcs3.vcxproj: remove unused paths in AdditionalLibraryDirectories 2017-10-15 14:23:48 +01:00
scribam 64b2ae3cd5 appveyor.yml: use Visual Studio solution to build the project and cleanup 2017-10-15 14:23:48 +01:00
kd-11 a11d66f52d update vulkan submodules (#3600) 2017-10-15 14:37:52 +03:00
Megamouse 304a4a1b61 GUI: add some visual studio filters (#3375) 2017-10-14 19:06:20 +03:00
132 changed files with 8014 additions and 2013 deletions
+8 -8
View File
@@ -54,7 +54,7 @@ before_script:
- git submodule update --init asmjit 3rdparty/ffmpeg 3rdparty/pugixml 3rdparty/GSL 3rdparty/libpng Utilities/yaml-cpp 3rdparty/cereal 3rdparty/hidapi 3rdparty/Optional Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
- mkdir build
- cd build
- export CMAKE_PREFIX_PATH=~/Qt/5.9.1/gcc_64/lib/cmake
- export CMAKE_PREFIX_PATH=~/Qt/5.9.2/gcc_64/lib/cmake
- if [ "$TRAVIS_PULL_REQUEST" = false ]; then
export CXXFLAGS="$CXXFLAGS -DBRANCH=$TRAVIS_REPO_SLUG/$TRAVIS_BRANCH";
else
@@ -64,20 +64,20 @@ before_script:
- make -j 3
- # AppImage generation
- if [ -n "$UPLOAD_URL" ] && [ "$TRAVIS_BRANCH" = "master" ] && [ "$CC" = "clang-4.0" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
export LD_LIBRARY_PATH=~/Qt/5.9.1/gcc_64/lib;
export LD_LIBRARY_PATH=~/Qt/5.9.2/gcc_64/lib;
make DESTDIR=appdir install ; find appdir/ ;
find ../bin ;
wget -c "https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage" ;
chmod a+x linuxdeployqt*.AppImage ;
export PATH=~/Qt/5.9.1/gcc_64/bin/:${PATH} ;
export PATH=~/Qt/5.9.2/gcc_64/bin/:${PATH} ;
./linuxdeployqt*.AppImage --appimage-extract ;
./linuxdeployqt*.AppImage ./appdir/usr/share/applications/*.desktop -bundle-non-qt-libs ;
mkdir ./appdir/usr/plugins/xcbglintegrations/ ;
mkdir ./appdir/usr/plugins/imageformats/ ;
cp ~/Qt/5.9.1/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
cp ~/Qt/5.9.1/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
cp ~/Qt/5.9.1/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
cp ~/Qt/5.9.1/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
cp ~/Qt/5.9.2/gcc_64/lib/libQt5Svg.so.5 ./appdir/usr/lib/ ;
cp ~/Qt/5.9.2/gcc_64/plugins/xcbglintegrations/* ./appdir/usr/plugins/xcbglintegrations/ ;
cp ~/Qt/5.9.2/gcc_64/plugins/imageformats/* ./appdir/usr/plugins/imageformats/ ;
cp ~/Qt/5.9.2/gcc_64/plugins/platforms/* ./appdir/usr/plugins/platforms/ ;
export PATH=${TRAVIS_BUILD_DIR}/build/squashfs-root/usr/bin/:${PATH} ;
./squashfs-root/usr/bin/appimagetool ${TRAVIS_BUILD_DIR}/build/appdir ;
find ./appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq ;
@@ -115,7 +115,7 @@ addons:
- libstdc++-5-dev
- lib32stdc++6
- zlib1g-dev
# We need to install qt 5.9.1 manually because the version trusty provides is too old.
# We need to install qt 5.9.2 manually because the version trusty provides is too old.
#- qtbase5-dev
- libudev-dev
- libevdev-dev
+3 -3
View File
@@ -24,7 +24,7 @@ If you want to contribute please take a look at the [Coding Style](https://githu
* [Visual C++ Redistributable Packages for Visual Studio 2015](http://www.microsoft.com/en-us/download/details.aspx?id=48145)
* [Cmake 3.1.0+](https://www.cmake.org/download/) (required; add to PATH)
* [Python 3.3+](https://www.python.org/downloads/) (required; add to PATH)
* [Qt 5.7+](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.7\msvc2015_64\` environment variable if you do not want to use the Visual Studio Qt Plugin)
* [Qt 5.8+](https://www.qt.io/download-open-source/) (required; add QTDIR `<QtInstallFolder>\5.8\msvc2015_64\` environment variable if you do not want to use the Visual Studio Qt Plugin)
* [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2015) (optional; see above)
### Linux
@@ -47,10 +47,10 @@ To initialize the repository don't forget to execute `git submodule update --ini
### Configuring Qt
*If you're using Visual Studio 2017 without Qt plugin support (or simply dont want to use it):*
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.7\msvc2015_64\` </br>
1) Add `QTDIR` environment variable and set it to `<QtInstallFolder>\5.8\msvc2015_64\` </br>
*If you wish to use the Visual Studio plugin for Qt:* </br>
1) Go to the Qt5 menu and edit Qt5 options. Add the path to your Qt installation with compiler e.g. `C:\Qt\5.7\msvc2015_64`. </br>
1) Go to the Qt5 menu and edit Qt5 options. Add the path to your Qt installation with compiler e.g. `C:\Qt\5.8\msvc2015_64`. </br>
2) While selecting the rpcs3qt project, go to Qt5->Project Setting and select the version you added.
### Building the projects
+1
View File
@@ -96,6 +96,7 @@ static fs::error to_error(DWORD e)
case ERROR_INVALID_NAME: return fs::error::inval;
case ERROR_SHARING_VIOLATION: return fs::error::acces;
case ERROR_DIR_NOT_EMPTY: return fs::error::notempty;
case ERROR_NOT_READY: return fs::error::noent;
default: fmt::throw_exception("Unknown Win32 error: %u.", e);
}
}
+21 -11
View File
@@ -1884,20 +1884,30 @@ void thread_ctrl::set_native_priority(int priority)
HANDLE _this_thread = GetCurrentThread();
INT native_priority = THREAD_PRIORITY_NORMAL;
switch (priority)
{
default:
case 0:
break;
case 1:
if (priority > 0)
native_priority = THREAD_PRIORITY_ABOVE_NORMAL;
break;
case -1:
if (priority < 0)
native_priority = THREAD_PRIORITY_BELOW_NORMAL;
break;
}
SetThreadPriority(_this_thread, native_priority);
if (!SetThreadPriority(_this_thread, native_priority))
{
LOG_ERROR(GENERAL, "SetThreadPriority() failed: 0x%x", GetLastError());
}
#else
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(), &policy, &param);
if (priority > 0)
param.sched_priority = sched_get_priority_max(policy);
if (priority < 0)
param.sched_priority = sched_get_priority_min(policy);
if (int err = pthread_setschedparam(pthread_self(), policy, &param))
{
LOG_ERROR(GENERAL, "pthraed_setschedparam() failed: %d", err);
}
#endif
}
+29 -2
View File
@@ -16,6 +16,7 @@ rem // Official git repository and contact information can be found at
rem // https://github.com/RPCS3/rpcs3 and http://rpcs3.net/.
setlocal ENABLEDELAYEDEXPANSION
setlocal ENABLEEXTENSIONS
set GIT_VERSION_FILE=%~p0..\rpcs3\git-version.h
if not defined GIT (
@@ -54,9 +55,35 @@ if errorlevel 1 (
goto done
)
rem // Get commit count from HEAD by default
for /F %%I IN ('call %GIT% rev-list HEAD --count') do set GIT_VERSION=%%I
rem // If we're in AppVeyor and we're building for master: Get commit count from unshallowed upstream
if defined APPVEYOR (
if not defined APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (
call %GIT% remote add upstream https://github.com/RPCS3/RPCS3.git
call %GIT% fetch --unshallow upstream
for /F %%I IN ('call %GIT% rev-list --count upstream/master') do set GIT_VERSION=%%I
)
)
if defined APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH (
if "%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"=="master" (
for /f "tokens=1* delims=/" %%a in ("%APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME%") do set user=%%a
set "GIT_BRANCH=!user!/%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%"
) else (
set GIT_BRANCH=%APPVEYOR_PULL_REQUEST_HEAD_REPO_BRANCH%
)
) else (
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
)
rem // Get last commit (shortened) and concat after commit count in GIT_VERSION
for /F %%I IN ('call %GIT% rev-parse --short HEAD') do set GIT_VERSION=%GIT_VERSION%-%%I
for /F %%I IN ('call %GIT% rev-parse --abbrev-ref HEAD') do set GIT_BRANCH=%%I
rem // Echo obtained GIT_VERSION for debug purposes if needed
echo %GIT_VERSION%
rem // Don't modify the file if it already has the current version.
if exist "%GIT_VERSION_FILE%" (
@@ -69,7 +96,7 @@ if exist "%GIT_VERSION_FILE%" (
echo // This is a generated file. > "%GIT_VERSION_FILE%"
echo. >> "%GIT_VERSION_FILE%"
echo #define RPCS3_GIT_VERSION "%GIT_VERSION%" >> "%GIT_VERSION_FILE%"
echo #define RPCS3_GIT_BRANCH "%GIT_BRANCH%" >> "%GIT_VERSION_FILE%"
echo #define RPCS3_GIT_BRANCH ^"%GIT_BRANCH%^" >> "%GIT_VERSION_FILE%"
echo. >> "%GIT_VERSION_FILE%"
echo // If you don't want this file to update/recompile, change to 1. >> "%GIT_VERSION_FILE%"
echo #define RPCS3_GIT_VERSION_NO_UPDATE 0 >> "%GIT_VERSION_FILE%"
+21 -1
View File
@@ -48,7 +48,7 @@
#define CONCATENATE_DETAIL(x, y) x ## y
#define CONCATENATE(x, y) CONCATENATE_DETAIL(x, y)
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE_DETAIL(x) #x ""
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
#define HERE "\n(in file " __FILE__ ":" STRINGIZE(__LINE__) ")"
@@ -534,6 +534,26 @@ inline u64 cntlz64(u64 arg, bool nonzero = false)
#endif
}
inline u32 cnttz32(u32 arg, bool nonzero = false)
{
#ifdef _MSC_VER
ulong res;
return _BitScanForward(&res, arg) || nonzero ? res : 32;
#else
return arg || nonzero ? __builtin_ctzll(arg) : 32;
#endif
}
inline u64 cnttz64(u64 arg, bool nonzero = false)
{
#ifdef _MSC_VER
ulong res;
return _BitScanForward64(&res, arg) || nonzero ? res : 64;
#else
return arg || nonzero ? __builtin_ctzll(arg) : 64;
#endif
}
// Helper function, used by ""_u16, ""_u32, ""_u64
constexpr u8 to_u8(char c)
{
+72 -34
View File
@@ -1,44 +1,82 @@
version: '0.0.3-{build}'
#---------------------------------#
# general configuration #
#---------------------------------#
os: Visual Studio 2015
platform: x64
clone_folder: C:\rpcs3
clone_depth: 3
test: off
# version format
version: '0.0.4-{build}'
configuration:
# Release
- ReleaseLLVM
#---------------------------------#
# environment configuration #
#---------------------------------#
before_build:
- ps: $env:Date="$(git show -s --date=short --format='%ad')"
- git submodule update --init 3rdparty/ffmpeg 3rdparty/pugixml asmjit 3rdparty/GSL 3rdparty/libpng Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers Utilities/yaml-cpp 3rdparty/cereal 3rdparty/zlib 3rdparty/hidapi 3rdparty/Optional
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
- 7z x vulkan.7z -aos -oC:\rpcs3\Vulkan > null
- set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%/#%APPVEYOR_PULL_REQUEST_NUMBER%
- if "%APPVEYOR_PULL_REQUEST_NUMBER%"=="" (set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%)
- set CXXFLAGS=-DBRANCH=%BRANCH%
- if %configuration%==Release (cmake -G "Visual Studio 14 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 14 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/lib/cmake/llvm -DZLIB_ROOT=C:/rpcs3/zlib/ -DVULKAN_PREBUILT=ON)
# Build worker image (VM template)
image: Visual Studio 2015
build_script:
- cmake --build . --config Release -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
# clone directory
clone_folder: c:\projects\rpcs3
install:
- if not exist llvmlibs.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8" -FileName llvmlibs.7z
- if not exist vulkan.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U" -FileName vulkan.7z
- if not exist zlib.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B-HVE3xvheVFX05lRFdnZlh5aUU" -FileName zlib.7z
- set QTDIR=C:\Qt\5.8\msvc2015_64
- set OPENALDIR=C:\rpcs3\3rdparty\OpenAL
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%QTDIR%;%PATH%
- set COMMIT_SHA=%APPVEYOR_REPO_COMMIT:~0,8%
# set clone depth
clone_depth: 3 # clone entire repository history if not defined
artifacts:
- path: bin
name: 'rpcs3-v0.0.3-$(Date)-$(COMMIT_SHA)_win64'
type: zip
# environment variables
environment:
QTDIR: C:\Qt\5.9.1\msvc2015_64
# build cache to preserve files/folders between builds
cache:
- llvmlibs.7z -> appveyor.yml
- vulkan.7z -> appveyor.yml
- zlib.7z -> appveyor.yml
# scripts that run after cloning repository
install:
- git submodule update --init 3rdparty/cereal 3rdparty/ffmpeg 3rdparty/GSL 3rdparty/hidapi 3rdparty/libpng 3rdparty/Optional 3rdparty/pugixml 3rdparty/zlib asmjit Utilities/yaml-cpp Vulkan/glslang Vulkan/Vulkan-LoaderAndValidationLayers
#---------------------------------#
# build configuration #
#---------------------------------#
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
platform: x64
# build Configuration, i.e. Debug, Release, etc.
configuration: Release - LLVM
build:
parallel: true # enable MSBuild parallel builds
project: rpcs3.sln # path to Visual Studio solution or project
# MSBuild verbosity level
verbosity: normal
# scripts to run before build
before_build:
- set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%/#%APPVEYOR_PULL_REQUEST_NUMBER%
- if "%APPVEYOR_PULL_REQUEST_NUMBER%"=="" (set BRANCH=%APPVEYOR_REPO_NAME%/%APPVEYOR_REPO_BRANCH%)
- set PATH=%PATH%;%QTDIR%
- if not exist llvmlibs.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRY2k3Q2Yya05lcm8" -FileName llvmlibs.7z
- 7z x llvmlibs.7z -aos -o%APPVEYOR_BUILD_FOLDER% > null
- if not exist vulkan.7z appveyor DownloadFile "https://drive.google.com/uc?export=download&id=0B8A6NaxhQAGRaHYxV3VOS2d0a0U" -FileName vulkan.7z
- 7z x vulkan.7z -aos -o"%APPVEYOR_BUILD_FOLDER%\lib\%CONFIGURATION%-%PLATFORM%" > null
# scripts to run *after* solution is built and *before* automatic packaging occurs (web apps, NuGet packages, Azure Cloud Services)
before_package:
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.exp
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.lib
- rm %APPVEYOR_BUILD_FOLDER%\bin\rpcs3.pdb
- set COMMIT_DATE=%APPVEYOR_REPO_COMMIT_TIMESTAMP:~0,10%
- set COMMIT_SHA=%APPVEYOR_REPO_COMMIT:~0,8%
#---------------------------------#
# tests configuration #
#---------------------------------#
# to disable automatic tests
test: off
#---------------------------------#
# artifacts configuration #
#---------------------------------#
# pushing entire folder as a zip archive
artifacts:
- path: bin
name: 'rpcs3-v0.0.4-$(COMMIT_DATE)-$(COMMIT_SHA)_win64'
+41 -41
View File
@@ -40,7 +40,7 @@ QWidget {
/* Mouse tooltips */
QToolTip {
border: 1px solid #323232;
border: 0.05em solid #323232;
background-color: #323232;
color: #ecf0f1;
}
@@ -49,29 +49,29 @@ QToolTip {
QHeaderView::section {
background-color: #323232;
color: #ecf0f1;
padding-left: 4px;
border: 1px solid #323232;
padding-left: 0.2em;
border: 0.05em solid #323232;
}
/* Settings Dialog: Tabs */
QTabBar::tab {
color: #ecf0f1;
border: 1px solid #444;
border: 0.05em solid #444;
border-bottom-style: none;
background-color: #333333;
padding-left: 16px;
padding-right: 16px;
padding-top: 4px;
padding-bottom: 4px;
margin-right: -2px;
padding-left: 0.9em;
padding-right: 0.9em;
padding-top: 0.2em;
padding-bottom: 0.2em;
margin-right: -0.2em;
}
QTabBar::tab:last {
margin-right: 0px;
margin-right: 0em;
}
QTabBar::tab:!selected {
color: #b1b1b1;
border-bottom-style: solid;
margin-top: 3px;
margin-top: 0.15em;
background-color: #292929;
}
QTabBar::tab:hover {
@@ -81,11 +81,11 @@ QTabBar::tab:hover {
/* Checkboxes */
QCheckBox::indicator {
border-radius: 2px;
border: 1px solid #ecf0f1;
width: 10px;
height: 10px;
margin-top: 1px;
border-radius: 0.1em;
border: 0.05em solid #ecf0f1;
margin-top: 0.05em;
width: 0.8em;
height: 0.8em;
}
QCheckBox::indicator:checked {
background-color: #2ecc71; /* Green */
@@ -99,11 +99,11 @@ QCheckBox::indicator::disabled {
/* Radio Buttons */
QRadioButton::indicator {
border-radius: 6px;
border: 1px solid #ecf0f1;
width: 10px;
height: 10px;
margin-top: 1px;
border-radius: 0.4em;
border: 0.05em solid;
border-color: white;
width: 0.8em;
height: 0.8em;
}
QRadioButton::indicator:checked {
background-color: #2ecc71; /* Green */
@@ -119,10 +119,10 @@ QRadioButton::indicator::disabled {
QComboBox {
background-color: #404040;
color: #fff;
border: 1px solid #1e1e1e;
border-radius: 3px;
padding-bottom: 2px;
padding-left: 4px;
border: 0.05em solid #1e1e1e;
border-radius: 0.15em;
padding-bottom: 0.2em;
padding-left: 0.4em;
}
QComboBox::disabled {
background-color: #828790;
@@ -131,15 +131,15 @@ QComboBox::disabled {
/* Group Boxes (Settings Dialog) */
QGroupBox {
margin-top: 17px;
font-size: 13px;
border: 1px solid #bdc3c7;
border-radius: 4px;
margin-top: 1em;
font-size: 8pt;
border: 0.05em solid #bdc3c7;
border-radius: 0.3em;
}
QGroupBox::title {
subcontrol-origin: margin;
subcontrol-position: top center;
padding: 5px 10px 5px 10px;
subcontrol-position: top;
padding: 0.3em 0.5em 0.3em 0.5em;
color: #fff;
}
@@ -154,19 +154,19 @@ QPushButton::disabled {
/* Log and Debugger borders */
QTextEdit {
border: 1px solid #828790;
border: 0.05em solid #828790;
}
/* For dock buttons to be visible */
QDockWidget::close-button, QDockWidget::float-button {
background-color: #bdc3c7;
border: 1px solid #000;
border-radius: 4px;
border: 0.05em solid #000;
border-radius: 0.3em;
}
/* Disable ugly borders */
QTabWidget::pane {
border: 0px solid #828790;
border: 0em solid #828790;
}
/* Top menu bar */
@@ -174,14 +174,14 @@ QMenuBar::item:selected {
background: #444444;
}
QMenu::item {
padding-left: 20px;
padding-right: 15px;
padding-top: 4px;
padding-bottom: 4px;
padding-left: 1.5em;
padding-right: 0.75em;
padding-top: 0.25em;
padding-bottom: 0.25em;
}
QMenu::item:selected {
background: #444444;
border: 1px solid #bdc3c7;
border: 0.05em solid #bdc3c7;
}
QMenu::item:disabled {
background-color: #444444;
@@ -223,7 +223,7 @@ QLabel#color_button {
/* Seachbar on main toolbar */
QLineEdit#mw_searchbar {
margin-left:14px;
margin-left: 0.7em;
color: #ecf0f1;
}
+1 -1
View File
@@ -32,7 +32,7 @@ Controller.prototype.ComponentSelectionPageCallback = function() {
var widget = gui.currentPageWidget();
widget.deselectAll();
widget.selectComponent("qt.591.gcc_64");
widget.selectComponent("qt.592.gcc_64");
gui.clickButton(buttons.NextButton);
}
+2 -3
View File
@@ -29,8 +29,8 @@ if (NOT Qt5Widgets_FOUND)
if ("${CMAKE_SYSTEM}" MATCHES "Linux")
message(FATAL_ERROR "Most distros do not provide an up-to-date version of Qt.
If you're on Ubuntu or Linux Mint, there are PPAs you can use to install an up-to-date qt5 version.
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt591-xenial
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt591-trusty
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt592-xenial
https://launchpad.net/~beineri/+archive/ubuntu/opt-qt592-trusty
just make sure to run
source /opt/qt59/bin/qt59-env.sh
before re-running cmake")
@@ -342,7 +342,6 @@ if (NOT WIN32 AND VULKAN_FOUND)
"${RPCS3_SRC_DIR}/../Vulkan/glslang/glslang/MachineIndependent/*.cpp"
"${RPCS3_SRC_DIR}/../Vulkan/glslang/glslang/OSDependent/Unix/*.cpp"
"${RPCS3_SRC_DIR}/../Vulkan/glslang/OGLCompilersDLL/*.cpp"
"${RPCS3_SRC_DIR}/../Vulkan/glslang/hlsl/*.cpp"
"${RPCS3_SRC_DIR}/../Vulkan/glslang/SPIRV/*.cpp"
)
+6 -4
View File
@@ -50,6 +50,8 @@ OpenALThread::OpenALThread()
{
m_format = g_cfg.audio.convert_to_u16 ? AL_FORMAT_71CHN16 : AL_FORMAT_71CHN32;
}
m_buffers = std::make_unique<ALuint[]>(g_cfg.audio.frames);
}
OpenALThread::~OpenALThread()
@@ -83,7 +85,7 @@ void OpenALThread::Close()
if (alIsSource(m_source))
alDeleteSources(1, &m_source);
alDeleteBuffers(g_al_buffers_count, m_buffers);
alDeleteBuffers(g_cfg.audio.frames, m_buffers.get());
checkForAlError("alDeleteBuffers");
}
@@ -98,7 +100,7 @@ void OpenALThread::Open(const void* src, int size)
alGenSources(1, &m_source);
checkForAlError("alGenSources");
alGenBuffers(g_al_buffers_count, m_buffers);
alGenBuffers(g_cfg.audio.frames, m_buffers.get());
checkForAlError("alGenBuffers");
alSourcei(m_source, AL_LOOPING, AL_FALSE);
@@ -106,13 +108,13 @@ void OpenALThread::Open(const void* src, int size)
m_buffer_size = size;
for (uint i = 0; i<g_al_buffers_count; ++i)
for (int i = 0; i < g_cfg.audio.frames; ++i)
{
alBufferData(m_buffers[i], m_format, src, m_buffer_size, 48000);
checkForAlError("alBufferData");
}
alSourceQueueBuffers(m_source, g_al_buffers_count, m_buffers);
alSourceQueueBuffers(m_source, g_cfg.audio.frames, m_buffers.get());
checkForAlError("alSourceQueueBuffers");
Play();
}
+2 -3
View File
@@ -2,15 +2,14 @@
#include "Emu/Audio/AudioThread.h"
#include "3rdparty/OpenAL/include/alext.h"
#include <memory>
class OpenALThread : public AudioThread
{
private:
static const uint g_al_buffers_count = 24;
ALint m_format;
ALuint m_source;
ALuint m_buffers[g_al_buffers_count];
std::unique_ptr<ALuint[]> m_buffers;
ALsizei m_buffer_size;
public:
+1 -1
View File
@@ -59,7 +59,7 @@ ALSAThread::ALSAThread()
if (!check(snd_pcm_hw_params_set_channels(s_tls_handle, hw_params, g_cfg.audio.downmix_to_2ch ? 2 : 8), "snd_pcm_hw_params_set_channels"))
return;
if (!check(snd_pcm_hw_params_set_buffer_size(s_tls_handle, hw_params, 8 * 256), "snd_pcm_hw_params_set_buffer_size"))
if (!check(snd_pcm_hw_params_set_buffer_size(s_tls_handle, hw_params, g_cfg.audio.frames * 256), "snd_pcm_hw_params_set_buffer_size"))
return;
if (!check(snd_pcm_hw_params_set_period_size(s_tls_handle, hw_params, 256, 0), "snd_pcm_hw_params_set_period_size"))
+4 -2
View File
@@ -57,6 +57,8 @@ void audio_config::on_init(const std::shared_ptr<void>& _this)
void audio_config::on_task()
{
thread_ctrl::set_native_priority(1);
AudioDumper m_dump(g_cfg.audio.dump_to_file ? 2 : 0); // Init AudioDumper for 2 channels if enabled
float buf2ch[2 * BUFFER_SIZE]{}; // intermediate buffer for 2 channels
@@ -337,8 +339,8 @@ void audio_config::on_task()
case 8: m_dump.WriteData(&buf8ch, sizeof(buf8ch)); break; // write file data (8 ch)
}
cellAudio.trace("Audio perf: start=%d (access=%d, AddData=%d, events=%d, dump=%d)",
time_pos, stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
cellAudio.trace("Audio perf: (access=%d, AddData=%d, events=%d, dump=%d)",
stamp1 - stamp0, stamp2 - stamp1, stamp3 - stamp2, get_system_time() - stamp3);
}
}
+10
View File
@@ -659,6 +659,11 @@ error_code cellGameGetParamString(s32 id, vm::ptr<char> buf, u32 bufsize)
{
cellGame.warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
if (!buf || bufsize == 0)
{
return CELL_GAME_ERROR_PARAM;
}
const auto prm = fxm::get<content_permission>();
if (!prm)
@@ -685,6 +690,11 @@ error_code cellGameSetParamString(s32 id, vm::cptr<char> buf)
{
cellGame.warning("cellGameSetParamString(id=%d, buf=*0x%x)", id, buf);
if (!buf)
{
return CELL_GAME_ERROR_PARAM;
}
const auto prm = fxm::get<content_permission>();
if (!prm)
+13 -8
View File
@@ -74,7 +74,7 @@ s32 cellMouseGetInfo(vm::ptr<CellMouseInfo> info)
for (u32 i=0; i<CELL_MAX_MICE; i++) info->vendor_id[i] = current_info.vendor_id[i];
for (u32 i=0; i<CELL_MAX_MICE; i++) info->product_id[i] = current_info.product_id[i];
for (u32 i=0; i<CELL_MAX_MICE; i++) info->status[i] = current_info.status[i];
return CELL_OK;
}
@@ -96,7 +96,7 @@ s32 cellMouseInfoTabletMode(u32 port_no, vm::ptr<CellMouseInfoTablet> info)
info->is_supported = 0; // Unimplemented: (0=Tablet mode is not supported)
info->mode = 1; // Unimplemented: (1=Mouse mode)
return CELL_OK;
}
@@ -115,7 +115,7 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
{
return CELL_MOUSE_ERROR_NO_DEVICE;
}
MouseData& current_data = handler->GetData(port_no);
data->update = current_data.update;
data->buttons = current_data.buttons;
@@ -134,22 +134,27 @@ s32 cellMouseGetData(u32 port_no, vm::ptr<CellMouseData> data)
s32 cellMouseGetDataList(u32 port_no, vm::ptr<CellMouseDataList> data)
{
UNIMPLEMENTED_FUNC(sys_io);
return CELL_OK;
sys_io.todo("cellMouseGetDataList(port_no=%d, data=0x%x", port_no, data);
if (g_cfg.io.mouse == mouse_handler::null)
return CELL_MOUSE_ERROR_NO_DEVICE;
else
{
data->list_num = 0;
return CELL_OK;
}
}
s32 cellMouseSetTabletMode(u32 port_no, u32 mode)
{
UNIMPLEMENTED_FUNC(sys_io);
return CELL_OK;
}
s32 cellMouseGetTabletDataList(u32 port_no, u32 data_addr)
{
UNIMPLEMENTED_FUNC(sys_io);
return CELL_OK;
}
+2 -1
View File
@@ -147,7 +147,8 @@ s32 sceNpSnsFbCheckThrottle()
s32 sceNpSnsFbCheckConfig()
{
fmt::throw_exception("Unimplemented" HERE);
sceNpSns.todo("sceNpSnsFbCheckConfig()");
return CELL_OK;
}
s32 sceNpSnsFbLoadThrottle()
+40 -2
View File
@@ -16,6 +16,10 @@
logs::channel sceNpTrophy("sceNpTrophy");
TrophyNotificationBase::~TrophyNotificationBase()
{
}
struct trophy_context_t
{
static const u32 id_base = 1;
@@ -264,7 +268,7 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
const size_t kTargetBufferLength = 31;
char target[kTargetBufferLength + 1];
target[kTargetBufferLength] = 0;
strcpy_trunc(target, fmt::format("TROP_%02d.SFM", /*rpcs3::config.system.language.value()*/0));
strcpy_trunc(target, fmt::format("TROP_%02d.SFM", static_cast<s32>(g_cfg.sys.language)));
if (trp.ContainsEntry(target))
{
@@ -286,7 +290,7 @@ error_code sceNpTrophyRegisterContext(ppu_thread& ppu, u32 context, u32 handle,
for (s32 i = 0; i <= 18; i++)
{
strcpy_trunc(target, fmt::format("TROP_%02d.SFM", i));
if (i != /*rpcs3::config.system.language.value()*/0)
if (i != g_cfg.sys.language)
{
trp.RemoveEntry(target);
}
@@ -490,6 +494,40 @@ error_code sceNpTrophyUnlockTrophy(u32 context, u32 handle, s32 trophyId, vm::pt
*platinumId = SCE_NP_TROPHY_INVALID_TROPHY_ID; // TODO
}
if (g_cfg.misc.show_trophy_popups)
{
// Figure out how many zeros are needed for padding. (either 0, 1, or 2)
std::string padding = "";
if (trophyId < 10)
{
padding = "00";
}
else if (trophyId < 100)
{
padding = "0";
}
// Get icon for the notification.
std::string trophyIconPath = "/dev_hdd0/home/00000001/trophy/" + ctxt->trp_name + "/TROP" + padding + std::to_string(trophyId) + ".PNG";
fs::file trophyIconFile = fs::file(vfs::get(trophyIconPath));
u32 iconSize = trophyIconFile.size();
std::vector<uchar> trophyIconData;
trophyIconFile.read(trophyIconData, iconSize);
vm::ptr<SceNpTrophyDetails> details = vm::make_var(SceNpTrophyDetails());
vm::ptr<SceNpTrophyData> _ = vm::make_var(SceNpTrophyData());
s32 ret = sceNpTrophyGetTrophyInfo(context, handle, trophyId, details, _);
if (ret != CELL_OK)
{
sceNpTrophy.error("Failed to get info for trophy dialog. Error code %x", ret);
*details = SceNpTrophyDetails();
}
Emu.CallAfter([det = *details, trophyIconData]() {
Emu.GetCallbacks().get_trophy_notification_dialog()->ShowTrophyNotification(det, trophyIconData);
});
}
return CELL_OK;
}
+11
View File
@@ -137,3 +137,14 @@ enum
};
using SceNpTrophyStatusCallback = s32(u32 context, u32 status, s32 completed, s32 total, vm::ptr<void> arg);
// Forward declare this function since trophyunlock needs it
error_code sceNpTrophyGetTrophyInfo(u32 context, u32 handle, s32 trophyId, vm::ptr<SceNpTrophyDetails> details, vm::ptr<SceNpTrophyData> data);
class TrophyNotificationBase
{
public:
virtual ~TrophyNotificationBase();
virtual s32 ShowTrophyNotification(const SceNpTrophyDetails& trophy, const std::vector<uchar>& trophyIconBfr) = 0;
};
File diff suppressed because it is too large Load Diff
+736
View File
@@ -6,6 +6,7 @@
#include "Utilities/bit_set.h"
#include "Utilities/BEType.h"
#include "PPUOpcodes.h"
// PPU Function Attributes
enum class ppu_attr : u32
@@ -941,3 +942,738 @@ struct ppu_iname
return value;
}
};
// PPU Analyser Context
struct ppu_acontext
{
// General-purpose register range
struct spec_gpr
{
// Integral range: normalized undef = (0;UINT64_MAX), unnormalized undefs are possible (when max = min - 1)
// Bit range: constant 0 = (0;0), constant 1 = (1;1), normalized undef = (0;1), unnormalized undef = (1;0)
u64 imin = 0; // Integral range begin
u64 imax = -1; // Integral range end
u64 bmin = 0; // Bit range begin
u64 bmax = -1; // Bit range end
void set_undef()
{
imin = 0;
imax = -1;
bmin = 0;
bmax = -1;
}
// (Number of possible values - 1), 0 = const
u64 div() const
{
return imax - imin;
}
// Return zero bits for zeros, ones for ones or undefs
u64 mask() const
{
return bmin | bmax;
}
// Return one bits for ones, zeros for zeros or undefs
u64 ones() const
{
return bmin & bmax;
}
// Return one bits for undefs
u64 undefs() const
{
return bmin ^ bmax;
}
// Return number of trailing zero bits
u64 tz() const
{
return ::cnttz64(mask());
}
// Range NOT
spec_gpr operator ~() const
{
spec_gpr r;
r.imin = ~imax;
r.imax = ~imin;
r.bmin = ~bmax;
r.bmax = ~bmin;
return r;
}
// Range ADD
spec_gpr operator +(const spec_gpr& rhs) const
{
spec_gpr r{};
const u64 adiv = div();
const u64 bdiv = rhs.div();
// Check overflow, generate normalized range
if (adiv != -1 && bdiv != -1 && adiv <= adiv + bdiv)
{
r = range(imin + rhs.imin, imax + rhs.imax);
}
// Carry for bitrange computation
u64 cmin = 0;
u64 cmax = 0;
const u64 amask = mask();
const u64 bmask = rhs.mask();
const u64 aones = ones();
const u64 bones = rhs.ones();
for (u32 i = 0; i < 64; i++)
{
cmin += ((amask >> i) & 1) + ((bmask >> i) & 1);
cmax += ((aones >> i) & 1) + ((bones >> i) & 1);
// Discover some constant bits
if (cmin == cmax)
{
r.bmin |= (cmin & 1) << i;
r.bmax &= ~((~cmin & 1) << i);
}
cmin >>= 1;
cmax >>= 1;
}
return r;
}
// Range AND
spec_gpr operator &(const spec_gpr& rhs) const
{
// Ignore inverted ranges (TODO)
if (imin > imax || rhs.imin > rhs.imax)
{
return approx(ones() & rhs.ones(), mask() & rhs.mask());
}
// Const (TODO: remove when unnecessary)
if (imin == imax && rhs.imin == rhs.imax)
{
return fixed(imin & rhs.imin);
}
// Swap (TODO: remove when unnecessary)
if (imin == imax || rhs.undefs() > undefs())
{
return rhs & *this;
}
// Copy and attempt to partially preserve integral range
spec_gpr r = *this;
for (u32 i = 63; ~i; i--)
{
const u64 m = 1ull << i;
if (!(rhs.mask() & m))
{
if (r.undefs() & m)
{
// undef -> 0
r.imin &= ~(m - 1);
r.imax |= (m - 1);
r.imin &= ~m;
r.imax &= ~m;
}
else if (r.ones() & m)
{
// 1 -> 0
if ((r.imin ^ r.imax) > (m - 1))
{
r.imin &= ~(m - 1);
r.imax |= (m - 1);
}
r.imin &= ~m;
r.imax &= ~m;
}
}
else if (rhs.undefs() & m)
{
// -> undef
r.imin &= ~(m - 1);
r.imax |= (m - 1);
r.imin &= ~m;
r.imax |= m;
}
}
r.bmin = ones() & rhs.ones();
r.bmax = mask() & rhs.mask();
return r;
}
// Range OR
spec_gpr operator |(const spec_gpr& rhs) const
{
// Ignore inverted ranges (TODO)
if (imin > imax || rhs.imin > rhs.imax)
{
return approx(ones() | rhs.ones(), mask() | rhs.mask());
}
// Const (TODO: remove when unnecessary)
if (imin == imax && rhs.imin == rhs.imax)
{
return fixed(imin | rhs.imin);
}
// Swap (TODO: remove when unnecessary)
if (imin == imax || rhs.undefs() > undefs())
{
return rhs | *this;
}
// Copy and attempt to partially preserve integral range
spec_gpr r = *this;
for (u32 i = 63; ~i; i--)
{
const u64 m = 1ull << i;
if (rhs.ones() & m)
{
if (r.undefs() & m)
{
// undef -> 1
r.imin &= ~(m - 1);
r.imax |= (m - 1);
r.imin |= m;
r.imax |= m;
}
else if (!(r.mask() & m))
{
// 0 -> 1
if ((r.imin ^ r.imax) > (m - 1))
{
r.imin &= ~(m - 1);
r.imax |= (m - 1);
}
r.imin |= m;
r.imax |= m;
}
}
else if (rhs.undefs() & m)
{
// -> undef
r.imin &= ~(m - 1);
r.imax |= (m - 1);
r.imin &= ~m;
r.imax |= m;
}
}
r.bmin = ones() | rhs.ones();
r.bmax = mask() | rhs.mask();
return r;
}
// Range XOR
spec_gpr operator ^(const spec_gpr& rhs)
{
return (~*this & rhs) | (*this & ~rhs);
}
// Check whether the value is in range
bool test(u64 value) const
{
if (imin <= imax)
{
if (value < imin || value > imax)
{
return false;
}
}
else
{
if (value < imin && value > imax)
{
return false;
}
}
if ((value & mask()) != value)
{
return false;
}
if ((value | ones()) != value)
{
return false;
}
return true;
}
// Constant value
static spec_gpr fixed(u64 value)
{
spec_gpr r;
r.imin = value;
r.imax = value;
r.bmin = value;
r.bmax = value;
return r;
}
// Range (tz = number of constant trailing zeros)
static spec_gpr range(u64 min, u64 max, u64 tz = 0)
{
const u64 mask = tz < 64 ? ~0ull << tz : 0ull;
spec_gpr r;
r.bmin = 0;
r.bmax = mask;
// Normalize min/max for tz (TODO)
if (min < max)
{
// Inverted constant MSB mask
const u64 mix = ~0ull >> ::cntlz64(min ^ max, true);
r.bmin |= min & ~mix;
r.bmax &= max | mix;
r.imin = (min + ~mask) & mask;
r.imax = max & mask;
verify("Impossible range" HERE), r.imin <= r.imax;
}
else
{
r.imin = min & mask;
r.imax = (max + ~mask) & mask;
verify("Impossible range" HERE), r.imin >= r.imax;
}
// Fix const values
if (r.imin == r.imax)
{
r.bmin = r.imin;
r.bmax = r.imax;
}
return r;
}
// Make from bitrange (normalize, approximate range values)
static spec_gpr approx(u64 bmin, u64 bmax)
{
spec_gpr r;
r.imin = bmin & ~(bmin ^ bmax);
r.imax = bmax | (bmin ^ bmax);
r.bmin = bmin & ~(bmin ^ bmax);
r.bmax = bmax | (bmin ^ bmax);
return r;
}
} gpr[32]{};
// Vector registers (draft)
struct spec_vec
{
u8 imin8[16]{};
u8 imax8[16]{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255};
u16 imin16[8]{};
u16 imax16[8]{0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff};
u32 imin32[4]{};
u32 imax32[4]{0xffffffffu, 0xffffffffu, 0xffffffffu, 0xffffffffu};
u64 bmin64[2]{};
u64 bmax64[2]{0xffffffffffffffffull, 0xffffffffffffffffull};
};
// Info
u32 cia;
// Analyser step
void UNK(ppu_opcode_t);
void MFVSCR(ppu_opcode_t);
void MTVSCR(ppu_opcode_t);
void VADDCUW(ppu_opcode_t);
void VADDFP(ppu_opcode_t);
void VADDSBS(ppu_opcode_t);
void VADDSHS(ppu_opcode_t);
void VADDSWS(ppu_opcode_t);
void VADDUBM(ppu_opcode_t);
void VADDUBS(ppu_opcode_t);
void VADDUHM(ppu_opcode_t);
void VADDUHS(ppu_opcode_t);
void VADDUWM(ppu_opcode_t);
void VADDUWS(ppu_opcode_t);
void VAND(ppu_opcode_t);
void VANDC(ppu_opcode_t);
void VAVGSB(ppu_opcode_t);
void VAVGSH(ppu_opcode_t);
void VAVGSW(ppu_opcode_t);
void VAVGUB(ppu_opcode_t);
void VAVGUH(ppu_opcode_t);
void VAVGUW(ppu_opcode_t);
void VCFSX(ppu_opcode_t);
void VCFUX(ppu_opcode_t);
void VCMPBFP(ppu_opcode_t);
void VCMPEQFP(ppu_opcode_t);
void VCMPEQUB(ppu_opcode_t);
void VCMPEQUH(ppu_opcode_t);
void VCMPEQUW(ppu_opcode_t);
void VCMPGEFP(ppu_opcode_t);
void VCMPGTFP(ppu_opcode_t);
void VCMPGTSB(ppu_opcode_t);
void VCMPGTSH(ppu_opcode_t);
void VCMPGTSW(ppu_opcode_t);
void VCMPGTUB(ppu_opcode_t);
void VCMPGTUH(ppu_opcode_t);
void VCMPGTUW(ppu_opcode_t);
void VCTSXS(ppu_opcode_t);
void VCTUXS(ppu_opcode_t);
void VEXPTEFP(ppu_opcode_t);
void VLOGEFP(ppu_opcode_t);
void VMADDFP(ppu_opcode_t);
void VMAXFP(ppu_opcode_t);
void VMAXSB(ppu_opcode_t);
void VMAXSH(ppu_opcode_t);
void VMAXSW(ppu_opcode_t);
void VMAXUB(ppu_opcode_t);
void VMAXUH(ppu_opcode_t);
void VMAXUW(ppu_opcode_t);
void VMHADDSHS(ppu_opcode_t);
void VMHRADDSHS(ppu_opcode_t);
void VMINFP(ppu_opcode_t);
void VMINSB(ppu_opcode_t);
void VMINSH(ppu_opcode_t);
void VMINSW(ppu_opcode_t);
void VMINUB(ppu_opcode_t);
void VMINUH(ppu_opcode_t);
void VMINUW(ppu_opcode_t);
void VMLADDUHM(ppu_opcode_t);
void VMRGHB(ppu_opcode_t);
void VMRGHH(ppu_opcode_t);
void VMRGHW(ppu_opcode_t);
void VMRGLB(ppu_opcode_t);
void VMRGLH(ppu_opcode_t);
void VMRGLW(ppu_opcode_t);
void VMSUMMBM(ppu_opcode_t);
void VMSUMSHM(ppu_opcode_t);
void VMSUMSHS(ppu_opcode_t);
void VMSUMUBM(ppu_opcode_t);
void VMSUMUHM(ppu_opcode_t);
void VMSUMUHS(ppu_opcode_t);
void VMULESB(ppu_opcode_t);
void VMULESH(ppu_opcode_t);
void VMULEUB(ppu_opcode_t);
void VMULEUH(ppu_opcode_t);
void VMULOSB(ppu_opcode_t);
void VMULOSH(ppu_opcode_t);
void VMULOUB(ppu_opcode_t);
void VMULOUH(ppu_opcode_t);
void VNMSUBFP(ppu_opcode_t);
void VNOR(ppu_opcode_t);
void VOR(ppu_opcode_t);
void VPERM(ppu_opcode_t);
void VPKPX(ppu_opcode_t);
void VPKSHSS(ppu_opcode_t);
void VPKSHUS(ppu_opcode_t);
void VPKSWSS(ppu_opcode_t);
void VPKSWUS(ppu_opcode_t);
void VPKUHUM(ppu_opcode_t);
void VPKUHUS(ppu_opcode_t);
void VPKUWUM(ppu_opcode_t);
void VPKUWUS(ppu_opcode_t);
void VREFP(ppu_opcode_t);
void VRFIM(ppu_opcode_t);
void VRFIN(ppu_opcode_t);
void VRFIP(ppu_opcode_t);
void VRFIZ(ppu_opcode_t);
void VRLB(ppu_opcode_t);
void VRLH(ppu_opcode_t);
void VRLW(ppu_opcode_t);
void VRSQRTEFP(ppu_opcode_t);
void VSEL(ppu_opcode_t);
void VSL(ppu_opcode_t);
void VSLB(ppu_opcode_t);
void VSLDOI(ppu_opcode_t);
void VSLH(ppu_opcode_t);
void VSLO(ppu_opcode_t);
void VSLW(ppu_opcode_t);
void VSPLTB(ppu_opcode_t);
void VSPLTH(ppu_opcode_t);
void VSPLTISB(ppu_opcode_t);
void VSPLTISH(ppu_opcode_t);
void VSPLTISW(ppu_opcode_t);
void VSPLTW(ppu_opcode_t);
void VSR(ppu_opcode_t);
void VSRAB(ppu_opcode_t);
void VSRAH(ppu_opcode_t);
void VSRAW(ppu_opcode_t);
void VSRB(ppu_opcode_t);
void VSRH(ppu_opcode_t);
void VSRO(ppu_opcode_t);
void VSRW(ppu_opcode_t);
void VSUBCUW(ppu_opcode_t);
void VSUBFP(ppu_opcode_t);
void VSUBSBS(ppu_opcode_t);
void VSUBSHS(ppu_opcode_t);
void VSUBSWS(ppu_opcode_t);
void VSUBUBM(ppu_opcode_t);
void VSUBUBS(ppu_opcode_t);
void VSUBUHM(ppu_opcode_t);
void VSUBUHS(ppu_opcode_t);
void VSUBUWM(ppu_opcode_t);
void VSUBUWS(ppu_opcode_t);
void VSUMSWS(ppu_opcode_t);
void VSUM2SWS(ppu_opcode_t);
void VSUM4SBS(ppu_opcode_t);
void VSUM4SHS(ppu_opcode_t);
void VSUM4UBS(ppu_opcode_t);
void VUPKHPX(ppu_opcode_t);
void VUPKHSB(ppu_opcode_t);
void VUPKHSH(ppu_opcode_t);
void VUPKLPX(ppu_opcode_t);
void VUPKLSB(ppu_opcode_t);
void VUPKLSH(ppu_opcode_t);
void VXOR(ppu_opcode_t);
void TDI(ppu_opcode_t);
void TWI(ppu_opcode_t);
void MULLI(ppu_opcode_t);
void SUBFIC(ppu_opcode_t);
void CMPLI(ppu_opcode_t);
void CMPI(ppu_opcode_t);
void ADDIC(ppu_opcode_t);
void ADDI(ppu_opcode_t);
void ADDIS(ppu_opcode_t);
void BC(ppu_opcode_t);
void SC(ppu_opcode_t);
void B(ppu_opcode_t);
void MCRF(ppu_opcode_t);
void BCLR(ppu_opcode_t);
void CRNOR(ppu_opcode_t);
void CRANDC(ppu_opcode_t);
void ISYNC(ppu_opcode_t);
void CRXOR(ppu_opcode_t);
void CRNAND(ppu_opcode_t);
void CRAND(ppu_opcode_t);
void CREQV(ppu_opcode_t);
void CRORC(ppu_opcode_t);
void CROR(ppu_opcode_t);
void BCCTR(ppu_opcode_t);
void RLWIMI(ppu_opcode_t);
void RLWINM(ppu_opcode_t);
void RLWNM(ppu_opcode_t);
void ORI(ppu_opcode_t);
void ORIS(ppu_opcode_t);
void XORI(ppu_opcode_t);
void XORIS(ppu_opcode_t);
void ANDI(ppu_opcode_t);
void ANDIS(ppu_opcode_t);
void RLDICL(ppu_opcode_t);
void RLDICR(ppu_opcode_t);
void RLDIC(ppu_opcode_t);
void RLDIMI(ppu_opcode_t);
void RLDCL(ppu_opcode_t);
void RLDCR(ppu_opcode_t);
void CMP(ppu_opcode_t);
void TW(ppu_opcode_t);
void LVSL(ppu_opcode_t);
void LVEBX(ppu_opcode_t);
void SUBFC(ppu_opcode_t);
void ADDC(ppu_opcode_t);
void MULHDU(ppu_opcode_t);
void MULHWU(ppu_opcode_t);
void MFOCRF(ppu_opcode_t);
void LWARX(ppu_opcode_t);
void LDX(ppu_opcode_t);
void LWZX(ppu_opcode_t);
void SLW(ppu_opcode_t);
void CNTLZW(ppu_opcode_t);
void SLD(ppu_opcode_t);
void AND(ppu_opcode_t);
void CMPL(ppu_opcode_t);
void LVSR(ppu_opcode_t);
void LVEHX(ppu_opcode_t);
void SUBF(ppu_opcode_t);
void LDUX(ppu_opcode_t);
void DCBST(ppu_opcode_t);
void LWZUX(ppu_opcode_t);
void CNTLZD(ppu_opcode_t);
void ANDC(ppu_opcode_t);
void TD(ppu_opcode_t);
void LVEWX(ppu_opcode_t);
void MULHD(ppu_opcode_t);
void MULHW(ppu_opcode_t);
void LDARX(ppu_opcode_t);
void DCBF(ppu_opcode_t);
void LBZX(ppu_opcode_t);
void LVX(ppu_opcode_t);
void NEG(ppu_opcode_t);
void LBZUX(ppu_opcode_t);
void NOR(ppu_opcode_t);
void STVEBX(ppu_opcode_t);
void SUBFE(ppu_opcode_t);
void ADDE(ppu_opcode_t);
void MTOCRF(ppu_opcode_t);
void STDX(ppu_opcode_t);
void STWCX(ppu_opcode_t);
void STWX(ppu_opcode_t);
void STVEHX(ppu_opcode_t);
void STDUX(ppu_opcode_t);
void STWUX(ppu_opcode_t);
void STVEWX(ppu_opcode_t);
void SUBFZE(ppu_opcode_t);
void ADDZE(ppu_opcode_t);
void STDCX(ppu_opcode_t);
void STBX(ppu_opcode_t);
void STVX(ppu_opcode_t);
void SUBFME(ppu_opcode_t);
void MULLD(ppu_opcode_t);
void ADDME(ppu_opcode_t);
void MULLW(ppu_opcode_t);
void DCBTST(ppu_opcode_t);
void STBUX(ppu_opcode_t);
void ADD(ppu_opcode_t);
void DCBT(ppu_opcode_t);
void LHZX(ppu_opcode_t);
void EQV(ppu_opcode_t);
void ECIWX(ppu_opcode_t);
void LHZUX(ppu_opcode_t);
void XOR(ppu_opcode_t);
void MFSPR(ppu_opcode_t);
void LWAX(ppu_opcode_t);
void DST(ppu_opcode_t);
void LHAX(ppu_opcode_t);
void LVXL(ppu_opcode_t);
void MFTB(ppu_opcode_t);
void LWAUX(ppu_opcode_t);
void DSTST(ppu_opcode_t);
void LHAUX(ppu_opcode_t);
void STHX(ppu_opcode_t);
void ORC(ppu_opcode_t);
void ECOWX(ppu_opcode_t);
void STHUX(ppu_opcode_t);
void OR(ppu_opcode_t);
void DIVDU(ppu_opcode_t);
void DIVWU(ppu_opcode_t);
void MTSPR(ppu_opcode_t);
void DCBI(ppu_opcode_t);
void NAND(ppu_opcode_t);
void STVXL(ppu_opcode_t);
void DIVD(ppu_opcode_t);
void DIVW(ppu_opcode_t);
void LVLX(ppu_opcode_t);
void LDBRX(ppu_opcode_t);
void LSWX(ppu_opcode_t);
void LWBRX(ppu_opcode_t);
void LFSX(ppu_opcode_t);
void SRW(ppu_opcode_t);
void SRD(ppu_opcode_t);
void LVRX(ppu_opcode_t);
void LSWI(ppu_opcode_t);
void LFSUX(ppu_opcode_t);
void SYNC(ppu_opcode_t);
void LFDX(ppu_opcode_t);
void LFDUX(ppu_opcode_t);
void STVLX(ppu_opcode_t);
void STDBRX(ppu_opcode_t);
void STSWX(ppu_opcode_t);
void STWBRX(ppu_opcode_t);
void STFSX(ppu_opcode_t);
void STVRX(ppu_opcode_t);
void STFSUX(ppu_opcode_t);
void STSWI(ppu_opcode_t);
void STFDX(ppu_opcode_t);
void STFDUX(ppu_opcode_t);
void LVLXL(ppu_opcode_t);
void LHBRX(ppu_opcode_t);
void SRAW(ppu_opcode_t);
void SRAD(ppu_opcode_t);
void LVRXL(ppu_opcode_t);
void DSS(ppu_opcode_t);
void SRAWI(ppu_opcode_t);
void SRADI(ppu_opcode_t);
void EIEIO(ppu_opcode_t);
void STVLXL(ppu_opcode_t);
void STHBRX(ppu_opcode_t);
void EXTSH(ppu_opcode_t);
void STVRXL(ppu_opcode_t);
void EXTSB(ppu_opcode_t);
void STFIWX(ppu_opcode_t);
void EXTSW(ppu_opcode_t);
void ICBI(ppu_opcode_t);
void DCBZ(ppu_opcode_t);
void LWZ(ppu_opcode_t);
void LWZU(ppu_opcode_t);
void LBZ(ppu_opcode_t);
void LBZU(ppu_opcode_t);
void STW(ppu_opcode_t);
void STWU(ppu_opcode_t);
void STB(ppu_opcode_t);
void STBU(ppu_opcode_t);
void LHZ(ppu_opcode_t);
void LHZU(ppu_opcode_t);
void LHA(ppu_opcode_t);
void LHAU(ppu_opcode_t);
void STH(ppu_opcode_t);
void STHU(ppu_opcode_t);
void LMW(ppu_opcode_t);
void STMW(ppu_opcode_t);
void LFS(ppu_opcode_t);
void LFSU(ppu_opcode_t);
void LFD(ppu_opcode_t);
void LFDU(ppu_opcode_t);
void STFS(ppu_opcode_t);
void STFSU(ppu_opcode_t);
void STFD(ppu_opcode_t);
void STFDU(ppu_opcode_t);
void LD(ppu_opcode_t);
void LDU(ppu_opcode_t);
void LWA(ppu_opcode_t);
void STD(ppu_opcode_t);
void STDU(ppu_opcode_t);
void FDIVS(ppu_opcode_t);
void FSUBS(ppu_opcode_t);
void FADDS(ppu_opcode_t);
void FSQRTS(ppu_opcode_t);
void FRES(ppu_opcode_t);
void FMULS(ppu_opcode_t);
void FMADDS(ppu_opcode_t);
void FMSUBS(ppu_opcode_t);
void FNMSUBS(ppu_opcode_t);
void FNMADDS(ppu_opcode_t);
void MTFSB1(ppu_opcode_t);
void MCRFS(ppu_opcode_t);
void MTFSB0(ppu_opcode_t);
void MTFSFI(ppu_opcode_t);
void MFFS(ppu_opcode_t);
void MTFSF(ppu_opcode_t);
void FCMPU(ppu_opcode_t);
void FRSP(ppu_opcode_t);
void FCTIW(ppu_opcode_t);
void FCTIWZ(ppu_opcode_t);
void FDIV(ppu_opcode_t);
void FSUB(ppu_opcode_t);
void FADD(ppu_opcode_t);
void FSQRT(ppu_opcode_t);
void FSEL(ppu_opcode_t);
void FMUL(ppu_opcode_t);
void FRSQRTE(ppu_opcode_t);
void FMSUB(ppu_opcode_t);
void FMADD(ppu_opcode_t);
void FNMSUB(ppu_opcode_t);
void FNMADD(ppu_opcode_t);
void FCMPO(ppu_opcode_t);
void FNEG(ppu_opcode_t);
void FMR(ppu_opcode_t);
void FNABS(ppu_opcode_t);
void FABS(ppu_opcode_t);
void FCTID(ppu_opcode_t);
void FCTIDZ(ppu_opcode_t);
void FCFID(ppu_opcode_t);
};
+3 -3
View File
@@ -133,7 +133,7 @@ Function* PPUTranslator::Translate(const ppu_function& info)
const u64 base = m_reloc ? m_reloc->addr : 0;
m_addr = info.addr - base;
m_thread = &*m_function->getArgumentList().begin();
m_thread = &*m_function->arg_begin();
m_base_loaded = m_ir->CreateLoad(m_base);
m_body = BasicBlock::Create(m_context, "__body", m_function);
@@ -290,7 +290,7 @@ Value* PPUTranslator::RegInit(Value*& local)
Value* PPUTranslator::RegLoad(Value*& local)
{
const uint index = ::narrow<uint>(&local - m_locals);
const auto index = ::narrow<uint>(&local - m_locals);
if (local)
{
@@ -315,7 +315,7 @@ void PPUTranslator::FlushRegisters()
for (auto& local : m_locals)
{
const uint index = static_cast<uint>(&local - m_locals);
const auto index = ::narrow<uint>(&local - m_locals);
// Store value if necessary
if (local && m_globals[index])
+3 -1
View File
@@ -999,6 +999,7 @@ u32 SPUThread::get_ch_count(u32 ch)
case SPU_RdSigNotify2: return ch_snr2.get_count();
case MFC_RdAtomicStat: return ch_atomic_stat.get_count();
case SPU_RdEventStat: return get_events() != 0;
case MFC_Cmd: return std::max(16 - mfc_queue.size(), (u32)0);
}
fmt::throw_exception("Unknown/illegal channel (ch=%d [%s])" HERE, ch, ch < 128 ? spu_ch_name[ch] : "???");
@@ -1434,8 +1435,9 @@ bool SPUThread::set_ch_value(u32 ch, u32 value)
case MFC_Cmd:
{
ch_mfc_cmd.cmd = MFC(value & 0xff);
auto cmd = ch_mfc_cmd; // save and restore previous command arguments
process_mfc_cmd();
ch_mfc_cmd = {}; // clear non-persistent data
ch_mfc_cmd = cmd;
return true;
}
+9 -1
View File
@@ -3,6 +3,7 @@
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Crypto/unedat.h"
#include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h"
#include "sys_lwmutex.h"
@@ -288,13 +289,20 @@ void _sys_process_exit2(ppu_thread& ppu, s32 status, vm::ptr<sys_exit2_param> ar
vm::temporary_unlock(ppu);
Emu.CallAfter([path = std::move(path), argv = std::move(argv), envp = std::move(envp), data = std::move(data)]()
Emu.CallAfter([path = std::move(path), argv = std::move(argv), envp = std::move(envp), data = std::move(data), disc = vfs::get("/dev_bdvd/"), klic = fxm::get_always<LoadedNpdrmKeys_t>()->devKlic]() mutable
{
sys_process.success("Process finished -> %s", argv[0]);
Emu.Stop();
Emu.argv = std::move(argv);
Emu.envp = std::move(envp);
Emu.data = std::move(data);
Emu.disc = std::move(disc);
if (klic != std::array<u8, 16>{})
{
Emu.klic.assign(klic.begin(), klic.end());
}
Emu.BootGame(path, true);
if (Emu.IsReady() && !g_cfg.misc.autostart)
+7
View File
@@ -242,6 +242,7 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
case 0x001: // FIFO
render->ctrl->get = a3;
render->ctrl->put = a4;
render->internal_get = a3;
break;
case 0x100: // Display mode set
@@ -322,6 +323,12 @@ s32 sys_rsx_context_attribute(s32 context_id, u32 package_id, u64 a3, u64 a4, u6
//a5 low bits = ret.format = base | ((base + ((size - 1) / 0x10000)) << 13) | (comp << 26) | (1 << 30);
auto& tile = render->tiles[a3];
// When tile is going to be unbinded, we can use it as a hint that the address will no longer be used as a surface and can be removed/invalidated
// Todo: There may be more checks such as format/size/width can could be done
if (tile.binded && a5 == 0)
render->notify_tile_unbound(a3);
tile.location = ((a4 >> 32) & 0xF) - 1;
tile.offset = ((((a4 >> 32) & 0xFFFFFFFF) >> 16) * 0x10000);
tile.size = ((((a4 & 0x7FFFFFFF) >> 16) + 1) * 0x10000) - tile.offset;
+1 -1
View File
@@ -11,7 +11,7 @@ const HCRYPTPROV s_crypto_provider = []() -> HCRYPTPROV
{
HCRYPTPROV result;
if (!CryptAcquireContextW(&result, nullptr, nullptr, PROV_RSA_FULL, 0))
if (!CryptAcquireContextW(&result, nullptr, nullptr, PROV_RSA_FULL, 0) && !CryptAcquireContextW(&result, nullptr, nullptr, PROV_RSA_FULL, CRYPT_NEWKEYSET))
{
return 0;
}
+84 -97
View File
@@ -456,18 +456,22 @@ void write_vertex_array_data_to_buffer(gsl::span<gsl::byte> raw_dst_span, gsl::s
namespace
{
template<typename T>
std::tuple<T, T> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
std::tuple<T, T, u32> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
{
T min_index = -1;
T max_index = 0;
verify(HERE), (dst.size_bytes() >= src.size_bytes());
size_t dst_idx = 0;
u32 dst_idx = 0;
for (T index : src)
{
if (is_primitive_restart_enabled && index == primitive_restart_index)
{
// List types do not need primitive restart. Just skip over this instead
if (rsx::method_registers.current_draw_clause.is_disjoint_primitive)
continue;
index = -1;
}
else
@@ -478,125 +482,108 @@ std::tuple<T, T> upload_untouched(gsl::span<to_be_t<const T>> src, gsl::span<T>
dst[dst_idx++] = index;
}
return std::make_tuple(min_index, max_index);
return std::make_tuple(min_index, max_index, dst_idx);
}
// FIXME: expanded primitive type may not support primitive restart correctly
template<typename T>
std::tuple<T, T> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
std::tuple<T, T, u32> expand_indexed_triangle_fan(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
{
T min_index = -1;
const T invalid_index = (T)-1;
T min_index = invalid_index;
T max_index = 0;
verify(HERE), (dst.size() >= 3 * (src.size() - 2));
const T index0 = src[0];
if (!is_primitive_restart_enabled || index0 != -1) // Cut
u32 dst_idx = 0;
u32 src_idx = 0;
bool needs_anchor = true;
T anchor = invalid_index;
T last_index = invalid_index;
for (size_t src_idx = 0; src_idx < src.size(); ++src_idx)
{
min_index = std::min(min_index, index0);
max_index = std::max(max_index, index0);
if (needs_anchor)
{
if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index)
continue;
anchor = src[src_idx];
needs_anchor = false;
continue;
}
if (is_primitive_restart_enabled && src[src_idx] == primitive_restart_index)
{
needs_anchor = true;
last_index = invalid_index;
continue;
}
T index = src[src_idx];
max_index = std::max(max_index, index);
min_index = std::min(min_index, index);
if (last_index == invalid_index)
{
//Need at least one anchor and one outer index to create a triange
last_index = index;
continue;
}
dst[dst_idx++] = anchor;
dst[dst_idx++] = last_index;
dst[dst_idx++] = index;
last_index = index;
}
size_t dst_idx = 0;
while (src.size() > 2)
{
gsl::span<to_be_t<const T>> tri_indexes = src.subspan(0, 2);
T index1 = tri_indexes[0];
if (is_primitive_restart_enabled && index1 == primitive_restart_index)
{
index1 = -1;
}
else
{
min_index = std::min(min_index, index1);
max_index = std::max(max_index, index1);
}
T index2 = tri_indexes[1];
if (is_primitive_restart_enabled && index2 == primitive_restart_index)
{
index2 = -1;
}
else
{
min_index = std::min(min_index, index2);
max_index = std::max(max_index, index2);
}
dst[dst_idx++] = index0;
dst[dst_idx++] = index1;
dst[dst_idx++] = index2;
src = src.subspan(2);
}
return std::make_tuple(min_index, max_index);
return std::make_tuple(min_index, max_index, dst_idx);
}
// FIXME: expanded primitive type may not support primitive restart correctly
template<typename T>
std::tuple<T, T> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
std::tuple<T, T, u32> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span<T> dst, bool is_primitive_restart_enabled, T primitive_restart_index)
{
T min_index = -1;
T max_index = 0;
verify(HERE), (4 * dst.size_bytes() >= 6 * src.size_bytes());
size_t dst_idx = 0;
while (!src.empty())
u32 dst_idx = 0;
u8 set_size = 0;
T tmp_indices[4];
for (int src_idx = 0; src_idx < src.size(); ++src_idx)
{
gsl::span<to_be_t<const T>> quad_indexes = src.subspan(0, 4);
T index0 = quad_indexes[0];
if (is_primitive_restart_enabled && index0 == primitive_restart_index)
T index = src[src_idx];
if (is_primitive_restart_enabled && index == primitive_restart_index)
{
index0 = -1;
}
else
{
min_index = std::min(min_index, index0);
max_index = std::max(max_index, index0);
}
T index1 = quad_indexes[1];
if (is_primitive_restart_enabled && index1 == primitive_restart_index)
{
index1 = -1;
}
else
{
min_index = std::min(min_index, index1);
max_index = std::max(max_index, index1);
}
T index2 = quad_indexes[2];
if (is_primitive_restart_enabled && index2 == primitive_restart_index)
{
index2 = -1;
}
else
{
min_index = std::min(min_index, index2);
max_index = std::max(max_index, index2);
}
T index3 = quad_indexes[3];
if (is_primitive_restart_enabled &&index3 == primitive_restart_index)
{
index3 = -1;
}
else
{
min_index = std::min(min_index, index3);
max_index = std::max(max_index, index3);
//empty temp buffer
set_size = 0;
continue;
}
// First triangle
dst[dst_idx++] = index0;
dst[dst_idx++] = index1;
dst[dst_idx++] = index2;
// Second triangle
dst[dst_idx++] = index2;
dst[dst_idx++] = index3;
dst[dst_idx++] = index0;
tmp_indices[set_size++] = index;
max_index = std::max(max_index, index);
min_index = std::min(min_index, index);
src = src.subspan(4);
if (set_size == 4)
{
// First triangle
dst[dst_idx++] = tmp_indices[0];
dst[dst_idx++] = tmp_indices[1];
dst[dst_idx++] = tmp_indices[2];
// Second triangle
dst[dst_idx++] = tmp_indices[2];
dst[dst_idx++] = tmp_indices[3];
dst[dst_idx++] = tmp_indices[0];
set_size = 0;
}
}
return std::make_tuple(min_index, max_index);
return std::make_tuple(min_index, max_index, dst_idx);
}
}
@@ -714,7 +701,7 @@ namespace
// TODO: Unify indexed and non indexed primitive expansion ?
template<typename T>
std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T> dst,
std::tuple<T, T, u32> write_index_array_data_to_buffer_impl(gsl::span<T> dst,
gsl::span<const be_t<T>> src,
rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
std::function<bool(rsx::primitive_type)> expands)
@@ -743,7 +730,7 @@ namespace
}
}
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst,
std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst,
gsl::span<const gsl::byte> src,
rsx::index_array_type type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
std::function<bool(rsx::primitive_type)> expands)
+2 -2
View File
@@ -29,10 +29,10 @@ u32 get_index_type_size(rsx::index_array_type type);
/**
* Write count indexes using (first, first + count) ranges.
* Returns min/max index found during the process.
* Returns min/max index found during the process and the number of valid indices written to the buffer.
* The function expands index buffer for non native primitive type if expands(draw_mode) return true.
*/
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, gsl::span<const gsl::byte> src,
std::tuple<u32, u32, u32> write_index_array_data_to_buffer(gsl::span<gsl::byte> dst, gsl::span<const gsl::byte> src,
rsx::index_array_type, rsx::primitive_type draw_mode, bool restart_index_enabled, u32 restart_index, const std::vector<std::pair<u32, u32> > &first_count_arguments,
std::function<bool(rsx::primitive_type)> expands);
@@ -735,21 +735,12 @@ std::string FragmentProgramDecompiler::Decompile()
if (SIP()) break;
if (handle_tex_srb(opcode)) break;
if (forced_unit == FORCE_NONE)
{
if (handle_sct(opcode)) break;
if (handle_scb(opcode)) break;
}
else if (forced_unit == FORCE_SCT)
{
forced_unit = FORCE_NONE;
if (handle_sct(opcode)) break;
}
else if (forced_unit == FORCE_SCB)
{
forced_unit = FORCE_NONE;
if (handle_scb(opcode)) break;
}
//FENCT/FENCB do not actually reject instructions if they dont match the forced unit
//Tested with Dark Souls II where the repecting FENCX instruction will result in empty luminance averaging shaders
//TODO: More reasearch is needed to determine what real HW does
if (handle_sct(opcode)) break;
if (handle_scb(opcode)) break;
forced_unit = FORCE_NONE;
LOG_ERROR(RSX, "Unknown/illegal instruction: 0x%x (forced unit %d)", opcode, prev_force_unit);
break;
+73 -5
View File
@@ -278,6 +278,8 @@ namespace glsl
OS << "vec4 read_location(int location)\n";
OS << "{\n";
OS << " attribute_desc desc = fetch_desc(location);\n";
OS << " //if attribute is disabled return 1 (makes all operations with it nop except add/sub - TODO)\n";
OS << " if (desc.attribute_size == 0) return vec4(1.);\n";
OS << "\n";
OS << " int vertex_id = " << vertex_id_name << " - int(vertex_base_index);\n";
OS << " if (desc.frequency == 0)\n";
@@ -334,11 +336,6 @@ namespace glsl
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
OS << "}\n\n";
OS << "vec4 texture2DReconstruct(sampler2DRect tex, vec2 coord)\n";
OS << "{\n";
OS << " return decodeLinearDepth(texture(tex, coord.xy).r);\n";
OS << "}\n\n";
OS << "vec4 get_wpos()\n";
OS << "{\n";
OS << " float abs_scale = abs(wpos_scale);\n";
@@ -350,4 +347,75 @@ namespace glsl
{
program_common::insert_fog_declaration(OS, "vec4", "fog_c");
}
static std::string getFunctionImpl(FUNCTION f)
{
switch (f)
{
default:
abort();
case FUNCTION::FUNCTION_DP2:
return "vec4(dot($0.xy, $1.xy))";
case FUNCTION::FUNCTION_DP2A:
return "vec4(dot($0.xy, $1.xy) + $2.x)";
case FUNCTION::FUNCTION_DP3:
return "vec4(dot($0.xyz, $1.xyz))";
case FUNCTION::FUNCTION_DP4:
return "vec4(dot($0, $1))";
case FUNCTION::FUNCTION_DPH:
return "vec4(dot(vec4($0.xyz, 1.0), $1))";
case FUNCTION::FUNCTION_SFL:
return "vec4(0., 0., 0., 0.)";
case FUNCTION::FUNCTION_STR:
return "vec4(1., 1., 1., 1.)";
case FUNCTION::FUNCTION_FRACT:
return "fract($0)";
case FUNCTION::FUNCTION_REFL:
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
return "texture($t, $0.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
return "textureLod($t, $0.x, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
return "textureGrad($t, $0.x, $1.x, $2.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
return "texture($t, $0.xy * texture_parameters[$_i].xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
return "textureProj($t, $0 , $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
return "textureLod($t, $0.xy * texture_parameters[$_i].xy, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
return "textureGrad($t, $0.xy * texture_parameters[$_i].xy , $1.xy, $2.xy)";
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
return "texture($t, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
return "textureLod($t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
return "textureLod($t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD:
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
case FUNCTION::FUNCTION_DFDX:
return "dFdx($0)";
case FUNCTION::FUNCTION_DFDY:
return "dFdy($0)";
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
return "textureLod($t, $0.xy, 0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
return "texture2DReconstruct($t, $0.xy * texture_parameters[$_i].xy)";
}
}
}
+7 -3
View File
@@ -46,6 +46,8 @@ struct data_heap
size_t m_min_guard_size; //If an allocation touches the guard region, reset the heap to avoid going over budget
size_t m_current_allocated_size;
size_t m_largest_allocated_pool;
char* m_name;
public:
data_heap() = default;
~data_heap() = default;
@@ -54,8 +56,10 @@ public:
size_t m_get_pos; // End of free space
void init(size_t heap_size, size_t min_guard_size=0x10000)
void init(size_t heap_size, const char* buffer_name = "unnamed", size_t min_guard_size=0x10000)
{
m_name = const_cast<char*>(buffer_name);
m_size = heap_size;
m_put_pos = 0;
m_get_pos = heap_size - 1;
@@ -71,8 +75,8 @@ public:
{
if (!can_alloc<Alignement>(size))
{
fmt::throw_exception("Working buffer not big enough, buffer_length=%d allocated=%d requested=%d guard=%d largest_pool=%d" HERE,
m_size, m_current_allocated_size, size, m_min_guard_size, m_largest_allocated_pool);
fmt::throw_exception("[%s] Working buffer not big enough, buffer_length=%d allocated=%d requested=%d guard=%d largest_pool=%d" HERE,
m_name, m_size, m_current_allocated_size, size, m_min_guard_size, m_largest_allocated_pool);
}
size_t alloc_size = align(size, Alignement);
+194 -67
View File
@@ -17,6 +17,7 @@ namespace rsx
struct surface_subresource_storage
{
surface_type surface = nullptr;
u32 base_address = 0;
u16 x = 0;
u16 y = 0;
@@ -29,8 +30,8 @@ namespace rsx
surface_subresource_storage() {}
surface_subresource_storage(surface_type src, u16 X, u16 Y, u16 W, u16 H, bool _Bound, bool _Depth, bool _Clipped = false)
: surface(src), x(X), y(Y), w(W), h(H), is_bound(_Bound), is_depth_surface(_Depth), is_clipped(_Clipped)
surface_subresource_storage(u32 addr, surface_type src, u16 X, u16 Y, u16 W, u16 H, bool _Bound, bool _Depth, bool _Clipped = false)
: base_address(addr), surface(src), x(X), y(Y), w(W), h(H), is_bound(_Bound), is_depth_surface(_Depth), is_clipped(_Clipped)
{}
};
@@ -46,11 +47,25 @@ namespace rsx
template <typename image_storage_type>
struct render_target_descriptor
{
GcmTileInfo *tile = nullptr;
rsx::surface_antialiasing aa_mode = rsx::surface_antialiasing::center_1_sample;
u16 raster_offset_x = 0;
u16 raster_offset_y = 0;
u32 raster_address_offset = 0;
virtual image_storage_type get_surface() const = 0;
virtual u16 get_surface_width() const = 0;
virtual u16 get_surface_height() const = 0;
virtual u16 get_rsx_pitch() const = 0;
virtual u16 get_native_pitch() const = 0;
void set_raster_offset(u16 x, u16 y, u8 bpp)
{
raster_offset_x = x;
raster_offset_y = y;
raster_address_offset = (y * get_rsx_pitch()) + (x * bpp);
}
};
/**
@@ -114,6 +129,7 @@ namespace rsx
std::tuple<u32, surface_type> m_bound_depth_stencil = {};
std::list<surface_storage_type> invalidated_resources;
u64 cache_tag = 0ull;
surface_store() = default;
~surface_store() = default;
@@ -163,8 +179,11 @@ namespace rsx
new_surface_storage = std::move(rtt);
if (old_surface)
{
//Exchange this surface with the invalidated one
Traits::notify_surface_invalidated(old_surface_storage);
rtt = std::move(old_surface_storage);
}
else
//rtt is now empty - erase it
invalidated_resources.erase(It);
@@ -177,8 +196,11 @@ namespace rsx
}
if (old_surface != nullptr && new_surface == nullptr)
{
//This was already determined to be invalid and is excluded from testing above
Traits::notify_surface_invalidated(old_surface_storage);
invalidated_resources.push_back(std::move(old_surface_storage));
}
if (new_surface != nullptr)
{
@@ -227,8 +249,11 @@ namespace rsx
new_surface_storage = std::move(ds);
if (old_surface)
{
//Exchange this surface with the invalidated one
Traits::notify_surface_invalidated(old_surface_storage);
ds = std::move(old_surface_storage);
}
else
invalidated_resources.erase(It);
@@ -240,8 +265,11 @@ namespace rsx
}
if (old_surface != nullptr && new_surface == nullptr)
{
//This was already determined to be invalid and is excluded from testing above
Traits::notify_surface_invalidated(old_surface_storage);
invalidated_resources.push_back(std::move(old_surface_storage));
}
if (new_surface != nullptr)
{
@@ -272,6 +300,8 @@ namespace rsx
// u32 clip_x = clip_horizontal_reg;
// u32 clip_y = clip_vertical_reg;
cache_tag++;
// Make previous RTTs sampleable
for (std::tuple<u32, surface_type> &rtt : m_bound_render_targets)
{
@@ -494,8 +524,11 @@ namespace rsx
if (surface == ref)
{
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second));
m_render_targets_storage.erase(It);
cache_tag++;
return;
}
}
@@ -509,21 +542,63 @@ namespace rsx
if (surface == ref)
{
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second));
m_depth_stencil_storage.erase(It);
cache_tag++;
return;
}
}
}
}
/**
* Invalidates surface that exists at an address
*/
void invalidate_surface_address(u32 addr, bool depth)
{
if (address_is_bound(addr, depth))
{
LOG_ERROR(RSX, "Cannot invalidate a currently bound render target!");
return;
}
if (!depth)
{
auto It = m_render_targets_storage.find(addr);
if (It != m_render_targets_storage.end())
{
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second));
m_render_targets_storage.erase(It);
cache_tag++;
return;
}
}
else
{
auto It = m_depth_stencil_storage.find(addr);
if (It != m_depth_stencil_storage.end())
{
Traits::notify_surface_invalidated(It->second);
invalidated_resources.push_back(std::move(It->second));
m_depth_stencil_storage.erase(It);
cache_tag++;
return;
}
}
}
/**
* Clipping and fitting lookup funcrions
* surface_overlaps - returns true if surface overlaps a given surface address and returns the relative x and y position of the surface address within the surface
* address_is_bound - returns true if the surface at a given address is actively bound
* get_surface_subresource_if_available - returns a sectiion descriptor that allows to crop surfaces stored in memory
*/
bool surface_overlaps_address(surface_type surface, u32 surface_address, u32 texaddr, u16 *x, u16 *y, bool scale_to_fit, bool double_height)
bool surface_overlaps_address(surface_type surface, u32 surface_address, u32 texaddr, u16 *x, u16 *y)
{
bool is_subslice = false;
u16 x_offset = 0;
@@ -532,52 +607,70 @@ namespace rsx
if (surface_address > texaddr)
return false;
u32 offset = texaddr - surface_address;
if (texaddr >= surface_address)
const u32 offset = texaddr - surface_address;
if (offset == 0)
{
if (offset == 0)
*x = 0;
*y = 0;
return true;
}
else
{
surface_format_info info;
Traits::get_surface_info(surface, &info);
bool doubled_x = false;
bool doubled_y = false;
switch (surface->aa_mode)
{
case rsx::surface_antialiasing::square_rotated_4_samples:
case rsx::surface_antialiasing::square_centered_4_samples:
doubled_y = true;
//fall through
case rsx::surface_antialiasing::diagonal_centered_2_samples:
doubled_x = true;
break;
}
u32 range = info.rsx_pitch * info.surface_height;
if (doubled_y) range <<= 1;
if (offset < range)
{
y_offset = (offset / info.rsx_pitch);
x_offset = (offset % info.rsx_pitch) / info.bpp;
if (doubled_x) x_offset /= 2;
if (doubled_y) y_offset /= 2;
is_subslice = true;
}
else
{
surface_format_info info;
Traits::get_surface_info(surface, &info);
u32 range = info.rsx_pitch * info.surface_height;
if (double_height) range *= 2;
if (offset < range)
{
const u32 y = (offset / info.rsx_pitch);
u32 x = (offset % info.rsx_pitch) / info.bpp;
if (scale_to_fit)
{
const f32 x_scale = (f32)info.rsx_pitch / info.native_pitch;
x = (u32)((f32)x / x_scale);
}
x_offset = x;
y_offset = y;
if (double_height) y_offset /= 2;
is_subslice = true;
}
}
if (is_subslice)
{
*x = x_offset;
*y = y_offset;
return true;
}
}
if (is_subslice)
{
*x = x_offset;
*y = y_offset;
return true;
}
return false;
}
//Fast hit test
inline bool surface_overlaps_address_fast(surface_type surface, u32 surface_address, u32 texaddr)
{
if (surface_address > texaddr)
return false;
const u32 offset = texaddr - surface_address;
const u32 range = surface->get_rsx_pitch() * surface->get_surface_height();
return (offset < range);
}
bool address_is_bound(u32 address, bool is_depth) const
{
if (is_depth)
@@ -604,30 +697,35 @@ namespace rsx
return true;
}
surface_subresource get_surface_subresource_if_applicable(u32 texaddr, u16 requested_width, u16 requested_height, u16 requested_pitch, bool scale_to_fit = false, bool crop = false, bool ignore_depth_formats = false, bool double_height = false)
surface_subresource get_surface_subresource_if_applicable(u32 texaddr, u16 requested_width, u16 requested_height, u16 requested_pitch,
bool crop = false, bool ignore_depth_formats = false, bool ignore_color_formats = false)
{
auto test_surface = [&](surface_type surface, u32 this_address, u16 &x_offset, u16 &y_offset, u16 &w, u16 &h, bool &clipped)
{
if (surface_overlaps_address(surface, this_address, texaddr, &x_offset, &y_offset, scale_to_fit, double_height))
if (surface_overlaps_address(surface, this_address, texaddr, &x_offset, &y_offset))
{
surface_format_info info;
Traits::get_surface_info(surface, &info);
if (info.rsx_pitch != requested_pitch)
return false;
u16 real_width = requested_width;
u16 real_height = requested_height;
if (scale_to_fit)
switch (surface->aa_mode)
{
f32 pitch_scaling = (f32)requested_pitch / info.native_pitch;
real_width = (u16)((f32)requested_width / pitch_scaling);
case rsx::surface_antialiasing::diagonal_centered_2_samples:
real_width /= 2;
break;
case rsx::surface_antialiasing::square_centered_4_samples:
case rsx::surface_antialiasing::square_rotated_4_samples:
real_width /= 2;
real_height /= 2;
break;
}
if (region_fits(info.surface_width, info.surface_height, x_offset, y_offset, real_width, requested_height))
if (region_fits(info.surface_width, info.surface_height, x_offset, y_offset, real_width, real_height))
{
w = real_width;
h = requested_height;
h = real_height;
clipped = false;
return true;
@@ -640,17 +738,17 @@ namespace rsx
u16 remaining_height = info.surface_height - y_offset;
w = std::min(real_width, remaining_width);
h = std::min(requested_height, remaining_height);
h = std::min(real_height, remaining_height);
clipped = true;
return true;
}
if (info.surface_width >= requested_width && info.surface_height >= requested_height)
if (info.surface_width >= real_width && info.surface_height >= real_height)
{
LOG_WARNING(RSX, "Overlapping surface exceeds bounds; returning full surface region");
w = real_width;
h = requested_height;
h = real_height;
clipped = true;
return true;
@@ -668,26 +766,55 @@ namespace rsx
u16 w;
u16 h;
for (auto &tex_info : m_render_targets_storage)
if (!ignore_color_formats)
{
u32 this_address = std::get<0>(tex_info);
surface = std::get<1>(tex_info).get();
for (auto &tex_info : m_render_targets_storage)
{
const u32 this_address = std::get<0>(tex_info);
if (texaddr < this_address)
continue;
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
return { surface, x_offset, y_offset, w, h, address_is_bound(this_address, false), false, clipped };
surface = std::get<1>(tex_info).get();
if (surface->get_rsx_pitch() != requested_pitch)
continue;
if (requested_width == 0 || requested_height == 0)
{
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
continue;
else
return{ this_address, surface, 0, 0, 0, 0, false, false, false };
}
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
return{ this_address, surface, x_offset, y_offset, w, h, address_is_bound(this_address, false), false, clipped };
}
}
if (ignore_depth_formats)
return{};
//Check depth surfaces for overlap
for (auto &tex_info : m_depth_stencil_storage)
if (!ignore_depth_formats)
{
u32 this_address = std::get<0>(tex_info);
surface = std::get<1>(tex_info).get();
//Check depth surfaces for overlap
for (auto &tex_info : m_depth_stencil_storage)
{
const u32 this_address = std::get<0>(tex_info);
if (texaddr < this_address)
continue;
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
return { surface, x_offset, y_offset, w, h, address_is_bound(this_address, true), true, clipped };
surface = std::get<1>(tex_info).get();
if (surface->get_rsx_pitch() != requested_pitch)
continue;
if (requested_width == 0 || requested_height == 0)
{
if (!surface_overlaps_address_fast(surface, this_address, texaddr))
continue;
else
return{ this_address, surface, 0, 0, 0, 0, false, true, false };
}
if (test_surface(surface, this_address, x_offset, y_offset, w, h, clipped))
return{ this_address, surface, x_offset, y_offset, w, h, address_is_bound(this_address, true), true, clipped };
}
}
return{};
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -410,7 +410,7 @@ namespace
gsl::span<gsl::byte> dst{
reinterpret_cast<gsl::byte*>(mapped_buffer), ::narrow<u32>(buffer_size)};
std::tie(min_index, max_index) =
std::tie(min_index, max_index, index_count) =
write_index_array_data_to_buffer(dst, command.raw_index_buffer, indexed_type,
rsx::method_registers.current_draw_clause.primitive,
rsx::method_registers.restart_index_enabled(),
+1
View File
@@ -183,4 +183,5 @@ protected:
virtual std::array<std::vector<gsl::byte>, 4> copy_render_targets_to_memory() override;
virtual std::array<std::vector<gsl::byte>, 2> copy_depth_stencil_buffer_to_memory() override;
virtual std::pair<std::string, std::string> get_programs() const override;
virtual void notify_tile_unbound(u32 tile) override;
};
+7 -1
View File
@@ -54,7 +54,7 @@ void D3D12GSRender::load_program()
};
get_current_vertex_program();
get_current_fragment_program(rtt_lookup_func);
get_current_fragment_program_legacy(rtt_lookup_func);
if (!current_fragment_program.valid)
return;
@@ -316,4 +316,10 @@ std::pair<std::string, std::string> D3D12GSRender::get_programs() const
{
return std::make_pair(m_pso_cache.get_transform_program(current_vertex_program).content, m_pso_cache.get_shader_program(current_fragment_program).content);
}
void D3D12GSRender::notify_tile_unbound(u32 tile)
{
u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
m_rtts.invalidate_surface_address(addr, false);
}
#endif
@@ -103,9 +103,6 @@ namespace
void D3D12GSRender::clear_surface(u32 arg)
{
// Ignore clear if surface target is set to CELL_GCM_SURFACE_TARGET_NONE
if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
std::chrono::time_point<steady_clock> start_duration = steady_clock::now();
std::chrono::time_point<steady_clock> rtt_duration_start = steady_clock::now();
@@ -142,6 +142,9 @@ struct render_target_traits
//TODO
}
static
void notify_surface_invalidated(const ComPtr<ID3D12Resource>&)
{}
static
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_color_format surface_color_format, size_t width, size_t height, bool=false)
-71
View File
@@ -4,77 +4,6 @@
namespace gl
{
std::string getFunctionImpl(FUNCTION f)
{
switch (f)
{
default:
abort();
case FUNCTION::FUNCTION_DP2:
return "vec4(dot($0.xy, $1.xy))";
case FUNCTION::FUNCTION_DP2A:
return "vec4(dot($0.xy, $1.xy) + $2.x)";
case FUNCTION::FUNCTION_DP3:
return "vec4(dot($0.xyz, $1.xyz))";
case FUNCTION::FUNCTION_DP4:
return "vec4(dot($0, $1))";
case FUNCTION::FUNCTION_DPH:
return "vec4(dot(vec4($0.xyz, 1.0), $1))";
case FUNCTION::FUNCTION_SFL:
return "vec4(0., 0., 0., 0.)";
case FUNCTION::FUNCTION_STR:
return "vec4(1., 1., 1., 1.)";
case FUNCTION::FUNCTION_FRACT:
return "fract($0)";
case FUNCTION::FUNCTION_REFL:
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
return "texture($t, $0.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
return "textureLod($t, $0.x, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
return "textureGrad($t, $0.x, $1.x, $2.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
return "texture($t, $0.xy * $t_coord_scale)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
return "textureProj($t, $0 , $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
return "textureLod($t, $0.xy * $t_coord_scale, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
return "textureGrad($t, $0.xy * $t_coord_scale , $1.xy, $2.xy)";
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
return "texture($t, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
return "textureLod($t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
return "textureLod($t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_GRAD:
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
case FUNCTION::FUNCTION_DFDX:
return "dFdx($0)";
case FUNCTION::FUNCTION_DFDY:
return "dFdy($0)";
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
return "textureLod($t, $0.xy, 0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
return "texture2DReconstruct($t, $0.xy * $t_coord_scale)";
}
}
int get_varying_register_location(const std::string &var_name)
{
static const std::pair<std::string, int> reg_table[] =
-1
View File
@@ -6,6 +6,5 @@
namespace gl
{
std::string getFunctionImpl(FUNCTION f);
int get_varying_register_location(const std::string &var_name);
}
+1 -6
View File
@@ -15,7 +15,7 @@ std::string GLFragmentDecompilerThread::getFloatTypeName(size_t elementCount)
std::string GLFragmentDecompilerThread::getFunction(FUNCTION f)
{
return gl::getFunctionImpl(f);
return glsl::getFunctionImpl(f);
}
std::string GLFragmentDecompilerThread::saturate(const std::string & code)
@@ -173,11 +173,6 @@ namespace
case rsx::texture_dimension_extended::texture_dimension_3d:
case rsx::texture_dimension_extended::texture_dimension_cubemap: vec_type = "vec3";
}
if (prog.unnormalized_coords & (1 << index))
OS << "\t" << vec_type << " tex" << index << "_coord_scale = texture_parameters[" << index << "].xy / textureSize(tex" << index << ", 0);\n";
else
OS << "\t" << vec_type << " tex" << index << "_coord_scale = " << vec_type << "(1.);\n";
}
std::string insert_texture_fetch(const RSXFragmentProgram& prog, int index)
+386 -284
View File
@@ -24,14 +24,14 @@ namespace
GLGSRender::GLGSRender() : GSRender()
{
m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1"));
m_shaders_cache.reset(new gl::shader_cache(m_prog_buffer, "opengl", "v1.1"));
if (g_cfg.video.disable_vertex_cache)
m_vertex_cache.reset(new gl::null_vertex_cache());
else
m_vertex_cache.reset(new gl::weak_vertex_cache());
supports_multidraw = true;
supports_multidraw = !g_cfg.video.strict_rendering_mode;
}
extern CellGcmContextData current_context;
@@ -51,7 +51,7 @@ namespace
case rsx::comparison_function::greater_or_equal: return GL_GEQUAL;
case rsx::comparison_function::always: return GL_ALWAYS;
}
throw;
fmt::throw_exception("Unsupported comparison op 0x%X" HERE, (u32)op);;
}
GLenum stencil_op(rsx::stencil_op op)
@@ -67,7 +67,7 @@ namespace
case rsx::stencil_op::incr_wrap: return GL_INCR_WRAP;
case rsx::stencil_op::decr_wrap: return GL_DECR_WRAP;
}
throw;
fmt::throw_exception("Unsupported stencil op 0x%X" HERE, (u32)op);
}
GLenum blend_equation(rsx::blend_equation op)
@@ -75,16 +75,20 @@ namespace
switch (op)
{
// Note : maybe add is signed on gl
case rsx::blend_equation::add_signed:
LOG_TRACE(RSX, "blend equation add_signed used. Emulating using FUNC_ADD");
case rsx::blend_equation::add: return GL_FUNC_ADD;
case rsx::blend_equation::min: return GL_MIN;
case rsx::blend_equation::max: return GL_MAX;
case rsx::blend_equation::substract: return GL_FUNC_SUBTRACT;
case rsx::blend_equation::reverse_substract_signed:
LOG_TRACE(RSX, "blend equation reverse_subtract_signed used. Emulating using FUNC_REVERSE_SUBTRACT");
case rsx::blend_equation::reverse_substract: return GL_FUNC_REVERSE_SUBTRACT;
case rsx::blend_equation::reverse_substract_signed: throw "unsupported";
case rsx::blend_equation::add_signed: throw "unsupported";
case rsx::blend_equation::reverse_add_signed: throw "unsupported";
case rsx::blend_equation::reverse_add_signed:
default:
LOG_ERROR(RSX, "Blend equation 0x%X is unimplemented!", (u32)op);
return GL_FUNC_ADD;
}
throw;
}
GLenum blend_factor(rsx::blend_factor op)
@@ -107,7 +111,7 @@ namespace
case rsx::blend_factor::constant_alpha: return GL_CONSTANT_ALPHA;
case rsx::blend_factor::one_minus_constant_alpha: return GL_ONE_MINUS_CONSTANT_ALPHA;
}
throw;
fmt::throw_exception("Unsupported blend factor 0x%X" HERE, (u32)op);
}
GLenum logic_op(rsx::logic_op op)
@@ -131,7 +135,7 @@ namespace
case rsx::logic_op::logic_nand: return GL_NAND;
case rsx::logic_op::logic_set: return GL_SET;
}
throw;
fmt::throw_exception("Unsupported logic op 0x%X" HERE, (u32)op);
}
GLenum front_face(rsx::front_face op)
@@ -143,7 +147,7 @@ namespace
case rsx::front_face::cw: return (invert ? GL_CCW : GL_CW);
case rsx::front_face::ccw: return (invert ? GL_CW : GL_CCW);
}
throw;
fmt::throw_exception("Unsupported front face 0x%X" HERE, (u32)op);
}
GLenum cull_face(rsx::cull_face op)
@@ -156,7 +160,7 @@ namespace
case rsx::cull_face::back: return (invert ? GL_FRONT : GL_BACK);
case rsx::cull_face::front_and_back: return GL_FRONT_AND_BACK;
}
throw;
fmt::throw_exception("Unsupported cull face 0x%X" HERE, (u32)op);
}
}
@@ -171,141 +175,13 @@ void GLGSRender::begin()
return;
init_buffers();
if (!framebuffer_status_valid)
return;
std::chrono::time_point<steady_clock> then = steady_clock::now();
bool color_mask_b = rsx::method_registers.color_mask_b();
bool color_mask_g = rsx::method_registers.color_mask_g();
bool color_mask_r = rsx::method_registers.color_mask_r();
bool color_mask_a = rsx::method_registers.color_mask_a();
gl_state.color_mask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
if (gl_state.enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST))
{
gl_state.depth_func(comparison_op(rsx::method_registers.depth_func()));
float range_near = rsx::method_registers.clip_min();
float range_far = rsx::method_registers.clip_max();
//Workaround to preserve depth precision but respect z direction
//Ni no Kuni sets a very restricted z range (0.9x - 1.) and depth reads / tests are broken
if (range_near <= range_far)
gl_state.depth_range(0.f, 1.f);
else
gl_state.depth_range(1.f, 0.f);
}
if (glDepthBoundsEXT && (gl_state.enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT)))
{
gl_state.depth_bounds(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max());
}
gl_state.enable(rsx::method_registers.dither_enabled(), GL_DITHER);
if (gl_state.enable(rsx::method_registers.blend_enabled(), GL_BLEND))
{
glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_sfactor_a()),
blend_factor(rsx::method_registers.blend_func_dfactor_a()));
auto blend_colors = rsx::get_constant_blend_colors();
glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()),
blend_equation(rsx::method_registers.blend_equation_a()));
}
if (gl_state.enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST))
{
glStencilFunc(comparison_op(rsx::method_registers.stencil_func()),
rsx::method_registers.stencil_func_ref(),
rsx::method_registers.stencil_func_mask());
glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()),
stencil_op(rsx::method_registers.stencil_op_zpass()));
if (rsx::method_registers.two_sided_stencil_test_enabled())
{
glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask());
glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()),
rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask());
glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()),
stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass()));
}
}
gl_state.enablei(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1);
gl_state.enablei(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2);
gl_state.enablei(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3);
if (gl_state.enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
{
gl_state.logic_op(logic_op(rsx::method_registers.logic_operation()));
}
gl_state.line_width(rsx::method_registers.line_width());
gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
gl_state.enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT);
gl_state.enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE);
gl_state.enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL);
//offset_bias is the constant factor, multiplied by the implementation factor R
//offst_scale is the slope factor, multiplied by the triangle slope factor M
gl_state.polygon_offset(rsx::method_registers.poly_offset_scale(), rsx::method_registers.poly_offset_bias());
if (gl_state.enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE))
{
gl_state.cull_face(cull_face(rsx::method_registers.cull_face_mode()));
}
gl_state.front_face(front_face(rsx::method_registers.front_face_mode()));
//TODO
//NV4097_SET_ANISO_SPREAD
//NV4097_SET_SPECULAR_ENABLE
//NV4097_SET_TWO_SIDE_LIGHT_EN
//NV4097_SET_FLAT_SHADE_OP
//NV4097_SET_EDGE_FLAG
//NV4097_SET_COLOR_KEY_COLOR
//NV4097_SET_SHADER_CONTROL
//NV4097_SET_ZMIN_MAX_CONTROL
//NV4097_SET_ANTI_ALIASING_CONTROL
//NV4097_SET_CLIP_ID_TEST_ENABLE
std::chrono::time_point<steady_clock> now = steady_clock::now();
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
}
namespace
{
GLenum get_gl_target_for_texture(const rsx::fragment_texture& tex)
GLenum get_gl_target_for_texture(const rsx::texture_dimension_extended type)
{
switch (tex.get_extended_texture_dimension())
{
case rsx::texture_dimension_extended::texture_dimension_1d: return GL_TEXTURE_1D;
case rsx::texture_dimension_extended::texture_dimension_2d: return GL_TEXTURE_2D;
case rsx::texture_dimension_extended::texture_dimension_cubemap: return GL_TEXTURE_CUBE_MAP;
case rsx::texture_dimension_extended::texture_dimension_3d: return GL_TEXTURE_3D;
}
fmt::throw_exception("Unknown texture target" HERE);
}
GLenum get_gl_target_for_texture(const rsx::vertex_texture& tex)
{
switch (tex.get_extended_texture_dimension())
switch (type)
{
case rsx::texture_dimension_extended::texture_dimension_1d: return GL_TEXTURE_1D;
case rsx::texture_dimension_extended::texture_dimension_2d: return GL_TEXTURE_2D;
@@ -318,12 +194,17 @@ namespace
void GLGSRender::end()
{
std::chrono::time_point<steady_clock> state_check_start = steady_clock::now();
if (skip_frame || !framebuffer_status_valid || (conditional_render_enabled && conditional_render_test_failed) || !check_program_state())
{
rsx::thread::end();
return;
}
std::chrono::time_point<steady_clock> state_check_end = steady_clock::now();
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(state_check_end - state_check_start).count();
if (manually_flush_ring_buffers)
{
//Use approximations to reseve space. This path is mostly for debug purposes anyway
@@ -342,6 +223,73 @@ void GLGSRender::end()
std::optional<std::tuple<GLenum, u32> > indexed_draw_info;
std::tie(vertex_draw_count, actual_vertex_count, vertex_base, indexed_draw_info) = set_vertex_buffer();
//Load textures
{
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
std::lock_guard<std::mutex> lock(m_sampler_mutex);
void* unused = nullptr;
bool update_framebuffer_sourced = false;
if (surface_store_tag != m_rtts.cache_tag)
{
update_framebuffer_sourced = true;
surface_store_tag = m_rtts.cache_tag;
}
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
if (!fs_sampler_state[i])
fs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>();
if (m_samplers_dirty || m_textures_dirty[i] ||
(update_framebuffer_sourced && fs_sampler_state[i]->upload_context == rsx::texture_upload_context::framebuffer_storage))
{
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
if (rsx::method_registers.fragment_textures[i].enabled())
{
*sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.fragment_textures[i], m_rtts);
if (m_textures_dirty[i])
m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i]);
}
else
{
*sampler_state = {};
}
m_textures_dirty[i] = false;
}
}
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{
if (!vs_sampler_state[i])
vs_sampler_state[i] = std::make_unique<gl::texture_cache::sampled_image_descriptor>();
if (m_samplers_dirty || m_vertex_textures_dirty[i] ||
(update_framebuffer_sourced && vs_sampler_state[i]->upload_context == rsx::texture_upload_context::framebuffer_storage))
{
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
if (rsx::method_registers.vertex_textures[i].enabled())
{
*sampler_state = m_gl_texture_cache.upload_texture(unused, rsx::method_registers.vertex_textures[i], m_rtts);
}
else
*sampler_state = {};
m_vertex_textures_dirty[i] = false;
}
}
m_samplers_dirty.store(false);
std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
}
std::chrono::time_point<steady_clock> program_start = steady_clock::now();
//Load program here since it is dependent on vertex state
@@ -361,20 +309,102 @@ void GLGSRender::end()
//glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
}
//Bind textures and resolve external copy operations
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
int unused_location;
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
if (m_program->uniforms.has_location("tex" + std::to_string(i), &unused_location))
{
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(fs_sampler_state[i].get());
if (sampler_state->flag)
continue;
sampler_state->flag = true;
auto &tex = rsx::method_registers.fragment_textures[i];
glActiveTexture(GL_TEXTURE0 + i);
if (tex.enabled())
{
GLenum target = get_gl_target_for_texture(sampler_state->image_type);
if (sampler_state->image_handle)
{
glBindTexture(target, sampler_state->image_handle);
}
else if (sampler_state->external_subresource_desc.external_handle)
{
void *unused = nullptr;
glBindTexture(target, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
sampler_state->flag = false;
}
else
{
glBindTexture(target, GL_NONE);
}
}
else
{
glBindTexture(GL_TEXTURE_2D, GL_NONE);
}
}
}
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{
if (m_program->uniforms.has_location("vtex" + std::to_string(i), &unused_location))
{
auto sampler_state = static_cast<gl::texture_cache::sampled_image_descriptor*>(vs_sampler_state[i].get());
if (sampler_state->flag)
continue;
sampler_state->flag = true;
glActiveTexture(GL_TEXTURE0 + rsx::limits::fragment_textures_count + i);
if (sampler_state->image_handle)
{
glBindTexture(GL_TEXTURE_2D, sampler_state->image_handle);
}
else if (sampler_state->external_subresource_desc.external_handle)
{
void *unused = nullptr;
glBindTexture(GL_TEXTURE_2D, m_gl_texture_cache.create_temporary_subresource(unused, sampler_state->external_subresource_desc));
sampler_state->flag = false;
}
else
{
glBindTexture(GL_TEXTURE_2D, GL_NONE);
}
}
}
std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
update_draw_state();
//Check if depth buffer is bound and valid
//If ds is not initialized clear it; it seems new depth textures should have depth cleared
auto copy_rtt_contents = [](gl::render_target *surface)
{
//Copy data from old contents onto this one
//1. Clip a rectangular region defning the data
//2. Perform a GPU blit
u16 parent_w = surface->old_contents->width();
u16 parent_h = surface->old_contents->height();
u16 copy_w, copy_h;
if (surface->get_compatible_internal_format() == surface->old_contents->get_compatible_internal_format())
{
//Copy data from old contents onto this one
//1. Clip a rectangular region defning the data
//2. Perform a GPU blit
u16 parent_w = surface->old_contents->width();
u16 parent_h = surface->old_contents->height();
u16 copy_w, copy_h;
std::tie(std::ignore, std::ignore, copy_w, copy_h) = rsx::clip_region<u16>(parent_w, parent_h, 0, 0, surface->width(), surface->height(), true);
glCopyImageSubData(surface->old_contents->id(), GL_TEXTURE_2D, 0, 0, 0, 0, surface->id(), GL_TEXTURE_2D, 0, 0, 0, 0, copy_w, copy_h, 1);
surface->set_cleared();
}
//TODO: download image contents and reupload them or do a memory cast to copy memory contents if not compatible
std::tie(std::ignore, std::ignore, copy_w, copy_h) = rsx::clip_region<u16>(parent_w, parent_h, 0, 0, surface->width(), surface->height(), true);
glCopyImageSubData(surface->old_contents->id(), GL_TEXTURE_2D, 0, 0, 0, 0, surface->id(), GL_TEXTURE_2D, 0, 0, 0, 0, copy_w, copy_h, 1);
surface->set_cleared();
surface->old_contents = nullptr;
};
@@ -452,43 +482,6 @@ void GLGSRender::end()
glEnable(GL_SCISSOR_TEST);
std::chrono::time_point<steady_clock> textures_start = steady_clock::now();
//Setup textures
//Setting unused texture to 0 is not needed, but makes program validation happy if we choose to enforce it
for (int i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
int location;
if (rsx::method_registers.fragment_textures[i].enabled() && m_program->uniforms.has_location("tex" + std::to_string(i), &location))
{
m_gl_texture_cache.upload_and_bind_texture(i, get_gl_target_for_texture(rsx::method_registers.fragment_textures[i]), rsx::method_registers.fragment_textures[i], m_rtts);
if (m_textures_dirty[i])
{
m_gl_sampler_states[i].apply(rsx::method_registers.fragment_textures[i]);
m_textures_dirty[i] = false;
}
}
}
//Vertex textures
for (int i = 0; i < rsx::limits::vertex_textures_count; ++i)
{
int texture_index = i + rsx::limits::fragment_textures_count;
int location;
if (!rsx::method_registers.vertex_textures[i].enabled())
continue;
if (m_program->uniforms.has_location("vtex" + std::to_string(i), &location))
{
m_gl_texture_cache.upload_and_bind_texture(texture_index, GL_TEXTURE_2D, rsx::method_registers.vertex_textures[i], m_rtts);
}
}
std::chrono::time_point<steady_clock> textures_end = steady_clock::now();
m_textures_upload_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(textures_end - textures_start).count();
std::chrono::time_point<steady_clock> draw_start = steady_clock::now();
if (g_cfg.video.debug_output)
@@ -497,14 +490,15 @@ void GLGSRender::end()
}
const GLenum draw_mode = gl::draw_mode(rsx::method_registers.current_draw_clause.primitive);
bool single_draw = rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive;
bool single_draw = !supports_multidraw || (rsx::method_registers.current_draw_clause.first_count_commands.size() <= 1 || rsx::method_registers.current_draw_clause.is_disjoint_primitive);
if (indexed_draw_info)
{
const GLenum index_type = std::get<0>(indexed_draw_info.value());
const u32 index_offset = std::get<1>(indexed_draw_info.value());
const bool restarts_valid = gl::is_primitive_native(rsx::method_registers.current_draw_clause.primitive) && !rsx::method_registers.current_draw_clause.is_disjoint_primitive;
if (gl_state.enable(rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
if (gl_state.enable(restarts_valid && rsx::method_registers.restart_index_enabled(), GL_PRIMITIVE_RESTART))
{
glPrimitiveRestartIndex((index_type == GL_UNSIGNED_SHORT)? 0xffff: 0xffffffff);
}
@@ -545,21 +539,32 @@ void GLGSRender::end()
}
else
{
std::vector<GLint> firsts;
std::vector<GLsizei> counts;
const auto draw_count = rsx::method_registers.current_draw_clause.first_count_commands.size();
firsts.reserve(draw_count);
counts.reserve(draw_count);
u32 base_index = rsx::method_registers.current_draw_clause.first_count_commands.front().first;
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
if (gl::get_driver_caps().vendor_AMD == false)
{
firsts.push_back(range.first - base_index);
counts.push_back(range.second);
}
std::vector<GLint> firsts;
std::vector<GLsizei> counts;
const auto draw_count = rsx::method_registers.current_draw_clause.first_count_commands.size();
glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count);
firsts.reserve(draw_count);
counts.reserve(draw_count);
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
{
firsts.push_back(range.first - base_index);
counts.push_back(range.second);
}
glMultiDrawArrays(draw_mode, firsts.data(), counts.data(), (GLsizei)draw_count);
}
else
{
//MultiDrawArrays is broken on some primitive types using AMD. One known type is GL_TRIANGLE_STRIP but there could be more
for (const auto &range : rsx::method_registers.current_draw_clause.first_count_commands)
{
glDrawArrays(draw_mode, range.first - base_index, range.second);
}
}
}
}
@@ -614,6 +619,9 @@ void GLGSRender::on_init_thread()
{
GSRender::on_init_thread();
m_frame->disable_wm_event_queue();
m_frame->hide();
gl::init();
//Enable adaptive vsync if vsync is requested
@@ -754,12 +762,13 @@ void GLGSRender::on_init_thread()
m_thread_id = std::this_thread::get_id();
m_shaders_cache->load();
m_frame->enable_wm_event_queue();
m_frame->show();
}
void GLGSRender::on_exit()
{
glFinish();
m_prog_buffer.clear();
if (draw_fbo)
@@ -827,13 +836,15 @@ void GLGSRender::on_exit()
glDeleteQueries(1, &query.handle);
}
return GSRender::on_exit();
glFlush();
glFinish();
GSRender::on_exit();
}
void GLGSRender::clear_surface(u32 arg)
{
if (skip_frame || !framebuffer_status_valid) return;
if (rsx::method_registers.surface_color_target() == rsx::surface_target::none) return;
if ((arg & 0xf3) == 0) return;
GLbitfield mask = 0;
@@ -925,49 +936,23 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
bool GLGSRender::check_program_state()
{
auto rtt_lookup_func = [this](u32 texaddr, rsx::fragment_texture &tex, bool is_depth) -> std::tuple<bool, u16>
{
gl::render_target *surface = nullptr;
if (!is_depth)
surface = m_rtts.get_texture_from_render_target_if_applicable(texaddr);
else
{
surface = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr);
if (!surface && m_gl_texture_cache.is_depth_texture(texaddr, (u32)get_texture_size(tex)))
return std::make_tuple(true, 0);
}
if (!surface)
{
auto rsc = m_rtts.get_surface_subresource_if_applicable(texaddr, 0, 0, tex.pitch());
if (!rsc.surface || rsc.is_depth_surface != is_depth)
return std::make_tuple(false, 0);
surface = rsc.surface;
}
return std::make_tuple(true, surface->get_native_pitch());
};
get_current_fragment_program(rtt_lookup_func);
if (current_fragment_program.valid == false)
return false;
get_current_vertex_program();
return true;
return (rsx::method_registers.shader_program_address() != 0);
}
void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
{
get_current_fragment_program(fs_sampler_state);
verify(HERE), current_fragment_program.valid;
get_current_vertex_program();
auto &fragment_program = current_fragment_program;
auto &vertex_program = current_vertex_program;
vertex_program.skip_vertex_input_check = true; //not needed for us since decoding is done server side
fragment_program.unnormalized_coords = 0; //unused
void* pipeline_properties = nullptr;
auto old_program = m_program;
m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, pipeline_properties);
m_program->use();
@@ -1034,6 +1019,122 @@ void GLGSRender::load_program(u32 vertex_base, u32 vertex_count)
m_transform_constants_dirty = false;
}
void GLGSRender::update_draw_state()
{
std::chrono::time_point<steady_clock> then = steady_clock::now();
bool color_mask_b = rsx::method_registers.color_mask_b();
bool color_mask_g = rsx::method_registers.color_mask_g();
bool color_mask_r = rsx::method_registers.color_mask_r();
bool color_mask_a = rsx::method_registers.color_mask_a();
gl_state.color_mask(color_mask_r, color_mask_g, color_mask_b, color_mask_a);
gl_state.depth_mask(rsx::method_registers.depth_write_enabled());
gl_state.stencil_mask(rsx::method_registers.stencil_mask());
if (gl_state.enable(rsx::method_registers.depth_test_enabled(), GL_DEPTH_TEST))
{
gl_state.depth_func(comparison_op(rsx::method_registers.depth_func()));
float range_near = rsx::method_registers.clip_min();
float range_far = rsx::method_registers.clip_max();
//Workaround to preserve depth precision but respect z direction
//Ni no Kuni sets a very restricted z range (0.9x - 1.) and depth reads / tests are broken
if (range_near <= range_far)
gl_state.depth_range(0.f, 1.f);
else
gl_state.depth_range(1.f, 0.f);
}
if (glDepthBoundsEXT && (gl_state.enable(rsx::method_registers.depth_bounds_test_enabled(), GL_DEPTH_BOUNDS_TEST_EXT)))
{
gl_state.depth_bounds(rsx::method_registers.depth_bounds_min(), rsx::method_registers.depth_bounds_max());
}
gl_state.enable(rsx::method_registers.dither_enabled(), GL_DITHER);
if (gl_state.enable(rsx::method_registers.blend_enabled(), GL_BLEND))
{
glBlendFuncSeparate(blend_factor(rsx::method_registers.blend_func_sfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_dfactor_rgb()),
blend_factor(rsx::method_registers.blend_func_sfactor_a()),
blend_factor(rsx::method_registers.blend_func_dfactor_a()));
auto blend_colors = rsx::get_constant_blend_colors();
glBlendColor(blend_colors[0], blend_colors[1], blend_colors[2], blend_colors[3]);
glBlendEquationSeparate(blend_equation(rsx::method_registers.blend_equation_rgb()),
blend_equation(rsx::method_registers.blend_equation_a()));
}
if (gl_state.enable(rsx::method_registers.stencil_test_enabled(), GL_STENCIL_TEST))
{
glStencilFunc(comparison_op(rsx::method_registers.stencil_func()),
rsx::method_registers.stencil_func_ref(),
rsx::method_registers.stencil_func_mask());
glStencilOp(stencil_op(rsx::method_registers.stencil_op_fail()), stencil_op(rsx::method_registers.stencil_op_zfail()),
stencil_op(rsx::method_registers.stencil_op_zpass()));
if (rsx::method_registers.two_sided_stencil_test_enabled())
{
glStencilMaskSeparate(GL_BACK, rsx::method_registers.back_stencil_mask());
glStencilFuncSeparate(GL_BACK, comparison_op(rsx::method_registers.back_stencil_func()),
rsx::method_registers.back_stencil_func_ref(), rsx::method_registers.back_stencil_func_mask());
glStencilOpSeparate(GL_BACK, stencil_op(rsx::method_registers.back_stencil_op_fail()),
stencil_op(rsx::method_registers.back_stencil_op_zfail()), stencil_op(rsx::method_registers.back_stencil_op_zpass()));
}
}
gl_state.enablei(rsx::method_registers.blend_enabled_surface_1(), GL_BLEND, 1);
gl_state.enablei(rsx::method_registers.blend_enabled_surface_2(), GL_BLEND, 2);
gl_state.enablei(rsx::method_registers.blend_enabled_surface_3(), GL_BLEND, 3);
if (gl_state.enable(rsx::method_registers.logic_op_enabled(), GL_COLOR_LOGIC_OP))
{
gl_state.logic_op(logic_op(rsx::method_registers.logic_operation()));
}
gl_state.line_width(rsx::method_registers.line_width());
gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
gl_state.enable(rsx::method_registers.poly_offset_point_enabled(), GL_POLYGON_OFFSET_POINT);
gl_state.enable(rsx::method_registers.poly_offset_line_enabled(), GL_POLYGON_OFFSET_LINE);
gl_state.enable(rsx::method_registers.poly_offset_fill_enabled(), GL_POLYGON_OFFSET_FILL);
//offset_bias is the constant factor, multiplied by the implementation factor R
//offst_scale is the slope factor, multiplied by the triangle slope factor M
gl_state.polygon_offset(rsx::method_registers.poly_offset_scale(), rsx::method_registers.poly_offset_bias());
if (gl_state.enable(rsx::method_registers.cull_face_enabled(), GL_CULL_FACE))
{
gl_state.cull_face(cull_face(rsx::method_registers.cull_face_mode()));
}
gl_state.front_face(front_face(rsx::method_registers.front_face_mode()));
//TODO
//NV4097_SET_ANISO_SPREAD
//NV4097_SET_SPECULAR_ENABLE
//NV4097_SET_TWO_SIDE_LIGHT_EN
//NV4097_SET_FLAT_SHADE_OP
//NV4097_SET_EDGE_FLAG
//NV4097_SET_COLOR_KEY_COLOR
//NV4097_SET_SHADER_CONTROL
//NV4097_SET_ZMIN_MAX_CONTROL
//NV4097_SET_ANTI_ALIASING_CONTROL
//NV4097_SET_CLIP_ID_TEST_ENABLE
std::chrono::time_point<steady_clock> now = steady_clock::now();
m_begin_time += (u32)std::chrono::duration_cast<std::chrono::microseconds>(now - then).count();
}
void GLGSRender::flip(int buffer)
{
if (skip_frame)
@@ -1156,7 +1257,9 @@ void GLGSRender::flip(int buffer)
m_text_printer.print_text(0, 72, m_frame->client_width(), m_frame->client_height(), "draw call execution: " + std::to_string(m_draw_time) + "us");
auto num_dirty_textures = m_gl_texture_cache.get_unreleased_textures_count();
auto texture_memory_size = m_gl_texture_cache.get_texture_memory_in_use() / (1024 * 1024);
m_text_printer.print_text(0, 108, m_frame->client_width(), m_frame->client_height(), "Unreleased textures: " + std::to_string(num_dirty_textures));
m_text_printer.print_text(0, 126, m_frame->client_width(), m_frame->client_height(), "Texture memory: " + std::to_string(texture_memory_size) + "M");
}
m_frame->flip(m_context);
@@ -1169,10 +1272,6 @@ void GLGSRender::flip(int buffer)
tex->remove();
m_rtts.invalidated_resources.clear();
if (g_cfg.video.invalidate_surface_cache_every_frame)
m_rtts.invalidate_surface_cache_data(nullptr);
m_vertex_cache->purge();
//If we are skipping the next frame, do not reset perf counters
@@ -1195,38 +1294,45 @@ u64 GLGSRender::timestamp() const
bool GLGSRender::on_access_violation(u32 address, bool is_writing)
{
if (is_writing)
return m_gl_texture_cache.invalidate_address(address);
else
bool can_flush = (std::this_thread::get_id() == m_thread_id);
auto result = m_gl_texture_cache.invalidate_address(address, is_writing, can_flush);
if (!result.violation_handled)
return false;
{
if (std::this_thread::get_id() != m_thread_id)
{
bool flushable;
gl::cached_texture_section* section_to_post;
std::tie(flushable, section_to_post) = m_gl_texture_cache.address_is_flushable(address);
if (!flushable) return false;
work_item &task = post_flush_request(address, section_to_post);
vm::temporary_unlock();
{
std::unique_lock<std::mutex> lock(task.guard_mutex);
task.cv.wait(lock, [&task] { return task.processed; });
}
task.received = true;
return task.result;
}
return m_gl_texture_cache.flush_address(address);
std::lock_guard<std::mutex> lock(m_sampler_mutex);
m_samplers_dirty.store(true);
}
if (result.num_flushable > 0)
{
work_item &task = post_flush_request(address, result);
vm::temporary_unlock();
{
std::unique_lock<std::mutex> lock(task.guard_mutex);
task.cv.wait(lock, [&task] { return task.processed; });
}
task.received = true;
return true;
}
return true;
}
void GLGSRender::on_notify_memory_unmapped(u32 address_base, u32 size)
{
if (m_gl_texture_cache.invalidate_range(address_base, size, false))
//Discard all memory in that range without bothering with writeback (Force it for strict?)
if (m_gl_texture_cache.invalidate_range(address_base, size, true, true, false).violation_handled)
{
m_gl_texture_cache.purge_dirty();
{
std::lock_guard<std::mutex> lock(m_sampler_mutex);
m_samplers_dirty.store(true);
}
}
}
void GLGSRender::do_local_task()
@@ -1242,20 +1348,7 @@ void GLGSRender::do_local_task()
if (q.processed) continue;
std::unique_lock<std::mutex> lock(q.guard_mutex);
//Check if the suggested section is valid
if (!q.section_to_flush->is_flushed())
{
m_gl_texture_cache.flush_address(q.address_to_flush);
q.result = true;
}
else
{
//Another thread has unlocked this memory region already
//Return success
q.result = true;
}
q.result = m_gl_texture_cache.flush_all(q.section_data);
q.processed = true;
//Notify thread waiting on this
@@ -1264,14 +1357,14 @@ void GLGSRender::do_local_task()
}
}
work_item& GLGSRender::post_flush_request(u32 address, gl::cached_texture_section *section)
work_item& GLGSRender::post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data)
{
std::lock_guard<std::mutex> lock(queue_guard);
work_queue.emplace_back();
work_item &result = work_queue.back();
result.address_to_flush = address;
result.section_to_flush = section;
result.section_data = std::move(flush_data);
return result;
}
@@ -1286,9 +1379,18 @@ void GLGSRender::synchronize_buffers()
bool GLGSRender::scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate)
{
m_samplers_dirty.store(true);
return m_gl_texture_cache.blit(src, dst, interpolate, m_rtts);
}
void GLGSRender::notify_tile_unbound(u32 tile)
{
//TODO: Handle texture writeback
//u32 addr = rsx::get_address(tiles[tile].offset, tiles[tile].location);
//on_notify_memory_unmapped(addr, tiles[tile].size);
//m_rtts.invalidate_surface_address(addr, false);
}
void GLGSRender::check_zcull_status(bool framebuffer_swap, bool force_read)
{
if (g_cfg.video.disable_zcull_queries)
+11 -29
View File
@@ -28,7 +28,7 @@ struct work_item
std::mutex guard_mutex;
u32 address_to_flush = 0;
gl::cached_texture_section *section_to_flush = nullptr;
gl::texture_cache::thrashed_set section_data;
volatile bool processed = false;
volatile bool result = false;
@@ -310,33 +310,6 @@ struct driver_state
}
};
struct sw_ring_buffer
{
std::vector<u8> data;
u32 ring_pos = 0;
u32 ring_length = 0;
sw_ring_buffer(u32 size)
{
data.resize(size);
ring_length = size;
}
void* get(u32 dwords)
{
const u32 required = (dwords << 2);
if ((ring_pos + required) > ring_length)
{
ring_pos = 0;
return data.data();
}
void *result = data.data() + ring_pos;
ring_pos += required;
return result;
}
};
class GLGSRender : public GSRender
{
private:
@@ -405,6 +378,12 @@ private:
const u32 occlusion_query_count = 128;
std::array<occlusion_query_info, 128> occlusion_query_data = {};
std::mutex m_sampler_mutex;
u64 surface_store_tag = 0;
std::atomic_bool m_samplers_dirty = {true};
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count> fs_sampler_state = {};
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_sampler_state = {};
public:
GLGSRender();
@@ -422,13 +401,15 @@ private:
bool check_program_state();
void load_program(u32 vertex_base, u32 vertex_count);
void update_draw_state();
public:
void read_buffers();
void write_buffers();
void set_viewport();
void synchronize_buffers();
work_item& post_flush_request(u32 address, gl::cached_texture_section *section);
work_item& post_flush_request(u32 address, gl::texture_cache::thrashed_set& flush_data);
bool scaled_image_from_memory(rsx::blit_src_info& src_info, rsx::blit_dst_info& dst_info, bool interpolate) override;
@@ -453,6 +434,7 @@ protected:
bool on_access_violation(u32 address, bool is_writing) override;
void on_notify_memory_unmapped(u32 address_base, u32 size) override;
void notify_tile_unbound(u32 tile) override;
virtual std::array<std::vector<gsl::byte>, 4> copy_render_targets_to_memory() override;
virtual std::array<std::vector<gsl::byte>, 2> copy_depth_stencil_buffer_to_memory() override;
+7
View File
@@ -84,6 +84,7 @@ namespace gl
bool NV_texture_barrier_supported = false;
bool initialized = false;
bool vendor_INTEL = false;
bool vendor_AMD = false;
void initialize()
{
@@ -192,6 +193,12 @@ namespace gl
if (!EXT_dsa_supported && glGetTextureImageEXT && glTextureBufferRangeEXT)
EXT_dsa_supported = true;
}
#ifdef _WIN32
else if (vendor_string.find("amd") != std::string::npos || vendor_string.find("ati") != std::string::npos)
{
vendor_AMD = true;
}
#endif
initialized = true;
}
+52 -10
View File
@@ -165,21 +165,36 @@ void GLGSRender::init_buffers(bool skip_reading)
const u16 clip_horizontal = rsx::method_registers.surface_clip_width();
const u16 clip_vertical = rsx::method_registers.surface_clip_height();
const u16 clip_x = rsx::method_registers.surface_clip_origin_x();
const u16 clip_y = rsx::method_registers.surface_clip_origin_y();
framebuffer_status_valid = false;
if (clip_horizontal == 0 || clip_vertical == 0)
{
LOG_ERROR(RSX, "Invalid framebuffer setup, w=%d, h=%d", clip_horizontal, clip_vertical);
framebuffer_status_valid = false;
return;
}
const auto surface_addresses = get_color_surface_addresses();
const auto depth_address = get_zeta_surface_address();
for (const auto &addr: surface_addresses)
{
if (addr)
{
framebuffer_status_valid = true;
break;
}
}
if (!framebuffer_status_valid && !depth_address)
return;
const auto pitchs = get_pitchs();
const auto surface_format = rsx::method_registers.surface_color();
const auto depth_format = rsx::method_registers.surface_depth_fmt();
const auto surface_addresses = get_color_surface_addresses();
const auto depth_address = get_zeta_surface_address();
m_rtts.prepare_render_target(nullptr, surface_format, depth_format, clip_horizontal, clip_vertical,
rsx::method_registers.surface_color_target(),
surface_addresses, depth_address);
@@ -189,6 +204,11 @@ void GLGSRender::init_buffers(bool skip_reading)
bool old_format_found = false;
gl::texture::format old_format;
const auto color_offsets = get_offsets();
const auto color_locations = get_locations();
const auto aa_mode = rsx::method_registers.surface_antialias();
const auto bpp = get_format_block_size_in_bytes(surface_format);
for (int i = 0; i < rsx::limits::color_buffers_count; ++i)
{
if (surface_info[i].pitch && g_cfg.video.write_color_buffers)
@@ -204,14 +224,15 @@ void GLGSRender::init_buffers(bool skip_reading)
if (std::get<0>(m_rtts.m_bound_render_targets[i]))
{
__glcheck draw_fbo.color[i] = *std::get<1>(m_rtts.m_bound_render_targets[i]);
auto rtt = std::get<1>(m_rtts.m_bound_render_targets[i]);
draw_fbo.color[i] = *rtt;
std::get<1>(m_rtts.m_bound_render_targets[i])->set_rsx_pitch(pitchs[i]);
rtt->set_rsx_pitch(pitchs[i]);
surface_info[i] = { surface_addresses[i], pitchs[i], false, surface_format, depth_format, clip_horizontal, clip_vertical };
//Verify pitch given is correct if pitch <= 64 (especially 64)
if (pitchs[i] <= 64)
{
{
const u16 native_pitch = std::get<1>(m_rtts.m_bound_render_targets[i])->get_native_pitch();
if (native_pitch > pitchs[i])
{
@@ -223,6 +244,14 @@ void GLGSRender::init_buffers(bool skip_reading)
surface_info[i].pitch = 0;
}
}
rtt->tile = find_tile(color_offsets[i], color_locations[i]);
rtt->aa_mode = aa_mode;
rtt->set_raster_offset(clip_x, clip_y, bpp);
m_gl_texture_cache.notify_surface_changed(surface_addresses[i]);
if (surface_info[i].pitch)
m_gl_texture_cache.tag_framebuffer(surface_addresses[i] + rtt->raster_address_offset);
}
else
surface_info[i] = {};
@@ -230,10 +259,16 @@ void GLGSRender::init_buffers(bool skip_reading)
if (std::get<0>(m_rtts.m_bound_depth_stencil))
{
auto ds = std::get<1>(m_rtts.m_bound_depth_stencil);
u8 texel_size = 2;
if (depth_format == rsx::surface_depth_format::z24s8)
__glcheck draw_fbo.depth_stencil = *std::get<1>(m_rtts.m_bound_depth_stencil);
{
draw_fbo.depth_stencil = *ds;
texel_size = 4;
}
else
__glcheck draw_fbo.depth = *std::get<1>(m_rtts.m_bound_depth_stencil);
draw_fbo.depth = *ds;
const u32 depth_surface_pitch = rsx::method_registers.surface_z_pitch();
std::get<1>(m_rtts.m_bound_depth_stencil)->set_rsx_pitch(rsx::method_registers.surface_z_pitch());
@@ -253,6 +288,13 @@ void GLGSRender::init_buffers(bool skip_reading)
depth_surface_info.pitch = 0;
}
}
ds->aa_mode = aa_mode;
ds->set_raster_offset(clip_x, clip_y, texel_size);
m_gl_texture_cache.notify_surface_changed(depth_address);
if (depth_surface_info.pitch)
m_gl_texture_cache.tag_framebuffer(depth_address + ds->raster_address_offset);
}
else
depth_surface_info = {};
@@ -390,7 +432,7 @@ void GLGSRender::read_buffers()
}
else
{
m_gl_texture_cache.invalidate_range(texaddr, range);
m_gl_texture_cache.invalidate_range(texaddr, range, false, false, true);
std::unique_ptr<u8[]> buffer(new u8[pitch * height]);
color_buffer.read(buffer.get(), width, height, pitch);
+4
View File
@@ -253,6 +253,10 @@ struct gl_render_target_traits
static void invalidate_rtt_surface_contents(void *, gl::render_target *rtt, gl::render_target* /*old*/, bool forced) { if (forced) rtt->set_cleared(false); }
static void invalidate_depth_surface_contents(void *, gl::render_target *ds, gl::render_target* /*old*/, bool) { ds->set_cleared(false); }
static
void notify_surface_invalidated(const std::unique_ptr<gl::render_target>&)
{}
static
bool rtt_has_format_width_height(const std::unique_ptr<gl::render_target> &rtt, rsx::surface_color_format format, size_t width, size_t height, bool check_refs=false)
{
+1
View File
@@ -473,6 +473,7 @@ namespace gl
glBindTexture(target, id);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, mipmaps - 1);
+64 -28
View File
@@ -386,6 +386,8 @@ namespace gl
bool flush()
{
if (flushed) return true; //Already written, ignore
if (!copied)
{
LOG_WARNING(RSX, "Cache miss at address 0x%X. This is gonna hurt...", cpu_address_base);
@@ -399,7 +401,6 @@ namespace gl
}
}
protect(utils::protection::rw);
m_fence.wait_for_signal();
flushed = true;
@@ -443,22 +444,21 @@ namespace gl
{
//Read-only texture, destroy texture memory
glDeleteTextures(1, &vram_texture);
vram_texture = 0;
}
else
{
//Destroy pbo cache since vram texture is managed elsewhere
glDeleteBuffers(1, &pbo_id);
pbo_id = 0;
pbo_size = 0;
if (scaled_texture)
{
glDeleteTextures(1, &scaled_texture);
scaled_texture = 0;
}
}
vram_texture = 0;
scaled_texture = 0;
pbo_id = 0;
pbo_size = 0;
if (!m_fence.is_empty())
m_fence.destroy();
}
@@ -571,7 +571,7 @@ namespace gl
m_temporary_surfaces.resize(0);
}
u32 create_temporary_subresource(u32 src_id, GLenum sized_internal_fmt, u16 x, u16 y, u16 width, u16 height)
u32 create_temporary_subresource_impl(u32 src_id, GLenum sized_internal_fmt, const GLenum dst_type, u16 x, u16 y, u16 width, u16 height)
{
u32 dst_id = 0;
@@ -589,19 +589,23 @@ namespace gl
}
glGenTextures(1, &dst_id);
glBindTexture(GL_TEXTURE_2D, dst_id);
glBindTexture(dst_type, dst_id);
glTexStorage2D(GL_TEXTURE_2D, 1, sized_internal_fmt, width, height);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
if (dst_type == GL_TEXTURE_2D)
glTexStorage2D(GL_TEXTURE_2D, 1, sized_internal_fmt, width, height);
else if (dst_type == GL_TEXTURE_1D)
glTexStorage1D(GL_TEXTURE_1D, 1, sized_internal_fmt, width);
glTexParameteri(dst_type, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(dst_type, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(dst_type, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(dst_type, GL_TEXTURE_MAX_LEVEL, 0);
//Empty GL_ERROR
glGetError();
glCopyImageSubData(src_id, GL_TEXTURE_2D, 0, x, y, 0,
dst_id, GL_TEXTURE_2D, 0, 0, 0, 0, width, height, 1);
dst_id, dst_type, 0, 0, 0, 0, width, height, 1);
m_temporary_surfaces.push_back(dst_id);
@@ -625,22 +629,59 @@ namespace gl
u32 create_temporary_subresource_view(void*&, u32* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
{
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
return create_temporary_subresource(*src, ifmt, x, y, w, h);
return create_temporary_subresource_impl(*src, ifmt, GL_TEXTURE_2D, x, y, w, h);
}
u32 create_temporary_subresource_view(void*&, gl::texture* src, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
{
if (auto as_rtt = dynamic_cast<gl::render_target*>(src))
{
return create_temporary_subresource(src->id(), (GLenum)as_rtt->get_compatible_internal_format(), x, y, w, h);
return create_temporary_subresource_impl(src->id(), (GLenum)as_rtt->get_compatible_internal_format(), GL_TEXTURE_2D, x, y, w, h);
}
else
{
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
return create_temporary_subresource(src->id(), ifmt, x, y, w, h);
return create_temporary_subresource_impl(src->id(), ifmt, GL_TEXTURE_2D, x, y, w, h);
}
}
u32 generate_cubemap_from_images(void*&, const u32 gcm_format, u16 size, std::array<u32, 6>& sources) override
{
const GLenum ifmt = gl::get_sized_internal_format(gcm_format);
GLuint dst_id = 0;
glGenTextures(1, &dst_id);
glBindTexture(GL_TEXTURE_CUBE_MAP, dst_id);
glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, ifmt, size, size);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
//Empty GL_ERROR
glGetError();
for (int i = 0; i < 6; ++i)
{
if (sources[i] != 0)
{
glCopyImageSubData(sources[i], GL_TEXTURE_2D, 0, 0, 0, 0,
dst_id, GL_TEXTURE_CUBE_MAP, 0, 0, 0, i, size, size, 1);
}
}
m_temporary_surfaces.push_back(dst_id);
if (GLenum err = glGetError())
{
LOG_WARNING(RSX, "Failed to copy image subresource with GL error 0x%X", err);
return 0;
}
return dst_id;
}
cached_texture_section* create_new_texture(void*&, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, const u32 gcm_format,
const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags,
std::pair<std::array<u8, 4>, std::array<u8, 4>>& /*remap_vector*/) override
@@ -670,10 +711,14 @@ namespace gl
cached.set_depth_flag(depth_flag);
cached.set_view_flags(flags);
cached.set_context(context);
cached.set_image_type(type);
//Its not necessary to lock blit dst textures as they are just reused as necessary
if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode)
{
cached.protect(utils::protection::ro);
update_cache_tag();
}
return &cached;
}
@@ -773,6 +818,7 @@ namespace gl
}
clear_temporary_subresources();
m_temporary_subresource_cache.clear();
}
bool blit(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool linear_interpolate, gl_render_targets& m_rtts)
@@ -780,15 +826,5 @@ namespace gl
void* unused = nullptr;
return upload_scaled_image(src, dst, linear_interpolate, unused, m_rtts, m_hw_blitter);
}
template<typename RsxTextureType>
void upload_and_bind_texture(int index, GLenum target, RsxTextureType &tex, gl_render_targets &m_rtts)
{
glActiveTexture(GL_TEXTURE0 + index);
void* unused = nullptr;
auto id = upload_texture(unused, tex, m_rtts);
glBindTexture(target, id);
}
};
}
+1 -1
View File
@@ -51,7 +51,7 @@ namespace
u32 block_sz = vertex_draw_count * type_size;
gsl::span<gsl::byte> dst{ reinterpret_cast<gsl::byte*>(ptr), ::narrow<u32>(block_sz) };
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, raw_index_buffer,
std::tie(min_index, max_index, vertex_draw_count) = write_index_array_data_to_buffer(dst, raw_index_buffer,
type, draw_mode, rsx::method_registers.restart_index_enabled(), rsx::method_registers.restart_index(), first_count_commands,
[](auto prim) { return !gl::is_primitive_native(prim); });
+1 -2
View File
@@ -18,10 +18,9 @@ std::string GLVertexDecompilerThread::getIntTypeName(size_t elementCount)
return "ivec4";
}
std::string GLVertexDecompilerThread::getFunction(FUNCTION f)
{
return gl::getFunctionImpl(f);
return glsl::getFunctionImpl(f);
}
std::string GLVertexDecompilerThread::compareFunction(COMPARE f, const std::string &Op0, const std::string &Op1)
+12 -11
View File
@@ -4,16 +4,6 @@
#include "GSRender.h"
draw_context_t GSFrameBase::new_context()
{
if (void* context = make_context())
{
return std::shared_ptr<void>(context, [this](void* ctxt) { delete_context(ctxt); });
}
return nullptr;
}
GSRender::GSRender()
{
m_frame = Emu.GetCallbacks().get_gs_frame().release();
@@ -42,11 +32,22 @@ void GSRender::on_init_thread()
{
if (m_frame)
{
m_context = m_frame->new_context();
m_context = m_frame->make_context();
m_frame->set_current(m_context);
}
}
void GSRender::on_exit()
{
if (m_frame)
{
m_frame->delete_context(m_context);
m_context = nullptr;
}
rsx::thread::on_exit();
}
void GSRender::flip(int buffer)
{
if (m_frame)
+19 -6
View File
@@ -24,12 +24,15 @@ enum wm_event
geometry_change_notice, //about to start resizing and/or moving the window
geometry_change_in_progress, //window being resized and/or moved
window_resized, //window was resized
window_moved //window moved without resize
window_minimized, //window was minimized
window_restored, //window was restored from a minimized state
window_moved, //window moved without resize
window_visibility_changed
};
using RSXDebuggerPrograms = std::vector<RSXDebuggerProgram>;
using draw_context_t = std::shared_ptr<void>;
using draw_context_t = void*;
class GSFrameBase
{
@@ -42,8 +45,8 @@ public:
virtual void hide() = 0;
virtual void show() = 0;
draw_context_t new_context();
virtual void delete_context(draw_context_t ctx) = 0;
virtual draw_context_t make_context() = 0;
virtual void set_current(draw_context_t ctx) = 0;
virtual void flip(draw_context_t ctx, bool skip_frame=false) = 0;
virtual int client_width() = 0;
@@ -52,12 +55,11 @@ public:
virtual void* handle() const = 0;
protected:
virtual void delete_context(void* ctx) = 0;
virtual void* make_context() = 0;
//window manager event management
wm_event m_raised_event;
std::atomic_bool wm_event_raised = {};
std::atomic_bool wm_event_queue_enabled = {};
public:
//synchronize native window access
@@ -83,6 +85,16 @@ public:
return get_default_wm_event();
}
void disable_wm_event_queue()
{
wm_event_queue_enabled.store(false);
}
void enable_wm_event_queue()
{
wm_event_queue_enabled.store(true);
}
};
class GSRender : public rsx::thread
@@ -97,6 +109,7 @@ public:
void on_init_rsx() override;
void on_init_thread() override;
void on_exit() override;
void flip(int buffer) override;
};
+3 -6
View File
@@ -243,13 +243,10 @@ struct RSXFragmentProgram
void set_texture_dimension(const std::array<rsx::texture_dimension_extended, 16> &dimensions)
{
size_t id = 0;
for (const rsx::texture_dimension_extended &dim : dimensions)
texture_dimensions = 0;
for (u32 i = 0, offset = 0; i < 16; ++i, offset += 2)
{
texture_dimensions &= ~(0x3 << (id * 2));
u8 d = (u8)dim;
texture_dimensions |= ((d & 0x3) << (id * 2));
id++;
texture_dimensions |= (u32)dimensions[i] << offset;
}
}
+125 -28
View File
@@ -7,6 +7,7 @@
#include "Emu/Cell/PPUCallback.h"
#include "Common/BufferUtils.h"
#include "Common/texture_cache.h"
#include "rsx_methods.h"
#include "rsx_utils.h"
@@ -243,6 +244,7 @@ namespace rsx
};
m_rtts_dirty = true;
memset(m_textures_dirty, -1, sizeof(m_textures_dirty));
memset(m_vertex_textures_dirty, -1, sizeof(m_vertex_textures_dirty));
m_transform_constants_dirty = true;
}
@@ -477,10 +479,10 @@ namespace rsx
//Execute backend-local tasks first
do_local_task();
const u32 get = ctrl->get;
ctrl->get.store(internal_get.load());
const u32 put = ctrl->put;
if (put == get || !Emu.IsRunning())
if (put == internal_get || !Emu.IsRunning())
{
if (has_deferred_call)
flush_command_queue();
@@ -491,16 +493,16 @@ namespace rsx
//Validate put and get registers
//TODO: Who should handle graphics exceptions??
const u32 get_address = RSXIOMem.RealAddr(get);
const u32 get_address = RSXIOMem.RealAddr(internal_get);
if (!get_address)
{
LOG_ERROR(RSX, "Invalid FIFO queue get/put registers found, get=0x%X, put=0x%X", get, put);
LOG_ERROR(RSX, "Invalid FIFO queue get/put registers found, get=0x%X, put=0x%X", internal_get.load(), put);
if (mem_faults_count >= 3)
{
LOG_ERROR(RSX, "Application has failed to recover, discarding FIFO queue");
ctrl->get = put;
internal_get = put;
}
else
{
@@ -512,29 +514,29 @@ namespace rsx
continue;
}
const u32 cmd = ReadIO32(get);
const u32 cmd = ReadIO32(internal_get);
const u32 count = (cmd >> 18) & 0x7ff;
if ((cmd & RSX_METHOD_OLD_JUMP_CMD_MASK) == RSX_METHOD_OLD_JUMP_CMD)
{
u32 offs = cmd & 0x1ffffffc;
//LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
ctrl->get = offs;
internal_get = offs;
continue;
}
if ((cmd & RSX_METHOD_NEW_JUMP_CMD_MASK) == RSX_METHOD_NEW_JUMP_CMD)
{
u32 offs = cmd & 0xfffffffc;
//LOG_WARNING(RSX, "rsx jump(0x%x) #addr=0x%x, cmd=0x%x, get=0x%x, put=0x%x", offs, m_ioAddress + get, cmd, get, put);
ctrl->get = offs;
internal_get = offs;
continue;
}
if ((cmd & RSX_METHOD_CALL_CMD_MASK) == RSX_METHOD_CALL_CMD)
{
m_call_stack.push(get + 4);
m_call_stack.push(internal_get + 4);
u32 offs = cmd & ~3;
//LOG_WARNING(RSX, "rsx call(0x%x) #0x%x - 0x%x", offs, cmd, get);
ctrl->get = offs;
internal_get = offs;
continue;
}
if (cmd == RSX_METHOD_RETURN_CMD)
@@ -542,26 +544,26 @@ namespace rsx
u32 get = m_call_stack.top();
m_call_stack.pop();
//LOG_WARNING(RSX, "rsx return(0x%x)", get);
ctrl->get = get;
internal_get = get;
continue;
}
if (cmd == 0) //nop
{
ctrl->get = get + 4;
internal_get += 4;
continue;
}
//Validate the args ptr if the command attempts to read from it
const u32 args_address = RSXIOMem.RealAddr(get + 4);
const u32 args_address = RSXIOMem.RealAddr(internal_get + 4);
if (!args_address && count)
{
LOG_ERROR(RSX, "Invalid FIFO queue args ptr found, get=0x%X, cmd=0x%X, count=%d", get, cmd, count);
LOG_ERROR(RSX, "Invalid FIFO queue args ptr found, get=0x%X, cmd=0x%X, count=%d", internal_get.load(), cmd, count);
if (mem_faults_count >= 3)
{
LOG_ERROR(RSX, "Application has failed to recover, discarding FIFO queue");
ctrl->get = put;
internal_get = put;
}
else
{
@@ -595,6 +597,7 @@ namespace rsx
bool execute_method_call = true;
//TODO: Flatten draw calls when multidraw is not supported to simplify checking in the end() methods
if (supports_multidraw)
{
//TODO: Make this cleaner
@@ -713,11 +716,11 @@ namespace rsx
{
//This is almost guaranteed to be heap corruption at this point
//Ignore the rest of the chain
ctrl->get = put;
internal_get = put;
continue;
}
ctrl->get = get + (count + 1) * 4;
internal_get += (count + 1) * 4;
}
}
@@ -1320,7 +1323,99 @@ namespace rsx
return result;
}
void thread::get_current_fragment_program(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info)
void thread::get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors)
{
auto &result = current_fragment_program = {};
const u32 shader_program = rsx::method_registers.shader_program_address();
if (shader_program == 0)
return;
const u32 program_location = (shader_program & 0x3) - 1;
const u32 program_offset = (shader_program & ~0x3);
result.offset = program_offset;
result.addr = vm::base(rsx::get_address(program_offset, program_location));
result.valid = true;
result.ctrl = rsx::method_registers.shader_control();
result.unnormalized_coords = 0;
result.front_back_color_enabled = !rsx::method_registers.two_side_light_en();
result.back_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.front_color_diffuse_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTDIFFUSE);
result.front_color_specular_output = !!(rsx::method_registers.vertex_attrib_output_mask() & CELL_GCM_ATTRIB_OUTPUT_MASK_FRONTSPECULAR);
result.redirected_textures = 0;
result.shadow_textures = 0;
std::array<texture_dimension_extended, 16> texture_dimensions;
const auto resolution_scale = rsx::get_resolution_scale();
for (u32 i = 0; i < rsx::limits::fragment_textures_count; ++i)
{
auto &tex = rsx::method_registers.fragment_textures[i];
result.texture_scale[i][0] = sampler_descriptors[i]->scale_x;
result.texture_scale[i][1] = sampler_descriptors[i]->scale_y;
result.textures_alpha_kill[i] = 0;
result.textures_zfunc[i] = 0;
if (!tex.enabled())
{
texture_dimensions[i] = texture_dimension_extended::texture_dimension_2d;
}
else
{
texture_dimensions[i] = sampler_descriptors[i]->image_type;
if (tex.alpha_kill_enabled())
{
//alphakill can be ignored unless a valid comparison function is set
const rsx::comparison_function func = (rsx::comparison_function)tex.zfunc();
if (func < rsx::comparison_function::always && func > rsx::comparison_function::never)
{
result.textures_alpha_kill[i] = 1;
result.textures_zfunc[i] = (u8)func;
}
}
const u32 texaddr = rsx::get_address(tex.offset(), tex.location());
const u32 raw_format = tex.format();
if (raw_format & CELL_GCM_TEXTURE_UN)
result.unnormalized_coords |= (1 << i);
if (sampler_descriptors[i]->is_depth_texture)
{
const u32 format = raw_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
switch (format)
{
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
result.redirected_textures |= (1 << i);
break;
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
{
const auto compare_mode = (rsx::comparison_function)tex.zfunc();
if (result.textures_alpha_kill[i] == 0 &&
compare_mode < rsx::comparison_function::always &&
compare_mode > rsx::comparison_function::never)
result.shadow_textures |= (1 << i);
break;
}
default:
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
}
}
}
}
result.set_texture_dimension(texture_dimensions);
}
void thread::get_current_fragment_program_legacy(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info)
{
auto &result = current_fragment_program = {};
@@ -1411,8 +1506,8 @@ namespace rsx
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
result.redirected_textures |= (1 << i);
break;
result.redirected_textures |= (1 << i);
break;
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
@@ -1425,7 +1520,7 @@ namespace rsx
break;
}
default:
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
LOG_ERROR(RSX, "Depth texture bound to pipeline with unexpected format 0x%X", format);
}
}
}
@@ -1458,7 +1553,7 @@ namespace rsx
{
for (GcmTileInfo &tile : tiles)
{
if (!tile.binded || tile.location != location)
if (!tile.binded || (tile.location & 1) != (location & 1))
{
continue;
}
@@ -1570,6 +1665,7 @@ namespace rsx
u32 volatile_offset = 0;
u32 persistent_offset = 0;
//NOTE: Order is important! Transient ayout is always push_buffers followed by register data
if (rsx::method_registers.current_draw_clause.is_immediate_draw)
{
for (const auto &info : layout.volatile_blocks)
@@ -1764,12 +1860,7 @@ namespace rsx
return;
}
for (const u8 index : layout.referenced_registers)
{
memcpy(transient, rsx::method_registers.register_vertex_info[index].data.data(), 16);
transient += 16;
}
//NOTE: Order is important! Transient ayout is always push_buffers followed by register data
if (draw_call.is_immediate_draw)
{
//NOTE: It is possible for immediate draw to only contain index data, so vertex data can be in persistent memory
@@ -1779,6 +1870,12 @@ namespace rsx
transient += info.second;
}
}
for (const u8 index : layout.referenced_registers)
{
memcpy(transient, rsx::method_registers.register_vertex_info[index].data.data(), 16);
transient += 16;
}
}
if (persistent != nullptr)
+8 -1
View File
@@ -135,6 +135,8 @@ namespace rsx
std::array<attribute_buffer_placement, 16> attribute_placement;
};
struct sampled_image_descriptor_base;
class thread : public named_thread
{
std::shared_ptr<thread_ctrl> m_vblank_thread;
@@ -151,6 +153,7 @@ namespace rsx
public:
RsxDmaControl* ctrl = nullptr;
atomic_t<u32> internal_get{ 0 };
Timer timer_sync;
@@ -187,6 +190,7 @@ namespace rsx
bool m_rtts_dirty;
bool m_transform_constants_dirty;
bool m_textures_dirty[16];
bool m_vertex_textures_dirty[4];
protected:
std::array<u32, 4> get_color_surface_addresses() const;
@@ -207,7 +211,9 @@ namespace rsx
* get_surface_info is a helper takes 2 parameters: rsx_texture_address and surface_is_depth
* returns whether surface is a render target and surface pitch in native format
*/
void get_current_fragment_program(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info);
void get_current_fragment_program(const std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count>& sampler_descriptors);
void get_current_fragment_program_legacy(std::function<std::tuple<bool, u16>(u32, fragment_texture&, bool)> get_surface_info);
public:
double fps_limit = 59.94;
@@ -257,6 +263,7 @@ namespace rsx
virtual u64 timestamp() const;
virtual bool on_access_violation(u32 /*address*/, bool /*is_writing*/) { return false; }
virtual void on_notify_memory_unmapped(u32 /*address_base*/, u32 /*size*/) {}
virtual void notify_tile_unbound(u32 /*tile*/) {}
//zcull
virtual void notify_zcull_info_changed() {}
-63
View File
@@ -8,69 +8,6 @@ namespace vk
{
static TBuiltInResource g_default_config;
std::string getFunctionImpl(FUNCTION f)
{
switch (f)
{
default:
abort();
case FUNCTION::FUNCTION_DP2:
return "vec4(dot($0.xy, $1.xy))";
case FUNCTION::FUNCTION_DP2A:
return "vec4(dot($0.xy, $1.xy) + $2.x)";
case FUNCTION::FUNCTION_DP3:
return "vec4(dot($0.xyz, $1.xyz))";
case FUNCTION::FUNCTION_DP4:
return "vec4(dot($0, $1))";
case FUNCTION::FUNCTION_DPH:
return "vec4(dot(vec4($0.xyz, 1.0), $1))";
case FUNCTION::FUNCTION_SFL:
return "vec4(0., 0., 0., 0.)";
case FUNCTION::FUNCTION_STR:
return "vec4(1., 1., 1., 1.)";
case FUNCTION::FUNCTION_FRACT:
return "fract($0)";
case FUNCTION::FUNCTION_REFL:
return "vec4($0 - 2.0 * (dot($0, $1)) * $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
return "texture($t, $0.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
return "textureLod($t, $0.x, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_GRAD:
return "textureGrad($t, $0.x, $1.x, $2.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
return "texture($t, $0.xy * texture_parameters[$_i].xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
return "textureLod($t, $0.xy * texture_parameters[$_i].xy, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_GRAD:
return "textureGrad($t, $0.xy * texture_parameters[$_i].xy, $1.xy, $2.xy)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SHADOW2D_PROJ:
return "textureProj($t, $0, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
return "texture($t, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
return "textureLod($t, $0.xyz, $1.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_GRAD:
return "textureGrad($t, $0.xyz, $1.xyz, $2.xyz)";
case FUNCTION::FUNCTION_DFDX:
return "dFdx($0)";
case FUNCTION::FUNCTION_DFDY:
return "dFdy($0)";
case FUNCTION::FUNCTION_VERTEX_TEXTURE_FETCH2D:
return "textureLod($t, $0.xy, 0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_DEPTH_RGBA:
return "texture2DReconstruct($t, $0.xy)";
}
}
void init_default_resources(TBuiltInResource &rsc)
{
rsc.maxLights = 32;
-3
View File
@@ -12,9 +12,6 @@ namespace vk
int reg_location;
};
//Decompiler function lookup
std::string getFunctionImpl(FUNCTION f);
const varying_register_t& get_varying_register(const std::string& name);
bool compile_glsl_to_spv(std::string& shader, program_domain domain, std::vector<u32> &spv);
+3 -9
View File
@@ -14,7 +14,7 @@ std::string VKFragmentDecompilerThread::getFloatTypeName(size_t elementCount)
std::string VKFragmentDecompilerThread::getFunction(FUNCTION f)
{
return vk::getFunctionImpl(f);
return glsl::getFunctionImpl(f);
}
std::string VKFragmentDecompilerThread::saturate(const std::string & code)
@@ -118,11 +118,7 @@ void VKFragmentDecompilerThread::insertConstants(std::stringstream & OS)
const auto mask = (1 << index);
if (m_prog.unnormalized_coords & mask)
{
samplerType = "sampler2DRect";
}
else if (m_prog.shadow_textures & mask)
if (m_prog.shadow_textures & mask)
{
if (m_shadow_sampled_textures & mask)
{
@@ -458,7 +454,7 @@ void VKFragmentProgram::Decompile(const RSXFragmentProgram& prog)
void VKFragmentProgram::Compile()
{
fs::create_path(fs::get_config_dir() + "/shaderlog");
fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram.spirv", fs::rewrite).write(shader);
fs::file(fs::get_config_dir() + "shaderlog/FragmentProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader);
std::vector<u32> spir_v;
if (!vk::compile_glsl_to_spv(shader, glsl::glsl_fragment_program, spir_v))
@@ -474,8 +470,6 @@ void VKFragmentProgram::Compile()
VkDevice dev = (VkDevice)*vk::get_current_renderer();
vkCreateShaderModule(dev, &fs_info, nullptr, &handle);
id = UINT32_MAX;
}
void VKFragmentProgram::Delete()
File diff suppressed because it is too large Load Diff
+14
View File
@@ -129,6 +129,17 @@ private:
std::unique_ptr<vk::text_writer> m_text_writer;
std::mutex m_sampler_mutex;
u64 surface_store_tag = 0;
std::atomic_bool m_samplers_dirty = { true };
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::fragment_textures_count> fs_sampler_state = {};
std::array<std::unique_ptr<rsx::sampled_image_descriptor_base>, rsx::limits::vertex_textures_count> vs_sampler_state = {};
std::array<std::unique_ptr<vk::sampler>, rsx::limits::fragment_textures_count> fs_sampler_handles;
std::array<std::unique_ptr<vk::sampler>, rsx::limits::vertex_textures_count> vs_sampler_handles;
VkBufferView m_persistent_attribute_storage;
VkBufferView m_volatile_attribute_storage;
public:
//vk::fbo draw_fbo;
std::unique_ptr<vk::vertex_cache> m_vertex_cache;
@@ -295,6 +306,8 @@ private:
void begin_render_pass();
void close_render_pass();
void update_draw_state();
/// returns primitive topology, index_count, allocated_verts, vertex_base_index, (offset in index buffer, index type)
std::tuple<VkPrimitiveTopology, u32, u32, u32, std::optional<std::tuple<VkDeviceSize, VkIndexType> > > upload_vertex_data();
public:
@@ -316,6 +329,7 @@ protected:
void do_local_task() override;
bool scaled_image_from_memory(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate) override;
void notify_tile_unbound(u32 tile) override;
bool on_access_violation(u32 address, bool is_writing) override;
void on_notify_memory_unmapped(u32 address_base, u32 size) override;
+31 -2
View File
@@ -12,6 +12,7 @@ namespace vk
VkSampler g_null_sampler = nullptr;
bool g_cb_no_interrupt_flag = false;
bool g_drv_no_primitive_restart_flag = false;
u64 g_num_processed_frames = 0;
u64 g_num_total_frames = 0;
@@ -257,6 +258,34 @@ namespace vk
void set_current_renderer(const vk::render_device &device)
{
g_current_renderer = device;
const std::array<std::string, 8> black_listed =
{
// Black list all polaris unless its proven they dont have a problem with primitive restart
"RX 580",
"RX 570",
"RX 560",
"RX 550",
"RX 480",
"RX 470",
"RX 460",
"RX Vega",
};
const auto gpu_name = g_current_renderer.gpu().name();
for (const auto& test : black_listed)
{
if (gpu_name.find(test) != std::string::npos)
{
g_drv_no_primitive_restart_flag = true;
break;
}
}
}
bool emulate_primitive_restart()
{
return g_drv_no_primitive_restart_flag;
}
void change_image_layout(VkCommandBuffer cmd, VkImage image, VkImageLayout current_layout, VkImageLayout new_layout, VkImageSubresourceRange range)
@@ -453,8 +482,8 @@ namespace vk
case VK_ERROR_OUT_OF_POOL_MEMORY_KHR:
error_message = "Out of pool memory (VK_ERROR_OUT_OF_POOL_MEMORY_KHR)";
break;
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX:
error_message = "Invalid external handle (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX)";
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR:
error_message = "Invalid external handle (VK_ERROR_INVALID_EXTERNAL_HANDLE_KHR)";
break;
default:
error_message = fmt::format("Unknown Code (%Xh, %d)%s", (s32)error_code, (s32&)error_code, faulting_addr);
+44 -3
View File
@@ -66,6 +66,8 @@ namespace vk
vk::render_device *get_current_renderer();
void set_current_renderer(const vk::render_device &device);
bool emulate_primitive_restart();
VkComponentMapping default_component_map();
VkImageSubresource default_image_subresource();
VkImageSubresourceRange get_image_subresource_range(uint32_t base_layer, uint32_t base_mip, uint32_t layer_count, uint32_t level_count, VkImageAspectFlags aspect);
@@ -574,7 +576,7 @@ namespace vk
VkSamplerCreateInfo info = {};
sampler(VkDevice dev, VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
bool unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color,
VkBool32 depth_compare = false, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER)
: m_device(dev)
@@ -605,6 +607,21 @@ namespace vk
vkDestroySampler(m_device, value, nullptr);
}
bool matches(VkSamplerAddressMode clamp_u, VkSamplerAddressMode clamp_v, VkSamplerAddressMode clamp_w,
VkBool32 unnormalized_coordinates, float mipLodBias, float max_anisotropy, float min_lod, float max_lod,
VkFilter min_filter, VkFilter mag_filter, VkSamplerMipmapMode mipmap_mode, VkBorderColor border_color,
VkBool32 depth_compare = false, VkCompareOp depth_compare_mode = VK_COMPARE_OP_NEVER)
{
if (info.magFilter != mag_filter || info.minFilter != min_filter || info.mipmapMode != mipmap_mode ||
info.addressModeU != clamp_u || info.addressModeV != clamp_v || info.addressModeW != clamp_w ||
info.compareEnable != depth_compare || info.unnormalizedCoordinates != unnormalized_coordinates ||
info.mipLodBias != mipLodBias || info.maxAnisotropy != max_anisotropy || info.maxLod != max_lod ||
info.minLod != min_lod || info.compareOp != depth_compare_mode || info.borderColor != border_color)
return false;
return true;
}
sampler(const sampler&) = delete;
sampler(sampler&&) = delete;
private:
@@ -807,7 +824,7 @@ namespace vk
}
}
void init_swapchain(u32 width, u32 height)
bool init_swapchain(u32 width, u32 height)
{
VkSwapchainKHR old_swapchain = m_vk_swapchain;
vk::physical_device& gpu = const_cast<vk::physical_device&>(dev.gpu());
@@ -815,8 +832,16 @@ namespace vk
VkSurfaceCapabilitiesKHR surface_descriptors = {};
CHECK_RESULT(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, m_surface, &surface_descriptors));
VkExtent2D swapchainExtent;
if (surface_descriptors.maxImageExtent.width < width ||
surface_descriptors.maxImageExtent.height < height)
{
LOG_ERROR(RSX, "Swapchain: Swapchain creation failed because dimensions cannot fit. Max = %d, %d, Requested = %d, %d",
surface_descriptors.maxImageExtent.width, surface_descriptors.maxImageExtent.height, width, height);
return false;
}
VkExtent2D swapchainExtent;
if (surface_descriptors.currentExtent.width == (uint32_t)-1)
{
swapchainExtent.width = width;
@@ -824,6 +849,12 @@ namespace vk
}
else
{
if (surface_descriptors.currentExtent.width == 0 || surface_descriptors.currentExtent.height == 0)
{
LOG_WARNING(RSX, "Swapchain: Current surface extent is a null region. Is the window minimized?");
return false;
}
swapchainExtent = surface_descriptors.currentExtent;
width = surface_descriptors.currentExtent.width;
height = surface_descriptors.currentExtent.height;
@@ -930,6 +961,8 @@ namespace vk
{
m_swap_images[i].create(dev, swap_images[i], m_surface_format);
}
return true;
}
u32 get_swap_image_count()
@@ -1011,6 +1044,14 @@ namespace vk
vk::command_pool *pool = nullptr;
VkCommandBuffer commands = nullptr;
public:
enum access_type_hint
{
flush_only, //Only to be submitted/opened/closed via command flush
all //Auxilliary, can be sumitted/opened/closed at any time
}
access_hint = flush_only;
public:
command_buffer() {}
~command_buffer() {}
+3 -3
View File
@@ -23,7 +23,7 @@ namespace vk
if (memcmp(&att_state[0], &other.att_state[0], sizeof(VkPipelineColorBlendAttachmentState)))
return false;
if (render_pass != other.render_pass)
if (render_pass_location != other.render_pass_location)
return false;
if (memcmp(&rs, &other.rs, sizeof(VkPipelineRasterizationStateCreateInfo)))
@@ -83,16 +83,16 @@ struct VKTraits
void recompile_fragment_program(const RSXFragmentProgram &RSXFP, fragment_program_type& fragmentProgramData, size_t ID)
{
fragmentProgramData.Decompile(RSXFP);
fragmentProgramData.Compile();
fragmentProgramData.id = static_cast<u32>(ID);
fragmentProgramData.Compile();
}
static
void recompile_vertex_program(const RSXVertexProgram &RSXVP, vertex_program_type& vertexProgramData, size_t ID)
{
vertexProgramData.Decompile(RSXVP);
vertexProgramData.Compile();
vertexProgramData.id = static_cast<u32>(ID);
vertexProgramData.Compile();
}
static
+26 -4
View File
@@ -22,10 +22,15 @@ namespace vk
bool dirty = false;
u16 native_pitch = 0;
u16 rsx_pitch = 0;
u16 surface_width = 0;
u16 surface_height = 0;
VkImageAspectFlags attachment_aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT;
std::unique_ptr<vk::image_view> view;
render_target *old_contents = nullptr; //Data occupying the memory location that this surface is replacing
u64 frame_tag = 0; //frame id when invalidated, 0 if not invalid
render_target(vk::render_device &dev,
uint32_t memory_type_index,
@@ -60,12 +65,12 @@ namespace vk
u16 get_surface_width() const override
{
return rsx::apply_inverse_resolution_scale(width(), true);
return surface_width;
}
u16 get_surface_height() const override
{
return rsx::apply_inverse_resolution_scale(height(), true);
return surface_height;
}
u16 get_rsx_pitch() const override
@@ -142,6 +147,8 @@ namespace rsx
rtt->native_component_map = fmt.second;
rtt->native_pitch = (u16)width * get_format_block_size_in_bytes(format);
rtt->surface_width = (u16)width;
rtt->surface_height = (u16)height;
if (old_surface != nullptr && old_surface->info.format == requested_format)
{
@@ -196,6 +203,8 @@ namespace rsx
ds->native_pitch *= 2;
ds->attachment_aspect_flag = range.aspectMask;
ds->surface_width = (u16)width;
ds->surface_height = (u16)height;
if (old_surface != nullptr && old_surface->info.format == requested_format)
{
@@ -223,6 +232,7 @@ namespace rsx
//Reset deref count
surface->deref_count = 0;
surface->frame_tag = 0;
}
static void prepare_rtt_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface)
@@ -238,6 +248,7 @@ namespace rsx
//Reset deref count
surface->deref_count = 0;
surface->frame_tag = 0;
}
static void prepare_ds_for_sampling(vk::command_buffer* pcmd, vk::render_target *surface)
@@ -261,6 +272,13 @@ namespace rsx
ds->old_contents = old_surface;
}
static
void notify_surface_invalidated(const std::unique_ptr<vk::render_target> &surface)
{
surface->frame_tag = vk::get_current_frame_id();
if (!surface->frame_tag) surface->frame_tag = 1;
}
static bool rtt_has_format_width_height(const std::unique_ptr<vk::render_target> &rtt, surface_color_format format, size_t width, size_t height, bool check_refs=false)
{
if (check_refs && rtt->deref_count == 0) //Surface may still have read refs from data 'copy'
@@ -337,9 +355,13 @@ namespace rsx
void free_invalidated()
{
invalidated_resources.remove_if([](std::unique_ptr<vk::render_target> &rtt)
const u64 last_finished_frame = vk::get_last_completed_frame_id();
invalidated_resources.remove_if([&](std::unique_ptr<vk::render_target> &rtt)
{
if (rtt->deref_count >= 2) return true;
verify(HERE), rtt->frame_tag != 0;
if (rtt->deref_count >= 2 && rtt->frame_tag < last_finished_frame)
return true;
rtt->deref_count++;
return false;
+232 -29
View File
@@ -20,6 +20,7 @@ namespace vk
//DMA relevant data
VkFence dma_fence = VK_NULL_HANDLE;
bool synchronized = false;
bool flushed = false;
u64 sync_timestamp = 0;
u64 last_use_timestamp = 0;
vk::render_device* m_device = nullptr;
@@ -46,10 +47,17 @@ namespace vk
this->depth = depth;
this->mipmaps = mipmaps;
uploaded_image_view.reset(view);
vram_texture = image;
if (managed)
{
managed_texture.reset(image);
uploaded_image_view.reset(view);
}
else
{
verify(HERE), uploaded_image_view.get() == nullptr;
}
if (managed) managed_texture.reset(image);
vram_texture = image;
//TODO: Properly compute these values
if (rsx_pitch > 0)
@@ -62,6 +70,7 @@ namespace vk
//Even if we are managing the same vram section, we cannot guarantee contents are static
//The create method is only invoked when a new mangaged session is required
synchronized = false;
flushed = false;
sync_timestamp = 0ull;
last_use_timestamp = get_system_time();
}
@@ -80,6 +89,12 @@ namespace vk
}
}
void destroy()
{
vram_texture = nullptr;
release_dma_resources();
}
bool exists() const
{
return (vram_texture != nullptr);
@@ -97,7 +112,10 @@ namespace vk
vk::image_view* get_raw_view()
{
return uploaded_image_view.get();
if (context != rsx::texture_upload_context::framebuffer_storage)
return uploaded_image_view.get();
else
return static_cast<vk::render_target*>(vram_texture)->get_view();
}
vk::image* get_raw_texture()
@@ -149,15 +167,27 @@ namespace vk
const u16 internal_width = std::min(width, rsx::apply_resolution_scale(width, true));
const u16 internal_height = std::min(height, rsx::apply_resolution_scale(height, true));
VkImageAspectFlags aspect_flag = VK_IMAGE_ASPECT_COLOR_BIT;
switch (vram_texture->info.format)
{
case VK_FORMAT_D16_UNORM:
aspect_flag = VK_IMAGE_ASPECT_DEPTH_BIT;
break;
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
aspect_flag = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
break;
}
VkBufferImageCopy copyRegion = {};
copyRegion.bufferOffset = 0;
copyRegion.bufferRowLength = internal_width;
copyRegion.bufferImageHeight = internal_height;
copyRegion.imageSubresource = {VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1};
copyRegion.imageSubresource = {aspect_flag, 0, 0, 1};
copyRegion.imageOffset = {};
copyRegion.imageExtent = {internal_width, internal_height, 1};
VkImageSubresourceRange subresource_range = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
VkImageSubresourceRange subresource_range = { aspect_flag & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
VkImageLayout layout = vram_texture->current_layout;
change_image_layout(cmd, vram_texture, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
@@ -173,13 +203,16 @@ namespace vk
CHECK_RESULT(vkWaitForFences(*m_device, 1, &dma_fence, VK_TRUE, UINT64_MAX));
CHECK_RESULT(vkResetCommandBuffer(cmd, 0));
CHECK_RESULT(vkResetFences(*m_device, 1, &dma_fence));
if (cmd.access_hint != vk::command_buffer::access_type_hint::all)
cmd.begin();
}
synchronized = true;
sync_timestamp = get_system_time();
}
template<typename T>
template<typename T, bool swapped>
void do_memory_transfer(void *pixels_dst, const void *pixels_src)
{
if (sizeof(T) == 1)
@@ -187,17 +220,30 @@ namespace vk
else
{
const u32 block_size = width * height;
auto typed_dst = (be_t<T> *)pixels_dst;
auto typed_src = (T *)pixels_src;
for (u32 px = 0; px < block_size; ++px)
typed_dst[px] = typed_src[px];
if (swapped)
{
auto typed_dst = (be_t<T> *)pixels_dst;
auto typed_src = (T *)pixels_src;
for (u32 px = 0; px < block_size; ++px)
typed_dst[px] = typed_src[px];
}
else
{
auto typed_dst = (T *)pixels_dst;
auto typed_src = (T *)pixels_src;
for (u32 px = 0; px < block_size; ++px)
typed_dst[px] = typed_src[px];
}
}
}
bool flush(vk::render_device& dev, vk::command_buffer& cmd, vk::memory_type_mapping& memory_types, VkQueue submit_queue)
{
if (flushed) return true;
if (m_device == nullptr)
m_device = &dev;
@@ -211,31 +257,54 @@ namespace vk
result = false;
}
protect(utils::protection::rw);
flushed = true;
void* pixels_src = dma_buffer->map(0, cpu_address_range);
void* pixels_dst = vm::base(cpu_address_base);
const u8 bpp = real_pitch / width;
//We have to do our own byte swapping since the driver doesnt do it for us
bool swap_bytes = false;
switch (vram_texture->info.format)
{
case VK_FORMAT_D32_SFLOAT_S8_UINT:
case VK_FORMAT_D24_UNORM_S8_UINT:
//TODO: Hardware tests to determine correct memory layout
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_R16G16B16A16_SFLOAT:
case VK_FORMAT_R32G32B32A32_SFLOAT:
case VK_FORMAT_R32_SFLOAT:
swap_bytes = true;
break;
}
if (real_pitch == rsx_pitch)
{
//We have to do our own byte swapping since the driver doesnt do it for us
switch (bpp)
{
default:
LOG_ERROR(RSX, "Invalid bpp %d", bpp);
case 1:
do_memory_transfer<u8>(pixels_dst, pixels_src);
do_memory_transfer<u8, false>(pixels_dst, pixels_src);
break;
case 2:
do_memory_transfer<u16>(pixels_dst, pixels_src);
if (swap_bytes)
do_memory_transfer<u16, true>(pixels_dst, pixels_src);
else
do_memory_transfer<u16, false>(pixels_dst, pixels_src);
break;
case 4:
do_memory_transfer<u32>(pixels_dst, pixels_src);
if (swap_bytes)
do_memory_transfer<u32, true>(pixels_dst, pixels_src);
else
do_memory_transfer<u32, false>(pixels_dst, pixels_src);
break;
case 8:
do_memory_transfer<u64>(pixels_dst, pixels_src);
if (swap_bytes)
do_memory_transfer<u64, true>(pixels_dst, pixels_src);
else
do_memory_transfer<u64, false>(pixels_dst, pixels_src);
break;
}
}
@@ -245,7 +314,7 @@ namespace vk
//usually we can just get away with nearest filtering
const u8 samples = rsx_pitch / real_pitch;
rsx::scale_image_nearest(pixels_dst, pixels_src, width, height, rsx_pitch, real_pitch, bpp, samples, true);
rsx::scale_image_nearest(pixels_dst, pixels_src, width, height, rsx_pitch, real_pitch, bpp, samples, swap_bytes);
}
dma_buffer->unmap();
@@ -269,6 +338,19 @@ namespace vk
return vram_texture->info.format == tex->info.format;
}
bool is_depth_texture() const
{
switch (vram_texture->info.format)
{
case VK_FORMAT_D16_UNORM:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
case VK_FORMAT_D24_UNORM_S8_UINT:
return true;
default:
return false;
}
}
u64 get_sync_timestamp() const
{
return sync_timestamp;
@@ -280,6 +362,10 @@ namespace vk
std::unique_ptr<vk::image_view> view;
std::unique_ptr<vk::image> img;
//Memory held by this temp storage object
u32 block_size = 0;
//Frame id tag
const u64 frame_tag = vk::get_current_frame_id();
discarded_storage(std::unique_ptr<vk::image_view>& _view)
@@ -302,6 +388,7 @@ namespace vk
{
view = std::move(tex.get_view());
img = std::move(tex.get_texture());
block_size = tex.get_section_size();
}
const bool test(u64 ref_frame) const
@@ -323,7 +410,8 @@ namespace vk
//Stuff that has been dereferenced goes into these
std::list<discarded_storage> m_discardable_storage;
std::atomic<u32> m_discarded_memory_size = { 0 };
void purge_cache()
{
for (auto &address_range : m_cache)
@@ -347,17 +435,20 @@ namespace vk
m_discardable_storage.clear();
m_unreleased_texture_objects = 0;
m_texture_memory_in_use = 0;
m_discarded_memory_size = 0;
}
protected:
void free_texture_section(cached_texture_section& tex) override
{
m_discarded_memory_size += tex.get_section_size();
m_discardable_storage.push_back(tex);
tex.release_dma_resources();
tex.destroy();
}
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 /*gcm_format*/, u16 x, u16 y, u16 w, u16 h) override
vk::image_view* create_temporary_subresource_view_impl(vk::command_buffer& cmd, vk::image* source, VkImageType image_type, VkImageViewType view_type, u16 x, u16 y, u16 w, u16 h)
{
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
@@ -378,13 +469,13 @@ namespace vk
std::unique_ptr<vk::image_view> view;
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
source->info.imageType,
image_type,
source->info.format,
w, h, 1, 1, 1, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, source->info.flags));
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 1 };
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, VK_IMAGE_VIEW_TYPE_2D, source->info.format, source->native_component_map, view_range));
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, view_type, source->info.format, source->native_component_map, view_range));
VkImageLayout old_src_layout = source->current_layout;
@@ -393,7 +484,7 @@ namespace vk
VkImageCopy copy_rgn;
copy_rgn.srcOffset = { (s32)x, (s32)y, 0 };
copy_rgn.dstOffset = { (s32)x, (s32)y, 0 };
copy_rgn.dstOffset = { (s32)0, (s32)0, 0 };
copy_rgn.dstSubresource = { aspect, 0, 0, 1 };
copy_rgn.srcSubresource = { aspect, 0, 0, 1 };
copy_rgn.extent = { w, h, 1 };
@@ -402,15 +493,96 @@ namespace vk
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);
vk::change_image_layout(cmd, source, old_src_layout, subresource_range);
const u32 resource_memory = w * h * 4; //Rough approximate
m_discardable_storage.push_back({ image, view });
m_discardable_storage.back().block_size = resource_memory;
m_discarded_memory_size += resource_memory;
return m_discardable_storage.back().view.get();
}
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image* source, u32 /*gcm_format*/, u16 x, u16 y, u16 w, u16 h) override
{
return create_temporary_subresource_view_impl(cmd, source, source->info.imageType, VK_IMAGE_VIEW_TYPE_2D, x, y, w, h);
}
vk::image_view* create_temporary_subresource_view(vk::command_buffer& cmd, vk::image** source, u32 gcm_format, u16 x, u16 y, u16 w, u16 h) override
{
return create_temporary_subresource_view(cmd, *source, gcm_format, x, y, w, h);
}
vk::image_view* generate_cubemap_from_images(vk::command_buffer& cmd, const u32 gcm_format, u16 size, std::array<vk::image*, 6>& sources) override
{
std::unique_ptr<vk::image> image;
std::unique_ptr<vk::image_view> view;
image.reset(new vk::image(*vk::get_current_renderer(), m_memory_types.device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
VK_IMAGE_TYPE_2D,
vk::get_compatible_sampler_format(gcm_format),
size, size, 1, 1, 6, VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT));
VkImageSubresourceRange subresource_range = {};
VkImageAspectFlags aspect = VK_IMAGE_ASPECT_COLOR_BIT;
for (u32 n = 0; n < 6; ++n)
{
if (!view)
{
switch (sources[0]->info.format)
{
case VK_FORMAT_D16_UNORM:
aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
break;
case VK_FORMAT_D24_UNORM_S8_UINT:
case VK_FORMAT_D32_SFLOAT_S8_UINT:
aspect = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
break;
}
VkImageSubresourceRange view_range = { aspect & ~(VK_IMAGE_ASPECT_STENCIL_BIT), 0, 1, 0, 6 };
view.reset(new vk::image_view(*vk::get_current_renderer(), image->value, VK_IMAGE_VIEW_TYPE_CUBE, image->info.format, image->native_component_map, view_range));
subresource_range = view_range;
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, subresource_range);
subresource_range.layerCount = 1;
}
if (sources[n])
{
VkImageLayout old_src_layout = sources[n]->current_layout;
vk::change_image_layout(cmd, sources[n], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range);
VkImageCopy copy_rgn;
copy_rgn.srcOffset = { 0, 0, 0 };
copy_rgn.dstOffset = { 0, 0, 0 };
copy_rgn.dstSubresource = { aspect, 0, n, 1 };
copy_rgn.srcSubresource = { aspect, 0, 0, 1 };
copy_rgn.extent = { size, size, 1 };
vkCmdCopyImage(cmd, sources[n]->value, sources[n]->current_layout, image->value, image->current_layout, 1, &copy_rgn);
vk::change_image_layout(cmd, sources[n], old_src_layout, subresource_range);
}
else
{
//Clear to black
VkClearColorValue clear_color{};
auto range = subresource_range;
range.baseArrayLayer = n;
vkCmdClearColorImage(cmd, image->value, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clear_color, 1, &range);
}
}
subresource_range.layerCount = 6;
vk::change_image_layout(cmd, image.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range);
const u32 resource_memory = size * size * 6 * 4; //Rough approximate
m_discardable_storage.push_back({ image, view });
m_discardable_storage.back().block_size = resource_memory;
m_discarded_memory_size += resource_memory;
return m_discardable_storage.back().view.get();
}
cached_texture_section* create_new_texture(vk::command_buffer& cmd, u32 rsx_address, u32 rsx_size, u16 width, u16 height, u16 depth, u16 mipmaps, const u32 gcm_format,
const rsx::texture_upload_context context, const rsx::texture_dimension_extended type, const rsx::texture_create_flags flags,
std::pair<std::array<u8, 4>, std::array<u8, 4>>& remap_vector) override
@@ -523,10 +695,14 @@ namespace vk
region.create(width, height, section_depth, mipmaps, view, image);
region.set_dirty(false);
region.set_context(context);
region.set_image_type(type);
//Its not necessary to lock blit dst textures as they are just reused as necessary
if (context != rsx::texture_upload_context::blit_engine_dst || g_cfg.video.strict_rendering_mode)
{
region.protect(utils::protection::ro);
update_cache_tag();
}
read_only_range = region.get_min_max(read_only_range);
return &region;
@@ -660,13 +836,30 @@ namespace vk
void on_frame_end() override
{
if (m_unreleased_texture_objects >= m_max_zombie_objects)
if (m_unreleased_texture_objects >= m_max_zombie_objects ||
m_discarded_memory_size > 0x4000000) //If already holding over 64M in discardable memory, be frugal with memory resources
{
purge_dirty();
}
const u64 last_complete_frame = vk::get_last_completed_frame_id();
m_discardable_storage.remove_if([&](const discarded_storage& o) {return o.test(last_complete_frame);});
m_discardable_storage.remove_if([&](const discarded_storage& o)
{
if (o.test(last_complete_frame))
{
m_discarded_memory_size -= o.block_size;
return true;
}
return false;
});
m_temporary_subresource_cache.clear();
}
template<typename RsxTextureType>
sampled_image_descriptor _upload_texture(vk::command_buffer& cmd, RsxTextureType& tex, rsx::vk_render_targets& m_rtts)
{
return upload_texture(cmd, tex, m_rtts, *m_device, cmd, m_memory_types, const_cast<const VkQueue>(m_submit_queue));
}
bool blit(rsx::blit_src_info& src, rsx::blit_dst_info& dst, bool interpolate, rsx::vk_render_targets& m_rtts, vk::command_buffer& cmd)
@@ -707,12 +900,22 @@ namespace vk
}
helper(&cmd);
return upload_scaled_image(src, dst, interpolate, cmd, m_rtts, helper, *m_device, cmd, m_memory_types, m_submit_queue);
return upload_scaled_image(src, dst, interpolate, cmd, m_rtts, helper, *m_device, cmd, m_memory_types, const_cast<const VkQueue>(m_submit_queue));
}
const u32 get_unreleased_textures_count() const override
{
return std::max(m_unreleased_texture_objects, 0) + (u32)m_discardable_storage.size();
return m_unreleased_texture_objects + (u32)m_discardable_storage.size();
}
const u32 get_texture_memory_in_use() const override
{
return m_texture_memory_in_use;
}
const u32 get_temporary_memory_in_use()
{
return m_discarded_memory_size;
}
};
}
+33 -10
View File
@@ -141,18 +141,43 @@ namespace
VkDeviceSize offset_in_index_buffer = m_index_buffer_ring_info.alloc<256>(upload_size);
void* buf = m_index_buffer_ring_info.map(offset_in_index_buffer, upload_size);
gsl::span<gsl::byte> dst;
std::vector<gsl::byte> tmp;
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
{
tmp.resize(upload_size);
dst = tmp;
}
else
{
dst = gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), upload_size);
}
/**
* Upload index (and expands it if primitive type is not natively supported).
*/
u32 min_index, max_index;
std::tie(min_index, max_index) = write_index_array_data_to_buffer(
gsl::span<gsl::byte>(static_cast<gsl::byte*>(buf), index_count * type_size),
std::tie(min_index, max_index, index_count) = write_index_array_data_to_buffer(
dst,
command.raw_index_buffer, index_type,
rsx::method_registers.current_draw_clause.primitive,
rsx::method_registers.restart_index_enabled(),
rsx::method_registers.restart_index(), command.ranges_to_fetch_in_index_buffer,
[](auto prim) { return !vk::is_primitive_native(prim); });
if (rsx::method_registers.restart_index_enabled() && vk::emulate_primitive_restart())
{
//Emulate primitive restart by breaking up the draw calls
rsx::method_registers.current_draw_clause.alternate_first_count_commands.resize(0);
if (index_type == rsx::index_array_type::u16)
rsx::split_index_list(reinterpret_cast<u16*>(tmp.data()), index_count, (u16)UINT16_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands);
else
rsx::split_index_list(reinterpret_cast<u32*>(tmp.data()), index_count, (u32)UINT32_MAX, rsx::method_registers.current_draw_clause.alternate_first_count_commands);
memcpy(buf, tmp.data(), tmp.size());
}
m_index_buffer_ring_info.unmap();
std::optional<std::tuple<VkDeviceSize, VkIndexType>> index_info =
@@ -212,7 +237,8 @@ VKGSRender::upload_vertex_data()
auto required = calculate_memory_requirements(m_vertex_layout, vertex_count);
size_t persistent_offset = UINT64_MAX, volatile_offset = UINT64_MAX;
VkBufferView persistent_view = VK_NULL_HANDLE, volatile_view = VK_NULL_HANDLE;
m_persistent_attribute_storage = VK_NULL_HANDLE;
m_volatile_attribute_storage = VK_NULL_HANDLE;
if (required.first > 0)
{
@@ -252,11 +278,11 @@ VKGSRender::upload_vertex_data()
}
}
persistent_view = m_current_frame->buffer_views_to_clean.back()->value;
m_persistent_attribute_storage = m_current_frame->buffer_views_to_clean.back()->value;
}
else
{
persistent_view = null_buffer_view->value;
m_persistent_attribute_storage = null_buffer_view->value;
}
if (required.second > 0)
@@ -265,16 +291,13 @@ VKGSRender::upload_vertex_data()
m_current_frame->buffer_views_to_clean.push_back(std::make_unique<vk::buffer_view>(*m_device,
m_attrib_ring_info.heap->value, VK_FORMAT_R8_UINT, volatile_offset, required.second));
volatile_view = m_current_frame->buffer_views_to_clean.back()->value;
m_volatile_attribute_storage = m_current_frame->buffer_views_to_clean.back()->value;
}
else
{
volatile_view = null_buffer_view->value;
m_volatile_attribute_storage = null_buffer_view->value;
}
m_program->bind_uniform(persistent_view, "persistent_input_stream", m_current_frame->descriptor_set);
m_program->bind_uniform(volatile_view, "volatile_input_stream", m_current_frame->descriptor_set);
//Write all the data once if possible
if (required.first && required.second && volatile_offset > persistent_offset)
{
+2 -5
View File
@@ -15,10 +15,9 @@ std::string VKVertexDecompilerThread::getIntTypeName(size_t elementCount)
return "ivec4";
}
std::string VKVertexDecompilerThread::getFunction(FUNCTION f)
{
return vk::getFunctionImpl(f);
return glsl::getFunctionImpl(f);
}
std::string VKVertexDecompilerThread::compareFunction(COMPARE f, const std::string &Op0, const std::string &Op1)
@@ -339,7 +338,7 @@ void VKVertexProgram::Decompile(const RSXVertexProgram& prog)
void VKVertexProgram::Compile()
{
fs::create_path(fs::get_config_dir() + "/shaderlog");
fs::file(fs::get_config_dir() + "shaderlog/VertexProgram.spirv", fs::rewrite).write(shader);
fs::file(fs::get_config_dir() + "shaderlog/VertexProgram" + std::to_string(id) + ".spirv", fs::rewrite).write(shader);
std::vector<u32> spir_v;
if (!vk::compile_glsl_to_spv(shader, glsl::glsl_vertex_program, spir_v))
@@ -354,8 +353,6 @@ void VKVertexProgram::Compile()
VkDevice dev = (VkDevice)*vk::get_current_renderer();
vkCreateShaderModule(dev, &vs_info, nullptr, &handle);
id = UINT32_MAX;
}
void VKVertexProgram::Delete()
+26 -26
View File
@@ -157,7 +157,7 @@ namespace rsx
case comparison_function::greater_or_equal: return "Greater_equal";
case comparison_function::always: return "Always";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(stencil_op op)
@@ -173,7 +173,7 @@ namespace rsx
case stencil_op::decr_wrap: return "Decr_wrap";
case stencil_op::invert: return "Invert";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(fog_mode op)
@@ -187,7 +187,7 @@ namespace rsx
case fog_mode::linear: return "linear";
case fog_mode::linear_abs: return "linear(abs)";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(logic_op op)
@@ -211,7 +211,7 @@ namespace rsx
case logic_op::logic_or_inverted: return "Or_inverted";
case logic_op::logic_nand: return "Nand";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(front_face op)
@@ -221,7 +221,7 @@ namespace rsx
case front_face::ccw: return "counter clock wise";
case front_face::cw: return "clock wise";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(cull_face op)
@@ -232,7 +232,7 @@ namespace rsx
case cull_face::front: return "front";
case cull_face::front_and_back: return "front and back";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(surface_target target)
@@ -246,7 +246,7 @@ namespace rsx
case surface_target::surfaces_a_b_c: return "surfaces A, B and C";
case surface_target::surfaces_a_b_c_d: return "surfaces A,B, C and D";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(primitive_type draw_mode)
@@ -265,7 +265,7 @@ namespace rsx
case primitive_type::quad_strip: return "Quad_strip";
case primitive_type::polygon: return "Polygon";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blit_engine::transfer_operation op)
@@ -279,7 +279,7 @@ namespace rsx
case blit_engine::transfer_operation::srccopy_and: return "srccopy_and";
case blit_engine::transfer_operation::srccopy_premult: return "srccopy_premult";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blit_engine::transfer_source_format op)
@@ -300,7 +300,7 @@ namespace rsx
case blit_engine::transfer_source_format::y8: return "y8";
case blit_engine::transfer_source_format::yb8cr8ya8cb8: return "yb8cr8ya8cb8";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blit_engine::context_surface op)
@@ -310,7 +310,7 @@ namespace rsx
case blit_engine::context_surface::surface2d: return "surface 2d";
case blit_engine::context_surface::swizzle2d: return "swizzle 2d";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blit_engine::transfer_destination_format op)
@@ -321,7 +321,7 @@ namespace rsx
case blit_engine::transfer_destination_format::r5g6b5: return "r5g6b5";
case blit_engine::transfer_destination_format::y32: return "y32";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
@@ -338,7 +338,7 @@ namespace rsx
case blend_equation::reverse_add_signed: return "Reverse_add_signed";
case blend_equation::reverse_substract_signed: return "Reverse_substract_signed";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blend_factor factor)
@@ -361,7 +361,7 @@ namespace rsx
case blend_factor::constant_alpha: return "const.a";
case blend_factor::one_minus_constant_alpha: return "(1 - const.a)";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(window_origin origin)
@@ -371,7 +371,7 @@ namespace rsx
case window_origin::bottom: return "bottom";
case window_origin::top: return "top";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(window_pixel_center in)
@@ -381,7 +381,7 @@ namespace rsx
case window_pixel_center::half: return "half";
case window_pixel_center::integer: return "integer";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(user_clip_plane_op op)
@@ -392,7 +392,7 @@ namespace rsx
case user_clip_plane_op::greater_or_equal: return "greater or equal";
case user_clip_plane_op::less_than: return "less than";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
@@ -404,7 +404,7 @@ namespace rsx
case surface_depth_format::z16: return "CELL_GCM_SURFACE_Z16";
case surface_depth_format::z24s8: return "CELL_GCM_SURFACE_Z24S8";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(surface_antialiasing format)
@@ -416,7 +416,7 @@ namespace rsx
case surface_antialiasing::square_centered_4_samples: return "4 samples square centered";
case surface_antialiasing::square_rotated_4_samples: return "4 samples diagonal rotated";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(surface_color_format format)
@@ -438,7 +438,7 @@ namespace rsx
case surface_color_format::x8b8g8r8_o8b8g8r8: return "CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8";
case surface_color_format::a8b8g8r8: return "CELL_GCM_SURFACE_A8B8G8R8";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(index_array_type arg)
@@ -448,7 +448,7 @@ namespace rsx
case index_array_type::u16: return "unsigned short";
case index_array_type::u32: return "unsigned int";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blit_engine::context_dma op)
@@ -459,7 +459,7 @@ namespace rsx
case blit_engine::context_dma::to_memory_get_report: return "to memory get report";
case blit_engine::context_dma::memory_host_buffer: return "memory host buffer";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blit_engine::transfer_origin op)
@@ -469,7 +469,7 @@ namespace rsx
case blit_engine::transfer_origin::center: return "center";
case blit_engine::transfer_origin::corner: return "corner";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(blit_engine::transfer_interpolator op)
@@ -479,7 +479,7 @@ namespace rsx
case blit_engine::transfer_interpolator::foh: return "foh";
case blit_engine::transfer_interpolator::zoh: return "zoh";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(shading_mode op)
@@ -489,7 +489,7 @@ namespace rsx
case shading_mode::flat: return "flat";
case shading_mode::smooth: return "smooth";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
std::string to_string(polygon_mode op)
@@ -500,7 +500,7 @@ namespace rsx
case polygon_mode::line: return "line";
case polygon_mode::point: return "point";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
} // end namespace rsx
+9
View File
@@ -238,6 +238,11 @@ namespace rsx
return std::make_pair(min, max);
}
utils::protection get_protection() const
{
return protection;
}
};
template <typename pipeline_storage_type, typename backend_storage>
@@ -328,12 +333,16 @@ namespace rsx
dlg->Create("Preloading cached shaders from disk.\nPlease wait...");
});
const auto prefix_length = version_prefix.length();
u32 processed = 0;
while (root.read(tmp) && !Emu.IsStopped())
{
if (tmp.name == "." || tmp.name == "..")
continue;
if (tmp.name.compare(0, prefix_length, version_prefix) != 0)
continue;
std::vector<u8> bytes;
fs::file f(directory_path + "/" + tmp.name);
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once
#include "Utilities/types.h"
#include "Utilities/BitField.h"
#include "Utilities/StrFmt.h"
#include <tuple>
#include "gcm_enums.h"
#pragma warning(disable:4503)
@@ -27,7 +28,7 @@ namespace
case rsx::vertex_base_type::cmp: return "CMP";
case rsx::vertex_base_type::ub256: return "Unsigned byte unormalized";
}
throw;
fmt::throw_exception("Unexpected enum found" HERE);
}
}
+25 -1
View File
@@ -469,6 +469,15 @@ namespace rsx
rsx->m_textures_dirty[index] = true;
}
};
template<u32 index>
struct set_vertex_texture_dirty_bit
{
static void impl(thread* rsx, u32 _reg, u32 arg)
{
rsx->m_vertex_textures_dirty[index] = true;
}
};
}
namespace nv308a
@@ -486,7 +495,8 @@ namespace rsx
LOG_ERROR(RSX, "%s: y is not null (0x%x)", __FUNCTION__, y);
}
u32 address = get_address(method_registers.blit_engine_output_offset_nv3062() + (x << 2) + index * 4, method_registers.blit_engine_output_location_nv3062());
const u32 pixel_offset = (method_registers.blit_engine_output_pitch_nv3062() * y) + (x << 2);
u32 address = get_address(method_registers.blit_engine_output_offset_nv3062() + pixel_offset + index * 4, method_registers.blit_engine_output_location_nv3062());
vm::ps3::write32(address, arg);
}
};
@@ -626,6 +636,12 @@ namespace rsx
u32 convert_w = (u32)(scale_x * in_w);
u32 convert_h = (u32)(scale_y * in_h);
if (convert_w == 0 || convert_h == 0)
{
LOG_ERROR(RSX, "NV3089_IMAGE_IN: Invalid dimensions or scaling factor. Request ignored");
return;
}
u32 slice_h = clip_h;
blit_src_info src_info = {};
blit_dst_info dst_info = {};
@@ -1538,6 +1554,14 @@ namespace rsx
bind_range<NV4097_SET_TEXTURE_FILTER, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_IMAGE_RECT, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_BORDER_COLOR, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_OFFSET, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_FORMAT, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_ADDRESS, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_CONTROL0, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_CONTROL3, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_FILTER, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_IMAGE_RECT, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind_range<NV4097_SET_VERTEX_TEXTURE_BORDER_COLOR, 8, 4, nv4097::set_vertex_texture_dirty_bit>();
bind<NV4097_SET_RENDER_ENABLE, nv4097::set_render_mode>();
bind<NV4097_SET_ZCULL_EN, nv4097::set_zcull_render_enable>();
bind<NV4097_SET_ZCULL_STATS_ENABLE, nv4097::set_zcull_stats_enable>();
+25
View File
@@ -38,6 +38,11 @@ namespace rsx
*/
std::vector<std::pair<u32, u32> > first_count_commands;
/**
* Optionally split first-count pairs for disjoint range rendering. Valid when emulating primitive restart
*/
std::vector<std::pair<u32, u32> > alternate_first_count_commands;
/**
* Returns how many vertex or index will be consumed by the draw clause.
*/
@@ -1166,6 +1171,26 @@ namespace rsx
{
return registers[NV4097_SET_TRANSFORM_BRANCH_BITS];
}
u16 msaa_sample_mask()
{
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_sample_mask();
}
bool msaa_enabled()
{
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_enabled();
}
bool msaa_alpha_to_coverage_enabled()
{
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_alpha_to_coverage();
}
bool msaa_alpha_to_one_enabled()
{
return decode<NV4097_SET_ANTI_ALIASING_CONTROL>().msaa_alpha_to_one();
}
};
extern rsx_state method_registers;
+29
View File
@@ -251,4 +251,33 @@ namespace rsx
return result;
}
template <typename T>
void split_index_list(T* indices, int index_count, T restart_index, std::vector<std::pair<u32, u32>>& out)
{
int last_valid_index = -1;
int last_start = -1;
for (int i = 0; i < index_count; ++i)
{
if (indices[i] == UINT16_MAX)
{
if (last_start >= 0)
{
out.push_back(std::make_pair(last_start, i - last_start));
last_start = -1;
}
continue;
}
if (last_start < 0)
last_start = i;
last_valid_index = i;
}
if (last_start >= 0)
out.push_back(std::make_pair(last_start, last_valid_index - last_start + 1));
}
}
+32 -13
View File
@@ -190,7 +190,7 @@ void Emulator::Init()
{
g_tty.open(fs::get_config_dir() + "TTY.log", fs::rewrite + fs::append);
}
idm::init();
fxm::init();
@@ -308,10 +308,13 @@ void Emulator::Load(bool add_only)
{
return sfov;
}
else
if (Emu.disc.size())
{
return fs::file(elf_dir + "/../PARAM.SFO");
return fs::file{Emu.disc + "/PS3_GAME/PARAM.SFO"};
}
return fs::file(elf_dir + "/../PARAM.SFO");
}());
m_title = psf::get_string(_psf, "TITLE", m_path);
m_title_id = psf::get_string(_psf, "TITLE_ID");
@@ -370,7 +373,7 @@ void Emulator::Load(bool add_only)
const std::string hdd0_game = vfs::get("/dev_hdd0/game/");
const std::string hdd0_disc = vfs::get("/dev_hdd0/disc/");
if (_cat == "DG" && m_path.find(hdd0_game) != -1)
if (_cat == "DG" && m_path.find(hdd0_game) != -1 && Emu.disc.empty())
{
// Booting disc game from wrong location
LOG_ERROR(LOADER, "Disc game %s found at invalid location /dev_hdd0/game/", m_title_id);
@@ -389,7 +392,7 @@ void Emulator::Load(bool add_only)
}
// Booting disc game
if (_cat == "DG" && bdvd_dir.empty())
if (_cat == "DG" && bdvd_dir.empty() && Emu.disc.empty())
{
// Mount /dev_bdvd/ if necessary
if (auto pos = elf_dir.rfind("/PS3_GAME/") + 1)
@@ -399,7 +402,7 @@ void Emulator::Load(bool add_only)
}
// Booting patch data
if (_cat == "GD" && bdvd_dir.empty())
if (_cat == "GD" && bdvd_dir.empty() && Emu.disc.empty())
{
// Load /dev_bdvd/ from game list if available
if (auto node = games[m_title_id])
@@ -413,7 +416,7 @@ void Emulator::Load(bool add_only)
}
// Check /dev_bdvd/
if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
if (Emu.disc.empty() && !bdvd_dir.empty() && fs::is_dir(bdvd_dir))
{
fs::file sfb_file;
@@ -440,6 +443,11 @@ void Emulator::Load(bool add_only)
out << games;
fs::file(fs::get_config_dir() + "/games.yml", fs::rewrite).write(out.c_str(), out.size());
}
else if (!Emu.disc.empty())
{
vfs::mount("dev_bdvd", Emu.disc);
LOG_NOTICE(LOADER, "Disk: %s", vfs::get("/dev_bdvd"));
}
else if (_cat == "DG" || _cat == "GD")
{
LOG_ERROR(LOADER, "Failed to mount disc directory for the disc game %s", m_title_id);
@@ -493,7 +501,7 @@ void Emulator::Load(bool add_only)
else
{
// Decrypt SELF
elf_file = decrypt_self(std::move(elf_file));
elf_file = decrypt_self(std::move(elf_file), klic.empty() ? nullptr : klic.data());
if (fs::file elf_out{decrypted_path, fs::rewrite})
{
@@ -528,21 +536,26 @@ void Emulator::Load(bool add_only)
vm::ps3::init();
if (argv.empty())
{
argv.resize(1);
}
if (argv[0].empty())
{
if (m_path.find(hdd0_game) != -1)
{
argv.emplace_back("/dev_hdd0/game/" + m_path.substr(hdd0_game.size()));
argv[0] = "/dev_hdd0/game/" + m_path.substr(hdd0_game.size());
}
else if (!bdvd_dir.empty() && fs::is_dir(bdvd_dir))
{
// Disc games are on /dev_bdvd/
const std::size_t pos = m_path.rfind("PS3_GAME");
argv.emplace_back("/dev_bdvd/" + m_path.substr(pos));
argv[0] = "/dev_bdvd/" + m_path.substr(pos);
}
else
{
// For homebrew
argv.emplace_back("/host_root/" + m_path);
argv[0] = "/host_root/" + m_path;
}
LOG_NOTICE(LOADER, "Elf path: %s", argv[0]);
@@ -581,7 +594,12 @@ void Emulator::Load(bool add_only)
if (argv.empty())
{
argv.emplace_back("host_root:" + m_path);
argv.resize(1);
}
if (argv[0].empty())
{
argv[0] = "host_root:" + m_path;
LOG_NOTICE(LOADER, "Elf path: %s", argv[0]);
}
@@ -631,7 +649,6 @@ void Emulator::Run()
return;
}
GetCallbacks().on_run();
m_pause_start_time = 0;
@@ -829,6 +846,8 @@ void Emulator::Stop()
argv.clear();
envp.clear();
data.clear();
disc.clear();
klic.clear();
}
s32 error_code::error_report(const fmt_type_info* sup, u64 arg, const fmt_type_info* sup2, u64 arg2)
+5 -1
View File
@@ -165,6 +165,7 @@ struct EmuCallbacks
std::function<std::shared_ptr<class AudioThread>()> get_audio;
std::function<std::shared_ptr<class MsgDialogBase>()> get_msg_dialog;
std::function<std::unique_ptr<class SaveDialogBase>()> get_save_dialog;
std::function<std::unique_ptr<class TrophyNotificationBase>()> get_trophy_notification_dialog;
};
class Emulator final
@@ -213,6 +214,8 @@ public:
std::vector<std::string> argv;
std::vector<std::string> envp;
std::vector<u8> data;
std::vector<u8> klic;
std::string disc;
const std::string& GetBoot() const
{
@@ -324,7 +327,6 @@ struct cfg_root : cfg::node
cfg::_bool use_gpu_texture_scaling{this, "Use GPU texture scaling", true};
cfg::_bool stretch_to_display_area{this, "Stretch To Display Area"};
cfg::_bool force_high_precision_z_buffer{this, "Force High Precision Z buffer"};
cfg::_bool invalidate_surface_cache_every_frame{this, "Invalidate Cache Every Frame", true};
cfg::_bool strict_rendering_mode{this, "Strict Rendering Mode"};
cfg::_bool disable_zcull_queries{this, "Disable ZCull Occlusion Queries", false};
cfg::_bool disable_vertex_cache{this, "Disable Vertex Cache", false};
@@ -363,6 +365,7 @@ struct cfg_root : cfg::node
cfg::_bool dump_to_file{this, "Dump to file"};
cfg::_bool convert_to_u16{this, "Convert to 16 bit"};
cfg::_bool downmix_to_2ch{this, "Downmix to Stereo", true};
cfg::_int<2, 128> frames{this, "Buffer Count", 32};
} audio{this};
@@ -403,6 +406,7 @@ struct cfg_root : cfg::node
cfg::_bool autoexit{this, "Exit RPCS3 when process finishes"};
cfg::_bool start_fullscreen{ this, "Start games in fullscreen mode" };
cfg::_bool show_fps_in_title{ this, "Show FPS counter in window title", true};
cfg::_bool show_trophy_popups{ this, "Show trophy popups", true};
cfg::_int<1, 65535> gdb_server_port{this, "Port", 2345};
} misc{this};
+11 -8
View File
@@ -1,6 +1,7 @@
{
"audio": {
"audioOutBox": "Windows: Always use XAudio, no exceptions.\n\nLinux: ALSA uses the native Linux sound system to output sound.\nThis option has good compatibility and sound quality.\nOpenAL uses a cross-platform approach but will have poor audio quality and stuttering sound in most games.\nIf unsure, use ALSA.",
"audioOutBox": "Always use XAudio, no exceptions.\nOpenAL uses a cross-platform approach but will have poor audio quality and stuttering sound in most games.",
"audioOutBox_Linux": "PulseAudio uses the recommended native Linux sound system and has good compatibility and sound quality. If it is unavailable on your system, ALSA is the next best alternative. \nOpenAL uses a cross-platform approach but will have poor audio quality and stuttering sound in most games.",
"audioDump": "Saves all audio as a raw wave file. If unsure, leave this unchecked.",
"convert": "Uses 16-bit audio samples instead of default 32-bit floating point.\nUse with buggy audio drivers if you have no sound or completely broken sound.",
"downmix": "Uses stereo audio output instead of default 7.1 surround sound.\nUse with stereo audio devices. Disable it only if you are using a surround sound audio system."
@@ -30,7 +31,7 @@
"spuLoopDetection": "Try to detect loop conditions in SPU kernels and use them as scheduling hints.\nImproves performance and reduces CPU usage.\nMay cause severe audio stuttering in rare cases."
},
"comboboxes": {
"preferredSPUThreads": "Preferred number of threads allowed to enter some sensitive SPU stages.\nSome SPU stages are sensitive to race conditions and allowing a limited number at a time helps alleviate performance stalls.\nSetting this to a smaller value might improve performance and reduce stuttering in some games.\nLeave this on auto if performance is negatively affected when setting a small value."
"preferredSPUThreads": "Some SPU stages are sensitive to race conditions and allowing a limited number at a time helps alleviate performance stalls.\nSetting this to a smaller value might improve performance and reduce stuttering in some games.\nLeave this on auto if performance is negatively affected when setting a small value."
}
},
"debug": {
@@ -46,12 +47,12 @@
"logProg": "Dump game shaders to file. Only useful to developers.\nIf unsure, don't use this option.",
"disableOcclusionQueries": "Disables running occlusion queries. Minor to moderate performance boost.\nMight introduce issues with broken occlusion e.g missing geometry and extreme pop-in.",
"disableVertexCache": "Disables the vertex cache.\nMight resolve missing or flickering graphics output.\nMay degrade performance.",
"forceCpuBlitEmulation": "Forces emulation of all blit and image manipulation operations on the cpu.\nRequires 'Write Color Buffers' option to also be enabled in most cases to avoid missing graphics.\nSignificatly degrades performance but is more accurate in some cases.\nThis setting overrides the 'GPU texture scaling' option."
"forceCpuBlitEmulation": "Forces emulation of all blit and image manipulation operations on the CPU.\nRequires 'Write Color Buffers' option to also be enabled in most cases to avoid missing graphics.\nSignificantly degrades performance but is more accurate in some cases.\nThis setting overrides the 'GPU texture scaling' option."
},
"emulator": {
"gui": {
"configs": "Only useful to developers.\nIf unsure, don't use this option.",
"stylesheets": "Only useful to developers.\nIf unsure, don't use this option.",
"stylesheets": "Changes the overall look of RPCS3.\nChoose a stylesheet and click Apply to change between styles.",
"show_welcome": "Shows the initial welcome screen upon starting RPCS3.",
"custom_colors": "Prioritize custom user interface colors over properties set in stylesheet."
},
@@ -61,15 +62,17 @@
"startGameFullscreen": "Automatically puts the game window in fullscreen.\nDouble click on the game window or press alt+enter to toggle fullscreen and windowed mode.",
"showFPSInTitle": "Shows the framerate in the game window title. May cause buggy or outdated recording software to not notice RPCS3.",
"gs_resizeOnBoot": "Automatically resizes the game window on boot.\nThis does not change the internal game resolution.",
"showTrophyPopups": "Show trophy popups when a trophy is unlocked.",
"gs_disableMouse": "Disables the activation of fullscreen mode per doubleclick while the game screen is active.\nCheck this if you want to play with mouse and keyboard (for example with UCR)."
}
},
"gpu": {
"comboboxes": {
"renderBox": "Vulkan is the fastest renderer. OpenGL is the most accurate renderer.\nIf unsure, use Vulkan. Should you have any compatibility issues, fall back to OpenGL.\nDirectX 12 is deprecated and should never be used.",
"resBox": "This setting will be ignored if the Resolution Scale is set to anything other than 100%!\nLeave this on 1280x720, every PS3 game is compatible with this resolution.\nSet it to 1920x1080 only if supported by the game. Lower resolutions may work but are not practical.\nHowever rarely due to emulation bugs some games will only render at low resolutions like 480p.",
"renderBox_Linux": "Vulkan is the fastest renderer. OpenGL is the most accurate renderer.\nIf unsure, use Vulkan. Should you have any compatibility issues, fall back to OpenGL.",
"resBox": "This setting will be ignored if the Resolution Scale is set to anything other than 100%!\nLeave this on 1280x720, every PS3 game is compatible with this resolution.\nOnly use 1920x1080 if the game supports it.\nRarely due to emulation bugs some games will only render at low resolutions like 480p.",
"graphicsAdapterBox": "On multi GPU systems select which GPU to use in RPCS3 when using Vulkan or DirectX 12.\nThis is not needed when using OpenGL.",
"aspectBox": "Leave this on 16:9 unless you have a 4:3 monitor.\nAuto also works well especially if you use a resolution that is not 720p.",
"aspectBox": "Leave this on 16:9 unless you have a 4:3 monitor.\nAuto also works well, especially if you use a resolution that is not 720p.",
"frameLimitBox": "Off is the best option as it performs faster.\nUsing the frame limiter will add extra overhead and slow down the game.\nHowever, some games will crash if the framerate is too high.\nIf that happens, set value to anything other than Off.",
"anisotropicFilterOverride": "Higher values increase sharpness of textures on sloped surfaces at the cost of GPU resources.\nModern GPUs can handle this setting just fine even at 16x.\nKeep this on Automatic if you want to use the original setting used by a real PS3."
},
@@ -80,14 +83,14 @@
"main": {
"dumpColor": "Enable this option if you get missing graphics or broken lighting ingame.\nMight degrade performance and introduce stuttering in some cases.\nRequired for Demon's Souls.",
"vsync": "By having this off you might obtain a higher frame rate at the cost of tearing artifacts in the game.",
"autoInvalidateCache": "Enable this option if the game has broken shadows. May slightly degrade performance.",
"gpuTextureScaling": "Small to significant performance boost in most games and rarely with side effects.\nMay cause texture corruption in rare cases.",
"scrictModeRendering": "Enforces strict compliance to the API specification.\nMight result in degraded performance in some games.\nCan resolve rare cases of missing graphics and flickering.\nIf unsure, don't use this option.",
"stretchToDisplayArea": "Overrides the aspect ratio and stretches the image to the full display area."
}
},
"input": {
"padHandlerBox": "If you want to use the keyboard to control, select the Keyboard option.\nYou can change the button mappings in Configuration --> Controls.\nIf you have a DualShock 4, select DualShock 4.\nWindows: If you have an Xbox controller, or another compatible device, use XInput.\nOlder controllers such as PS2 controllers with an adapter usually work fine with MMJoystick.\nCheck button mappings in the Windows control panel.\n\nLinux: evdev input is WIP.",
"padHandlerBox": "If you want to use the keyboard to control, select the Keyboard option.\nIf you have a DualShock 4, select DualShock 4.\nIf you have an Xbox controller, or another compatible device, use XInput.\nOlder controllers such as PS2 controllers with an adapter usually work fine with MMJoystick.\nCheck button mappings in the Windows control panel.",
"padHandlerBox_Linux": "If you want to use the keyboard to control, select the Keyboard option.\nIf you have a DualShock 4, select DualShock 4.\nevdev input is WIP.",
"keyboardHandlerBox": "Some games support native keyboard input.\nBasic will work in these cases.",
"mouseHandlerBox": "Some games support native mouse input.\nBasic will work in these cases.",
"cameraBox": "Camera support is not implemented, leave this on null.",
+6 -6
View File
@@ -9,14 +9,12 @@ bool TROPUSRLoader::Load(const std::string& filepath, const std::string& configp
{
const std::string& path = vfs::get(filepath);
if (!Generate(filepath, configpath))
{
return false;
}
if (!m_file.open(path, fs::read))
{
return false;
if (!Generate(filepath, configpath))
{
return false;
}
}
if (!LoadHeader() || !LoadTableHeaders() || !LoadTables())
@@ -209,6 +207,7 @@ u32 TROPUSRLoader::GetTrophyUnlockState(u32 id)
if (id >= m_table6.size())
{
LOG_WARNING(LOADER, "TROPUSRLoader::GetUnlockState: Invalid id=%d", id);
return 0;
}
return m_table6[id].trophy_state; // Let's assume the trophies are stored ordered
@@ -219,6 +218,7 @@ u64 TROPUSRLoader::GetTrophyTimestamp(u32 id)
if (id >= m_table6.size())
{
LOG_WARNING(LOADER, "TROPUSRLoader::GetTrophyTimestamp: Invalid id=%d", id);
return 0;
}
// TODO: What timestamp does sceNpTrophyGetTrophyInfo want, timestamp1 or timestamp2?
+46 -15
View File
@@ -119,16 +119,16 @@ bool evdev_joystick_handler::try_open_dev(u32 index)
pads[index]->m_port_status |= CELL_PAD_STATUS_ASSIGN_CHANGES;
pads[index]->m_port_status |= CELL_PAD_STATUS_CONNECTED;
int buttons=0;
for (u32 i=BTN_JOYSTICK; i<KEY_MAX; i++)
int buttons = 0;
for (u32 i = BTN_JOYSTICK; i < KEY_MAX; i++)
if (libevdev_has_event_code(dev, EV_KEY, i))
{
LOG_NOTICE(GENERAL, "Joystick #%d has button %d as %d", index, i, buttons);
joy_button_maps[index][i - BTN_MISC] = buttons++;
}
int axes=0;
for (u32 i=ABS_X; i<=ABS_RZ; i++)
int axes = 0;
for (u32 i = ABS_X; i <= ABS_RZ; i++)
{
if (libevdev_has_event_code(dev, EV_ABS, i))
@@ -144,7 +144,7 @@ bool evdev_joystick_handler::try_open_dev(u32 index)
}
}
for (u32 i=ABS_HAT0X; i<=ABS_HAT3Y; i+=2)
for (u32 i = ABS_HAT0X; i <= ABS_HAT3Y; i += 2)
if (libevdev_has_event_code(dev, EV_ABS, i) ||
libevdev_has_event_code(dev, EV_ABS, i+1))
{
@@ -351,7 +351,7 @@ void evdev_joystick_handler::ThreadProc()
{
update_devs();
for (int i=0; i<joy_devs.size(); i++)
for (int i = 0; i<joy_devs.size(); i++)
{
auto pad = pads[i];
auto& dev = joy_devs[i];
@@ -413,10 +413,41 @@ void evdev_joystick_handler::ThreadProc()
break;
}
case EV_ABS:
LOG_NOTICE(GENERAL, "Joystick #%d EV_ABS: %d %d", i, evt.code, evt.value);
{
if (evt.code >= ABS_HAT0X && evt.code <= ABS_HAT3Y) {
int hat = evt.code - ABS_HAT0X;
LOG_NOTICE(GENERAL, "Joystick #%d EV_ABS: %d %d", i, evt.code, evt.value);
//duplicate the evt.code and evt.value, so that they're still available
//for the analog input
int code2 = evt.code;
int value2 = evt.value;
if (g_evdev_joystick_config.left_analog_to_dpad)
{
//some gamepad have a -32767 to +32767 range; others have a 0 to 255
float center2 = (axis_ranges[evt.code].second + axis_ranges[evt.code].first) / 2;
//arbitrary decision: when the value is higher than a 1/3 of the range, we simulate a dpad press
float threshold2 = (axis_ranges[evt.code].second-center2)/3;
if (code2 == 0 || code2 == 1)
{
value2 = 0;
if (evt.value > center2 + threshold2)
value2 = 1;
else if (evt.value < center2 - threshold2)
value2 = -1;
if (revaxis[code2])
value2 = -value2;
if (g_evdev_joystick_config.lxstick < g_evdev_joystick_config.lystick)
{
code2 = (code2 == 0) ? ABS_HAT0X : ABS_HAT0Y;
}
else
{
code2 = (code2 == 0) ? ABS_HAT0Y : ABS_HAT0X;
}
}
}
if (code2 >= ABS_HAT0X && code2 <= ABS_HAT3Y)
{
int hat = code2 - ABS_HAT0X;
if (hat != joy_hat_ids[i] && hat-1 != joy_hat_ids[i])
{
LOG_ERROR(GENERAL, "Joystick #%d sent HAT event for invalid hat %d (expected %d)", i, hat, joy_hat_ids[i]);
@@ -429,7 +460,7 @@ void evdev_joystick_handler::ThreadProc()
{
if (bt.m_keyCode != source_axis) continue;
if (evt.value == 0)
if (value2 == 0)
{
bt.m_pressed = false;
bt.m_value = 0;
@@ -439,13 +470,12 @@ void evdev_joystick_handler::ThreadProc()
int code;
if (source_axis == EVDEV_DPAD_HAT_AXIS_X)
{
code = evt.value > 0 ? CELL_PAD_CTRL_RIGHT : CELL_PAD_CTRL_LEFT;
code = value2 > 0 ? CELL_PAD_CTRL_RIGHT : CELL_PAD_CTRL_LEFT;
}
else
{
code = evt.value > 0 ? CELL_PAD_CTRL_DOWN : CELL_PAD_CTRL_UP;
code = value2 > 0 ? CELL_PAD_CTRL_DOWN : CELL_PAD_CTRL_UP;
}
if (bt.m_outKeyCode == code)
{
bt.m_pressed = true;
@@ -457,7 +487,7 @@ void evdev_joystick_handler::ThreadProc()
else if (axistrigger && (evt.code == ABS_Z || evt.code == ABS_RZ))
{
// For Xbox controllers, a third axis represent the left/right triggers.
int which_trigger=0;
int which_trigger = 0;
if (evt.code == ABS_Z)
{
@@ -486,7 +516,7 @@ void evdev_joystick_handler::ThreadProc()
which_button->m_pressed = value > 0;
which_button->m_value = value;
}
else if (evt.code >= ABS_X && evt.code <= ABS_RZ)
if (evt.code >= ABS_X && evt.code <= ABS_RZ)
{
int axis = joy_axis_maps[i][evt.code - ABS_X];
@@ -531,6 +561,7 @@ void evdev_joystick_handler::ThreadProc()
pad->m_sticks[axis].m_value = scale_axis(evt.code, value);
}
break;
}
default:
LOG_ERROR(GENERAL, "Unknown joystick #%d event %d", i, evt.type);
break;
+2 -1
View File
@@ -46,7 +46,8 @@ struct evdev_joystick_config final : cfg::node
cfg::_bool axistrigger{this, "Z axis triggers", true};
cfg::_bool squirclejoysticks{this, "Squircle Joysticks", true};
cfg::int32 squirclefactor{this, "Squircle Factor", 5000};
cfg::int32 deadzone{this, "Deadzone", 10};
cfg::int32 deadzone{this, "Deadzone", 10};
cfg::_bool left_analog_to_dpad{this, "Left Analog to Dpad", false};
bool load()
{
+20 -3
View File
@@ -47,16 +47,33 @@ int main(int argc, char** argv)
QCommandLineParser parser;
parser.setApplicationDescription("Welcome to RPCS3 command line.");
parser.addPositionalArgument("(S)ELF", "Path for directly executing a (S)ELF");
parser.addPositionalArgument("[Args...]", "Optional args for the executable");
parser.addHelpOption();
parser.process(app);
app.Init();
if (parser.positionalArguments().length() > 0)
QStringList args = parser.positionalArguments();
if (args.length() > 0)
{
// Ugly workaround
QTimer::singleShot(2, [path = sstr(QFileInfo(parser.positionalArguments().at(0)).canonicalFilePath())]
// Propagate command line arguments
std::vector<std::string> argv;
if (args.length() > 1)
{
argv.emplace_back();
for (std::size_t i = 1; i < args.length(); i++)
{
argv.emplace_back(args[i].toStdString());
}
}
// Ugly workaround
QTimer::singleShot(2, [path = sstr(QFileInfo(args.at(0)).canonicalFilePath()), argv = std::move(argv)]() mutable
{
Emu.argv = std::move(argv);
Emu.BootGame(path, true);
Emu.Run();
});
+51 -5
View File
@@ -144,7 +144,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;HLSL.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmain.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGL.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5Quick.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Qml.lib;$(QTDIR)\lib\Qt5Network.lib;$(QTDIR)\lib\Qt5Core.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5WinExtras.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
@@ -185,7 +185,7 @@
<ExceptionHandling>Sync</ExceptionHandling>
<ObjectFileName>$(IntDir)</ObjectFileName>
<Optimization>MaxSpeed</Optimization>
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_QUICK_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>_WINDOWS;UNICODE;WIN32;WIN64;QT_NO_DEBUG;QT_OPENGL_LIB;QT_WIDGETS_LIB;QT_QUICK_LIB;QT_GUI_LIB;QT_QML_LIB;QT_NETWORK_LIB;QT_CORE_LIB;NDEBUG;QT_WINEXTRAS_LIB;BRANCH=$(BRANCH);%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessToFile>false</PreprocessToFile>
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@@ -196,7 +196,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;HLSL.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmain.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGL.lib;$(QTDIR)\lib\Qt5Widgets.lib;$(QTDIR)\lib\Qt5Quick.lib;$(QTDIR)\lib\Qt5Gui.lib;$(QTDIR)\lib\Qt5Qml.lib;$(QTDIR)\lib\Qt5Network.lib;$(QTDIR)\lib\Qt5Core.lib;Qt5Core.lib;Qt5Gui.lib;Qt5Widgets.lib;Qt5WinExtras.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Release;..\Vulkan\glslang-build\SPIRV\Release;..\Vulkan\glslang-build\OGLCompilersDLL\Release;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Release;..\Vulkan\Vulkan-build\loader\Release;..\Vulkan\glslang-build\glslang\Release;..\lib\$(CONFIGURATION)-$(PLATFORM);..\3rdparty\minidx12\Lib;$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
@@ -248,7 +248,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;HLSLd.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmaind.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGLd.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5Quickd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Qmld.lib;$(QTDIR)\lib\Qt5Networkd.lib;$(QTDIR)\lib\Qt5Cored.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5WinExtrasd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
@@ -301,7 +301,7 @@
</ClCompile>
<Link>
<AdditionalDependencies>..\hidapi.lib;winmm.lib;OpenAL.lib;XAudio.lib;D3D12GSRender.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;VKstatic.1.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;HLSLd.lib;Advapi32.lib;user32.lib;zlib.lib;..\libpng.lib;asmjit.lib;yaml-cpp.lib;emucore.lib;dxgi.lib;$(QTDIR)\lib\qtmaind.lib;shell32.lib;opengl32.lib;$(QTDIR)\lib\Qt5OpenGLd.lib;$(QTDIR)\lib\Qt5Widgetsd.lib;$(QTDIR)\lib\Qt5Quickd.lib;$(QTDIR)\lib\Qt5Guid.lib;$(QTDIR)\lib\Qt5Qmld.lib;$(QTDIR)\lib\Qt5Networkd.lib;$(QTDIR)\lib\Qt5Cored.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;Qt5WinExtrasd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;C:\utils\my_sql\my_sql\lib;C:\utils\postgresql\pgsql\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\3rdparty\OpenAL\libs\Win64;..\Vulkan\glslang-build\hlsl\Debug;..\Vulkan\glslang-build\SPIRV\Debug;..\Vulkan\glslang-build\OGLCompilersDLL\Debug;..\Vulkan\glslang-build\glslang\OSDependent\Windows\Debug;..\Vulkan\Vulkan-build\loader\Debug;..\Vulkan\glslang-build\glslang\Debug;..\3rdparty\minidx12\Lib;..\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /VERBOSE %(AdditionalOptions)</AdditionalOptions>
<DataExecutionPrevention>true</DataExecutionPrevention>
<GenerateDebugInformation>Debug</GenerateDebugInformation>
@@ -455,6 +455,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_syntax_highlighter.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_vfs_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -585,6 +590,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_syntax_highlighter.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_vfs_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
@@ -725,6 +735,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_syntax_highlighter.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_vfs_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
@@ -855,6 +870,11 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_syntax_highlighter.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_vfs_dialog.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
@@ -874,8 +894,12 @@
<ClCompile Include="rpcs3qt\gamepads_settings_dialog.cpp" />
<ClCompile Include="rpcs3qt\game_list_grid.cpp" />
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp" />
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp" />
<ClCompile Include="rpcs3qt\save_data_info_dialog.cpp" />
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp" />
<ClCompile Include="rpcs3qt\trophy_manager_dialog.cpp" />
<ClCompile Include="rpcs3qt\trophy_notification_frame.cpp" />
<ClCompile Include="rpcs3qt\trophy_notification_helper.cpp" />
<ClCompile Include="rpcs3qt\vfs_dialog.cpp" />
<ClCompile Include="rpcs3qt\vfs_dialog_tab.cpp" />
<ClCompile Include="rpcs3qt\welcome_dialog.cpp" />
@@ -1243,6 +1267,24 @@
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="rpcs3qt\gl_gs_frame.h" />
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">Moc%27ing syntax_highlighter.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing syntax_highlighter.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing syntax_highlighter.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DNDEBUG -DQT_WINEXTRAS_LIB -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
<Message Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">Moc%27ing syntax_highlighter.h...</Message>
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras"</Command>
</CustomBuild>
<ClInclude Include="rpcs3qt\instruction_editor_dialog.h" />
<ClInclude Include="rpcs3qt\memory_viewer_panel.h" />
<CustomBuild Include="rpcs3qt\msg_dialog_frame.h">
@@ -1392,6 +1434,10 @@
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
<Command Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_OPENGL_LIB -DQT_WIDGETS_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -DQT_WINEXTRAS_LIB -DLLVM_AVAILABLE -D_SCL_SECURE_NO_WARNINGS -D_UNICODE "-I.\..\Vulkan\Vulkan-LoaderAndValidationLayers\include" "-I.\.." "-I.\..\3rdparty\minidx12\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtOpenGL" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtQuick" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtANGLE" "-I$(QTDIR)\include\QtQml" "-I$(QTDIR)\include\QtNetwork" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I$(QTDIR)\mkspecs\win32-msvc2015" "-I.\QTGeneratedFiles\$(ConfigurationName)\." "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtWinExtras" "-I$(NOINHERIT)\."</Command>
</CustomBuild>
<ClInclude Include="rpcs3qt\trophy_manager_dialog.h" />
<ClInclude Include="rpcs3qt\trophy_notification_frame.h" />
<ClInclude Include="rpcs3qt\trophy_notification_helper.h" />
<ClInclude Include="rpcs3qt\trophy_tree_widget_item.h" />
<ClInclude Include="xinput_pad_handler.h" />
<ClInclude Include="\rpcs3qt\*.h" />
</ItemGroup>
+245 -167
View File
@@ -60,9 +60,42 @@
<Extensions>ui</Extensions>
<ParseFiles>true</ParseFiles>
</Filter>
<Filter Include="Gui\saves">
<Filter Include="Gui\trophy">
<UniqueIdentifier>{d49ebf7f-ea65-4006-943a-2c47f25c9aa7}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\save">
<UniqueIdentifier>{31799965-1274-4c87-83a3-3bff31e8715d}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\vfs">
<UniqueIdentifier>{e0821fe5-e58f-4ddd-8b30-8c324916b15e}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\debugger">
<UniqueIdentifier>{32359024-92ef-44f2-97d8-120a3539c629}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\dev tools">
<UniqueIdentifier>{2183c937-7c45-45d5-bab1-c654bba97e15}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\game list">
<UniqueIdentifier>{d181920e-98c2-49b9-9ad6-bf3c2caf886a}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\game window">
<UniqueIdentifier>{92da2292-18f9-4c41-997e-b8d288f03d5a}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\log">
<UniqueIdentifier>{b90a63fe-afa9-41e1-9f99-1db049864d58}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\message dialog">
<UniqueIdentifier>{dae67696-f925-4d24-b1b7-96d1d0176dec}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\settings">
<UniqueIdentifier>{ce01674e-ca9e-4fb7-bb4e-cdde3764317d}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\misc dialogs">
<UniqueIdentifier>{114eef25-61bf-4df5-8867-09156cf51b8a}</UniqueIdentifier>
</Filter>
<Filter Include="Gui\syntax highlighter">
<UniqueIdentifier>{adb985ae-88db-4274-a6fd-6bcf230451ca}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="\rpcs3qt\*.cpp">
@@ -71,9 +104,6 @@
<ClCompile Include="main.cpp">
<Filter>rpcs3</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\auto_pause_settings_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_auto_pause_settings_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -98,9 +128,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_cg_disasm_window.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\cg_disasm_window.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_debugger_frame.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -113,9 +140,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_debugger_frame.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\debugger_frame.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_emu_settings.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -128,9 +152,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_emu_settings.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\emu_settings.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_game_list_frame.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -143,12 +164,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_game_list_frame.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\game_list_frame.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\gl_gs_frame.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_gs_frame.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -161,9 +176,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_gs_frame.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\gs_frame.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_gui_settings.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -176,9 +188,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_gui_settings.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\gui_settings.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_kernel_explorer.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -191,9 +200,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_kernel_explorer.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\kernel_explorer.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_log_frame.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -206,9 +212,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_log_frame.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\log_frame.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_main_window.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -221,9 +224,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_main_window.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\main_window.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_memory_string_searcher.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -236,9 +236,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_memory_string_searcher.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\memory_string_searcher.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_pad_settings_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -251,9 +248,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_pad_settings_dialog.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\pad_settings_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_rsx_debugger.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -266,9 +260,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_rsx_debugger.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\rsx_debugger.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_settings_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -281,9 +272,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_settings_dialog.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\settings_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="basic_keyboard_handler.cpp">
<Filter>Io\Basic</Filter>
</ClCompile>
@@ -341,15 +329,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_rpcs3_app.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\instruction_editor_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\memory_viewer_panel.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\msg_dialog_frame.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_msg_dialog_frame.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -362,15 +341,9 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_msg_dialog_frame.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\register_editor_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\qrc_resources.cpp">
<Filter>Generated Files</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\welcome_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_welcome_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -383,9 +356,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_welcome_dialog.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\game_list_grid.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_game_list_grid.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -398,12 +368,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_game_list_grid.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\vfs_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_vfs_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -416,9 +380,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_vfs_dialog.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\vfs_dialog_tab.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_vfs_dialog_tab.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -431,9 +392,6 @@
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_vfs_dialog_tab.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\about_dialog.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_about_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
@@ -471,16 +429,19 @@
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\save_data_dialog.cpp">
<Filter>Gui\saves</Filter>
<Filter>Gui\save</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\save_data_info_dialog.cpp">
<Filter>Gui\saves</Filter>
<Filter>Gui\save</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\save_data_list_dialog.cpp">
<Filter>Gui\saves</Filter>
<Filter>Gui\save</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp">
<Filter>Gui\saves</Filter>
<ClCompile Include="rpcs3qt\trophy_notification_helper.cpp">
<Filter>Gui\trophy</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\trophy_notification_frame.cpp">
<Filter>Gui\trophy</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_save_manager_dialog.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
@@ -497,20 +458,113 @@
<ClCompile Include="pad_thread.cpp">
<Filter>Io</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\about_dialog.cpp">
<Filter>Gui\misc dialogs</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\welcome_dialog.cpp">
<Filter>Gui\misc dialogs</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\auto_pause_settings_dialog.cpp">
<Filter>Gui\dev tools</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\cg_disasm_window.cpp">
<Filter>Gui\dev tools</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\debugger_frame.cpp">
<Filter>Gui\debugger</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\emu_settings.cpp">
<Filter>Gui\settings</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\gui_settings.cpp">
<Filter>Gui\settings</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\gl_gs_frame.cpp">
<Filter>Gui\game window</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\gs_frame.cpp">
<Filter>Gui\game window</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\gamepads_settings_dialog.cpp">
<Filter>Gui\settings</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\pad_settings_dialog.cpp">
<Filter>Gui\settings</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\log_frame.cpp">
<Filter>Gui\log</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\main_window.cpp">
<Filter>Gui</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release - LLVM\moc_syntax_highlighter.cpp">
<Filter>Generated Files\Release - LLVM</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug\moc_syntax_highlighter.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Release\moc_syntax_highlighter.cpp">
<Filter>Generated Files\Release</Filter>
</ClCompile>
<ClCompile Include="QTGeneratedFiles\Debug - LLVM\moc_syntax_highlighter.cpp">
<Filter>Generated Files\Debug - LLVM</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp">
<Filter>Gui\syntax highlighter</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\kernel_explorer.cpp">
<Filter>Gui\dev tools</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\game_list_frame.cpp">
<Filter>Gui\game list</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\game_list_grid.cpp">
<Filter>Gui\game list</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\game_list_grid_delegate.cpp">
<Filter>Gui\game list</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\memory_string_searcher.cpp">
<Filter>Gui\dev tools</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\memory_viewer_panel.cpp">
<Filter>Gui\dev tools</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\settings_dialog.cpp">
<Filter>Gui\settings</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\vfs_dialog.cpp">
<Filter>Gui\vfs</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\vfs_dialog_tab.cpp">
<Filter>Gui\vfs</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\rsx_debugger.cpp">
<Filter>Gui\dev tools</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\register_editor_dialog.cpp">
<Filter>Gui\debugger</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\instruction_editor_dialog.cpp">
<Filter>Gui\debugger</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\msg_dialog_frame.cpp">
<Filter>Gui\message dialog</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\syntax_highlighter.cpp">
<Filter>Generated Files\Debug</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\save_manager_dialog.cpp">
<Filter>Gui\save</Filter>
</ClCompile>
<ClCompile Include="rpcs3qt\trophy_manager_dialog.cpp">
<Filter>Gui\trophy</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="\rpcs3qt\*.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\gl_gs_frame.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\table_item_delegate.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="keyboard_pad_handler.h">
<Filter>Io\Basic</Filter>
</ClInclude>
@@ -523,18 +577,6 @@
<ClInclude Include="xinput_pad_handler.h">
<Filter>Io\XInput</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\instruction_editor_dialog.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\memory_viewer_panel.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\register_editor_dialog.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="QTGeneratedFiles\ui_about_dialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
@@ -550,17 +592,47 @@
<ClInclude Include="QTGeneratedFiles\ui_welcome_dialog.h">
<Filter>Generated Files</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\game_list.h">
<Filter>Gui</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\save_data_dialog.h">
<Filter>Gui\saves</Filter>
<Filter>Gui\save</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\trophy_notification_helper.h">
<Filter>Gui\trophy</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\trophy_notification_frame.h">
<Filter>Gui\trophy</Filter>
</ClInclude>
<ClInclude Include="pad_thread.h">
<Filter>Io</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\gl_gs_frame.h">
<Filter>Gui\game window</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\gamepads_settings_dialog.h">
<Filter>Gui</Filter>
<Filter>Gui\settings</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\game_list.h">
<Filter>Gui\game list</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\game_list_grid_delegate.h">
<Filter>Gui\game list</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\table_item_delegate.h">
<Filter>Gui\game list</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\memory_viewer_panel.h">
<Filter>Gui\dev tools</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\register_editor_dialog.h">
<Filter>Gui\debugger</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\instruction_editor_dialog.h">
<Filter>Gui\debugger</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\trophy_manager_dialog.h">
<Filter>Gui\trophy</Filter>
</ClInclude>
<ClInclude Include="rpcs3qt\trophy_tree_widget_item.h">
<Filter>Gui\trophy</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
@@ -570,48 +642,6 @@
<CustomBuild Include="release\moc_predefs.h.cbt">
<Filter>Generated Files</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\auto_pause_settings_dialog.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\cg_disasm_window.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\debugger_frame.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\emu_settings.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\game_list_frame.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\gs_frame.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\gui_settings.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\kernel_explorer.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\log_frame.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\main_window.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\memory_string_searcher.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\pad_settings_dialog.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\rsx_debugger.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\settings_dialog.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="basic_keyboard_handler.h">
<Filter>Io\Basic</Filter>
</CustomBuild>
@@ -621,27 +651,12 @@
<CustomBuild Include="rpcs3_app.h">
<Filter>rpcs3</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\msg_dialog_frame.h">
<Filter>Gui</Filter>
</CustomBuild>
<ClInclude Include="resource.h">
<Filter>Resource Files</Filter>
</ClInclude>
<CustomBuild Include="resources.qrc">
<Filter>Resource Files</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\welcome_dialog.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\game_list_grid.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\vfs_dialog.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\vfs_dialog_tab.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\about_dialog.ui">
<Filter>Form Files</Filter>
</CustomBuild>
@@ -657,17 +672,80 @@
<CustomBuild Include="rpcs3qt\welcome_dialog.ui">
<Filter>Form Files</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\about_dialog.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\save_data_info_dialog.h">
<Filter>Gui\saves</Filter>
<Filter>Gui\save</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\save_data_list_dialog.h">
<Filter>Gui\saves</Filter>
<Filter>Gui\save</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
<Filter>Gui\syntax highlighter</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\about_dialog.h">
<Filter>Gui\misc dialogs</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\welcome_dialog.h">
<Filter>Gui\misc dialogs</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\auto_pause_settings_dialog.h">
<Filter>Gui\dev tools</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\cg_disasm_window.h">
<Filter>Gui\dev tools</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\debugger_frame.h">
<Filter>Gui\debugger</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\emu_settings.h">
<Filter>Gui\settings</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\gui_settings.h">
<Filter>Gui\settings</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\gs_frame.h">
<Filter>Gui\game window</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\pad_settings_dialog.h">
<Filter>Gui\settings</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\log_frame.h">
<Filter>Gui\log</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\main_window.h">
<Filter>Gui</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\kernel_explorer.h">
<Filter>Gui\dev tools</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\game_list_frame.h">
<Filter>Gui\game list</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\game_list_grid.h">
<Filter>Gui\game list</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\memory_string_searcher.h">
<Filter>Gui\dev tools</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\settings_dialog.h">
<Filter>Gui\settings</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\vfs_dialog_tab.h">
<Filter>Gui\vfs</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\vfs_dialog.h">
<Filter>Gui\vfs</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\rsx_debugger.h">
<Filter>Gui\dev tools</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\msg_dialog_frame.h">
<Filter>Gui\message dialog</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\syntax_highlighter.h">
<Filter>Generated Files</Filter>
</CustomBuild>
<CustomBuild Include="rpcs3qt\save_manager_dialog.h">
<Filter>Gui\saves</Filter>
<Filter>Gui\save</Filter>
</CustomBuild>
</ItemGroup>
<ItemGroup>
+8
View File
@@ -6,6 +6,9 @@
#include "rpcs3qt/gs_frame.h"
#include "rpcs3qt/gl_gs_frame.h"
#include "Emu/Cell/Modules/sceNpTrophy.h"
#include "rpcs3qt/trophy_notification_helper.h"
#include "Emu/Cell/Modules/cellSaveData.h"
#include "rpcs3qt/save_data_dialog.h"
@@ -241,6 +244,11 @@ void rpcs3_app::InitializeCallbacks()
return std::make_unique<save_data_dialog>();
};
callbacks.get_trophy_notification_dialog = [=]() -> std::unique_ptr<TrophyNotificationBase>
{
return std::make_unique<trophy_notification_helper>(gameWindow);
};
callbacks.on_run = [=]() { OnEmulatorRun(); };
callbacks.on_pause = [=]() { OnEmulatorPause(); };
callbacks.on_resume = [=]() { OnEmulatorResume(); };
+1 -1
View File
@@ -9,5 +9,5 @@ namespace rpcs3
return RPCS3_GIT_BRANCH;
}
const extern utils::version version{ 0, 0, 3, utils::version_type::alpha, 1, RPCS3_GIT_VERSION };
const extern utils::version version{ 0, 0, 4, utils::version_type::alpha, 1, RPCS3_GIT_VERSION };
}
+1
View File
@@ -23,6 +23,7 @@ about_dialog::about_dialog(QWidget* parent) : QDialog(parent), ui(new Ui::about_
connect(ui->patreon, &QAbstractButton::clicked, [] { QDesktopServices::openUrl(QUrl("https://www.patreon.com/Nekotekina")); });
connect(ui->close, &QAbstractButton::clicked, this, &QWidget::close);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
layout()->setSizeConstraint(QLayout::SetFixedSize);
}
+2 -2
View File
@@ -210,7 +210,7 @@
<x>0</x>
<y>0</y>
<width>863</width>
<height>707</height>
<height>737</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3" stretch="1,1,1,1">
@@ -246,7 +246,7 @@
<item>
<widget class="QLabel" name="supporters">
<property name="text">
<string>&lt;p&gt;&lt;b&gt;Supporters:&lt;/b&gt;&lt;br&gt;&lt;br&gt;Howard Garrison&lt;br&gt;EXPotemkin&lt;br&gt;Marko V.&lt;br&gt;danhp&lt;br&gt;Jake (5315825)&lt;br&gt;Ian Reid&lt;br&gt;Tad Sherlock&lt;br&gt;Tyler Friesen&lt;br&gt;Folzar&lt;br&gt;Payton Williams&lt;br&gt;RedPill Australia&lt;br&gt;yanghong&lt;br&gt;Mohammed El-Serougi&lt;br&gt;Дима ~Ximer13~ Кулин&lt;br&gt;James Reed&lt;br&gt;BaroqueSonata&lt;br&gt;Bonzay0&lt;br&gt;Henrijs Kons&lt;br&gt;eoiz&lt;br&gt;Lena Stöffler&lt;br&gt;Michael Holder&lt;br&gt;Max Bosse&lt;br&gt;Tyler Whisinnand&lt;br&gt;Gato Harvey&lt;br&gt;cain4355&lt;br&gt;Thomas Peltier&lt;br&gt;Loli Co.&lt;br&gt;MapleLoonie&lt;br&gt;Travis McEwen&lt;br&gt;Scott Singratsomboune&lt;br&gt;T.E&lt;br&gt;Lukas Rieger&lt;br&gt;Dane Madsen&lt;br&gt;Jacob Gustin&lt;br&gt;Jonatan R&lt;br&gt;Luke Johnson&lt;br&gt;Thomas Zaorski&lt;br&gt;MyOwnFan&lt;br&gt;Alexandros Mandravillis&lt;br&gt;Socker Bopper&lt;br&gt;Faris Leonhart&lt;br&gt;Fabien Net&lt;br&gt;Raves&lt;br&gt;Barrowsx&lt;br&gt;kilsuton&lt;br&gt;Max Mason&lt;br&gt;Ethan Condon&lt;br&gt;jfidone&lt;br&gt;iaDRM&lt;br&gt;Kazer2.0&lt;br&gt;Bryce Quintin&lt;/p&gt;</string>
<string>&lt;p&gt;&lt;b&gt;Supporters:&lt;/b&gt;&lt;br&gt;&lt;br&gt;Howard Garrison&lt;br&gt;EXPotemkin&lt;br&gt;Marko V.&lt;br&gt;danhp&lt;br&gt;Jake (5315825)&lt;br&gt;Ian Reid&lt;br&gt;Tad Sherlock&lt;br&gt;Tyler Friesen&lt;br&gt;Folzar&lt;br&gt;Payton Williams&lt;br&gt;RedPill Australia&lt;br&gt;yanghong&lt;br&gt;Mohammed El-Serougi&lt;br&gt;Дима ~Ximer13~ Кулин&lt;br&gt;James Reed&lt;br&gt;BaroqueSonata&lt;br&gt;Bonzay0&lt;br&gt;Henrijs Kons&lt;br&gt;eoiz&lt;br&gt;Lena Stöffler&lt;br&gt;Michael Holder&lt;br&gt;Max Bosse&lt;br&gt;Tyler Whisinnand&lt;br&gt;Gato Harvey&lt;br&gt;cain4355&lt;br&gt;Thomas Peltier&lt;br&gt;Loli Co.&lt;br&gt;MapleLoonie&lt;br&gt;Travis McEwen&lt;br&gt;Scott Singratsomboune&lt;br&gt;T.E&lt;br&gt;Lukas Rieger&lt;br&gt;Dane Madsen&lt;br&gt;Jacob Gustin&lt;br&gt;Jonatan R&lt;br&gt;Luke Johnson&lt;br&gt;Thomas Zaorski&lt;br&gt;MyOwnFan&lt;br&gt;Alexandros Mandravillis&lt;br&gt;Socker Bopper&lt;br&gt;Faris Leonhart&lt;br&gt;Fabien Net&lt;br&gt;Raves&lt;br&gt;Barrowsx&lt;br&gt;kilsuton&lt;br&gt;Max Mason&lt;br&gt;Ethan Condon&lt;br&gt;jfidone&lt;br&gt;iaDRM&lt;br&gt;Kazer2.0&lt;br&gt;Bryce Quintin&lt;br&gt;Yuri Kunde Schlesner&lt;/p&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
@@ -5,6 +5,8 @@ constexpr auto qstr = QString::fromStdString;
auto_pause_settings_dialog::auto_pause_settings_dialog(QWidget *parent) : QDialog(parent)
{
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QLabel *description = new QLabel(tr("To use auto pause: enter the ID(s) of a function or a system call.\nRestart of the game is required to apply. You can enable/disable this in the settings."), this);
pauseList = new QTableWidget(this);
+114
View File
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "cg_disasm_window.h"
#include "syntax_highlighter.h"
#include <QSplitter>
#include <QMenu>
@@ -39,6 +40,119 @@ cg_disasm_window::cg_disasm_window(std::shared_ptr<gui_settings> xSettings): xgu
m_glsl_text->setWordWrapMode(QTextOption::NoWrap);
m_glsl_text->setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont));
// m_disasm_text syntax highlighter
syntax_highlighter* sh_asm = new syntax_highlighter(m_disasm_text->document());
sh_asm->AddCommentRule("#", QColor(Qt::darkGreen));
sh_asm->AddCommentRule("\/\*", QColor(Qt::darkGreen), true, "\*\/");
sh_asm->AddSimpleRule(QStringList("^([^\\s]+).*$"), QColor(Qt::darkBlue)); // Instructions
sh_asm->AddSimpleRule(QStringList(",?\\s(-?R\\d[^,;\\s]*)"), QColor(Qt::darkRed)); // -R0.*
sh_asm->AddSimpleRule(QStringList(",?\\s(-?H\\d[^,;\\s]*)"), QColor(Qt::red)); // -H1.*
sh_asm->AddSimpleRule(QStringList(",?\\s(-?v\\[\\d\\]*[^,;\\s]*)"), QColor(Qt::darkCyan)); // -v[xyz].*
sh_asm->AddSimpleRule(QStringList(",?\\s(-?o\\[\\d\\]*[^,;\\s]*)"), QColor(Qt::darkMagenta)); // -o[xyz].*
sh_asm->AddSimpleRule(QStringList(",?\\s(-?c\\[\\d\\]*[^,;\\s]*)"), QColor(Qt::darkYellow)); // -c[xyz].*
//sh_asm->AddMultiRule(
// "^([^\\s]+)(?:,?\\s*([^,\\;\\s]+))?(?:,?\\s*([^,\\;\\s]+))?(?:,?\\s*([^,\\;\\s]+))?(?:,?\\s*([^,\\;\\s]+))?.*$",
// { QColor(Qt::black), QColor(Qt::darkBlue), QColor(Qt::darkRed), QColor(Qt::darkMagenta), QColor(Qt::darkYellow), QColor(Qt::darkCyan) });
// m_glsl_text syntax highlighter
QStringList glsl_syntax = QStringList()
// Selection-Iteration-Jump Statements:
<< "if" << "else" << "switch" << "case" << "default"
<< "for" << "while" << "do" << "foreach" //?
<< "return" << "break" << "continue" << "discard"
// Misc:
<< "void" << "char" << "short" << "long" << "template"
<< "class" << "struct" << "union" << "enum"
<< "static" << "virtual" << "inline" << "explicit"
<< "public" << "private" << "protected" << "namespace"
<< "typedef" << "typename" << "signed" << "unsigned"
<< "friend" << "operator" << "signals" << "slots"
// Qualifiers:
<< "in" << "packed" << "precision" << "const" << "smooth" << "sample"
<< "out" << "shared" << "highp" << "invariant" << "noperspective" << "centroid"
<< "inout" << "std140" << "mediump" << "uniform" << "flat" << "patch"
<< "buffer" << "std430" << "lowp"
<< "image"
// Removed Qualifiers?
<< "attribute" << "varying"
// Memory Qualifiers
<< "coherent" << "volatile" << "restrict" << "readonly" << "writeonly"
// Layout Qualifiers:
//<< "subroutine" << "layout" << "xfb_buffer" << "textureGrad" << "texture" << "dFdx" << "dFdy"
//<< "location" << "component" << "binding" << "offset"
//<< "xfb_offset" << "xfb_stride" << "vertices" << "max_vertices"
// Scalars and Vectors:
<< "bool" << "int" << "uint" << "float" << "double"
<< "bvec2" << "ivec2" << "uvec2" << "vec2" << "dvec2"
<< "bvec3" << "ivec3" << "uvec3" << "vec3" << "dvec3"
<< "bvec4" << "ivec4" << "uvec4" << "vec4" << "dvec4"
// Matrices:
<< "mat2" << "mat2x3" << "mat2x4"
<< "mat3" << "mat3x2" << "mat3x4"
<< "mat4" << "mat4x2" << "mat4x3"
// Sampler Types:
<< "sampler1D" << "isampler1D" << "usampler1D"
<< "sampler2D" << "isampler2D" << "usampler2D"
<< "sampler3D" << "isampler3D" << "usampler3D"
<< "samplerCube" << "isamplerCube" << "usamplerCube"
<< "sampler2DRect" << "isampler2DRect" << "usampler2DRect"
<< "sampler1DArray" << "isampler1DArray" << "usampler1DArray"
<< "sampler2DArray" << "isampler2DArray" << "usampler2DArray"
<< "samplerCubeArray" << "isamplerCubeArray" << "usamplerCubeArray"
<< "samplerBuffer" << "isamplerBuffer" << "usamplerBuffer"
<< "sampler2DMS" << "isampler2DMS" << "usampler2DMS"
<< "sampler2DMSArray" << "isampler2DMSArray" << "usampler2DMSArray"
// Shadow Samplers:
<< "sampler1DShadow"
<< "sampler2DShadow"
<< "samplerCubeShadow"
<< "sampler2DRectShadow"
<< "sampler1DArrayShadow"
<< "sampler2DArrayShadow"
<< "samplerCubeArrayShadow"
// Image Types:
<< "image1D" << "iimage1D" << "uimage1D"
<< "image2D" << "iimage2D" << "uimage2D"
<< "image3D" << "iimage3D" << "uimage3D"
<< "imageCube" << "iimageCube" << "uimageCube"
<< "image2DRect" << "iimage2DRect" << "uimage2DRect"
<< "image1DArray" << "iimage1DArray" << "uimage1DArray"
<< "image2DArray" << "iimage2DArray" << "uimage2DArray"
<< "imageCubeArray" << "iimageCubeArray" << "uimageCubeArray"
<< "imageBuffer" << "iimageBuffer" << "uimageBuffer"
<< "image2DMS" << "iimage2DMS" << "uimage2DMS"
<< "image2DMSArray" << "iimage2DMSArray" << "uimage2DMSArray"
// Image Formats:
// Floating-point: // Signed integer:
<< "rgba32f" << "rgba32i"
<< "rgba16f" << "rgba16i"
<< "rg32f" << "rgba8i"
<< "rg16f" << "rg32i"
<< "r11f_g11f_b10f" << "rg16i"
<< "r32f" << "rg8i"
<< "r16f" << "r32i"
<< "rgba16" << "r16i"
<< "rgb10_a2" << "r8i"
<< "rgba8" << "r8ui"
<< "rg16" // Unsigned integer:
<< "rg8" << "rgba32ui"
<< "r16" << "rgba16ui"
<< "r8" << "rgb10_a2ui"
<< "rgba16_snorm" << "rgba8ui"
<< "rgba8_snorm" << "rg32ui"
<< "rg16_snorm" << "rg16ui"
<< "rg8_snorm" << "rg8ui"
<< "r16_snorm" << "r32ui"
<< "r8_snorm" << "r16ui"
;
syntax_highlighter* sh_glsl = new syntax_highlighter(m_glsl_text->document());
sh_glsl->AddWordRule(glsl_syntax, QColor(Qt::darkBlue)); // normal words like: soka, nani, or gomen
sh_glsl->AddSimpleRule(QStringList("\\bGL_(?:[A-Z]|_)+\\b"), QColor(Qt::darkMagenta)); // constants like: GL_OMAE_WA_MOU_SHINDEIRU
sh_glsl->AddSimpleRule(QStringList("\\bgl_(?:[A-Z]|[a-z]|_)+\\b"), QColor(Qt::darkCyan)); // reserved types like: gl_exploooooosion
sh_glsl->AddSimpleRule(QStringList("\\B#[^\\s]+\\b"), QColor(Qt::darkGray)); // preprocessor instructions like: #waifu megumin
sh_glsl->AddCommentRule("\/\/", QColor(Qt::darkGreen)); // comments like: // No comment
sh_glsl->AddCommentRule("\/\*", QColor(Qt::darkGreen), true, "\*\/"); // comments like: /* I am trapped! Please help me! */
QSplitter* splitter = new QSplitter();
splitter->addWidget(m_disasm_text);
splitter->addWidget(m_glsl_text);
+106 -4
View File
@@ -4,6 +4,7 @@
#include <QApplication>
#include <QFontDatabase>
#include <QCompleter>
#include <QMenu>
constexpr auto qstr = QString::fromStdString;
extern bool user_asked_for_frame_capture;
@@ -22,6 +23,10 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
QHBoxLayout* hbox_b_main = new QHBoxLayout();
m_list = new debugger_list(this);
m_breakpoints_list = new QListWidget(this);
m_breakpoints_list->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_breakpoints_list->setContextMenuPolicy(Qt::CustomContextMenu);
m_breakpoints_list->setSelectionMode(QAbstractItemView::ExtendedSelection);
m_choice_units = new QComboBox(this);
m_choice_units->setSizeAdjustPolicy(QComboBox::AdjustToContents);
m_choice_units->setMaxVisibleItems(30);
@@ -33,6 +38,11 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
m_choice_units->completer()->setMaxVisibleItems(30);
m_choice_units->completer()->setFilterMode(Qt::MatchContains);
m_breakpoints_list_delete = new QAction("Delete", m_breakpoints_list);
m_breakpoints_list_delete->setShortcut(Qt::Key_Delete);
m_breakpoints_list_delete->setShortcutContext(Qt::WidgetShortcut);
m_breakpoints_list->addAction(m_breakpoints_list_delete);
m_go_to_addr = new QPushButton(tr("Go To Address"), this);
m_go_to_pc = new QPushButton(tr("Go To PC"), this);
m_btn_capture = new QPushButton(tr("Capture"), this);
@@ -58,9 +68,15 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
m_list->setFont(m_mono);
m_regs->setFont(m_mono);
m_right_splitter = new QSplitter(this);
m_right_splitter->setOrientation(Qt::Vertical);
m_right_splitter->addWidget(m_regs);
m_right_splitter->addWidget(m_breakpoints_list);
m_right_splitter->setStretchFactor(0, 1);
m_splitter = new QSplitter(this);
m_splitter->addWidget(m_list);
m_splitter->addWidget(m_regs);
m_splitter->addWidget(m_right_splitter);
QHBoxLayout* hbox_w_list = new QHBoxLayout();
hbox_w_list->addWidget(m_splitter);
@@ -117,6 +133,10 @@ debugger_frame::debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *
connect(m_choice_units, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &debugger_frame::OnSelectUnit);
connect(this, &QDockWidget::visibilityChanged, this, &debugger_frame::EnableUpdateTimer);
connect(m_breakpoints_list, &QListWidget::itemDoubleClicked, this, &debugger_frame::OnBreakpointList_doubleClicked);
connect(m_breakpoints_list, &QListWidget::customContextMenuRequested, this, &debugger_frame::OnBreakpointList_rightClicked);
connect(m_breakpoints_list_delete, &QAction::triggered, this, &debugger_frame::OnBreakpointList_delete);
m_list->ShowAddr(CentrePc(m_list->m_pc));
UpdateUnitList();
}
@@ -194,7 +214,7 @@ u32 debugger_frame::GetPc() const
u32 debugger_frame::CentrePc(u32 pc) const
{
return pc/* - ((m_item_count / 2) * 4)*/;
return pc - ((m_list->m_item_count / 2) * 4);
}
void debugger_frame::UpdateUI()
@@ -473,9 +493,56 @@ void debugger_frame::EnableButtons(bool enable)
void debugger_frame::ClearBreakpoints()
{
//This is required to actually delete the breakpoints, not just visually.
for (std::map<u32, bool>::iterator it = g_breakpoints.begin(); it != g_breakpoints.end(); it++)
m_list->RemoveBreakPoint(it->first, false);
g_breakpoints.clear();
}
void debugger_frame::OnBreakpointList_doubleClicked()
{
m_list->ShowAddr(CentrePc(m_breakpoints_list->currentItem()->data(Qt::UserRole).value<u32>()));
m_list->setCurrentRow(16);
}
void debugger_frame::OnBreakpointList_rightClicked(const QPoint &pos)
{
if (m_breakpoints_list->itemAt(pos) == NULL)
return;
QMenu* menu = new QMenu();
if (m_breakpoints_list->selectedItems().count() == 1)
{
menu->addAction("Rename");
menu->addSeparator();
}
menu->addAction(m_breakpoints_list_delete);
QAction* selectedItem = menu->exec(QCursor::pos());
if (selectedItem != NULL)
{
if (selectedItem->text() == "Rename")
{
QListWidgetItem* currentItem = m_breakpoints_list->selectedItems().at(0);
currentItem->setFlags(currentItem->flags() | Qt::ItemIsEditable);
m_breakpoints_list->editItem(currentItem);
}
}
}
void debugger_frame::OnBreakpointList_delete()
{
int selectedCount = m_breakpoints_list->selectedItems().count();
for (int i = selectedCount - 1; i >= 0; i--)
{
m_list->RemoveBreakPoint(m_breakpoints_list->item(i)->data(Qt::UserRole).value<u32>());
}
}
debugger_list::debugger_list(debugger_frame* parent) : QListWidget(parent)
{
m_pc = 0;
@@ -543,12 +610,47 @@ void debugger_list::AddBreakPoint(u32 pc)
{
g_breakpoints.emplace(pc, false);
ppu_breakpoint(pc);
const auto cpu = m_debugFrame->cpu.lock();
const u32 cpu_offset = g_system == system_type::ps3 && cpu->id_type() != 1 ? static_cast<SPUThread&>(*cpu).offset : 0;
m_debugFrame->m_disasm->offset = (u8*)vm::base(cpu_offset);
m_debugFrame->m_disasm->disasm(m_debugFrame->m_disasm->dump_pc = pc);
QString breakpointItemText = qstr(m_debugFrame->m_disasm->last_opcode);
breakpointItemText.remove(10, 13);
QListWidgetItem* breakpointItem = new QListWidgetItem(breakpointItemText);
breakpointItem->setTextColor(m_text_color_bp);
breakpointItem->setBackgroundColor(m_color_bp);
QVariant pcVariant;
pcVariant.setValue(pc);
breakpointItem->setData(Qt::UserRole, pcVariant);
m_debugFrame->m_breakpoints_list->addItem(breakpointItem);
}
void debugger_list::RemoveBreakPoint(u32 pc)
void debugger_list::RemoveBreakPoint(u32 pc, bool eraseFromMap)
{
g_breakpoints.erase(pc);
if(eraseFromMap)
g_breakpoints.erase(pc);
ppu_breakpoint(pc);
int breakpointsListCount = m_debugFrame->m_breakpoints_list->count();
for (int i = 0; i < breakpointsListCount; i++)
{
QListWidgetItem* currentItem = m_debugFrame->m_breakpoints_list->item(i);
if (currentItem->data(Qt::UserRole).value<u32>() == pc)
{
delete m_debugFrame->m_breakpoints_list->takeItem(i);
break;
}
}
ShowAddr(m_pc - (m_item_count) * 4);
}
void debugger_list::keyPressEvent(QKeyEvent* event)
+10 -1
View File
@@ -36,6 +36,7 @@ class debugger_frame : public QDockWidget
Q_OBJECT
debugger_list* m_list;
QSplitter* m_right_splitter;
QFont m_mono;
QTextEdit* m_regs;
QPushButton* m_go_to_addr;
@@ -61,8 +62,11 @@ class debugger_frame : public QDockWidget
std::shared_ptr<gui_settings> xgui_settings;
QAction* m_breakpoints_list_delete;
public:
std::unique_ptr<CPUDisAsm> m_disasm;
QListWidget* m_breakpoints_list;
std::weak_ptr<cpu_thread> cpu;
public:
@@ -93,6 +97,9 @@ Q_SIGNALS:
public Q_SLOTS:
void DoStep();
private Q_SLOTS:
void OnBreakpointList_doubleClicked();
void OnBreakpointList_rightClicked(const QPoint &pos);
void OnBreakpointList_delete();
void OnSelectUnit();
void Show_Val();
void Show_PC();
@@ -117,11 +124,11 @@ public:
public:
debugger_list(debugger_frame* parent);
void ShowAddr(u32 addr);
void RemoveBreakPoint(u32 pc, bool eraseFromMap = true);
private:
bool IsBreakPoint(u32 pc);
void AddBreakPoint(u32 pc);
void RemoveBreakPoint(u32 pc);
protected:
void keyPressEvent(QKeyEvent* event);
@@ -129,3 +136,5 @@ protected:
void wheelEvent(QWheelEvent* event);
void resizeEvent(QResizeEvent* event);
};
Q_DECLARE_METATYPE(u32);
+2 -2
View File
@@ -56,7 +56,6 @@ public:
D3D12Adapter,
VulkanAdapter,
ForceHighpZ,
AutoInvalidateCache,
StrictRenderingMode,
DisableVertexCache,
DisableOcclusionQueries,
@@ -83,6 +82,7 @@ public:
StartOnBoot,
StartGameFullscreen,
ShowFPSInTitle,
ShowTrophyPopups,
ShowWelcomeScreen,
// Network
@@ -209,7 +209,6 @@ private:
{ GPUTextureScaling, { "Video", "Use GPU texture scaling"}},
{ StretchToDisplayArea, { "Video", "Stretch To Display Area"}},
{ ForceHighpZ, { "Video", "Force High Precision Z buffer"}},
{ AutoInvalidateCache, { "Video", "Invalidate Cache Every Frame"}},
{ StrictRenderingMode, { "Video", "Strict Rendering Mode"}},
{ DisableVertexCache, { "Video", "Disable Vertex Cache"}},
{ DisableOcclusionQueries, { "Video", "Disable ZCull Occlusion Queries" }},
@@ -238,6 +237,7 @@ private:
{StartOnBoot, { "Miscellaneous", "Automatically start games after boot" }},
{StartGameFullscreen, { "Miscellaneous", "Start games in fullscreen mode"}},
{ShowFPSInTitle, { "Miscellaneous", "Show FPS counter in window title"}},
{ShowTrophyPopups, { "Miscellaneous", "Show trophy popups"}},
{ShowWelcomeScreen, { "Miscellaneous", "Show Welcome Screen"}},
// Networking
+69 -12
View File
@@ -19,7 +19,6 @@
#include <QListView>
#include <QMenuBar>
#include <QMessageBox>
#include <QProcess>
#include <QTimer>
#include <QUrl>
#include <QLabel>
@@ -37,6 +36,8 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
m_Text_Factor = xgui_settings->GetValue(GUI::gl_textFactor).toReal();
m_showToolBar = xgui_settings->GetValue(GUI::gl_toolBarVisible).toBool();
m_Icon_Color = xgui_settings->GetValue(GUI::gl_iconColor).value<QColor>();
m_colSortOrder = xgui_settings->GetValue(GUI::gl_sortAsc).toBool() ? Qt::AscendingOrder : Qt::DescendingOrder;
m_sortColumn = xgui_settings->GetValue(GUI::gl_sortCol).toInt();
m_oldLayoutIsList = m_isListLayout;
@@ -144,6 +145,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
m_gameList->setSelectionMode(QAbstractItemView::SingleSelection);
m_gameList->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
m_gameList->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
m_gameList->verticalScrollBar()->installEventFilter(this);
m_gameList->verticalScrollBar()->setSingleStep(20);
m_gameList->horizontalScrollBar()->setSingleStep(20);
m_gameList->verticalHeader()->setSectionResizeMode(QHeaderView::Fixed);
@@ -157,6 +159,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> guiSettings, std:
m_gameList->horizontalHeader()->setDefaultSectionSize(150);
m_gameList->setContextMenuPolicy(Qt::CustomContextMenu);
m_gameList->setAlternatingRowColors(true);
m_gameList->installEventFilter(this);
m_gameList->setColumnCount(GUI::COLUMN_COUNT);
m_gameList->setHorizontalHeaderItem( GUI::COLUMN_ICON, new QTableWidgetItem(tr("Icon")));
@@ -545,17 +548,7 @@ static void open_dir(const std::string& spath)
{
fs::create_dir(spath);
QString path = qstr(spath);
QProcess* process = new QProcess();
#ifdef _WIN32
std::string command = "explorer";
std::replace(path.begin(), path.end(), '/', '\\');
process->start("explorer", QStringList() << path);
#elif __APPLE__
process->start("open", QStringList() << path);
#else
process->start("xdg-open", QStringList() << path);
#endif
QDesktopServices::openUrl(QUrl("file:///" + path));
}
void game_list_frame::doubleClickedSlot(const QModelIndex& index)
@@ -639,6 +632,7 @@ void game_list_frame::ShowSpecifiedContextMenu(const QPoint &pos, int row)
QAction* removeGame = myMenu.addAction(tr("&Remove"));
QAction* removeConfig = myMenu.addAction(tr("&Remove Custom Configuration"));
QAction* deleteShadersCache = myMenu.addAction(tr("&Delete Shaders Cache"));
QAction* deleteLLVMCache = myMenu.addAction(tr("&Delete LLVM Cache"));
myMenu.addSeparator();
QAction* openGameFolder = myMenu.addAction(tr("&Open Install Folder"));
QAction* openConfig = myMenu.addAction(tr("&Open Config Folder"));
@@ -679,6 +673,31 @@ void game_list_frame::ShowSpecifiedContextMenu(const QPoint &pos, int row)
{
DeleteShadersCache(row);
});
connect(deleteLLVMCache, &QAction::triggered, [=]()
{
if (QMessageBox::question(this, tr("Confirm Delete"), tr("Delete LLVM cache?")) == QMessageBox::Yes)
{
const std::string config_base_dir = fs::get_config_dir() + "data/" + m_game_data[row].info.serial;
for (auto&& subdir : fs::dir{config_base_dir})
{
if (!subdir.is_directory || subdir.name == "." || subdir.name == "..")
{
continue;
}
for (auto&& entry : fs::dir{config_base_dir + "/" + subdir.name})
{
if (entry.name.size() >= 4 && entry.name.compare(entry.name.size() - 4, 4, ".obj", 4) == 0)
{
fs::remove_file(config_base_dir + "/" + subdir.name + "/" + entry.name);
}
}
}
}
});
connect(openGameFolder, &QAction::triggered, [=]()
{
open_dir(currGame.path);
@@ -950,6 +969,42 @@ void game_list_frame::resizeEvent(QResizeEvent *event)
QDockWidget::resizeEvent(event);
}
bool game_list_frame::eventFilter(QObject *object, QEvent *event)
{
// Zoom gamelist/gamegrid
if (event->type() == QEvent::Wheel && (object == m_gameList->verticalScrollBar() || object == m_xgrid->verticalScrollBar()))
{
QWheelEvent *wheelEvent = static_cast<QWheelEvent *>(event);
if (wheelEvent->modifiers() & Qt::ControlModifier)
{
QPoint numSteps = wheelEvent->angleDelta() / 8 / 15; // http://doc.qt.io/qt-5/qwheelevent.html#pixelDelta
const int value = numSteps.y();
m_Slider_Size->setValue(m_Slider_Size->value() + value);
return true;
}
}
else if (event->type() == QEvent::KeyPress && (object == m_gameList || object == m_xgrid))
{
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
if (keyEvent->modifiers() & Qt::ControlModifier)
{
if (keyEvent->key() == Qt::Key_Plus)
{
m_Slider_Size->setValue(m_Slider_Size->value() + 1);
return true;
}
else if (keyEvent->key() == Qt::Key_Minus)
{
m_Slider_Size->setValue(m_Slider_Size->value() - 1);
return true;
}
}
}
return QDockWidget::eventFilter(object, event);
}
/**
Cleans and readds entries to table widget in UI.
*/
@@ -1099,6 +1154,8 @@ void game_list_frame::PopulateGameGrid(uint maxCols, const QSize& image_size, co
m_xgrid->resizeColumnsToContents();
m_xgrid->resizeRowsToContents();
m_xgrid->installEventFilter(this);
m_xgrid->verticalScrollBar()->installEventFilter(this);
}
/**
+3 -2
View File
@@ -103,9 +103,9 @@ namespace category // (see PARAM.SFO in psdevwiki.com) TODO: Disc Categories
inline bool CategoryInMap(const std::string& cat, const q_from_char& map)
{
auto map_contains_category = [cat](std::pair<std::string, const QString> p)
auto map_contains_category = [s = qstr(cat)](const auto& p)
{
return p.second == qstr(cat);
return p.second == s;
};
return std::find_if(map.begin(), map.end(), map_contains_category) != map.end();
@@ -236,6 +236,7 @@ protected:
/** Override inherited method from Qt to allow signalling when close happened.*/
void closeEvent(QCloseEvent* event) override;
void resizeEvent(QResizeEvent *event) override;
bool eventFilter(QObject *object, QEvent *event);
private:
QPixmap PaintedPixmap(const QImage& img, bool paintConfigIcon = false);
bool Boot(const GameInfo& info);
@@ -11,6 +11,9 @@
#include "../Emu/Io/Null/NullPadHandler.h"
#include "../Emu/System.h"
#include <QJsonObject>
#include <QJsonDocument>
input_config input_cfg;
// taken from https://stackoverflow.com/a/30818424/8353754
@@ -38,6 +41,13 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
{
setWindowTitle(tr("Gamepads Settings"));
// read tooltips from json
QFile json_file(":/Json/tooltips.json");
json_file.open(QIODevice::ReadOnly | QIODevice::Text);
QJsonObject json_input = QJsonDocument::fromJson(json_file.readAll()).object().value("input").toObject();
json_file.close();
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
QVBoxLayout *dialog_layout = new QVBoxLayout();
QHBoxLayout *all_players = new QHBoxLayout();
@@ -90,6 +100,11 @@ gamepads_settings_dialog::gamepads_settings_dialog(QWidget* parent)
co_inputtype[i] = new QComboBox();
co_inputtype[i]->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
co_inputtype[i]->view()->setTextElideMode(Qt::ElideNone);
#ifdef WIN32
co_inputtype[i]->setToolTip(json_input["padHandlerBox"].toString());
#else
co_inputtype[i]->setToolTip(json_input["padHandlerBox_Linux"].toString());
#endif
ppad_layout->addWidget(co_inputtype[i]);
co_deviceID[i] = new QComboBox();
+24 -7
View File
@@ -22,7 +22,7 @@ gl_gs_frame::gl_gs_frame(int w, int h, QIcon appIcon, bool disableMouse)
setFormat(m_format);
}
void* gl_gs_frame::make_context()
draw_context_t gl_gs_frame::make_context()
{
auto context = new QOpenGLContext();
context->setFormat(m_format);
@@ -33,16 +33,33 @@ void* gl_gs_frame::make_context()
void gl_gs_frame::set_current(draw_context_t ctx)
{
if (!((QOpenGLContext*)ctx.get())->makeCurrent(this))
if (!((QOpenGLContext*)ctx)->makeCurrent(this))
{
create();
((QOpenGLContext*)ctx.get())->makeCurrent(this);
((QOpenGLContext*)ctx)->makeCurrent(this);
}
}
void gl_gs_frame::delete_context(void* ctx)
void gl_gs_frame::delete_context(draw_context_t ctx)
{
((QOpenGLContext*)ctx)->deleteLater();
auto gl_ctx = (QOpenGLContext*)ctx;
gl_ctx->doneCurrent();
#ifndef _WIN32
delete gl_ctx;
#else
//AMD driver crashes when executing wglDeleteContext
//Catch with SEH
__try
{
delete gl_ctx;
}
__except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
{
LOG_FATAL(RSX, "Your graphics driver just crashed whilst cleaning up. All consumed VRAM should have been released, but you may want to restart the emulator just in case");
}
#endif
}
void gl_gs_frame::flip(draw_context_t context, bool skip_frame)
@@ -52,6 +69,6 @@ void gl_gs_frame::flip(draw_context_t context, bool skip_frame)
//Do not swap buffers if frame skip is active
if (skip_frame) return;
((QOpenGLContext*)context.get())->makeCurrent(this);
((QOpenGLContext*)context.get())->swapBuffers(this);
((QOpenGLContext*)context)->makeCurrent(this);
((QOpenGLContext*)context)->swapBuffers(this);
}
+2 -2
View File
@@ -11,8 +11,8 @@ private:
public:
gl_gs_frame(int w, int h, QIcon appIcon, bool disableMouse);
void* make_context() override;
draw_context_t make_context() override;
void set_current(draw_context_t context) override;
void delete_context(void* context) override;
void delete_context(draw_context_t context) override;
void flip(draw_context_t context, bool skip_frame=false) override;
};
+84 -62
View File
@@ -26,7 +26,7 @@ gs_frame::gs_frame(const QString& title, int w, int h, QIcon appIcon, bool disab
version = version.substr(0 , version.find_last_of("-"));
//Add branch to version on frame , unless it's master.
if (rpcs3::get_branch() != "master" || rpcs3::get_branch() != "HEAD")
if (rpcs3::get_branch().compare("master") != 0 && rpcs3::get_branch().compare("HEAD") != 0)
{
version = version + "-" + rpcs3::get_branch();
}
@@ -154,7 +154,7 @@ void* gs_frame::handle() const
#endif
}
void* gs_frame::make_context()
draw_context_t gs_frame::make_context()
{
return nullptr;
}
@@ -164,7 +164,7 @@ void gs_frame::set_current(draw_context_t ctx)
Q_UNUSED(ctx);
}
void gs_frame::delete_context(void* ctx)
void gs_frame::delete_context(draw_context_t ctx)
{
Q_UNUSED(ctx);
}
@@ -246,77 +246,99 @@ bool gs_frame::event(QEvent* ev)
bool gs_frame::nativeEvent(const QByteArray &eventType, void *message, long *result)
{
#ifdef _WIN32
//Wait for consumer to clear notification pending flag
while (wm_event_raised.load(std::memory_order_consume));
if (wm_event_queue_enabled.load(std::memory_order_consume) && !Emu.IsStopped())
{
std::lock_guard<std::mutex> lock(wm_event_lock);
MSG* msg = static_cast<MSG*>(message);
switch (msg->message)
{
case WM_WINDOWPOSCHANGING:
{
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & SWP_NOSIZE;
if (m_in_sizing_event || flags != 0)
break;
//Wait for consumer to clear notification pending flag
while (wm_event_raised.load(std::memory_order_consume) && !Emu.IsStopped());
//About to resize
m_in_sizing_event = true;
m_interactive_resize = false;
m_raised_event = wm_event::geometry_change_notice;
wm_event_raised.store(true);
break;
}
case WM_WINDOWPOSCHANGED:
{
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & (SWP_NOSIZE | SWP_NOMOVE);
if (!m_in_sizing_event || m_user_interaction_active || flags == (SWP_NOSIZE | SWP_NOMOVE))
break;
if (flags & SWP_NOSIZE)
m_raised_event = wm_event::window_moved;
else
m_raised_event = wm_event::window_resized;
//Just finished resizing using maximize or SWP
m_in_sizing_event = false;
wm_event_raised.store(true);
break;
}
case WM_ENTERSIZEMOVE:
m_user_interaction_active = true;
break;
case WM_EXITSIZEMOVE:
m_user_interaction_active = false;
if (m_in_sizing_event && !m_user_interaction_active)
std::lock_guard<std::mutex> lock(wm_event_lock);
MSG* msg = static_cast<MSG*>(message);
switch (msg->message)
{
//Just finished resizing using manual interaction. The corresponding WM_SIZE is consumed before this event fires
m_raised_event = m_interactive_resize ? wm_event::window_resized : wm_event::window_moved;
case WM_WINDOWPOSCHANGING:
{
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & SWP_NOSIZE;
if (m_in_sizing_event || flags != 0)
break;
//About to resize
m_in_sizing_event = true;
m_interactive_resize = false;
m_raised_event = wm_event::geometry_change_notice;
wm_event_raised.store(true);
break;
}
case WM_WINDOWPOSCHANGED:
{
const auto flags = reinterpret_cast<LPWINDOWPOS>(msg->lParam)->flags & (SWP_NOSIZE | SWP_NOMOVE);
if (!m_in_sizing_event || m_user_interaction_active || flags == (SWP_NOSIZE | SWP_NOMOVE))
break;
if (flags & SWP_NOSIZE)
{
m_raised_event = wm_event::window_moved;
}
else
{
LPWINDOWPOS wpos = reinterpret_cast<LPWINDOWPOS>(msg->lParam);
if (wpos->cx <= GetSystemMetrics(SM_CXMINIMIZED) || wpos->cy <= GetSystemMetrics(SM_CYMINIMIZED))
{
//Minimize event
m_minimized = true;
m_raised_event = wm_event::window_minimized;
}
else if (m_minimized)
{
m_minimized = false;
m_raised_event = wm_event::window_restored;
}
else
{
m_raised_event = wm_event::window_resized;
}
}
//Just finished resizing using maximize or SWP
m_in_sizing_event = false;
wm_event_raised.store(true);
break;
}
break;
case WM_SIZE:
{
if (m_user_interaction_active)
case WM_ENTERSIZEMOVE:
m_user_interaction_active = true;
break;
case WM_EXITSIZEMOVE:
m_user_interaction_active = false;
if (m_in_sizing_event && !m_user_interaction_active)
{
//Just finished resizing using manual interaction. The corresponding WM_SIZE is consumed before this event fires
m_raised_event = m_interactive_resize ? wm_event::window_resized : wm_event::window_moved;
m_in_sizing_event = false;
wm_event_raised.store(true);
}
break;
case WM_SIZE:
{
//Interaction is a resize not a move
m_interactive_resize = true;
if (m_user_interaction_active)
{
//Interaction is a resize not a move
m_interactive_resize = true;
}
else if (m_in_sizing_event)
{
//Any other unexpected resize mode will give an unconsumed WM_SIZE event
m_raised_event = wm_event::window_resized;
m_in_sizing_event = false;
wm_event_raised.store(true);
}
break;
}
else if (m_in_sizing_event)
{
//Any other unexpected resize mode will give an unconsumed WM_SIZE event
m_raised_event = wm_event::window_resized;
m_in_sizing_event = false;
wm_event_raised.store(true);
}
break;
}
}
//Do not enter DefWndProc until the consumer has consumed the message
while (wm_event_raised.load(std::memory_order_consume) && !Emu.IsStopped());
}
//Do not enter DefWndProc until the consumer has consumed the message
while (wm_event_raised.load(std::memory_order_consume));
#endif
//Let the default handler deal with this. Only the notification is required
+5 -3
View File
@@ -17,10 +17,15 @@ class gs_frame : public QWindow, public GSFrameBase
bool m_in_sizing_event = false; //a signal that the window is about to be resized was received
bool m_user_interaction_active = false; //a signal indicating the window is being manually moved/resized was received
bool m_interactive_resize = false; //resize signal received while dragging window
bool m_minimized = false;
public:
gs_frame(const QString& title, int w, int h, QIcon appIcon, bool disableMouse);
draw_context_t make_context() override;
void set_current(draw_context_t context) override;
void delete_context(draw_context_t context) override;
wm_event get_default_wm_event() const override;
protected:
virtual void paintEvent(QPaintEvent *event);
@@ -37,9 +42,6 @@ protected:
void* handle() const override;
void* make_context() override;
void set_current(draw_context_t context) override;
void delete_context(void* context) override;
void flip(draw_context_t context, bool skip_frame=false) override;
int client_width() override;
int client_height() override;

Some files were not shown because too many files have changed in this diff Show More