Compare commits

...

118 Commits

Author SHA1 Message Date
Zangetsu38 bd8edee77f Some Change in Gui. 2016-02-15 14:39:52 +01:00
Raul Tambre 787619cdba Merge pull request #1496 from kd-11/rsx_textureinfo_fix
Correctly fetch correct pitch and depth for textures from RSX
2016-02-15 11:03:48 +02:00
kd-11 7d70be42af Correctly fetch correct pitch and depth for textures from RSX
Include vertex textures too

Set correct stride for vertex texture params

Change references to gl_Position in D3D12FragmentProgramDecompiler

Revert bad commit
2016-02-15 11:15:51 +03:00
Ivan 9671a654b7 Merge pull request #1499 from tambry/master
Fix CMake libpng linking
2016-02-15 00:06:37 +03:00
Raul Tambre 6963157e63 Fix rpcs3-tests to use default properties
Cut down some stuff in the file also.
2016-02-14 20:08:56 +02:00
Raul Tambre 9452c6b08c Fix CMake libpng linking 2016-02-14 19:50:36 +02:00
vlj 035875825e Merge pull request #1497 from vlj/rsx
rsx/common/d3d12: Support non default alpha function
2016-02-13 17:22:57 +01:00
Vincent Lejeune 837e06e85b rsx/common/d3d12: Support non default alpha function
Fix After burner climax cloud effects.
2016-02-13 17:07:12 +01:00
vlj 9e3132c3fc Merge pull request #1491 from kd-11/fs_input_fix
Fragment position is given as gl_FragCoord not gl_Position
2016-02-13 16:51:56 +01:00
kd-11 843d0ed298 Fragment position is given as gl_FragCoord not gl_Position
Fix references to gl_Position in Dx12
2016-02-12 18:34:41 +03:00
Raul Tambre f7f4c049fc Merge pull request #1359 from tambry/ostrich
cellPngDec rewrite
2016-02-12 15:08:10 +02:00
Raul Tambre 1072540e3e Fix compiling 2016-02-08 19:12:30 +02:00
Raul Tambre 0c8c13b8b7 Rewrite cellPngDec to use libpng
Improvements made:
* Supports tEXt chunks
* Supports chunk information
* Supports 16-bit depth image packing (fixes #1127)
* Supports fixed alpha values
* And more.
2016-02-08 19:12:29 +02:00
vlj 303a109286 Merge pull request #1477 from vlj/rsx
Rsx: HLSL/GLSL fixes and support two side color.
2016-02-08 18:04:29 +01:00
Vincent Lejeune f0dc38cadd rsx/common/d3d12: Support back spec/diffuse color.
Fix green car in Outrun.
2016-02-08 17:35:52 +01:00
Vincent Lejeune 4efa2266e6 rsx/common/d3d12: Use m_texture_dirty[i] to signal texture state change and avoid unecessary bind operation. 2016-02-08 17:35:50 +01:00
Vincent Lejeune 1f7a1e4078 rsx/common/d3d12/gl: Fix lit and rsq behavior near 0 in vertex shaders. 2016-02-08 17:35:49 +01:00
vlj 2ead9b1f21 Merge pull request #1467 from kd-11/gl_shader_fixes
gl: Support rectangle textures
2016-02-07 18:09:47 +01:00
kd-11 ddf5b52360 Implement rectangle textures natively on OpenGL 2016-02-07 08:57:04 +03:00
vlj f66468ffcd Merge pull request #1476 from kd-11/llvm_fix
Fix LLVM build by changing variable to appropriate type
2016-02-06 19:18:52 +01:00
kd-11 d3405da5c4 Fix LLVM build by changing variable to appropriate type 2016-02-05 18:57:57 +03:00
vlj 020d282868 Merge pull request #1474 from kd-11/gl_shader_validate
gl: Move program validation from link-time to draw-time to comply with spec
2016-02-04 22:31:15 +01:00
kd-11 137821c866 Move program validation from link-time to draw-time to compy with spec 2016-02-04 11:19:13 +03:00
vlj e6d2e05b6e Merge pull request #1461 from kd-11/gl_vertex_textures
Add vertex texture buffers for VS input and support attribute instancing using VertexID
2016-02-04 01:24:31 +01:00
kd-11 7b889a10cc Add vertex texture buffers for VS input
Support vertex instancing in vertex shader using VertexID

Relax OpenGL requirements by removing 4.5 features

Use EXT version of TexBufferRange; Implement buffer copy using TexBuffer

Apply travis workaround by danilaml

Fix vertex upload in in case of inlined array
2016-02-03 13:38:23 +03:00
vlj 1e1c2007a3 Merge pull request #1443 from kd-11/gl_swizzle_mem_vector
Rework OGL texture swizzles
2016-02-02 23:43:24 +01:00
kd-11 660f491310 Rework OGL texture swizzles;
Decode textures using TextureUtils

Shut compiler up about missing return value (unsure)

Revert "Shut compiler up about missing return value (unsure)"

This reverts commit db43ba448776e6c0d6c90909b4037b6f698a545c.

Change some functions in rsx::gl::texture to static.

Replace large switch block in gl::textures::mandates_expansion with simple if tests
2016-02-01 20:11:33 +03:00
vlj 670660c244 Merge pull request #1469 from vlj/d3d12
D3d12: Fix and improvement
2016-01-31 21:36:16 +01:00
Vincent Lejeune 3d960064ef d3d12: Use unnormalized_coords info in RSXFragment 2016-01-30 22:04:36 +01:00
Vincent Lejeune f6d2409b20 rsx/common/d3d12: Support for shader window setting. 2016-01-30 21:58:12 +01:00
vlj 39bc897b93 Merge pull request #1464 from vlj/rsx
rsx/common/d3d12: Support for texture 1d too.
2016-01-30 21:00:50 +01:00
Vincent Lejeune 5f35f2ac7d rsx/common/d3d12: Support for texture 1d too.
They are used in after burner climax
2016-01-30 01:13:15 +01:00
vlj e1eb075604 Merge pull request #1462 from vlj/d3d12
d3d12: Fix for #1459
2016-01-30 00:27:08 +01:00
Vincent Lejeune d19d9ccd0b d3d12: Fix for #1459 2016-01-29 20:18:52 +01:00
Raul Tambre b4b4ae7a78 Merge pull request #1458 from vlj/rsx
rsx/common: Make RSXFragmentProgram key and not just pointer.
2016-01-28 07:42:08 +02:00
Vincent Lejeune 149fa9d750 rsx/common: Make RSXFragmentProgram key and not just pointer. 2016-01-27 23:16:06 +01:00
vlj 791070c158 Merge pull request #1456 from vlj/rsx-debug
rsx-debug: Dump windows origin/pixel center.
2016-01-27 23:11:40 +01:00
Vincent Lejeune 3bd2114815 rsx-debug: Dump windows origin/pixel center. 2016-01-27 22:41:19 +01:00
vlj 46de48593c Merge pull request #1457 from vlj/rsx
rsx/common: Base offset is actually correctly supported.
2016-01-27 22:28:23 +01:00
Vincent Lejeune acd384ae2d rsx/common: Base offset is actually correctly supported.
Outrun uses it and cars are correctly displayed.
2016-01-27 22:05:43 +01:00
Nekotekina b77666cbba cellGame fix 2016-01-27 19:39:31 +03:00
Nekotekina 128ee67bba PSF Loader simplified 2016-01-27 19:17:01 +03:00
Nekotekina 7417033d7f GLGSRender fix 2016-01-27 18:14:39 +03:00
DHrpcs3 e8a940172c fixed GameViewer crash if entry not exists
fixed psf::entry::as_string & psf::entry::value(string)
2016-01-27 18:14:38 +03:00
DHrpcs3 290bdc4566 added psf::object::get 2016-01-27 18:14:36 +03:00
DHrpcs3 220aab1fd0 Reimplemented psf loader 2016-01-27 18:14:35 +03:00
vlj 8e9f456029 Merge pull request #1455 from vlj/d3d12
D3d12: Drop IAInputLayout and use SV_VertexID + SRV instead
2016-01-27 16:10:38 +01:00
Vincent Lejeune aa450b56f1 d3d12: Make some memory helper structure uncopyable/unmovable. 2016-01-26 23:20:23 +01:00
Vincent Lejeune 6d70f3c237 d3d12: Compare mipmap/depth count when checking texture compatibility.
d3d12: Check for depth in texture cache.

Fix Resogun crash when loading a level.
2016-01-26 23:13:30 +01:00
Vincent Lejeune 6384541345 d3d12: Store vertex attributes as SRV and disable Input_layout. 2016-01-26 23:13:29 +01:00
vlj ffb014ca3d Merge pull request #1453 from vlj/rsx
RSX: Start implementing texture3d support
2016-01-26 18:22:45 +01:00
Vincent Lejeune 3c3f92f29b rsx/common/d3d12: Support 3d textures 2016-01-26 17:56:02 +01:00
Vincent Lejeune 24255f7883 rsx/common/d3d12/gl: Add some texture info to RSXFragmentProgram 2016-01-26 17:56:01 +01:00
vlj 40fa836b81 Merge pull request #1452 from vlj/rsx-debug
rsx-debug: Print number of vertex draw again.
2016-01-26 17:45:48 +01:00
Vincent Lejeune b71caa94ac rsx-debug: Print number of vertex draw again. 2016-01-25 18:48:53 +01:00
vlj 39658c0c52 Merge pull request #1450 from vlj/rsx
rsx/common: Div is vector over scalar division
2016-01-24 21:30:09 +01:00
Vincent Lejeune 9b8522e734 rsx/common: Div is vector over scalar division
According to investigation on Resogun.
2016-01-24 00:13:17 +01:00
vlj 9875bf9c7b Merge pull request #1448 from vlj/rsx
rsx: Add vertex input and output in RSXVertexProgram.
2016-01-23 23:59:56 +01:00
Vincent Lejeune 4ce4cf5242 rsx: Add vertex input and output in RSXVertexProgram. 2016-01-22 01:24:54 +01:00
DHrpcs3 52110e0647 Merge pull request #1447 from RPCS3/rsx_cache
RSX vertex/OpenGL texture cache preparation
2016-01-20 21:44:48 +03:00
DHrpcs3 19ce0cdc09 rsx methods constants moved to rsx namespace
minor fix
2016-01-20 20:12:48 +03:00
DHrpcs3 2e58f312d5 rsx: implemented internal tasks queue (WIP) 2016-01-20 17:12:49 +03:00
DHrpcs3 7523d01e0f Code style fixes #2 2016-01-20 16:39:06 +03:00
DHrpcs3 7972cb5bdc Code style fixes #1 2016-01-20 16:23:25 +03:00
DHrpcs3 685d5d3ea3 Access violation handled by rsx::thread
gfxHandler -> rsx::g_access_violation_handler
2016-01-20 15:46:58 +03:00
vlj 9f7caf90e3 Merge pull request #1446 from vlj/rsx
rsx/common/d3d12: Move surface_store in common
2016-01-19 23:51:54 +01:00
Vincent Lejeune f453194e32 rsx: Fix int type not big enough
Fix glitch in After Burner Climax
2016-01-19 23:24:39 +01:00
Vincent Lejeune 440c637b1f rsx/common/d3d12: Move surface_store in common 2016-01-19 22:49:10 +01:00
vlj d95809a069 Merge pull request #1445 from vlj/rsx
d3d12/gl: Use r1 as depth output.
2016-01-19 01:16:57 +01:00
Vincent Lejeune 6aac972bda d3d12/gl: Use r1 as depth output.
The "Output_from_h0" flag seems to concern color output.
There might be another flag for depth from half float value.
2016-01-19 00:45:26 +01:00
vlj df3fddc026 Merge pull request #1442 from vlj/rsx-debug
rsx-debug/d3d12: Support all rtt formats.
2016-01-18 16:11:55 +01:00
Vincent Lejeune 1ce49b60d9 rsx-debug/d3d12: Support all rtt formats. 2016-01-17 20:02:30 +01:00
B1ackDaemon 8b5b23e6c0 Merge pull request #1439 from vlj/d3d12
D3d12: Fixes
2016-01-17 10:17:03 +02:00
Vincent Lejeune 26f329d186 d3d12: Fix dsv increment size
Typo.
2016-01-16 18:25:20 +01:00
Vincent Lejeune 5ace4438e2 d3d12: Fix texture proj
I misinterpreted "last component" from glsl doc... it's w, not z.
2016-01-16 18:25:19 +01:00
Vincent Lejeune b8e10225f9 d3d12: Use first color output for alpha discard instead of 0.
Fix Naruto 2 shader miscompilation.
2016-01-16 18:25:18 +01:00
Vincent Lejeune 224facf3ba d3d12: Never pass nullptr as render target descriptor, even if unused.
Function interface doesn't allow this.
2016-01-16 18:25:16 +01:00
B1ackDaemon 9c12d8ff22 Merge pull request #1433 from vlj/rsx
rsx: Use enum class for surface related regs
2016-01-16 01:23:53 +02:00
Vincent Lejeune 3b4339c8e0 rsx: Use enum class for surface related regs 2016-01-15 23:44:27 +01:00
Ivan 8e12c4cb00 Merge pull request #1355 from bentley/malloc-stdlib
Already implemented. Test.
2016-01-14 21:42:38 +03:00
Nekotekina efe1678088 "Build Solution" fix 2016-01-14 20:41:36 +03:00
Nekotekina 2f5be3559e Hotfix 2016-01-14 20:13:41 +03:00
Nekotekina 960668ecf1 For #1355
offsetof() eliminated
OFFSET_32, SIZE_32, ALIGN_32 used
2016-01-14 19:07:27 +03:00
Nekotekina 83084467c6 For #1356 2016-01-14 19:07:26 +03:00
Nekotekina 8464ab6a23 Fixes (#1432)
/dev_bdvd/, rap file loading fix
2016-01-14 19:07:24 +03:00
raven02 74ec128e62 Use CELL_GCM_TEXTURE_CONVOLUTION_MAG for Mag 4 2016-01-14 19:00:16 +03:00
vlj 194c6b8bee Merge pull request #1431 from vlj/gl
gl: Fix warnings and enable treat warning as error.
2016-01-14 00:28:19 +01:00
Vincent Lejeune 69272edba6 gl: Fix warnings and enable trat warning as error. 2016-01-13 23:53:11 +01:00
Nekotekina 38531459df Logging system rewritten
GUI doesn't freeze anymore
Some things simplified
2016-01-13 18:54:57 +03:00
Nekotekina b3e3c68f15 File utility improved
+ minor fixes
2016-01-13 14:12:04 +03:00
B1ackDaemon 5029dff73a Merge pull request #1428 from vlj/rsx
rsx/common/d3d12: Consider separate index range as a whole.
2016-01-13 02:08:23 +02:00
Vincent Lejeune 689dee9944 rsx/common/d3d12: Consider separate index range as a whole.
Fix Wolf of the Battlefield 3
2016-01-13 00:28:48 +01:00
B1ackDaemon 68f9898171 Merge pull request #1415 from vlj/d3d12
D3d12: Factoring
2016-01-12 00:52:45 +02:00
Vincent Lejeune 08622a41b4 d3d12: Use CHECK_HRESULT in D3D12Utils.cpp 2016-01-11 21:17:33 +01:00
Vincent Lejeune 669a3277ff d3d12: Support mag filter 4 2016-01-11 21:17:32 +01:00
Vincent Lejeune e6bd681227 d3d12: factorize render_target code in a template class to be shared with others backends. 2016-01-11 20:47:01 +01:00
Vincent Lejeune 0c5cfdddba d3d12: Gather constant and vtx/idx heap and turn readback heap to buffer 2016-01-11 20:46:58 +01:00
vlj d08ce79d04 Merge pull request #1417 from vlj/rsx
rsx/common/d3d12/gl: Clean ProgramStateCache
2016-01-11 19:45:19 +01:00
Vincent Lejeune bab52c132d rsx/common/d3d12/gl: Clean ProgramStateCache
Use a_b_c format.
Use using =
Use tuple as output
Use RAII to delete program safely
Ensure const correctness.
2016-01-11 19:21:57 +01:00
DHrpcs3 cc1efd2a46 Merge pull request #1419 from RPCS3/minor_fixes
Minor fixes
2016-01-11 00:20:30 +02:00
DHrpcs3 8297d963bf d3d12 texture cache: align to bottom texture address 2016-01-10 23:28:30 +02:00
DHrpcs3 a17c41b4e1 nv4097::get_report: use DMA 2016-01-10 23:22:55 +02:00
B1ackDaemon b055747d4f Merge pull request #1414 from vlj/rsx
Rsx: Fix for vertex buffer filling and for some non IEEE compliant fragment instructions.
2016-01-10 02:44:29 +02:00
Vincent Lejeune 4ef76866a5 rsx/common/d3d12/gl: Support texture lod sampling. 2016-01-10 00:16:26 +01:00
Vincent Lejeune 675ccd4510 rsx/common/d3d12/gl: Mimic divsq and rsq fragment instruction behaviour with 0.
Fix Super Puzzle Turbo HD 2 and SH3 HD
2016-01-09 23:18:05 +01:00
Vincent Lejeune 31a925b4f0 rsx: reenable frame capture
Likely commented out by accident.
2016-01-09 23:18:04 +01:00
Vincent Lejeune d153575e59 rsx/common/d3d12/gl: Support for CMP/non pow of 2 size vertex formats.
Also use class enum for base_vertex_type everywhere.
Fix Bomberman Ultra color and Cubixx HD geometry.
2016-01-09 23:18:03 +01:00
Raul Tambre 3afc62e525 Fix #1368 2016-01-08 08:39:34 +02:00
Raul Tambre f8446b227b Implement inet_ntop and CELL_NET_CTL_INFO_LINK
Also fixed the default address not being set for all cases. Also tried
to fix the Win32 version of CELL_NET_CTL_INFO_IP_ADDRESS failing the
first time around.
2016-01-08 08:39:34 +02:00
Raul Tambre 8f937bda0f Various minor logging improvements
Also changed the default connection state, because chances are, that
you're connected to Internet.
2016-01-08 08:39:33 +02:00
vlj 9d1208bf95 Merge pull request #1394 from vlj/build
Add Guidelines Support Library
2016-01-08 02:09:05 +01:00
Vincent Lejeune e7591439f4 Add Guidelines Support Library 2016-01-08 00:59:08 +01:00
vlj fef0b1dd46 Merge pull request #1409 from vlj/fix-mention-bot
Hopefully fix mention bot's ignore list
2016-01-08 00:51:29 +01:00
Raul Tambre 3281a1982e Hopefully fix mention bot's ignore list 2016-01-07 23:46:32 +01:00
DHrpcs3 b8486a489d Merge pull request #1406 from RPCS3/minor_fixes
Minor fixes
2016-01-07 22:02:35 +02:00
DHrpcs3 f97d791fe8 PSF loader: implemented 0x0004 entry format 2016-01-07 21:22:36 +02:00
DHrpcs3 657a6c9511 elf64 loader: fixed too small primary stack size usage 2016-01-07 18:14:15 +02:00
Anthony J. Bentley aa4fb80465 By definition, malloc() is available in stdlib.h. malloc.h is deprecated. 2015-12-20 03:20:48 -07:00
280 changed files with 9163 additions and 7706 deletions
+6
View File
@@ -19,3 +19,9 @@
[submodule "rsx_program_decompiler"]
path = rsx_program_decompiler
url = https://github.com/RPCS3/rsx_program_decompiler
[submodule "GSL"]
path = GSL
url = https://github.com/Microsoft/GSL.git
[submodule "libpng"]
path = libpng
url = https://github.com/RPCS3/libpng
+1 -1
View File
@@ -1,3 +1,3 @@
{
"userBlacklist": [AlexAltea]
"userBlacklist": ["AlexAltea"]
}
+9 -5
View File
@@ -33,11 +33,13 @@ git:
before_install:
# shutdown services on Travis, which may have a memory impact
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then
echo "yes" | sudo apt-add-repository 'deb http://repos.codelite.org/wx3.0/ubuntu/ precise universe';
sudo apt-get install libwxgtk3.0-dev;
sudo apt-add-repository -y ppa:libreoffice/ppa;
sudo apt-get update;
sudo apt-get install libglew-dev;
fi;
- if [ "$TRAVIS_OS_NAME" = "linux" ] && [ "$CXX" = "g++" ]; then
export CXX="g++-4.9" CC="gcc-4.9" CXXFLAGS="-Wno-format-security";
export CXX="g++-5" CC="gcc-5" CXXFLAGS="-Wno-format-security";
export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01';
elif [ "$TRAVIS_OS_NAME" = "linux" ]; then
export CXX="clang++-3.6" CC="clang-3.6";
@@ -51,7 +53,7 @@ before_install:
fi;
before_script:
- git submodule update --init asmjit ffmpeg rsx_program_decompiler
- git submodule update --init asmjit ffmpeg rsx_program_decompiler GSL libpng
- mkdir build
- cd build
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then cmake ..; else cmake .. -DLLVM_DIR=/usr/local/opt/llvm36/lib/llvm-3.6/share/llvm/cmake; fi
@@ -73,15 +75,17 @@ addons:
- cmake
- libopenal-dev
- freeglut3-dev
- libglew-dev
# - libglew-dev apt version is too old
- libc6-dev
- llvm-3.6
- llvm-3.6-dev
- libedit-dev
- g++-4.9
- g++-5
- gcc-5
- clang-3.6
- libstdc++-4.8-dev
- lib32stdc++6
- zlib1g-dev
coverity_scan:
project:
name: $TRAVIS_REPO_SLUG
+5
View File
@@ -11,7 +11,12 @@ if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message( FATAL_ERROR "RPCS3 can only be compiled on 64-bit platforms." )
endif()
# We use libpng's static library and don't need to build the shared library and run the tests
set(PNG_SHARED OFF CACHE BOOL "Build shared lib." FORCE)
set(PNG_TESTS OFF CACHE BOOL "Build tests." FORCE)
add_subdirectory( asmjit )
add_subdirectory( libpng )
# TODO: do real installation, including copying directory structure
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${PROJECT_BINARY_DIR}/bin")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${PROJECT_BINARY_DIR}/bin")
Submodule
+1
Submodule GSL added at fc5fce4f4f
+1 -1
View File
@@ -25,7 +25,7 @@ __Windows__
* [Python](https://www.python.org/downloads/) (optional, required only for LLVM build; add to PATH)
__Linux__
* GCC 4.9.0+ or Clang 3.5.0+
* GCC 5.1+ or Clang 3.5.0+
* Debian & Ubuntu: `sudo apt-get install libopenal-dev libwxgtk3.0-dev build-essential libglew-dev`
* Arch: `sudo pacman -S glew openal wxgtk cmake llvm`
+2 -2
View File
@@ -530,7 +530,7 @@ template<typename T> class se_t<T, true>
static_assert(!std::is_pointer<type>::value, "se_t<> error: invalid type (pointer)");
static_assert(!std::is_reference<type>::value, "se_t<> error: invalid type (reference)");
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
static_assert(!std::is_enum<type>::value, "se_t<> error: invalid type (enumeration), use integral type instead");
//static_assert(!std::is_enum<type>::value, "se_t<> error: invalid type (enumeration), use integral type instead");
static_assert(alignof(type) == alignof(stype), "se_t<> error: unexpected alignment");
template<typename T2, typename = void> struct bool_converter
@@ -642,7 +642,7 @@ template<typename T> class se_t<T, false>
static_assert(!std::is_pointer<type>::value, "se_t<> error: invalid type (pointer)");
static_assert(!std::is_reference<type>::value, "se_t<> error: invalid type (reference)");
static_assert(!std::is_array<type>::value, "se_t<> error: invalid type (array)");
static_assert(!std::is_enum<type>::value, "se_t<> error: invalid type (enumeration), use integral type instead");
//static_assert(!std::is_enum<type>::value, "se_t<> error: invalid type (enumeration), use integral type instead");
public:
se_t() = default;
+490 -316
View File
File diff suppressed because it is too large Load Diff
+115 -55
View File
@@ -1,15 +1,8 @@
#pragma once
enum class fsm : u32 // file seek mode
{
begin,
cur,
end,
};
namespace fom // file open mode
{
enum : u32
enum open_mode : u32
{
read = 1 << 0, // enable reading
write = 1 << 1, // enable writing
@@ -18,19 +11,18 @@ namespace fom // file open mode
trunc = 1 << 4, // clear opened file if it's not empty
excl = 1 << 5, // failure if the file already exists (used with `create`)
rewrite = write | create | trunc, // write + create + trunc
rewrite = write | create | trunc,
};
};
enum class fse : u32 // filesystem (file or dir) error
{
ok, // no error
invalid_arguments,
};
namespace fs
{
thread_local extern fse g_tls_error;
enum seek_mode : u32 // file seek mode
{
seek_set,
seek_cur,
seek_end,
};
struct stat_t
{
@@ -42,6 +34,9 @@ namespace fs
s64 ctime;
};
// Get parent directory for the path (returns empty string on failure)
std::string get_parent_dir(const std::string& path);
// Get file information
bool stat(const std::string& path, stat_t& info);
@@ -49,16 +44,16 @@ namespace fs
bool exists(const std::string& path);
// Check whether the file exists and is NOT a directory
bool is_file(const std::string& file);
bool is_file(const std::string& path);
// Check whether the directory exists and is NOT a file
bool is_dir(const std::string& dir);
bool is_dir(const std::string& path);
// Delete empty directory
bool remove_dir(const std::string& dir);
bool remove_dir(const std::string& path);
// Create directory
bool create_dir(const std::string& dir);
bool create_dir(const std::string& path);
// Create directories
bool create_path(const std::string& path);
@@ -70,10 +65,10 @@ namespace fs
bool copy_file(const std::string& from, const std::string& to, bool overwrite);
// Delete file
bool remove_file(const std::string& file);
bool remove_file(const std::string& path);
// Change file size (possibly appending zeros)
bool truncate_file(const std::string& file, u64 length);
bool truncate_file(const std::string& path, u64 length);
class file final
{
@@ -83,14 +78,15 @@ namespace fs
handle_type m_fd = null;
friend class file_ptr;
friend class file_read_map;
friend class file_write_map;
public:
file() = default;
explicit file(const std::string& filename, u32 mode = fom::read)
explicit file(const std::string& path, u32 mode = fom::read)
{
open(filename, mode);
open(path, mode);
}
file(file&& other)
@@ -120,7 +116,7 @@ namespace fs
}
// Open specified file with specified mode
bool open(const std::string& filename, u32 mode = fom::read);
bool open(const std::string& path, u32 mode = fom::read);
// Change file size (possibly appending zero bytes)
bool trunc(u64 size) const;
@@ -129,7 +125,7 @@ namespace fs
bool stat(stat_t& info) const;
// Close the file explicitly (destructor automatically closes the file)
bool close();
void close();
// Read the data from the file and return the amount of data written in buffer
u64 read(void* buffer, u64 count) const;
@@ -138,92 +134,112 @@ namespace fs
u64 write(const void* buffer, u64 count) const;
// Move file pointer
u64 seek(s64 offset, fsm seek_mode = fsm::begin) const;
u64 seek(s64 offset, seek_mode whence = seek_set) const;
// Get file size
u64 size() const;
// Write std::string
const file& operator <<(const std::string& str) const
// Write std::string unconditionally
const file& write(const std::string& str) const
{
CHECK_ASSERTION(write(str.data(), str.size()) == str.size());
return *this;
}
// Write POD
// Write POD unconditionally
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, const file&> operator <<(const T& data) const
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, const file&> write(const T& data) const
{
CHECK_ASSERTION(write(std::addressof(data), sizeof(T)) == sizeof(T));
return *this;
}
// Write POD std::vector
// Write POD std::vector unconditionally
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, const file&> operator <<(const std::vector<T>& vec) const
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, const file&> write(const std::vector<T>& vec) const
{
CHECK_ASSERTION(write(vec.data(), vec.size() * sizeof(T)) == vec.size() * sizeof(T));
return *this;
}
// Read std::string
// Read std::string, size must be set by resize() method
bool read(std::string& str) const
{
return read(&str[0], str.size()) == str.size();
}
// Read POD
// Read POD, sizeof(T) is used
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, bool> read(T& data) const
{
return read(&data, sizeof(T)) == sizeof(T);
}
// Read POD std::vector
// Read POD std::vector, size must be set by resize() method
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, bool> read(std::vector<T>& vec) const
{
return read(vec.data(), sizeof(T) * vec.size()) == sizeof(T) * vec.size();
}
// Convert to std::string
operator std::string() const
// Read POD (experimental)
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, T> read() const
{
T result;
CHECK_ASSERTION(read(result));
return result;
}
// Read full file to std::string
std::string to_string() const
{
std::string result;
result.resize(size() - seek(0, fsm::cur));
CHECK_ASSERTION(read(result));
result.resize(size());
CHECK_ASSERTION(seek(0) != -1 && read(result));
return result;
}
// Read full file to std::vector
template<typename T>
std::enable_if_t<std::is_pod<T>::value && !std::is_pointer<T>::value, std::vector<T>> to_vector() const
{
std::vector<T> result;
result.resize(size() / sizeof(T));
CHECK_ASSERTION(seek(0) != -1 && read(result));
return result;
}
};
class file_ptr final
// TODO
class file_read_map final
{
char* m_ptr = nullptr;
u64 m_size;
public:
file_ptr() = default;
file_read_map() = default;
file_ptr(file_ptr&& right)
file_read_map(file_read_map&& right)
: m_ptr(right.m_ptr)
, m_size(right.m_size)
{
right.m_ptr = 0;
}
file_ptr& operator =(file_ptr&& right)
file_read_map& operator =(file_read_map&& right)
{
std::swap(m_ptr, right.m_ptr);
std::swap(m_size, right.m_size);
return *this;
}
file_ptr(const file& f)
file_read_map(const file& f)
{
reset(f);
}
~file_ptr()
~file_read_map()
{
reset();
}
@@ -234,6 +250,52 @@ namespace fs
// Close file mapping
void reset();
// Get pointer
operator const char*() const
{
return m_ptr;
}
};
// TODO
class file_write_map final
{
char* m_ptr = nullptr;
u64 m_size;
public:
file_write_map() = default;
file_write_map(file_write_map&& right)
: m_ptr(right.m_ptr)
, m_size(right.m_size)
{
right.m_ptr = 0;
}
file_write_map& operator =(file_write_map&& right)
{
std::swap(m_ptr, right.m_ptr);
std::swap(m_size, right.m_size);
return *this;
}
file_write_map(const file& f)
{
reset(f);
}
~file_write_map()
{
reset();
}
// Open file mapping
void reset(const file& f);
// Close file mapping
void reset();
// Get pointer
operator char*() const
{
@@ -285,7 +347,7 @@ namespace fs
bool open(const std::string& dirname);
// Close the directory explicitly (destructor automatically closes the directory)
bool close();
void close();
// Get next directory entry (UTF-8 name and file stat)
bool read(std::string& name, stat_t& info);
@@ -318,18 +380,16 @@ namespace fs
return;
}
bool is_ok;
if (mode_ == mode::from_first)
{
is_ok = m_parent->first(m_entry.name, m_entry.info);
m_parent->first(m_entry.name, m_entry.info);
}
else
{
is_ok = m_parent->read(m_entry.name, m_entry.info);
m_parent->read(m_entry.name, m_entry.info);
}
if (!is_ok)
if (m_entry.name.empty())
{
m_parent = nullptr;
}
@@ -364,8 +424,8 @@ namespace fs
};
// Get configuration directory
std::string get_config_dir();
const std::string& get_config_dir();
// Get executable directory
std::string get_executable_dir();
const std::string& get_executable_dir();
}
-4
View File
@@ -35,10 +35,6 @@
#include <stdlib.h>
#include <cstdint>
#ifndef __APPLE__
#include <malloc.h>
#endif
#define _fpclass(x) std::fpclassify(x)
#define INFINITE 0xFFFFFFFF
+121 -256
View File
@@ -1,6 +1,4 @@
#include "stdafx.h"
#include <iostream>
#include <cinttypes>
#include "stdafx.h"
#include "Thread.h"
#include "File.h"
#include "Log.h"
@@ -9,277 +7,144 @@
#include <Windows.h>
#endif
using namespace Log;
std::unique_ptr<LogManager> g_log_manager;
u32 LogMessage::size() const
namespace _log
{
//1 byte for NULL terminator
return (u32)(sizeof(LogMessage::size_type) + sizeof(LogType) + sizeof(Severity) + sizeof(std::string::value_type) * mText.size() + 1);
}
void LogMessage::serialize(char *output) const
{
LogMessage::size_type size = this->size();
memcpy(output, &size, sizeof(LogMessage::size_type));
output += sizeof(LogMessage::size_type);
memcpy(output, &mType, sizeof(LogType));
output += sizeof(LogType);
memcpy(output, &mServerity, sizeof(Severity));
output += sizeof(Severity);
memcpy(output, mText.c_str(), mText.size() );
output += sizeof(std::string::value_type)*mText.size();
*output = '\0';
}
LogMessage LogMessage::deserialize(char *input, u32* size_out)
{
LogMessage msg;
LogMessage::size_type msgSize = *(reinterpret_cast<LogMessage::size_type*>(input));
input += sizeof(LogMessage::size_type);
msg.mType = *(reinterpret_cast<LogType*>(input));
input += sizeof(LogType);
msg.mServerity = *(reinterpret_cast<Severity*>(input));
input += sizeof(Severity);
if (msgSize > 9000)
logger& get_logger()
{
int wtf = 6;
// Use magic static for global logger instance
static logger instance;
return instance;
}
msg.mText.append(input, msgSize - 1 - sizeof(Severity) - sizeof(LogType));
if (size_out){(*size_out) = msgSize;}
return msg;
file_listener g_log_file(_PRGNAME_ ".log");
file_writer g_tty_file("TTY.log");
channel GENERAL("", level::notice);
channel LOADER("LDR", level::notice);
channel MEMORY("MEM", level::notice);
channel RSX("RSX", level::notice);
channel HLE("HLE", level::notice);
channel PPU("PPU", level::notice);
channel SPU("SPU", level::notice);
channel ARMv7("ARMv7");
}
LogChannel::LogChannel() : LogChannel("unknown")
{}
LogChannel::LogChannel(const std::string& name) :
name(name)
, mEnabled(true)
, mLogLevel(Severity::Warning)
{}
void LogChannel::log(const LogMessage &msg)
_log::listener::listener()
{
std::lock_guard<std::mutex> lock(mListenerLock);
for (auto &listener : mListeners)
// Register self
get_logger().add_listener(this);
}
_log::listener::~listener()
{
// Unregister self
get_logger().remove_listener(this);
}
_log::channel::channel(const std::string& name, _log::level init_level)
: name{ name }
, enabled{ init_level }
{
// TODO: register config property "name" associated with "enabled" member
}
void _log::logger::add_listener(_log::listener* listener)
{
std::lock_guard<shared_mutex> lock(m_mutex);
m_listeners.emplace(listener);
}
void _log::logger::remove_listener(_log::listener* listener)
{
std::lock_guard<shared_mutex> lock(m_mutex);
m_listeners.erase(listener);
}
void _log::logger::broadcast(const _log::channel& ch, _log::level sev, const std::string& text) const
{
reader_lock lock(m_mutex);
for (auto listener : m_listeners)
{
listener->log(msg);
listener->log(ch, sev, text);
}
}
void LogChannel::addListener(std::shared_ptr<LogListener> listener)
void _log::broadcast(const _log::channel& ch, _log::level sev, const std::string& text)
{
std::lock_guard<std::mutex> lock(mListenerLock);
mListeners.insert(listener);
}
void LogChannel::removeListener(std::shared_ptr<LogListener> listener)
{
std::lock_guard<std::mutex> lock(mListenerLock);
mListeners.erase(listener);
get_logger().broadcast(ch, sev, text);
}
struct CoutListener : LogListener
_log::file_writer::file_writer(const std::string& name)
{
void log(const LogMessage &msg) override
try
{
std::cerr << msg.mText << std::endl;
}
};
struct FileListener : LogListener
{
fs::file mFile;
bool mPrependChannelName;
FileListener(const std::string& name = _PRGNAME_ ".log", bool prependChannel = true)
: mFile(fs::get_config_dir() + name, fom::rewrite)
, mPrependChannelName(prependChannel)
{
if (!mFile)
if (!m_file.open(fs::get_config_dir() + name, fom::rewrite | fom::append))
{
throw EXCEPTION("Can't create log file %s (error %d)", name, errno);
}
}
catch (const fmt::exception& e)
{
#ifdef _WIN32
MessageBoxA(0, ("Can't create log file: " + name).c_str(), "Error", MB_ICONERROR);
MessageBoxA(0, e.what(), "_log::file_writer() failed", MB_ICONERROR);
#else
std::printf("Can't create log file: %s\n", name.c_str());
#endif
}
}
void log(const LogMessage &msg) override
{
std::string text = msg.mText;
if (mPrependChannelName)
{
text.insert(0, gTypeNameTable[static_cast<u32>(msg.mType)].mName);
if (msg.mType == Log::TTY)
{
text = fmt::escape(text);
if (text[text.length() - 1] != '\n')
{
text += '\n';
}
}
}
mFile << text;
}
};
LogManager::LogManager()
#ifdef BUFFERED_LOGGING
: mExiting(false), mLogConsumer()
#endif
{
auto it = mChannels.begin();
std::shared_ptr<LogListener> listener(new FileListener());
for (const LogTypeName& name : gTypeNameTable)
{
it->name = name.mName;
it->addListener(listener);
it++;
}
std::shared_ptr<LogListener> TTYListener(new FileListener("TTY.log", false));
getChannel(TTY).addListener(TTYListener);
#ifdef BUFFERED_LOGGING
mLogConsumer = std::thread(&LogManager::consumeLog, this);
#endif
}
LogManager::~LogManager()
{
#ifdef BUFFERED_LOGGING
mExiting = true;
mBufferReady.notify_all();
mLogConsumer.join();
}
void LogManager::consumeLog()
{
std::unique_lock<std::mutex> lock(mStatusMut);
while (!mExiting)
{
mBufferReady.wait(lock);
mBuffer.lockGet();
size_t size = mBuffer.size();
std::vector<char> local_messages(size);
mBuffer.popN(&local_messages.front(), size);
mBuffer.unlockGet();
u32 cursor = 0;
u32 removed = 0;
while (cursor < size)
{
Log::LogMessage msg = Log::LogMessage::deserialize(local_messages.data() + cursor, &removed);
cursor += removed;
getChannel(msg.mType).log(msg);
}
}
#endif
}
void LogManager::log(LogMessage msg)
{
//don't do any formatting changes or filtering to the TTY output since we
//use the raw output to do diffs with the output of a real PS3 and some
//programs write text in single bytes to the console
if (msg.mType != TTY)
{
std::string prefix;
switch (msg.mServerity)
{
case Severity::Success:
prefix = "S ";
break;
case Severity::Notice:
prefix = "! ";
break;
case Severity::Warning:
prefix = "W ";
break;
case Severity::Error:
prefix = "E ";
break;
}
if (auto thr = thread_ctrl::get_current())
{
prefix += "{" + thr->get_name() + "} ";
}
msg.mText.insert(0, prefix);
msg.mText.append(1,'\n');
}
#ifdef BUFFERED_LOGGING
size_t size = msg.size();
std::vector<char> temp_buffer(size);
msg.serialize(temp_buffer.data());
mBuffer.pushRange(temp_buffer.begin(), temp_buffer.end());
mBufferReady.notify_one();
#else
mChannels[static_cast<u32>(msg.mType)].log(msg);
#endif
}
void LogManager::addListener(std::shared_ptr<LogListener> listener)
{
for (auto& channel : mChannels)
{
channel.addListener(listener);
}
}
void LogManager::removeListener(std::shared_ptr<LogListener> listener)
{
for (auto& channel : mChannels)
{
channel.removeListener(listener);
}
}
LogManager& LogManager::getInstance()
{
if (!g_log_manager)
{
g_log_manager.reset(new LogManager());
}
return *g_log_manager;
}
LogChannel &LogManager::getChannel(LogType type)
{
return mChannels[static_cast<u32>(type)];
}
void log_message(Log::LogType type, Log::Severity sev, const char* text)
{
log_message(type, sev, std::string(text));
}
void log_message(Log::LogType type, Log::Severity sev, std::string text)
{
if (g_log_manager)
{
g_log_manager->log({ type, sev, std::move(text) });
}
else
{
const auto severity =
sev == Severity::Notice ? "Notice" :
sev == Severity::Warning ? "Warning" :
sev == Severity::Success ? "Success" :
sev == Severity::Error ? "Error" : "Unknown";
#ifdef _WIN32
MessageBoxA(0, text.c_str(), severity,
sev == Severity::Notice ? MB_ICONINFORMATION :
sev == Severity::Warning ? MB_ICONEXCLAMATION :
sev == Severity::Error ? MB_ICONERROR : MB_ICONINFORMATION);
#else
std::printf("[Log:%s] %s\n", severity, text.c_str());
std::printf("_log::file_writer() failed: %s\n", e.what());
#endif
}
}
void _log::file_writer::log(const std::string& text)
{
m_file.write(text);
}
std::size_t _log::file_writer::size() const
{
return m_file.seek(0, fs::seek_cur);
}
void _log::file_listener::log(const _log::channel& ch, _log::level sev, const std::string& text)
{
std::string msg; msg.reserve(text.size() + 200);
// Used character: U+00B7 (Middle Dot)
switch (sev)
{
case level::always: msg = u8"·A "; break;
case level::fatal: msg = u8"·F "; break;
case level::error: msg = u8"·E "; break;
case level::todo: msg = u8"·U "; break;
case level::success: msg = u8"·S "; break;
case level::warning: msg = u8"·W "; break;
case level::notice: msg = u8"·! "; break;
case level::trace: msg = u8"·T "; break;
}
// TODO: print time?
if (auto t = thread_ctrl::get_current())
{
msg += '{';
msg += t->get_name();
msg += "} ";
}
if (ch.name.size())
{
msg += ch.name;
msg += sev == level::todo ? " TODO: " : ": ";
}
else if (sev == level::todo)
{
msg += "TODO: ";
}
msg += text;
msg += '\n';
file_writer::log(msg);
}
+127 -106
View File
@@ -1,134 +1,155 @@
#pragma once
#include "Utilities/MTRingbuffer.h"
//#define BUFFERED_LOGGING 1
#include "SharedMutex.h"
//first parameter is of type Log::LogType and text is of type std::string
#define LOG_SUCCESS(logType, text, ...) log_message(logType, Log::Severity::Success, text, ##__VA_ARGS__)
#define LOG_NOTICE(logType, text, ...) log_message(logType, Log::Severity::Notice, text, ##__VA_ARGS__)
#define LOG_WARNING(logType, text, ...) log_message(logType, Log::Severity::Warning, text, ##__VA_ARGS__)
#define LOG_ERROR(logType, text, ...) log_message(logType, Log::Severity::Error, text, ##__VA_ARGS__)
namespace Log
namespace _log
{
const unsigned int MAX_LOG_BUFFER_LENGTH = 1024*1024;
const unsigned int gBuffSize = 1000;
enum LogType : u32
enum class level : uint
{
GENERAL = 0,
LOADER,
MEMORY,
RSX,
HLE,
PPU,
SPU,
ARMv7,
TTY,
always, // highest level (unused, cannot be disabled)
fatal,
error,
todo,
success,
warning,
notice,
trace, // lowest level (usually disabled)
};
struct channel;
struct listener;
struct LogTypeName
// Log manager
class logger final
{
LogType mType;
std::string mName;
mutable shared_mutex m_mutex;
std::set<listener*> m_listeners;
public:
// Register listener
void add_listener(listener* listener);
// Unregister listener
void remove_listener(listener* listener);
// Send log message to all listeners
void broadcast(const channel& ch, level sev, const std::string& text) const;
};
//well I'd love make_array() but alas manually counting is not the end of the world
static const std::array<LogTypeName, 9> gTypeNameTable = { {
{ GENERAL, "G: " },
{ LOADER, "LDR: " },
{ MEMORY, "MEM: " },
{ RSX, "RSX: " },
{ HLE, "HLE: " },
{ PPU, "PPU: " },
{ SPU, "SPU: " },
{ ARMv7, "ARM: " },
{ TTY, "TTY: " }
} };
// Send log message to global logger instance
void broadcast(const channel& ch, level sev, const std::string& text);
enum class Severity : u32
// Log channel (source)
struct channel
{
Notice = 0,
Warning,
Success,
Error,
// Channel prefix (also used for identification)
const std::string name;
// The lowest logging level enabled for this channel (used for early filtering)
std::atomic<level> enabled;
// Initialization (max level enabled by default)
channel(const std::string& name, level = level::trace);
virtual ~channel() = default;
// Log without formatting
force_inline void log(level sev, const std::string& text) const
{
if (sev <= enabled)
broadcast(*this, sev, text);
}
// Log with formatting
template<typename... Args>
force_inline safe_buffers void format(level sev, const char* fmt, const Args&... args) const
{
if (sev <= enabled)
broadcast(*this, sev, fmt::format(fmt, fmt::do_unveil(args)...));
}
#define GEN_LOG_METHOD(_sev)\
template<typename... Args>\
force_inline void _sev(const char* fmt, const Args&... args)\
{\
return format<Args...>(level::_sev, fmt, args...);\
}
GEN_LOG_METHOD(fatal)
GEN_LOG_METHOD(error)
GEN_LOG_METHOD(todo)
GEN_LOG_METHOD(success)
GEN_LOG_METHOD(warning)
GEN_LOG_METHOD(notice)
GEN_LOG_METHOD(trace)
#undef GEN_LOG_METHOD
};
struct LogMessage
// Log listener (destination)
struct listener
{
using size_type = u32;
LogType mType;
Severity mServerity;
std::string mText;
listener();
virtual ~listener();
u32 size() const;
void serialize(char *output) const;
static LogMessage deserialize(char *input, u32* size_out=nullptr);
virtual void log(const channel& ch, level sev, const std::string& text) = 0;
};
struct LogListener
class file_writer
{
virtual ~LogListener() {};
virtual void log(const LogMessage &msg) = 0;
// Could be memory-mapped file
fs::file m_file;
public:
file_writer(const std::string& name);
virtual ~file_writer() = default;
// Append raw data
void log(const std::string& text);
// Get current file size (may be used by secondary readers)
std::size_t size() const;
};
struct LogChannel
struct file_listener : public file_writer, public listener
{
LogChannel();
LogChannel(const std::string& name);
LogChannel(LogChannel& other) = delete;
void log(const LogMessage &msg);
void addListener(std::shared_ptr<LogListener> listener);
void removeListener(std::shared_ptr<LogListener> listener);
std::string name;
private:
bool mEnabled;
Severity mLogLevel;
std::mutex mListenerLock;
std::set<std::shared_ptr<LogListener>> mListeners;
file_listener(const std::string& name)
: file_writer(name)
, listener()
{
}
// Encode level, current thread name, channel name and write log message
virtual void log(const channel& ch, level sev, const std::string& text) override;
};
struct LogManager
{
LogManager();
~LogManager();
static LogManager& getInstance();
LogChannel& getChannel(LogType type);
void log(LogMessage msg);
void addListener(std::shared_ptr<LogListener> listener);
void removeListener(std::shared_ptr<LogListener> listener);
#ifdef BUFFERED_LOGGING
void consumeLog();
#endif
private:
#ifdef BUFFERED_LOGGING
MTRingbuffer<char, MAX_LOG_BUFFER_LENGTH> mBuffer;
std::condition_variable mBufferReady;
std::mutex mStatusMut;
std::atomic<bool> mExiting;
std::thread mLogConsumer;
#endif
std::array<LogChannel, std::tuple_size<decltype(gTypeNameTable)>::value> mChannels;
//std::array<LogChannel,gTypeNameTable.size()> mChannels; //TODO: use this once Microsoft sorts their shit out
};
// Global variable for RPCS3.log
extern file_listener g_log_file;
// Global variable for TTY.log
extern file_writer g_tty_file;
// Small set of predefined channels:
extern channel GENERAL;
extern channel LOADER;
extern channel MEMORY;
extern channel RSX;
extern channel HLE;
extern channel PPU;
extern channel SPU;
extern channel ARMv7;
}
static struct { inline operator Log::LogType() { return Log::LogType::GENERAL; } } GENERAL;
static struct { inline operator Log::LogType() { return Log::LogType::LOADER; } } LOADER;
static struct { inline operator Log::LogType() { return Log::LogType::MEMORY; } } MEMORY;
static struct { inline operator Log::LogType() { return Log::LogType::RSX; } } RSX;
static struct { inline operator Log::LogType() { return Log::LogType::HLE; } } HLE;
static struct { inline operator Log::LogType() { return Log::LogType::PPU; } } PPU;
static struct { inline operator Log::LogType() { return Log::LogType::SPU; } } SPU;
static struct { inline operator Log::LogType() { return Log::LogType::ARMv7; } } ARMv7;
static struct { inline operator Log::LogType() { return Log::LogType::TTY; } } TTY;
// Legacy:
void log_message(Log::LogType type, Log::Severity sev, const char* text);
void log_message(Log::LogType type, Log::Severity sev, std::string text);
template<typename... Args> never_inline void log_message(Log::LogType type, Log::Severity sev, const char* fmt, Args... args)
{
log_message(type, sev, fmt::format(fmt, fmt::do_unveil(args)...));
}
#define LOG_SUCCESS(ch, fmt, ...) _log::ch.success(fmt, ##__VA_ARGS__)
#define LOG_NOTICE(ch, fmt, ...) _log::ch.notice (fmt, ##__VA_ARGS__)
#define LOG_WARNING(ch, fmt, ...) _log::ch.warning(fmt, ##__VA_ARGS__)
#define LOG_ERROR(ch, fmt, ...) _log::ch.error (fmt, ##__VA_ARGS__)
#define LOG_TODO(ch, fmt, ...) _log::ch.todo (fmt, ##__VA_ARGS__)
#define LOG_TRACE(ch, fmt, ...) _log::ch.trace (fmt, ##__VA_ARGS__)
#define LOG_FATAL(ch, fmt, ...) _log::ch.fatal (fmt, ##__VA_ARGS__)
-155
View File
@@ -1,155 +0,0 @@
#pragma once
//Simple non-resizable FIFO Ringbuffer that can be simultaneously be read from and written to
//if we ever get to use boost please replace this with boost::circular_buffer, there's no reason
//why we would have to keep this amateur attempt at such a fundamental data-structure around
template< typename T, unsigned int MAX_MTRINGBUFFER_BUFFER_SIZE>
class MTRingbuffer{
std::array<T, MAX_MTRINGBUFFER_BUFFER_SIZE> mBuffer;
//this is a recursive mutex because the get methods lock it but the only
//way to be sure that they do not block is to check the size and the only
//way to check the size and use get atomically is to lock this mutex,
//so it goes:
//lock get mutex-->check size-->call get-->lock get mutex-->unlock get mutex-->return from get-->unlock get mutex
std::recursive_mutex mMutGet;
std::mutex mMutPut;
size_t mGet;
size_t mPut;
size_t moveGet(size_t by = 1){ return (mGet + by) % MAX_MTRINGBUFFER_BUFFER_SIZE; }
size_t movePut(size_t by = 1){ return (mPut + by) % MAX_MTRINGBUFFER_BUFFER_SIZE; }
public:
MTRingbuffer() : mGet(0), mPut(0){}
//blocks until there's something to get, so check "spaceLeft()" if you want to avoid blocking
//also lock the get mutex around the spaceLeft() check and the pop if you want to avoid racing
T pop()
{
std::lock_guard<std::recursive_mutex> lock(mMutGet);
while (mGet == mPut)
{
//wait until there's actually something to get
//throwing an exception might be better, blocking here is a little awkward
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
}
size_t ret = mGet;
mGet = moveGet();
return mBuffer[ret];
}
//blocks if the buffer is full until there's enough room
void push(T &putEle)
{
std::lock_guard<std::mutex> lock(mMutPut);
while (movePut() == mGet)
{
//if this is reached a lot it's time to increase the buffer size
//or implement dynamic re-sizing
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
}
mBuffer[mPut] = std::forward(putEle);
mPut = movePut();
}
bool empty()
{
return mGet == mPut;
}
//returns the amount of free places, this is the amount of actual free spaces-1
//since mGet==mPut signals an empty buffer we can't actually use the last free
//space, so we shouldn't report it as free.
size_t spaceLeft() //apparently free() is a macro definition in msvc in some conditions
{
if (mGet < mPut)
{
return mBuffer.size() - (mPut - mGet) - 1;
}
else if (mGet > mPut)
{
return mGet - mPut - 1;
}
else
{
return mBuffer.size() - 1;
}
}
size_t size()
{
//the magic -1 is the same magic 1 that is explained in the spaceLeft() function
return mBuffer.size() - spaceLeft() - 1;
}
//takes random access iterator to T
template<typename IteratorType>
void pushRange(IteratorType from, IteratorType until)
{
std::lock_guard<std::mutex> lock(mMutPut);
size_t length = until - from;
//if whatever we're trying to store is greater than the entire buffer the following loop will be infinite
assert(mBuffer.size() > length);
while (spaceLeft() < length)
{
//if this is reached a lot it's time to increase the buffer size
//or implement dynamic re-sizing
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
}
if (mPut + length <= mBuffer.size())
{
std::copy(from, until, mBuffer.begin() + mPut);
}
else
{
size_t tillEnd = mBuffer.size() - mPut;
std::copy(from, from + tillEnd, mBuffer.begin() + mPut);
std::copy(from + tillEnd, until, mBuffer.begin());
}
mPut = movePut(length);
}
//takes output iterator to T
template<typename IteratorType>
void popN(IteratorType output, size_t n)
{
std::lock_guard<std::recursive_mutex> lock(mMutGet);
//make sure we're not trying to retrieve more than is in
assert(n <= size());
peekN<IteratorType>(output, n);
mGet = moveGet(n);
}
//takes output iterator to T
template<typename IteratorType>
void peekN(IteratorType output, size_t n)
{
size_t lGet = mGet;
if (lGet + n <= mBuffer.size())
{
std::copy_n(mBuffer.begin() + lGet, n, output);
}
else
{
auto next = std::copy(mBuffer.begin() + lGet, mBuffer.end(), output);
std::copy_n(mBuffer.begin(), n - (mBuffer.size() - lGet), next);
}
}
//well this is just asking for trouble
//but the comment above the declaration of mMutGet explains why it's there
//if there's a better way please remove this
void lockGet()
{
mMutGet.lock();
}
//well this is just asking for trouble
//but the comment above the declaration of mMutGet explains why it's there
//if there's a better way please remove this
void unlockGet()
{
mMutGet.unlock();
}
};
+7 -6
View File
@@ -155,19 +155,19 @@ namespace fmt
}
};
template<> struct unveil<char*, false>
template<> struct unveil<const char*, false>
{
using result_type = const char*;
using result_type = const char* const;
force_inline static result_type get_value(const char* arg)
force_inline static result_type get_value(const char* const& arg)
{
return arg;
}
};
template<std::size_t N> struct unveil<const char[N], false>
template<std::size_t N> struct unveil<char[N], false>
{
using result_type = const char*;
using result_type = const char* const;
force_inline static result_type get_value(const char(&arg)[N])
{
@@ -220,7 +220,8 @@ namespace fmt
// vm::ptr, vm::bptr, ... (fmt::do_unveil) (vm_ptr.h) (with appropriate address type, using .addr() can be avoided)
// vm::ref, vm::bref, ... (fmt::do_unveil) (vm_ref.h)
//
template<typename... Args> safe_buffers std::string format(const char* fmt, Args... args)
template<typename... Args>
safe_buffers std::string format(const char* fmt, const Args&... args)
{
// fixed stack buffer for the first attempt
std::array<char, 4096> fixed_buf;
+48 -41
View File
@@ -19,7 +19,7 @@
#include <ucontext.h>
#endif
void report_fatal_error(const std::string& msg)
static void report_fatal_error(const std::string& msg)
{
#ifdef _WIN32
const auto& text = msg + "\n\nPlease report this error to the developers. Press (Ctrl+C) to copy this message.";
@@ -794,16 +794,18 @@ size_t get_x64_access_size(x64_context* context, x64_op_t op, x64_reg_t reg, siz
return d_size;
}
/**
* Callback that can be customised by GSRender backends to track memory access.
* Backends can protect memory pages and get this callback called when an access
* violation is met.
* Should return true if the backend handles the access violation.
*/
std::function<bool(u32 addr)> gfxHandler = [](u32) { return false; };
namespace rsx
{
extern std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
}
bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
{
if (rsx::g_access_violation_handler && rsx::g_access_violation_handler(addr, is_writing))
{
return true;
}
auto code = (const u8*)RIP(context);
x64_op_t op;
@@ -811,9 +813,6 @@ bool handle_access_violation(u32 addr, bool is_writing, x64_context* context)
size_t d_size;
size_t i_size;
if (gfxHandler(addr))
return true;
// decode single x64 instruction that causes memory access
decode_x64_reg_op(code, op, reg, d_size, i_size);
@@ -1148,7 +1147,7 @@ void prepare_throw_access_violation(x64_context* context, const char* cause, u32
#ifdef _WIN32
const auto g_exception_handler = AddVectoredExceptionHandler(1, [](PEXCEPTION_POINTERS pExp) -> LONG
static LONG exception_handler(PEXCEPTION_POINTERS pExp)
{
const u64 addr64 = pExp->ExceptionRecord->ExceptionInformation[1] - (u64)vm::base(0);
const bool is_writing = pExp->ExceptionRecord->ExceptionInformation[0] != 0;
@@ -1161,9 +1160,9 @@ const auto g_exception_handler = AddVectoredExceptionHandler(1, [](PEXCEPTION_PO
{
return EXCEPTION_CONTINUE_SEARCH;
}
});
}
const auto g_exception_filter = SetUnhandledExceptionFilter([](PEXCEPTION_POINTERS pExp) -> LONG
static LONG exception_filter(PEXCEPTION_POINTERS pExp)
{
std::string msg = fmt::format("Unhandled Win32 exception 0x%08X.\n", pExp->ExceptionRecord->ExceptionCode);
@@ -1191,16 +1190,36 @@ const auto g_exception_filter = SetUnhandledExceptionFilter([](PEXCEPTION_POINTE
}
}
msg += fmt::format("Instruction address: %p.\n", pExp->ContextRecord->Rip);
msg += fmt::format("Image base: %p.", GetModuleHandle(NULL));
// TODO: print registers and the callstack
// Report fatal error
report_fatal_error(msg);
return EXCEPTION_CONTINUE_SEARCH;
});
}
const bool g_exception_handler_set = []() -> bool
{
if (!AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)exception_handler))
{
report_fatal_error("AddVectoredExceptionHandler() failed.");
std::abort();
}
if (!SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)exception_filter))
{
report_fatal_error("SetUnhandledExceptionFilter() failed.");
std::abort();
}
return true;
}();
#else
void signal_handler(int sig, siginfo_t* info, void* uct)
static void signal_handler(int sig, siginfo_t* info, void* uct)
{
x64_context* context = (ucontext_t*)uct;
@@ -1230,17 +1249,21 @@ void signal_handler(int sig, siginfo_t* info, void* uct)
}
}
int setup_signal_handler()
const bool g_exception_handler_set = []() -> bool
{
struct sigaction sa;
struct ::sigaction sa;
sa.sa_flags = SA_SIGINFO;
sigemptyset(&sa.sa_mask);
sa.sa_sigaction = signal_handler;
return sigaction(SIGSEGV, &sa, NULL);
}
const int g_sigaction_result = setup_signal_handler();
if (::sigaction(SIGSEGV, &sa, NULL) == -1)
{
std::printf("sigaction() failed (0x%x).", errno);
std::abort();
}
return true;
}();
#endif
@@ -1253,16 +1276,6 @@ void thread_ctrl::initialize()
{
SetCurrentThreadDebugName(g_tls_this_thread->m_name().c_str());
#ifdef _WIN32
if (!g_exception_handler || !g_exception_filter)
#else
if (g_sigaction_result == -1)
#endif
{
report_fatal_error("Exception handler is not set correctly.");
std::abort();
}
// TODO
g_thread_count++;
}
@@ -1337,21 +1350,15 @@ void named_thread_t::start()
{
try
{
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(GENERAL, "Thread started");
}
LOG_TRACE(GENERAL, "Thread started");
thread->on_task();
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(GENERAL, "Thread ended");
}
LOG_TRACE(GENERAL, "Thread ended");
}
catch (const std::exception& e)
{
LOG_ERROR(GENERAL, "Exception: %s\nPlease report this to the developers.", e.what());
LOG_FATAL(GENERAL, "Exception: %s\nPlease report this to the developers.", e.what());
Emu.Pause();
}
catch (EmulationStopped)
+3 -3
View File
@@ -30,14 +30,14 @@ namespace convert
{
static bool func(const std::string& value)
{
return value == "true" ? true : false;
return value == "true" ? true : value == "false" ? false : throw std::invalid_argument(__FUNCTION__);
}
};
template<>
struct to_impl_t<std::string, char>
struct to_impl_t<std::string, signed char>
{
static std::string func(char value)
static std::string func(signed char value)
{
return std::to_string(value);
}
-1
View File
@@ -10,7 +10,6 @@
#ifndef _WIN32
#include <dirent.h>
#include <errno.h>
#endif
#include "rPlatform.h"
+5 -3
View File
@@ -14,10 +14,11 @@ branches:
before_build:
# until git for win 2.5 release with commit checkout
- git submodule update --init ffmpeg asmjit minidx9 rsx_program_decompiler
- git submodule update --init ffmpeg asmjit minidx9 rsx_program_decompiler GSL libpng
- 7z x wxWidgets.7z -aos -oC:\rpcs3\wxWidgets > null
- if %configuration%==Release (cmake -G "Visual Studio 14 Win64")
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 14 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/share/llvm/cmake)
- 7z x zlib.7z -aos -oC:\rpcs3\ > null
- if %configuration%==Release (cmake -G "Visual Studio 14 Win64" -DZLIB_ROOT=C:/rpcs3/zlib/)
else (7z x llvmlibs.7z -aos -oC:\rpcs3 > null && cmake -G "Visual Studio 14 Win64" -DLLVM_DIR=C:/rpcs3/llvm_build/share/llvm/cmake -DZLIB_ROOT=C:/rpcs3/zlib/)
build_script:
- cmake --build . --config Release -- /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
@@ -25,6 +26,7 @@ build_script:
install:
- ps: Start-FileDownload 'https://402331b94f8e4b87ae2ef4677347f7956cf3861f.googledrive.com/host/0B6v_qtb9hkicfmt0NG0wTTRtUmF4X3VTQk5Oc2JidEVKVnUteDA1dXdrYlNsVW9kREpsSHc/wxWidgets.7z'
- ps: Start-FileDownload 'https://402331b94f8e4b87ae2ef4677347f7956cf3861f.googledrive.com/host/0B6v_qtb9hkicfmt0NG0wTTRtUmF4X3VTQk5Oc2JidEVKVnUteDA1dXdrYlNsVW9kREpsSHc/llvmlibs.7z'
- ps: Start-FileDownload 'https://402331b94f8e4b87ae2ef4677347f7956cf3861f.googledrive.com/host/0B6v_qtb9hkicfmt0NG0wTTRtUmF4X3VTQk5Oc2JidEVKVnUteDA1dXdrYlNsVW9kREpsSHc/zlib.7z'
- set WXWIN=C:\rpcs3\wxWidgets
- set OPENALDIR=C:\rpcs3\OpenAL
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;C:\wxWidgets;%PATH%
+35 -45
View File
@@ -1,10 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug - LLVM|x64">
<Configuration>Debug - LLVM</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug - MemLeak|x64">
<Configuration>Debug - MemLeak</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release - LLVM|x64">
<Configuration>Release - LLVM</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
@@ -71,64 +83,42 @@
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<PropertyGroup Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\rpcs3_default.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="..\rpcs3_debug.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'" Label="PropertySheets">
<Import Project="..\rpcs3_debug.props" />
<Import Project="..\rpcs3_memleak.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'" Label="PropertySheets">
<Import Project="..\rpcs3_debug.props" />
<Import Project="..\rpcs3_llvm.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="..\rpcs3_release.props" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'" Label="PropertySheets">
<Import Project="..\rpcs3_release.props" />
<Import Project="..\rpcs3_llvm.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>
</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>
</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ItemDefinitionGroup>
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>ASMJIT_STATIC;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<PreprocessorDefinitions>ASMJIT_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>false</SDLCheck>
<PreprocessorDefinitions>ASMJIT_STATIC;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
Submodule
+1
Submodule libpng added at ea77a6fd49
+6 -24
View File
@@ -44,50 +44,32 @@
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\</OutDir>
<IncludePath>.\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include;$(UniversalCRT_IncludePath);..\minidx9\Include;..\minidx12\Include</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)bin\</OutDir>
<IncludePath>.\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;.\OpenAL\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include;$(UniversalCRT_IncludePath);..\minidx9\Include;..\minidx12\Include</IncludePath>
</PropertyGroup>
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\rpcs3_default.props" />
</ImportGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\;..\rpcs3;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;..\OpenAL\libs\Win64;..\ffmpeg\Windows\x86_64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>Use</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>..\;..\rpcs3;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;..\OpenAL\libs\Win64;..\ffmpeg\Windows\x86_64\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
+48 -17
View File
@@ -17,6 +17,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
{97FDAB45-9C58-5BC5-A2F4-EE42739EBC63} = {97FDAB45-9C58-5BC5-A2F4-EE42739EBC63}
{A1A8355B-0988-528E-9CC2-B971D6266669} = {A1A8355B-0988-528E-9CC2-B971D6266669}
{09F2F96A-1CC6-5E43-AF1D-956EC2A4888D} = {09F2F96A-1CC6-5E43-AF1D-956EC2A4888D}
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {D6973076-9317-4EF2-A0B8-B7A18AC0713E}
{8B867186-A0B5-5479-B824-E176EDD27C40} = {8B867186-A0B5-5479-B824-E176EDD27C40}
{87B42A9C-3F5C-53D7-9017-2B1CAE39457D} = {87B42A9C-3F5C-53D7-9017-2B1CAE39457D}
{8BC303AB-25BE-4276-8E57-73F171B2D672} = {8BC303AB-25BE-4276-8E57-73F171B2D672}
@@ -139,12 +140,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xrc", "wxWidgets\build\msw\
{24C45343-FD20-5C92-81C1-35A2AE841E79} = {24C45343-FD20-5C92-81C1-35A2AE841E79}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "stblib", "stblib", "{9D839DFB-76E6-4F10-8EED-BA2AC7CC3FB6}"
ProjectSection(SolutionItems) = preProject
stblib\stb_image.c = stblib\stb_image.c
stblib\stb_image.h = stblib\stb_image.h
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ribbon", "wxWidgets\build\msw\wx_ribbon.vcxproj", "{87B42A9C-3F5C-53D7-9017-2B1CAE39457D}"
ProjectSection(ProjectDependencies) = postProject
{24C45343-FD20-5C92-81C1-35A2AE841E79} = {24C45343-FD20-5C92-81C1-35A2AE841E79}
@@ -181,8 +176,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_custom_build", "wxWidgets\
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "copy_setup_h", "rpcs3\copy_setup_h.vcxproj", "{00D36322-6188-4A66-B514-3B3F183E998D}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GSRender", "GSRender", "{1A43FD7A-C7DD-4D04-A4D6-FAA194AAD9D2}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "D3D12GSRender", "rpcs3\D3D12GSRender.vcxproj", "{FAC9B17B-F4B8-4B75-8AEB-C8C7CB92B078}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3-tests", "rpcs3-tests\rpcs3-tests.vcxproj", "{AB222E8A-00CA-4ACF-A87E-5251C16C0587}"
@@ -205,6 +198,17 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "XAudio", "rpcs3\XAudio.vcxp
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenAL", "rpcs3\OpenAL.vcxproj", "{30A05C4D-F5FD-421C-A864-17A64BDEAA75}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "libpng", "libpng", "{A17D34F1-7E3E-4841-818D-3B7C6F5AF829}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libpng", "libpng\projects\vstudio\libpng\libpng.vcxproj", "{D6973076-9317-4EF2-A0B8-B7A18AC0713E}"
ProjectSection(ProjectDependencies) = postProject
{60F89955-91C6-3A36-8000-13C592FEC2DF} = {60F89955-91C6-3A36-8000-13C592FEC2DF}
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "zlib", "zlib", "{F0C19EFA-EDD0-43F2-97C1-18E865E96B4E}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zlib", "libpng\projects\vstudio\zlib\zlib.vcxproj", "{60F89955-91C6-3A36-8000-13C592FEC2DF}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug - LLVM|x64 = Debug - LLVM|x64
@@ -539,18 +543,18 @@ Global
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release - LLVM|x64.Build.0 = Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.ActiveCfg = Release|x64
{74827EBD-93DC-5110-BA95-3F2AB029B6B0}.Release|x64.Build.0 = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug - MemLeak|x64.Build.0 = Debug - MemLeak|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Debug|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Debug|x64.ActiveCfg = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Debug|x64.Build.0 = Debug|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Release|x64.ActiveCfg = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.DLL Release|x64.Build.0 = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.ActiveCfg = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.Build.0 = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.ActiveCfg = Release - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.ActiveCfg = Release|x64
{AC40FF01-426E-4838-A317-66354CEFAE88}.Release|x64.Build.0 = Release|x64
{C4A10229-4712-4BD2-B63E-50D93C67A038}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
@@ -623,9 +627,7 @@ Global
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug - LLVM|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug - LLVM|x64.Build.0 = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug - MemLeak|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug - MemLeak|x64.Build.0 = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Debug|x64.Build.0 = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.DLL Debug|x64.ActiveCfg = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.DLL Debug|x64.Build.0 = Debug|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.DLL Release|x64.ActiveCfg = Release|x64
@@ -633,7 +635,6 @@ Global
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Release - LLVM|x64.ActiveCfg = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Release - LLVM|x64.Build.0 = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Release|x64.ActiveCfg = Release|x64
{AB222E8A-00CA-4ACF-A87E-5251C16C0587}.Release|x64.Build.0 = Release|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - LLVM|x64.ActiveCfg = Debug - LLVM|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - LLVM|x64.Build.0 = Debug - LLVM|x64
{3384223A-6D97-4799-9862-359F85312892}.Debug - MemLeak|x64.ActiveCfg = Debug - MemLeak|x64
@@ -704,6 +705,34 @@ Global
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release - LLVM|x64.Build.0 = Release - LLVM|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release|x64.ActiveCfg = Release|x64
{30A05C4D-F5FD-421C-A864-17A64BDEAA75}.Release|x64.Build.0 = Release|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - LLVM|x64.ActiveCfg = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - LLVM|x64.Build.0 = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - MemLeak|x64.ActiveCfg = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug - MemLeak|x64.Build.0 = Debug Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|x64.ActiveCfg = Debug|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Debug|x64.Build.0 = Debug|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Debug|x64.ActiveCfg = Debug|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Debug|x64.Build.0 = Debug|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Release|x64.ActiveCfg = Release|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.DLL Release|x64.Build.0 = Release|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release - LLVM|x64.ActiveCfg = Release Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release - LLVM|x64.Build.0 = Release Library|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|x64.ActiveCfg = Release|x64
{D6973076-9317-4EF2-A0B8-B7A18AC0713E}.Release|x64.Build.0 = Release|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - LLVM|x64.ActiveCfg = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - LLVM|x64.Build.0 = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - MemLeak|x64.ActiveCfg = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug - MemLeak|x64.Build.0 = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|x64.ActiveCfg = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Debug|x64.Build.0 = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Debug|x64.ActiveCfg = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Debug|x64.Build.0 = Debug Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Release|x64.ActiveCfg = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.DLL Release|x64.Build.0 = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release - LLVM|x64.ActiveCfg = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release - LLVM|x64.Build.0 = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|x64.ActiveCfg = Release Library|x64
{60F89955-91C6-3A36-8000-13C592FEC2DF}.Release|x64.Build.0 = Release Library|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -741,5 +770,7 @@ Global
{7D73447B-3D2D-4DFE-BF62-57E644C1D09F} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{78CB2F39-B809-4A06-8329-8C0A19119D3D} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{30A05C4D-F5FD-421C-A864-17A64BDEAA75} = {10FBF193-D532-4CCF-B875-4C7091A7F6C2}
{D6973076-9317-4EF2-A0B8-B7A18AC0713E} = {A17D34F1-7E3E-4841-818D-3B7C6F5AF829}
{60F89955-91C6-3A36-8000-13C592FEC2DF} = {F0C19EFA-EDD0-43F2-97C1-18E865E96B4E}
EndGlobalSection
EndGlobal
+12 -6
View File
@@ -112,6 +112,8 @@ ${LLVM_INCLUDE_DIRS}
"${RPCS3_SRC_DIR}/.."
"${RPCS3_SRC_DIR}/../asmjit/src/asmjit"
"${RPCS3_SRC_DIR}/../glm"
"${RPCS3_SRC_DIR}/../libpng"
"${RPCS3_SRC_DIR}/../GSL/include"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/rsx_decompiler"
"${RPCS3_SRC_DIR}/../rsx_program_decompiler/shader_code"
)
@@ -139,7 +141,10 @@ else()
endif()
endif()
link_directories("${RPCS3_SRC_DIR}/../asmjit/" "${RPCS3_SRC_DIR}/../minidx12/")
link_directories(
"${RPCS3_SRC_DIR}/../asmjit/"
"${RPCS3_SRC_DIR}/../minidx12/"
)
if(MSVC OR NOT WIN32)
link_directories("${RPCS3_SRC_DIR}/../ffmpeg/${PLATFORM_ARCH}/lib")
@@ -155,6 +160,7 @@ GLOB_RECURSE
RPCS3_SRC
"${RPCS3_SRC_DIR}/rpcs3.cpp"
"${RPCS3_SRC_DIR}/config.cpp"
"${RPCS3_SRC_DIR}/stb_image.cpp"
"${RPCS3_SRC_DIR}/../Utilities/GNU.cpp"
"${RPCS3_SRC_DIR}/Emu/*"
"${RPCS3_SRC_DIR}/Gui/*"
@@ -183,14 +189,14 @@ if(WIN32) # I'm not sure we need all of these libs, but we link them in vs
else()
target_link_libraries(rpcs3 dxgi.lib d2d1.lib dwrite.lib)
endif()
target_link_libraries(rpcs3 asmjit.lib avformat.lib avcodec.lib avutil.lib swresample.lib swscale.lib ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${ADDITIONAL_LIBS})
target_link_libraries(rpcs3 asmjit.lib avformat.lib avcodec.lib avutil.lib swresample.lib swscale.lib png16_static ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${ADDITIONAL_LIBS})
else()
if(LLVM_FOUND)
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES} ${LLVM_LIBS} ${ADDITIONAL_LIBS})
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a png16_static ${ZLIB_LIBRARIES} ${LLVM_LIBS} ${ADDITIONAL_LIBS})
else()
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a ${ZLIB_LIBRARIES} ${ADDITIONAL_LIBS})
target_link_libraries(rpcs3 asmjit.a ${wxWidgets_LIBRARIES} ${OPENAL_LIBRARY} ${GLEW_LIBRARY} ${OPENGL_LIBRARIES})
target_link_libraries(rpcs3 libavformat.a libavcodec.a libavutil.a libswresample.a libswscale.a png16_static ${ZLIB_LIBRARIES} ${ADDITIONAL_LIBS})
endif()
endif()
+3 -2
View File
@@ -820,7 +820,6 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
// Prepare the files.
fs::file input(input_file_name);
fs::file output(output_file_name, fom::rewrite);
fs::file rap(rap_file_name);
// Set keys (RIF and DEVKLIC).
unsigned char rifkey[0x10];
@@ -879,8 +878,10 @@ int DecryptEDAT(const std::string& input_file_name, const std::string& output_fi
}
// Read the RAP file, if provided.
if (rap)
if (rap_file_name.size())
{
fs::file rap(rap_file_name);
unsigned char rapkey[0x10];
memset(rapkey, 0, 0x10);
+1 -1
View File
@@ -62,7 +62,7 @@ bool pkg_install(const fs::file& pkg_f, const std::string& dir, volatile f64& pr
const std::size_t BUF_SIZE = 8192 * 1024; // 8 MB
// Save current file offset (probably zero)
const u64 start_offset = pkg_f.seek(0, fsm::cur);
const u64 start_offset = pkg_f.seek(0, fs::seek_cur);
// Get basic PKG information
PKGHeader header;
+4 -2
View File
@@ -942,9 +942,9 @@ bool SELFDecrypter::DecryptNPDRM(u8 *metadata, u32 metadata_size)
bool SELFDecrypter::LoadMetadata()
{
aes_context aes;
u32 metadata_info_size = sizeof32(meta_info);
u32 metadata_info_size = SIZE_32(meta_info);
u8 *metadata_info = (u8 *)malloc(metadata_info_size);
u32 metadata_headers_size = sce_hdr.se_hsize - (sizeof32(sce_hdr) + sce_hdr.se_meta + sizeof32(meta_info));
u32 metadata_headers_size = sce_hdr.se_hsize - (SIZE_32(sce_hdr) + sce_hdr.se_meta + SIZE_32(meta_info));
u8 *metadata_headers = (u8 *)malloc(metadata_headers_size);
// Locate and read the encrypted metadata info.
@@ -1330,6 +1330,8 @@ bool CheckDebugSelf(const std::string& self, const std::string& elf)
bool DecryptSelf(const std::string& elf, const std::string& self)
{
LOG_NOTICE(LOADER, "Decrypting %s", self);
// Check for a debug SELF first.
if (!CheckDebugSelf(self, elf))
{
+1 -60
View File
@@ -61,66 +61,7 @@
<Import Project="..\rpcs3_llvm.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<IntDir>$(SolutionDir)tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - MemLeak|x64'">
<Lib>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - LLVM|x64'">
<Lib>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalDependencies />
<AdditionalLibraryDirectories />
</Lib>
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Lib>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Lib>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
</Lib>
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - LLVM|x64'">
<Lib>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<AdditionalDependencies />
<AdditionalLibraryDirectories />
</Lib>
<ItemDefinitionGroup>
<ClCompile>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
+4 -4
View File
@@ -1125,7 +1125,7 @@ struct ARMv7_op2_table_t
{
if (opcode.code & ~opcode.mask)
{
LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%04x, code=0x%04x)", opcode.name, opcode.mask >> 16, opcode.code >> 16);
LOG_ERROR(ARMv7, "%s: wrong opcode mask (mask=0x%04x, code=0x%04x)", opcode.name, opcode.mask >> 16, opcode.code >> 16);
}
t2.push_back(&opcode);
@@ -1164,7 +1164,7 @@ struct ARMv7_op4t_table_t
{
if (opcode.code & ~opcode.mask)
{
LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%04x 0x%04x, code=0x%04x 0x%04x)", opcode.name, opcode.mask >> 16, (u16)opcode.mask, opcode.code >> 16, (u16)opcode.code);
LOG_ERROR(ARMv7, "%s: wrong opcode mask (mask=0x%04x 0x%04x, code=0x%04x 0x%04x)", opcode.name, opcode.mask >> 16, (u16)opcode.mask, opcode.code >> 16, (u16)opcode.code);
}
table.push_back(&opcode);
@@ -1199,7 +1199,7 @@ struct ARMv7_op4arm_table_t
{
if (opcode.code & ~opcode.mask)
{
LOG_ERROR(GENERAL, "%s: wrong opcode mask (mask=0x%08x, code=0x%08x)", opcode.name, opcode.mask, opcode.code);
LOG_ERROR(ARMv7, "%s: wrong opcode mask (mask=0x%08x, code=0x%08x)", opcode.name, opcode.mask, opcode.code);
}
table.push_back(&opcode);
@@ -1365,7 +1365,7 @@ u32 ARMv7Decoder::DecodeMemory(const u32 address)
// "group" decoding algorithm (temporarily disabled)
//execute_main_group(&m_thr);
//// LOG_NOTICE(GENERAL, "%s, %d \n\n", m_thr.m_last_instr_name, m_thr.m_last_instr_size);
//// LOG_NOTICE(ARMv7, "%s, %d \n\n", m_thr.m_last_instr_name, m_thr.m_last_instr_size);
//m_thr.m_last_instr_name = "Unknown";
//return m_thr.m_last_instr_size;
}
+1 -1
View File
@@ -2005,7 +2005,7 @@ static void execute_main_group(ARMv7Thread* thr)
case 0xe: (*g_table_0xe).func(thr, (*g_table_0xe).type); break;
case 0xf: (*g_table_0xf).func(thr, (*g_table_0xf).type); break;
default: LOG_ERROR(GENERAL, "ARMv7Decoder: unknown group 0x%x", (thr->code.code0 & 0xf000) >> 12); Emu.Pause(); break;
default: LOG_ERROR(ARMv7, "ARMv7Decoder: unknown group 0x%x", (thr->code.code0 & 0xf000) >> 12); Emu.Pause(); break;
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
#pragma once
using SceFiosOpCallback = s32(vm::ptr<void> pContext, s32 op, u8 event, s32 err);
using SceFiosVprintfCallback = s32(vm::cptr<char> fmt, va_list ap);
using SceFiosVprintfCallback = s32(vm::cptr<char> fmt, armv7_va_args_t ap /* va_list */);
using SceFiosMemcpyCallback = vm::ptr<void>(vm::ptr<void> dst, vm::cptr<void> src, u32 len);
enum SceFiosWhence : s32
+44 -44
View File
@@ -33,7 +33,7 @@ s32 sceKernelGetMemBlockInfoByAddr(vm::ptr<void> vbase, vm::ptr<SceKernelMemBloc
s32 sceKernelCreateThread(vm::cptr<char> pName, vm::ptr<SceKernelThreadEntry> entry, s32 initPriority, u32 stackSize, u32 attr, s32 cpuAffinityMask, vm::cptr<SceKernelThreadOptParam> pOptParam)
{
sceLibKernel.Warning("sceKernelCreateThread(pName=*0x%x, entry=*0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=*0x%x)",
sceLibKernel.warning("sceKernelCreateThread(pName=*0x%x, entry=*0x%x, initPriority=%d, stackSize=0x%x, attr=0x%x, cpuAffinityMask=0x%x, pOptParam=*0x%x)",
pName, entry, initPriority, stackSize, attr, cpuAffinityMask, pOptParam);
auto armv7 = idm::make_ptr<ARMv7Thread>(pName.get_ptr());
@@ -48,7 +48,7 @@ s32 sceKernelCreateThread(vm::cptr<char> pName, vm::ptr<SceKernelThreadEntry> en
s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::cptr<void> pArgBlock)
{
sceLibKernel.Warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=*0x%x)", threadId, argSize, pArgBlock);
sceLibKernel.warning("sceKernelStartThread(threadId=0x%x, argSize=0x%x, pArgBlock=*0x%x)", threadId, argSize, pArgBlock);
const auto thread = idm::get<ARMv7Thread>(threadId);
@@ -78,7 +78,7 @@ s32 sceKernelStartThread(s32 threadId, u32 argSize, vm::cptr<void> pArgBlock)
s32 sceKernelExitThread(ARMv7Thread& context, s32 exitStatus)
{
sceLibKernel.Warning("sceKernelExitThread(exitStatus=0x%x)", exitStatus);
sceLibKernel.warning("sceKernelExitThread(exitStatus=0x%x)", exitStatus);
// exit status is stored in r0
context.exit();
@@ -88,7 +88,7 @@ s32 sceKernelExitThread(ARMv7Thread& context, s32 exitStatus)
s32 sceKernelDeleteThread(s32 threadId)
{
sceLibKernel.Warning("sceKernelDeleteThread(threadId=0x%x)", threadId);
sceLibKernel.warning("sceKernelDeleteThread(threadId=0x%x)", threadId);
const auto thread = idm::get<ARMv7Thread>(threadId);
@@ -110,7 +110,7 @@ s32 sceKernelDeleteThread(s32 threadId)
s32 sceKernelExitDeleteThread(ARMv7Thread& context, s32 exitStatus)
{
sceLibKernel.Warning("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus);
sceLibKernel.warning("sceKernelExitDeleteThread(exitStatus=0x%x)", exitStatus);
// exit status is stored in r0
context.stop();
@@ -123,91 +123,91 @@ s32 sceKernelExitDeleteThread(ARMv7Thread& context, s32 exitStatus)
s32 sceKernelChangeThreadCpuAffinityMask(s32 threadId, s32 cpuAffinityMask)
{
sceLibKernel.Todo("sceKernelChangeThreadCpuAffinityMask(threadId=0x%x, cpuAffinityMask=0x%x)", threadId, cpuAffinityMask);
sceLibKernel.todo("sceKernelChangeThreadCpuAffinityMask(threadId=0x%x, cpuAffinityMask=0x%x)", threadId, cpuAffinityMask);
throw EXCEPTION("");
}
s32 sceKernelGetThreadCpuAffinityMask(s32 threadId)
{
sceLibKernel.Todo("sceKernelGetThreadCpuAffinityMask(threadId=0x%x)", threadId);
sceLibKernel.todo("sceKernelGetThreadCpuAffinityMask(threadId=0x%x)", threadId);
throw EXCEPTION("");
}
s32 sceKernelChangeThreadPriority(s32 threadId, s32 priority)
{
sceLibKernel.Todo("sceKernelChangeThreadPriority(threadId=0x%x, priority=%d)", threadId, priority);
sceLibKernel.todo("sceKernelChangeThreadPriority(threadId=0x%x, priority=%d)", threadId, priority);
throw EXCEPTION("");
}
s32 sceKernelGetThreadCurrentPriority()
{
sceLibKernel.Todo("sceKernelGetThreadCurrentPriority()");
sceLibKernel.todo("sceKernelGetThreadCurrentPriority()");
throw EXCEPTION("");
}
u32 sceKernelGetThreadId(ARMv7Thread& context)
{
sceLibKernel.Log("sceKernelGetThreadId()");
sceLibKernel.trace("sceKernelGetThreadId()");
return context.get_id();
}
s32 sceKernelChangeCurrentThreadAttr(u32 clearAttr, u32 setAttr)
{
sceLibKernel.Todo("sceKernelChangeCurrentThreadAttr()");
sceLibKernel.todo("sceKernelChangeCurrentThreadAttr()");
throw EXCEPTION("");
}
s32 sceKernelGetThreadExitStatus(s32 threadId, vm::ptr<s32> pExitStatus)
{
sceLibKernel.Todo("sceKernelGetThreadExitStatus(threadId=0x%x, pExitStatus=*0x%x)", threadId, pExitStatus);
sceLibKernel.todo("sceKernelGetThreadExitStatus(threadId=0x%x, pExitStatus=*0x%x)", threadId, pExitStatus);
throw EXCEPTION("");
}
s32 sceKernelGetProcessId()
{
sceLibKernel.Todo("sceKernelGetProcessId()");
sceLibKernel.todo("sceKernelGetProcessId()");
throw EXCEPTION("");
}
s32 sceKernelCheckWaitableStatus()
{
sceLibKernel.Todo("sceKernelCheckWaitableStatus()");
sceLibKernel.todo("sceKernelCheckWaitableStatus()");
throw EXCEPTION("");
}
s32 sceKernelGetThreadInfo(s32 threadId, vm::ptr<SceKernelThreadInfo> pInfo)
{
sceLibKernel.Todo("sceKernelGetThreadInfo(threadId=0x%x, pInfo=*0x%x)", threadId, pInfo);
sceLibKernel.todo("sceKernelGetThreadInfo(threadId=0x%x, pInfo=*0x%x)", threadId, pInfo);
throw EXCEPTION("");
}
s32 sceKernelGetThreadRunStatus(vm::ptr<SceKernelThreadRunStatus> pStatus)
{
sceLibKernel.Todo("sceKernelGetThreadRunStatus(pStatus=*0x%x)", pStatus);
sceLibKernel.todo("sceKernelGetThreadRunStatus(pStatus=*0x%x)", pStatus);
throw EXCEPTION("");
}
s32 sceKernelGetSystemInfo(vm::ptr<SceKernelSystemInfo> pInfo)
{
sceLibKernel.Todo("sceKernelGetSystemInfo(pInfo=*0x%x)", pInfo);
sceLibKernel.todo("sceKernelGetSystemInfo(pInfo=*0x%x)", pInfo);
throw EXCEPTION("");
}
s32 sceKernelGetThreadmgrUIDClass(s32 uid)
{
sceLibKernel.Error("sceKernelGetThreadmgrUIDClass(uid=0x%x)", uid);
sceLibKernel.error("sceKernelGetThreadmgrUIDClass(uid=0x%x)", uid);
const auto type = idm::get_type(uid);
@@ -227,35 +227,35 @@ s32 sceKernelGetThreadmgrUIDClass(s32 uid)
s32 sceKernelChangeThreadVfpException(s32 clearMask, s32 setMask)
{
sceLibKernel.Todo("sceKernelChangeThreadVfpException(clearMask=0x%x, setMask=0x%x)", clearMask, setMask);
sceLibKernel.todo("sceKernelChangeThreadVfpException(clearMask=0x%x, setMask=0x%x)", clearMask, setMask);
throw EXCEPTION("");
}
s32 sceKernelGetCurrentThreadVfpException()
{
sceLibKernel.Todo("sceKernelGetCurrentThreadVfpException()");
sceLibKernel.todo("sceKernelGetCurrentThreadVfpException()");
throw EXCEPTION("");
}
s32 sceKernelDelayThread(u32 usec)
{
sceLibKernel.Todo("sceKernelDelayThread()");
sceLibKernel.todo("sceKernelDelayThread()");
throw EXCEPTION("");
}
s32 sceKernelDelayThreadCB(u32 usec)
{
sceLibKernel.Todo("sceKernelDelayThreadCB()");
sceLibKernel.todo("sceKernelDelayThreadCB()");
throw EXCEPTION("");
}
s32 sceKernelWaitThreadEnd(s32 threadId, vm::ptr<s32> pExitStatus, vm::ptr<u32> pTimeout)
{
sceLibKernel.Warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
sceLibKernel.warning("sceKernelWaitThreadEnd(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
const auto thread = idm::get<ARMv7Thread>(threadId);
@@ -285,7 +285,7 @@ s32 sceKernelWaitThreadEnd(s32 threadId, vm::ptr<s32> pExitStatus, vm::ptr<u32>
s32 sceKernelWaitThreadEndCB(s32 threadId, vm::ptr<s32> pExitStatus, vm::ptr<u32> pTimeout)
{
sceLibKernel.Todo("sceKernelWaitThreadEndCB(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
sceLibKernel.todo("sceKernelWaitThreadEndCB(threadId=0x%x, pExitStatus=*0x%x, pTimeout=*0x%x)", threadId, pExitStatus, pTimeout);
throw EXCEPTION("");
}
@@ -383,14 +383,14 @@ s32 sceKernelWaitMultipleEventsCB(vm::ptr<SceKernelWaitEvent> pWaitEventList, s3
s32 sceKernelCreateEventFlag(vm::cptr<char> pName, u32 attr, u32 initPattern, vm::cptr<SceKernelEventFlagOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateEventFlag(pName=*0x%x, attr=0x%x, initPattern=0x%x, pOptParam=*0x%x)", pName, attr, initPattern, pOptParam);
sceLibKernel.error("sceKernelCreateEventFlag(pName=*0x%x, attr=0x%x, initPattern=0x%x, pOptParam=*0x%x)", pName, attr, initPattern, pOptParam);
return idm::make<psv_event_flag_t>(pName.get_ptr(), attr, initPattern);
}
s32 sceKernelDeleteEventFlag(s32 evfId)
{
sceLibKernel.Error("sceKernelDeleteEventFlag(evfId=0x%x)", evfId);
sceLibKernel.error("sceKernelDeleteEventFlag(evfId=0x%x)", evfId);
const auto evf = idm::withdraw<psv_event_flag_t>(evfId);
@@ -410,7 +410,7 @@ s32 sceKernelDeleteEventFlag(s32 evfId)
s32 sceKernelOpenEventFlag(vm::cptr<char> pName)
{
sceLibKernel.Error("sceKernelOpenEventFlag(pName=*0x%x)", pName);
sceLibKernel.error("sceKernelOpenEventFlag(pName=*0x%x)", pName);
// For now, go through all objects to find the name
for (const auto& data : idm::get_map<psv_event_flag_t>())
@@ -428,7 +428,7 @@ s32 sceKernelOpenEventFlag(vm::cptr<char> pName)
s32 sceKernelCloseEventFlag(s32 evfId)
{
sceLibKernel.Error("sceKernelCloseEventFlag(evfId=0x%x)", evfId);
sceLibKernel.error("sceKernelCloseEventFlag(evfId=0x%x)", evfId);
const auto evf = idm::withdraw<psv_event_flag_t>(evfId);
@@ -448,7 +448,7 @@ s32 sceKernelCloseEventFlag(s32 evfId)
s32 sceKernelWaitEventFlag(ARMv7Thread& context, s32 evfId, u32 bitPattern, u32 waitMode, vm::ptr<u32> pResultPat, vm::ptr<u32> pTimeout)
{
sceLibKernel.Error("sceKernelWaitEventFlag(evfId=0x%x, bitPattern=0x%x, waitMode=0x%x, pResultPat=*0x%x, pTimeout=*0x%x)", evfId, bitPattern, waitMode, pResultPat, pTimeout);
sceLibKernel.error("sceKernelWaitEventFlag(evfId=0x%x, bitPattern=0x%x, waitMode=0x%x, pResultPat=*0x%x, pTimeout=*0x%x)", evfId, bitPattern, waitMode, pResultPat, pTimeout);
const u64 start_time = pTimeout ? get_system_time() : 0;
const u32 timeout = pTimeout ? pTimeout->value() : 0;
@@ -509,14 +509,14 @@ s32 sceKernelWaitEventFlag(ARMv7Thread& context, s32 evfId, u32 bitPattern, u32
s32 sceKernelWaitEventFlagCB(ARMv7Thread& context, s32 evfId, u32 bitPattern, u32 waitMode, vm::ptr<u32> pResultPat, vm::ptr<u32> pTimeout)
{
sceLibKernel.Todo("sceKernelWaitEventFlagCB(evfId=0x%x, bitPattern=0x%x, waitMode=0x%x, pResultPat=*0x%x, pTimeout=*0x%x)", evfId, bitPattern, waitMode, pResultPat, pTimeout);
sceLibKernel.todo("sceKernelWaitEventFlagCB(evfId=0x%x, bitPattern=0x%x, waitMode=0x%x, pResultPat=*0x%x, pTimeout=*0x%x)", evfId, bitPattern, waitMode, pResultPat, pTimeout);
return sceKernelWaitEventFlag(context, evfId, bitPattern, waitMode, pResultPat, pTimeout);
}
s32 sceKernelPollEventFlag(s32 evfId, u32 bitPattern, u32 waitMode, vm::ptr<u32> pResultPat)
{
sceLibKernel.Error("sceKernelPollEventFlag(evfId=0x%x, bitPattern=0x%x, waitMode=0x%x, pResultPat=*0x%x)", evfId, bitPattern, waitMode, pResultPat);
sceLibKernel.error("sceKernelPollEventFlag(evfId=0x%x, bitPattern=0x%x, waitMode=0x%x, pResultPat=*0x%x)", evfId, bitPattern, waitMode, pResultPat);
const auto evf = idm::get<psv_event_flag_t>(evfId);
@@ -541,7 +541,7 @@ s32 sceKernelPollEventFlag(s32 evfId, u32 bitPattern, u32 waitMode, vm::ptr<u32>
s32 sceKernelSetEventFlag(s32 evfId, u32 bitPattern)
{
sceLibKernel.Error("sceKernelSetEventFlag(evfId=0x%x, bitPattern=0x%x)", evfId, bitPattern);
sceLibKernel.error("sceKernelSetEventFlag(evfId=0x%x, bitPattern=0x%x)", evfId, bitPattern);
const auto evf = idm::get<psv_event_flag_t>(evfId);
@@ -586,7 +586,7 @@ s32 sceKernelSetEventFlag(s32 evfId, u32 bitPattern)
s32 sceKernelClearEventFlag(s32 evfId, u32 bitPattern)
{
sceLibKernel.Error("sceKernelClearEventFlag(evfId=0x%x, bitPattern=0x%x)", evfId, bitPattern);
sceLibKernel.error("sceKernelClearEventFlag(evfId=0x%x, bitPattern=0x%x)", evfId, bitPattern);
const auto evf = idm::get<psv_event_flag_t>(evfId);
@@ -604,7 +604,7 @@ s32 sceKernelClearEventFlag(s32 evfId, u32 bitPattern)
s32 sceKernelCancelEventFlag(s32 evfId, u32 setPattern, vm::ptr<s32> pNumWaitThreads)
{
sceLibKernel.Error("sceKernelCancelEventFlag(evfId=0x%x, setPattern=0x%x, pNumWaitThreads=*0x%x)", evfId, setPattern, pNumWaitThreads);
sceLibKernel.error("sceKernelCancelEventFlag(evfId=0x%x, setPattern=0x%x, pNumWaitThreads=*0x%x)", evfId, setPattern, pNumWaitThreads);
const auto evf = idm::get<psv_event_flag_t>(evfId);
@@ -632,7 +632,7 @@ s32 sceKernelCancelEventFlag(s32 evfId, u32 setPattern, vm::ptr<s32> pNumWaitThr
s32 sceKernelGetEventFlagInfo(s32 evfId, vm::ptr<SceKernelEventFlagInfo> pInfo)
{
sceLibKernel.Error("sceKernelGetEventFlagInfo(evfId=0x%x, pInfo=*0x%x)", evfId, pInfo);
sceLibKernel.error("sceKernelGetEventFlagInfo(evfId=0x%x, pInfo=*0x%x)", evfId, pInfo);
const auto evf = idm::get<psv_event_flag_t>(evfId);
@@ -643,7 +643,7 @@ s32 sceKernelGetEventFlagInfo(s32 evfId, vm::ptr<SceKernelEventFlagInfo> pInfo)
std::lock_guard<std::mutex> lock(evf->mutex);
pInfo->size = sizeof32(SceKernelEventFlagInfo);
pInfo->size = SIZE_32(SceKernelEventFlagInfo);
pInfo->evfId = evfId;
strcpy_trunc(pInfo->name, evf->name);
@@ -660,14 +660,14 @@ s32 sceKernelGetEventFlagInfo(s32 evfId, vm::ptr<SceKernelEventFlagInfo> pInfo)
s32 sceKernelCreateSema(vm::cptr<char> pName, u32 attr, s32 initCount, s32 maxCount, vm::cptr<SceKernelSemaOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateSema(pName=*0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=*0x%x)", pName, attr, initCount, maxCount, pOptParam);
sceLibKernel.error("sceKernelCreateSema(pName=*0x%x, attr=0x%x, initCount=%d, maxCount=%d, pOptParam=*0x%x)", pName, attr, initCount, maxCount, pOptParam);
return idm::make<psv_semaphore_t>(pName.get_ptr(), attr, initCount, maxCount);
}
s32 sceKernelDeleteSema(s32 semaId)
{
sceLibKernel.Error("sceKernelDeleteSema(semaId=0x%x)", semaId);
sceLibKernel.error("sceKernelDeleteSema(semaId=0x%x)", semaId);
const auto sema = idm::withdraw<psv_semaphore_t>(semaId);
@@ -693,7 +693,7 @@ s32 sceKernelCloseSema(s32 semaId)
s32 sceKernelWaitSema(s32 semaId, s32 needCount, vm::ptr<u32> pTimeout)
{
sceLibKernel.Error("sceKernelWaitSema(semaId=0x%x, needCount=%d, pTimeout=*0x%x)", semaId, needCount, pTimeout);
sceLibKernel.error("sceKernelWaitSema(semaId=0x%x, needCount=%d, pTimeout=*0x%x)", semaId, needCount, pTimeout);
const auto sema = idm::get<psv_semaphore_t>(semaId);
@@ -702,7 +702,7 @@ s32 sceKernelWaitSema(s32 semaId, s32 needCount, vm::ptr<u32> pTimeout)
return SCE_KERNEL_ERROR_INVALID_UID;
}
sceLibKernel.Error("*** name = %s", sema->name);
sceLibKernel.error("*** name = %s", sema->name);
Emu.Pause();
return SCE_OK;
}
@@ -736,14 +736,14 @@ s32 sceKernelGetSemaInfo(s32 semaId, vm::ptr<SceKernelSemaInfo> pInfo)
s32 sceKernelCreateMutex(vm::cptr<char> pName, u32 attr, s32 initCount, vm::cptr<SceKernelMutexOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateMutex(pName=*0x%x, attr=0x%x, initCount=%d, pOptParam=*0x%x)", pName, attr, initCount, pOptParam);
sceLibKernel.error("sceKernelCreateMutex(pName=*0x%x, attr=0x%x, initCount=%d, pOptParam=*0x%x)", pName, attr, initCount, pOptParam);
return idm::make<psv_mutex_t>(pName.get_ptr(), attr, initCount);
}
s32 sceKernelDeleteMutex(s32 mutexId)
{
sceLibKernel.Error("sceKernelDeleteMutex(mutexId=0x%x)", mutexId);
sceLibKernel.error("sceKernelDeleteMutex(mutexId=0x%x)", mutexId);
const auto mutex = idm::withdraw<psv_mutex_t>(mutexId);
@@ -843,7 +843,7 @@ s32 sceKernelGetLwMutexInfoById(s32 lwMutexId, vm::ptr<SceKernelLwMutexInfo> pIn
s32 sceKernelCreateCond(vm::cptr<char> pName, u32 attr, s32 mutexId, vm::cptr<SceKernelCondOptParam> pOptParam)
{
sceLibKernel.Error("sceKernelCreateCond(pName=*0x%x, attr=0x%x, mutexId=0x%x, pOptParam=*0x%x)", pName, attr, mutexId, pOptParam);
sceLibKernel.error("sceKernelCreateCond(pName=*0x%x, attr=0x%x, mutexId=0x%x, pOptParam=*0x%x)", pName, attr, mutexId, pOptParam);
const auto mutex = idm::get<psv_mutex_t>(mutexId);
@@ -857,7 +857,7 @@ s32 sceKernelCreateCond(vm::cptr<char> pName, u32 attr, s32 mutexId, vm::cptr<Sc
s32 sceKernelDeleteCond(s32 condId)
{
sceLibKernel.Error("sceKernelDeleteCond(condId=0x%x)", condId);
sceLibKernel.error("sceKernelDeleteCond(condId=0x%x)", condId);
const auto cond = idm::withdraw<psv_cond_t>(condId);
+16 -16
View File
@@ -150,7 +150,7 @@ namespace sce_libc_func
{
void __cxa_atexit(vm::ptr<atexit_func_t> func, vm::ptr<void> arg, vm::ptr<void> dso)
{
sceLibc.Warning("__cxa_atexit(func=*0x%x, arg=*0x%x, dso=*0x%x)", func, arg, dso);
sceLibc.warning("__cxa_atexit(func=*0x%x, arg=*0x%x, dso=*0x%x)", func, arg, dso);
std::lock_guard<std::mutex> lock(g_atexit_mutex);
@@ -162,7 +162,7 @@ namespace sce_libc_func
void __aeabi_atexit(vm::ptr<void> arg, vm::ptr<atexit_func_t> func, vm::ptr<void> dso)
{
sceLibc.Warning("__aeabi_atexit(arg=*0x%x, func=*0x%x, dso=*0x%x)", arg, func, dso);
sceLibc.warning("__aeabi_atexit(arg=*0x%x, func=*0x%x, dso=*0x%x)", arg, func, dso);
std::lock_guard<std::mutex> lock(g_atexit_mutex);
@@ -174,7 +174,7 @@ namespace sce_libc_func
void exit(ARMv7Thread& context)
{
sceLibc.Warning("exit()");
sceLibc.warning("exit()");
std::lock_guard<std::mutex> lock(g_atexit_mutex);
@@ -185,7 +185,7 @@ namespace sce_libc_func
func(context);
}
sceLibc.Success("Process finished");
sceLibc.success("Process finished");
Emu.CallAfter([]()
{
@@ -202,52 +202,52 @@ namespace sce_libc_func
void printf(ARMv7Thread& context, vm::cptr<char> fmt, armv7_va_args_t va_args)
{
sceLibc.Warning("printf(fmt=*0x%x)", fmt);
sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr());
sceLibc.warning("printf(fmt=*0x%x)", fmt);
sceLibc.trace("*** *fmt = '%s'", fmt.get_ptr());
const std::string& result = armv7_fmt(context, fmt, va_args.g_count, va_args.f_count, va_args.v_count);
sceLibc.Log("*** -> '%s'", result);
sceLibc.trace("*** -> '%s'", result);
LOG_NOTICE(TTY, result);
_log::g_tty_file.log(result);
}
void sprintf(ARMv7Thread& context, vm::ptr<char> str, vm::cptr<char> fmt, armv7_va_args_t va_args)
{
sceLibc.Warning("sprintf(str=*0x%x, fmt=*0x%x)", str, fmt);
sceLibc.Log("*** *fmt = '%s'", fmt.get_ptr());
sceLibc.warning("sprintf(str=*0x%x, fmt=*0x%x)", str, fmt);
sceLibc.trace("*** *fmt = '%s'", fmt.get_ptr());
const std::string& result = armv7_fmt(context, fmt, va_args.g_count, va_args.f_count, va_args.v_count);
sceLibc.Log("*** -> '%s'", result);
sceLibc.trace("*** -> '%s'", result);
::memcpy(str.get_ptr(), result.c_str(), result.size() + 1);
}
void __cxa_set_dso_handle_main(vm::ptr<void> dso)
{
sceLibc.Warning("__cxa_set_dso_handle_main(dso=*0x%x)", dso);
sceLibc.warning("__cxa_set_dso_handle_main(dso=*0x%x)", dso);
g_dso = dso;
}
void memcpy(vm::ptr<void> dst, vm::cptr<void> src, u32 size)
{
sceLibc.Warning("memcpy(dst=*0x%x, src=*0x%x, size=0x%x)", dst, src, size);
sceLibc.warning("memcpy(dst=*0x%x, src=*0x%x, size=0x%x)", dst, src, size);
::memcpy(dst.get_ptr(), src.get_ptr(), size);
}
void memset(vm::ptr<void> dst, s32 value, u32 size)
{
sceLibc.Warning("memset(dst=*0x%x, value=%d, size=0x%x)", dst, value, size);
sceLibc.warning("memset(dst=*0x%x, value=%d, size=0x%x)", dst, value, size);
::memset(dst.get_ptr(), value, size);
}
void _Assert(vm::cptr<char> text, vm::cptr<char> func)
{
sceLibc.Error("_Assert(text=*0x%x, func=*0x%x)", text, func);
sceLibc.error("_Assert(text=*0x%x, func=*0x%x)", text, func);
LOG_ERROR(TTY, "%s : %s\n", func.get_ptr(), text.get_ptr());
LOG_FATAL(HLE, "%s : %s\n", func.get_ptr(), text.get_ptr());
Emu.Pause();
}
}
+9 -9
View File
@@ -8,7 +8,7 @@ extern u64 get_system_time();
s32 scePerfArmPmonReset(ARMv7Thread& context, s32 threadId)
{
scePerf.Warning("scePerfArmPmonReset(threadId=0x%x)", threadId);
scePerf.warning("scePerfArmPmonReset(threadId=0x%x)", threadId);
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
{
@@ -22,7 +22,7 @@ s32 scePerfArmPmonReset(ARMv7Thread& context, s32 threadId)
s32 scePerfArmPmonSelectEvent(ARMv7Thread& context, s32 threadId, u32 counter, u8 eventCode)
{
scePerf.Warning("scePerfArmPmonSelectEvent(threadId=0x%x, counter=0x%x, eventCode=0x%x)", threadId, counter, eventCode);
scePerf.warning("scePerfArmPmonSelectEvent(threadId=0x%x, counter=0x%x, eventCode=0x%x)", threadId, counter, eventCode);
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
{
@@ -74,7 +74,7 @@ s32 scePerfArmPmonSelectEvent(ARMv7Thread& context, s32 threadId, u32 counter, u
s32 scePerfArmPmonStart(ARMv7Thread& context, s32 threadId)
{
scePerf.Warning("scePerfArmPmonStart(threadId=0x%x)", threadId);
scePerf.warning("scePerfArmPmonStart(threadId=0x%x)", threadId);
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
{
@@ -86,7 +86,7 @@ s32 scePerfArmPmonStart(ARMv7Thread& context, s32 threadId)
s32 scePerfArmPmonStop(ARMv7Thread& context, s32 threadId)
{
scePerf.Warning("scePerfArmPmonStop(threadId=0x%x)");
scePerf.warning("scePerfArmPmonStop(threadId=0x%x)");
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
{
@@ -98,7 +98,7 @@ s32 scePerfArmPmonStop(ARMv7Thread& context, s32 threadId)
s32 scePerfArmPmonGetCounterValue(ARMv7Thread& context, s32 threadId, u32 counter, vm::ptr<u32> pValue)
{
scePerf.Warning("scePerfArmPmonGetCounterValue(threadId=0x%x, counter=%d, pValue=*0x%x)", threadId, counter, pValue);
scePerf.warning("scePerfArmPmonGetCounterValue(threadId=0x%x, counter=%d, pValue=*0x%x)", threadId, counter, pValue);
if (threadId != SCE_PERF_ARM_PMON_THREAD_ID_SELF)
{
@@ -124,7 +124,7 @@ s32 scePerfArmPmonGetCounterValue(ARMv7Thread& context, s32 threadId, u32 counte
s32 scePerfArmPmonSoftwareIncrement(ARMv7Thread& context, u32 mask)
{
scePerf.Warning("scePerfArmPmonSoftwareIncrement(mask=0x%x)", mask);
scePerf.warning("scePerfArmPmonSoftwareIncrement(mask=0x%x)", mask);
if (mask > SCE_PERF_ARM_PMON_COUNTER_MASK_ALL)
{
@@ -144,14 +144,14 @@ s32 scePerfArmPmonSoftwareIncrement(ARMv7Thread& context, u32 mask)
u64 scePerfGetTimebaseValue()
{
scePerf.Warning("scePerfGetTimebaseValue()");
scePerf.warning("scePerfGetTimebaseValue()");
return get_system_time();
}
u32 scePerfGetTimebaseFrequency()
{
scePerf.Warning("scePerfGetTimebaseFrequency()");
scePerf.warning("scePerfGetTimebaseFrequency()");
return 1;
}
@@ -198,4 +198,4 @@ psv_log_base scePerf("ScePerf", []()
REG_FUNC(0xC3DE4C0A, sceRazorCpuPushMarker);
REG_FUNC(0xDC3224C3, sceRazorCpuPopMarker);
REG_FUNC(0x4F1385E3, sceRazorCpuSync);
});
});
+3 -3
View File
@@ -6,21 +6,21 @@
s32 sceSysmoduleLoadModule(u16 id)
{
sceSysmodule.Warning("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id);
sceSysmodule.warning("sceSysmoduleLoadModule(id=0x%04x) -> SCE_OK", id);
return SCE_OK; // loading succeeded
}
s32 sceSysmoduleUnloadModule(u16 id)
{
sceSysmodule.Warning("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id);
sceSysmodule.warning("sceSysmoduleUnloadModule(id=0x%04x) -> SCE_OK", id);
return SCE_OK; // unloading succeeded
}
s32 sceSysmoduleIsLoaded(u16 id)
{
sceSysmodule.Warning("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id);
sceSysmodule.warning("sceSysmoduleIsLoaded(id=0x%04x) -> SCE_OK", id);
return SCE_OK; // module is loaded
}
+2 -2
View File
@@ -4,14 +4,14 @@
#include "PSVFuncList.h"
psv_log_base::psv_log_base(const std::string& name, init_func_t init)
: m_name(name)
: _log::channel(name)
, m_init(init)
{
on_error = [this](s32 code, psv_func* func)
{
if (code < 0)
{
Error("%s() failed: 0x%08X", func->name, code);
error("%s() failed: 0x%08X", func->name, code);
Emu.Pause();
}
};
+2 -10
View File
@@ -2,16 +2,14 @@
#include "Emu/Memory/Memory.h"
#include "ARMv7Thread.h"
#include "Emu/SysCalls/LogBase.h"
namespace vm { using namespace psv; }
// PSV module class
class psv_log_base : public LogBase
class psv_log_base : public _log::channel
{
using init_func_t = void(*)();
std::string m_name;
init_func_t m_init;
public:
@@ -32,12 +30,6 @@ public:
m_init();
}
virtual const std::string& GetName() const override
{
return m_name;
}
};
using armv7_func_caller = void(*)(ARMv7Thread&);
@@ -321,7 +313,7 @@ namespace psv_func_detail
static const bool is_variadic = std::is_same<std::remove_cv_t<T>, armv7_va_args_t>::value;
static const bool is_general = !is_float && !is_vector && !is_context && !is_variadic;
static const u32 g_align = alignof32(T) > 4 ? alignof32(T) >> 2 : 1;
static const u32 g_align = ALIGN_32(T) > 4 ? ALIGN_32(T) >> 2 : 1;
static const u32 g_value = is_general ? ((g_count + (g_align - 1)) & ~(g_align - 1)) + (g_align) : g_count;
static const u32 f_value = f_count + is_float;
static const u32 v_value = v_count + is_vector;
+1 -15
View File
@@ -1,24 +1,10 @@
#include "stdafx.h"
#include "Emu/System.h"
#include "AudioManager.h"
#include "Emu/state.h"
AudioManager::AudioManager() : m_audio_out(nullptr)
{
}
AudioManager::~AudioManager()
{
Close();
}
void AudioManager::Init()
{
if (m_audio_out) return;
m_audio_info.Init();
m_audio_out = Emu.GetCallbacks().get_audio();
if (!m_audio_out) m_audio_out = Emu.GetCallbacks().get_audio();
}
void AudioManager::Close()
+2 -18
View File
@@ -2,29 +2,13 @@
#include "AudioThread.h"
// it cannot be configured currently, and it must NOT use cellSysutil definitions
struct AudioInfo
{
AudioInfo()
{
}
void Init()
{
}
};
class AudioManager
{
AudioInfo m_audio_info;
std::shared_ptr<AudioThread> m_audio_out;
public:
AudioManager();
~AudioManager();
public:
void Init();
void Close();
AudioThread& GetAudioOut() { assert(m_audio_out); return *m_audio_out; }
AudioInfo& GetInfo() { return m_audio_info; }
AudioThread& GetAudioOut() { return *m_audio_out; }
};
+3 -1
View File
@@ -3,9 +3,11 @@
#include "Emu/Audio/AudioThread.h"
#pragma push_macro("_WIN32_WINNT")
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0601 // This is to be sure that correct (2.7) header is included
#include "minidx9/Include/XAudio2.h" // XAudio2 2.8 available only on Win8+, used XAudio2 2.7 from dxsdk
#undef _WIN32_WINNT
#pragma pop_macro("_WIN32_WINNT")
class XAudio2Thread : public AudioThread
{
+1 -1
View File
@@ -89,7 +89,7 @@ void CPUThread::dump_info() const
{
if (!Emu.IsStopped())
{
LOG_NOTICE(GENERAL, RegsToString());
LOG_NOTICE(GENERAL, "%s", RegsToString());
}
}
+4 -4
View File
@@ -1778,7 +1778,7 @@ void ppu_interpreter::LWARX(PPUThread& CPU, ppu_opcode_t op)
const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb];
be_t<u32> value;
vm::reservation_acquire(&value, VM_CAST(addr), sizeof32(value));
vm::reservation_acquire(&value, VM_CAST(addr), SIZE_32(value));
CPU.GPR[op.rd] = value;
}
@@ -1949,7 +1949,7 @@ void ppu_interpreter::LDARX(PPUThread& CPU, ppu_opcode_t op)
const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb];
be_t<u64> value;
vm::reservation_acquire(&value, VM_CAST(addr), sizeof32(value));
vm::reservation_acquire(&value, VM_CAST(addr), SIZE_32(value));
CPU.GPR[op.rd] = value;
}
@@ -2079,7 +2079,7 @@ void ppu_interpreter::STWCX_(PPUThread& CPU, ppu_opcode_t op)
const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb];
const be_t<u32> value = (u32)CPU.GPR[op.rs];
CPU.SetCR_EQ(0, vm::reservation_update(VM_CAST(addr), &value, sizeof32(value)));
CPU.SetCR_EQ(0, vm::reservation_update(VM_CAST(addr), &value, SIZE_32(value)));
}
void ppu_interpreter::STWX(PPUThread& CPU, ppu_opcode_t op)
@@ -2139,7 +2139,7 @@ void ppu_interpreter::STDCX_(PPUThread& CPU, ppu_opcode_t op)
const u64 addr = op.ra ? CPU.GPR[op.ra] + CPU.GPR[op.rb] : CPU.GPR[op.rb];
const be_t<u64> value = CPU.GPR[op.rs];
CPU.SetCR_EQ(0, vm::reservation_update(VM_CAST(addr), &value, sizeof32(value)));
CPU.SetCR_EQ(0, vm::reservation_update(VM_CAST(addr), &value, SIZE_32(value)));
}
void ppu_interpreter::STBX(PPUThread& CPU, ppu_opcode_t op)
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -188,7 +188,7 @@ void ppu_recompiler_llvm::Compiler::translate_to_llvm_ir(llvm::Module *module, c
std::string verify;
raw_string_ostream verify_ostream(verify);
if (verifyFunction(*m_state.function, &verify_ostream)) {
// m_recompilation_engine.Log() << "Verification failed: " << verify_ostream.str() << "\n";
// m_recompilation_engine.trace() << "Verification failed: " << verify_ostream.str() << "\n";
}
m_module = nullptr;
@@ -421,13 +421,13 @@ std::pair<Executable, llvm::ExecutionEngine *> RecompilationEngine::compile(cons
Function *llvm_function = module_ptr->getFunction(name);
void *function = execution_engine->getPointerToFunction(llvm_function);
/* m_recompilation_engine.Log() << "\nDisassembly:\n";
/* m_recompilation_engine.trace() << "\nDisassembly:\n";
auto disassembler = LLVMCreateDisasm(sys::getProcessTriple().c_str(), nullptr, 0, nullptr, nullptr);
for (size_t pc = 0; pc < mci.size();) {
char str[1024];
auto size = LLVMDisasmInstruction(disassembler, ((u8 *)mci.address()) + pc, mci.size() - pc, (uint64_t)(((u8 *)mci.address()) + pc), str, sizeof(str));
m_recompilation_engine.Log() << fmt::format("0x%08X: ", (u64)(((u8 *)mci.address()) + pc)) << str << '\n';
m_recompilation_engine.trace() << fmt::format("0x%08X: ", (u64)(((u8 *)mci.address()) + pc)) << str << '\n';
pc += size;
}
+25 -25
View File
@@ -5097,33 +5097,33 @@ Value * Compiler::SetNibble(Value * val, u32 n, Value * b0, Value * b1, Value *
}
Value * Compiler::GetPc() {
auto pc_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, PC));
auto pc_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, PC));
auto pc_i32_ptr = m_ir_builder->CreateBitCast(pc_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(pc_i32_ptr, 4);
}
void Compiler::SetPc(Value * val_ix) {
auto pc_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, PC));
auto pc_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, PC));
auto pc_i32_ptr = m_ir_builder->CreateBitCast(pc_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
auto val_i32 = m_ir_builder->CreateZExtOrTrunc(val_ix, m_ir_builder->getInt32Ty());
m_ir_builder->CreateAlignedStore(val_i32, pc_i32_ptr, 4);
}
Value * Compiler::GetGpr(u32 r, u32 num_bits) {
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, GPR[r]));
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, GPR[r]));
auto r_ix_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getIntNTy(num_bits)->getPointerTo());
return m_ir_builder->CreateAlignedLoad(r_ix_ptr, 8);
}
void Compiler::SetGpr(u32 r, Value * val_x64) {
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, GPR[r]));
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, GPR[r]));
auto r_i64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
m_ir_builder->CreateAlignedStore(val_i64, r_i64_ptr, 8);
}
Value * Compiler::GetCr() {
auto cr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, CR));
auto cr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, CR));
auto cr_i32_ptr = m_ir_builder->CreateBitCast(cr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(cr_i32_ptr, 4);
}
@@ -5134,7 +5134,7 @@ Value * Compiler::GetCrField(u32 n) {
void Compiler::SetCr(Value * val_x32) {
auto val_i32 = m_ir_builder->CreateBitCast(val_x32, m_ir_builder->getInt32Ty());
auto cr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, CR));
auto cr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, CR));
auto cr_i32_ptr = m_ir_builder->CreateBitCast(cr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i32, cr_i32_ptr, 4);
}
@@ -5176,33 +5176,33 @@ void Compiler::SetCr6AfterVectorCompare(u32 vr) {
}
Value * Compiler::GetLr() {
auto lr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, LR));
auto lr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, LR));
auto lr_i64_ptr = m_ir_builder->CreateBitCast(lr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(lr_i64_ptr, 8);
}
void Compiler::SetLr(Value * val_x64) {
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
auto lr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, LR));
auto lr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, LR));
auto lr_i64_ptr = m_ir_builder->CreateBitCast(lr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i64, lr_i64_ptr, 8);
}
Value * Compiler::GetCtr() {
auto ctr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, CTR));
auto ctr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, CTR));
auto ctr_i64_ptr = m_ir_builder->CreateBitCast(ctr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(ctr_i64_ptr, 8);
}
void Compiler::SetCtr(Value * val_x64) {
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
auto ctr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, CTR));
auto ctr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, CTR));
auto ctr_i64_ptr = m_ir_builder->CreateBitCast(ctr_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i64, ctr_i64_ptr, 8);
}
Value * Compiler::GetXer() {
auto xer_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, XER));
auto xer_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, XER));
auto xer_i64_ptr = m_ir_builder->CreateBitCast(xer_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(xer_i64_ptr, 8);
}
@@ -5217,7 +5217,7 @@ Value * Compiler::GetXerSo() {
void Compiler::SetXer(Value * val_x64) {
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
auto xer_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, XER));
auto xer_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, XER));
auto xer_i64_ptr = m_ir_builder->CreateBitCast(xer_i8_ptr, m_ir_builder->getInt64Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i64, xer_i64_ptr, 8);
}
@@ -5235,7 +5235,7 @@ void Compiler::SetXerSo(Value * so) {
}
Value * Compiler::GetVrsave() {
auto vrsave_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VRSAVE));
auto vrsave_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VRSAVE));
auto vrsave_i32_ptr = m_ir_builder->CreateBitCast(vrsave_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
auto val_i32 = m_ir_builder->CreateAlignedLoad(vrsave_i32_ptr, 4);
return m_ir_builder->CreateZExtOrTrunc(val_i32, m_ir_builder->getInt64Ty());
@@ -5244,26 +5244,26 @@ Value * Compiler::GetVrsave() {
void Compiler::SetVrsave(Value * val_x64) {
auto val_i64 = m_ir_builder->CreateBitCast(val_x64, m_ir_builder->getInt64Ty());
auto val_i32 = m_ir_builder->CreateZExtOrTrunc(val_i64, m_ir_builder->getInt32Ty());
auto vrsave_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VRSAVE));
auto vrsave_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VRSAVE));
auto vrsave_i32_ptr = m_ir_builder->CreateBitCast(vrsave_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i32, vrsave_i32_ptr, 8);
}
Value * Compiler::GetFpscr() {
auto fpscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, FPSCR));
auto fpscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, FPSCR));
auto fpscr_i32_ptr = m_ir_builder->CreateBitCast(fpscr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(fpscr_i32_ptr, 4);
}
void Compiler::SetFpscr(Value * val_x32) {
auto val_i32 = m_ir_builder->CreateBitCast(val_x32, m_ir_builder->getInt32Ty());
auto fpscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, FPSCR));
auto fpscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, FPSCR));
auto fpscr_i32_ptr = m_ir_builder->CreateBitCast(fpscr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i32, fpscr_i32_ptr, 4);
}
Value * Compiler::GetFpr(u32 r, u32 bits, bool as_int) {
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, FPR[r]));
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, FPR[r]));
if (!as_int) {
auto r_f64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getDoubleTy()->getPointerTo());
auto r_f64 = m_ir_builder->CreateAlignedLoad(r_f64_ptr, 8);
@@ -5287,7 +5287,7 @@ Value * Compiler::GetFpr(u32 r, u32 bits, bool as_int) {
}
void Compiler::SetFpr(u32 r, Value * val) {
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, FPR[r]));
auto r_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, FPR[r]));
auto r_f64_ptr = m_ir_builder->CreateBitCast(r_i8_ptr, m_ir_builder->getDoubleTy()->getPointerTo());
Value* val_f64;
@@ -5306,47 +5306,47 @@ void Compiler::SetFpr(u32 r, Value * val) {
}
Value * Compiler::GetVscr() {
auto vscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VSCR));
auto vscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VSCR));
auto vscr_i32_ptr = m_ir_builder->CreateBitCast(vscr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
return m_ir_builder->CreateAlignedLoad(vscr_i32_ptr, 4);
}
void Compiler::SetVscr(Value * val_x32) {
auto val_i32 = m_ir_builder->CreateBitCast(val_x32, m_ir_builder->getInt32Ty());
auto vscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VSCR));
auto vscr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VSCR));
auto vscr_i32_ptr = m_ir_builder->CreateBitCast(vscr_i8_ptr, m_ir_builder->getInt32Ty()->getPointerTo());
m_ir_builder->CreateAlignedStore(val_i32, vscr_i32_ptr, 4);
}
Value * Compiler::GetVr(u32 vr) {
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VPR[vr]));
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VPR[vr]));
auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo());
return m_ir_builder->CreateAlignedLoad(vr_i128_ptr, 16);
}
Value * Compiler::GetVrAsIntVec(u32 vr, u32 vec_elt_num_bits) {
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VPR[vr]));
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VPR[vr]));
auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo());
auto vr_vec_ptr = m_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(m_ir_builder->getIntNTy(vec_elt_num_bits), 128 / vec_elt_num_bits)->getPointerTo());
return m_ir_builder->CreateAlignedLoad(vr_vec_ptr, 16);
}
Value * Compiler::GetVrAsFloatVec(u32 vr) {
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VPR[vr]));
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VPR[vr]));
auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo());
auto vr_v4f32_ptr = m_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(m_ir_builder->getFloatTy(), 4)->getPointerTo());
return m_ir_builder->CreateAlignedLoad(vr_v4f32_ptr, 16);
}
Value * Compiler::GetVrAsDoubleVec(u32 vr) {
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VPR[vr]));
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VPR[vr]));
auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo());
auto vr_v2f64_ptr = m_ir_builder->CreateBitCast(vr_i128_ptr, VectorType::get(m_ir_builder->getDoubleTy(), 2)->getPointerTo());
return m_ir_builder->CreateAlignedLoad(vr_v2f64_ptr, 16);
}
void Compiler::SetVr(u32 vr, Value * val_x128) {
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], (unsigned int)offsetof(PPUThread, VPR[vr]));
auto vr_i8_ptr = m_ir_builder->CreateConstGEP1_32(m_state.args[CompileTaskState::Args::State], OFFSET_32(PPUThread, VPR[vr]));
auto vr_i128_ptr = m_ir_builder->CreateBitCast(vr_i8_ptr, m_ir_builder->getIntNTy(128)->getPointerTo());
auto val_i128 = m_ir_builder->CreateBitCast(val_x128, m_ir_builder->getIntNTy(128));
m_ir_builder->CreateAlignedStore(val_i128, vr_i128_ptr, 16);
+2 -2
View File
@@ -349,9 +349,9 @@ cpu_thread& ppu_thread::args(std::initializer_list<std::string> values)
assert(argc == 0);
envp.set(vm::alloc(align(sizeof32(*envp), stack_align), vm::main));
envp.set(vm::alloc(align(SIZE_32(*envp), stack_align), vm::main));
*envp = 0;
argv.set(vm::alloc(sizeof32(*argv) * (u32)values.size(), vm::main));
argv.set(vm::alloc(SIZE_32(*argv) * (u32)values.size(), vm::main));
for (auto &arg : values)
{
+3 -1
View File
@@ -1017,6 +1017,8 @@ enum : u32
{
MFF_FORCED_HLE = (1 << 0), // always call HLE function
MFF_NO_RETURN = (1 << 1), // uses EIF_USE_BRANCH flag with LLE, ignored with MFF_FORCED_HLE
MFF_PERFECT = /* 0 */ MFF_FORCED_HLE, // can be set for fully implemented functions with LLE compatibility
};
// flags passed with index
@@ -1026,5 +1028,5 @@ enum : u32
EIF_PERFORM_BLR = (1 << 24), // do BLR after calling HLE/LLE function
EIF_USE_BRANCH = (1 << 23), // do only branch, LLE must be set, last_syscall must be zero
EIF_FLAGS = 0x3800000, // all flags
EIF_FLAGS = 0x3800000, // all flags
};
+1 -1
View File
@@ -60,7 +60,7 @@ bool RawSPUThread::read_reg(const u32 addr, u32& value)
}
}
LOG_ERROR(Log::SPU, "RawSPUThread[%d]: Read32(0x%x): unknown/illegal offset (0x%x)", index, addr, offset);
LOG_ERROR(SPU, "RawSPUThread[%d]: Read32(0x%x): unknown/illegal offset (0x%x)", index, addr, offset);
return false;
}
+15 -17
View File
@@ -15,13 +15,11 @@
#include "asmjit.h"
#define OFFSET_OF(type, x) static_cast<s32>(reinterpret_cast<uintptr_t>(&(((type*)0)->x)))
#define SPU_OFF_128(x) asmjit::host::oword_ptr(*cpu, OFFSET_OF(SPUThread, x))
#define SPU_OFF_64(x) asmjit::host::qword_ptr(*cpu, OFFSET_OF(SPUThread, x))
#define SPU_OFF_32(x) asmjit::host::dword_ptr(*cpu, OFFSET_OF(SPUThread, x))
#define SPU_OFF_16(x) asmjit::host::word_ptr(*cpu, OFFSET_OF(SPUThread, x))
#define SPU_OFF_8(x) asmjit::host::byte_ptr(*cpu, OFFSET_OF(SPUThread, x))
#define SPU_OFF_128(x) asmjit::host::oword_ptr(*cpu, OFFSET_32(SPUThread, x))
#define SPU_OFF_64(x) asmjit::host::qword_ptr(*cpu, OFFSET_32(SPUThread, x))
#define SPU_OFF_32(x) asmjit::host::dword_ptr(*cpu, OFFSET_32(SPUThread, x))
#define SPU_OFF_16(x) asmjit::host::word_ptr(*cpu, OFFSET_32(SPUThread, x))
#define SPU_OFF_8(x) asmjit::host::byte_ptr(*cpu, OFFSET_32(SPUThread, x))
spu_recompiler::spu_recompiler()
: m_jit(std::make_shared<asmjit::JitRuntime>())
@@ -31,7 +29,7 @@ spu_recompiler::spu_recompiler()
LOG_SUCCESS(SPU, "SPU Recompiler (ASMJIT) created...");
fs::file(fs::get_config_dir() + "SPUJIT.log", fom::rewrite) << fmt::format("SPU JIT initialization...\n\nTitle: %s\nTitle ID: %s\n\n", Emu.GetTitle().c_str(), Emu.GetTitleID().c_str());
fs::file(fs::get_config_dir() + "SPUJIT.log", fom::rewrite).write(fmt::format("SPU JIT initialization...\n\nTitle: %s\nTitle ID: %s\n\n", Emu.GetTitle().c_str(), Emu.GetTitleID().c_str()));
}
void spu_recompiler::compile(spu_function_t& f)
@@ -216,7 +214,7 @@ void spu_recompiler::compile(spu_function_t& f)
log += "\n\n\n";
// Append log file
fs::file(fs::get_config_dir() + "SPUJIT.log", fom::write | fom::append) << log;
fs::file(fs::get_config_dir() + "SPUJIT.log", fom::write | fom::append).write(log);
}
spu_recompiler::XmmLink spu_recompiler::XmmAlloc() // get empty xmm register
@@ -1083,7 +1081,7 @@ void spu_recompiler::CBX(spu_opcode_t op)
const XmmLink& vr = XmmAlloc();
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(asmjit::host::byte_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), 0x03);
c->mov(asmjit::host::byte_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), 0x03);
c->unuse(*addr);
}
@@ -1097,7 +1095,7 @@ void spu_recompiler::CHX(spu_opcode_t op)
const XmmLink& vr = XmmAlloc();
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(asmjit::host::word_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), 0x0203);
c->mov(asmjit::host::word_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), 0x0203);
c->unuse(*addr);
}
@@ -1111,7 +1109,7 @@ void spu_recompiler::CWX(spu_opcode_t op)
const XmmLink& vr = XmmAlloc();
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(asmjit::host::dword_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), 0x00010203);
c->mov(asmjit::host::dword_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), 0x00010203);
c->unuse(*addr);
}
@@ -1126,7 +1124,7 @@ void spu_recompiler::CDX(spu_opcode_t op)
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(*qw0, asmjit::imm_u(0x0001020304050607));
c->mov(asmjit::host::qword_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), *qw0);
c->mov(asmjit::host::qword_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), *qw0);
c->unuse(*addr);
c->unuse(*qw0);
}
@@ -1254,7 +1252,7 @@ void spu_recompiler::CBD(spu_opcode_t op)
const XmmLink& vr = XmmAlloc();
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(asmjit::host::byte_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), 0x03);
c->mov(asmjit::host::byte_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), 0x03);
c->unuse(*addr);
}
@@ -1279,7 +1277,7 @@ void spu_recompiler::CHD(spu_opcode_t op)
const XmmLink& vr = XmmAlloc();
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(asmjit::host::word_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), 0x0203);
c->mov(asmjit::host::word_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), 0x0203);
c->unuse(*addr);
}
@@ -1304,7 +1302,7 @@ void spu_recompiler::CWD(spu_opcode_t op)
const XmmLink& vr = XmmAlloc();
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(asmjit::host::dword_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), 0x00010203);
c->mov(asmjit::host::dword_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), 0x00010203);
c->unuse(*addr);
}
@@ -1330,7 +1328,7 @@ void spu_recompiler::CDD(spu_opcode_t op)
c->movdqa(vr, XmmConst(_mm_set_epi32(0x10111213, 0x14151617, 0x18191a1b, 0x1c1d1e1f)));
c->movdqa(SPU_OFF_128(gpr[op.rt]), vr);
c->mov(*qw0, asmjit::imm_u(0x0001020304050607));
c->mov(asmjit::host::qword_ptr(*cpu, *addr, 0, OFFSET_OF(SPUThread, gpr[op.rt])), *qw0);
c->mov(asmjit::host::qword_ptr(*cpu, *addr, 0, OFFSET_32(SPUThread, gpr[op.rt])), *qw0);
c->unuse(*addr);
c->unuse(*qw0);
}
+13 -52
View File
@@ -376,10 +376,7 @@ void SPUThread::do_dma_list_cmd(u32 cmd, spu_mfc_arg_t args)
void SPUThread::process_mfc_cmd(u32 cmd)
{
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "DMA %s: cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x", get_mfc_cmd_name(cmd), cmd, ch_mfc_args.lsa, ch_mfc_args.ea, ch_mfc_args.tag, ch_mfc_args.size);
}
LOG_TRACE(SPU, "DMA %s: cmd=0x%x, lsa=0x%x, ea=0x%llx, tag=0x%x, size=0x%x", get_mfc_cmd_name(cmd), cmd, ch_mfc_args.lsa, ch_mfc_args.ea, ch_mfc_args.tag, ch_mfc_args.size);
switch (cmd)
{
@@ -576,10 +573,7 @@ void SPUThread::set_interrupt_status(bool enable)
u32 SPUThread::get_ch_count(u32 ch)
{
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "get_ch_count(ch=%d [%s])", ch, ch < 128 ? spu_ch_name[ch] : "???");
}
LOG_TRACE(SPU, "get_ch_count(ch=%d [%s])", ch, ch < 128 ? spu_ch_name[ch] : "???");
switch (ch)
{
@@ -603,10 +597,7 @@ u32 SPUThread::get_ch_count(u32 ch)
u32 SPUThread::get_ch_value(u32 ch)
{
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "get_ch_value(ch=%d [%s])", ch, ch < 128 ? spu_ch_name[ch] : "???");
}
LOG_TRACE(SPU, "get_ch_value(ch=%d [%s])", ch, ch < 128 ? spu_ch_name[ch] : "???");
auto read_channel = [this](spu_channel_t& channel) -> u32
{
@@ -767,10 +758,7 @@ u32 SPUThread::get_ch_value(u32 ch)
void SPUThread::set_ch_value(u32 ch, u32 value)
{
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "set_ch_value(ch=%d [%s], value=0x%x)", ch, ch < 128 ? spu_ch_name[ch] : "???", value);
}
LOG_TRACE(SPU, "set_ch_value(ch=%d [%s], value=0x%x)", ch, ch < 128 ? spu_ch_name[ch] : "???", value);
switch (ch)
{
@@ -826,10 +814,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
ch_out_mbox.set_value(data, 0);
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data);
}
LOG_TRACE(SPU, "sys_spu_thread_send_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data);
const auto queue = this->spup[spup].lock();
@@ -865,10 +850,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
ch_out_mbox.set_value(data, 0);
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_WARNING(SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data);
}
LOG_TRACE(SPU, "sys_spu_thread_throw_event(spup=%d, data0=0x%x, data1=0x%x)", spup, value & 0x00ffffff, data);
const auto queue = this->spup[spup].lock();
@@ -915,10 +897,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
throw EXCEPTION("sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d)): Invalid flag", data, value, flag);
}
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_WARNING(SPU, "sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d))", data, value, flag);
}
LOG_TRACE(SPU, "sys_event_flag_set_bit(id=%d, value=0x%x (flag=%d))", data, value, flag);
const auto eflag = idm::get<lv2_event_flag_t>(data);
@@ -959,10 +938,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
throw EXCEPTION("sys_event_flag_set_bit_impatient(id=%d, value=0x%x (flag=%d)): Invalid flag", data, value, flag);
}
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_WARNING(SPU, "sys_event_flag_set_bit_impatient(id=%d, value=0x%x (flag=%d))", data, value, flag);
}
LOG_TRACE(SPU, "sys_event_flag_set_bit_impatient(id=%d, value=0x%x (flag=%d))", data, value, flag);
const auto eflag = idm::get<lv2_event_flag_t>(data);
@@ -1158,10 +1134,7 @@ void SPUThread::set_ch_value(u32 ch, u32 value)
void SPUThread::stop_and_signal(u32 code)
{
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "stop_and_signal(code=0x%x)", code);
}
LOG_TRACE(SPU, "stop_and_signal(code=0x%x)", code);
if (m_type == CPU_THREAD_RAW_SPU)
{
@@ -1229,10 +1202,7 @@ void SPUThread::stop_and_signal(u32 code)
ch_out_mbox.set_value(spuq, 0);
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq);
}
LOG_TRACE(SPU, "sys_spu_thread_receive_event(spuq=0x%x)", spuq);
const auto group = tg.lock();
@@ -1355,10 +1325,7 @@ void SPUThread::stop_and_signal(u32 code)
ch_out_mbox.set_value(value, 0);
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "sys_spu_thread_group_exit(status=0x%x)", value);
}
LOG_TRACE(SPU, "sys_spu_thread_group_exit(status=0x%x)", value);
const auto group = tg.lock();
@@ -1394,10 +1361,7 @@ void SPUThread::stop_and_signal(u32 code)
throw EXCEPTION("sys_spu_thread_exit(): Out_MBox is empty");
}
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "sys_spu_thread_exit(status=0x%x)", ch_out_mbox.get_value());
}
LOG_TRACE(SPU, "sys_spu_thread_exit(status=0x%x)", ch_out_mbox.get_value());
const auto group = tg.lock();
@@ -1425,10 +1389,7 @@ void SPUThread::stop_and_signal(u32 code)
void SPUThread::halt()
{
if (rpcs3::config.misc.log.hle_logging.value())
{
LOG_NOTICE(SPU, "halt()");
}
LOG_TRACE(SPU, "halt()");
if (m_type == CPU_THREAD_RAW_SPU)
{
+3 -5
View File
@@ -26,11 +26,9 @@ bool vfsFile::Open(const std::string& path, u32 mode)
return m_stream && m_stream->IsOpened();
}
bool vfsFile::Close()
void vfsFile::Close()
{
m_stream.reset();
return true;
}
u64 vfsFile::GetSize() const
@@ -48,9 +46,9 @@ u64 vfsFile::Read(void* dst, u64 size)
return m_stream->Read(dst, size);
}
u64 vfsFile::Seek(s64 offset, fsm mode)
u64 vfsFile::Seek(s64 offset, fs::seek_mode whence)
{
return m_stream->Seek(offset, mode);
return m_stream->Seek(offset, whence);
}
u64 vfsFile::Tell() const
+2 -2
View File
@@ -12,14 +12,14 @@ public:
vfsFile(const std::string& path, u32 mode = fom::read);
virtual bool Open(const std::string& path, u32 mode = fom::read) override;
virtual bool Close() override;
virtual void Close() override;
virtual u64 GetSize() const override;
virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override;
virtual u64 Seek(s64 offset, fsm seek_mode = fsm::begin) override;
virtual u64 Seek(s64 offset, fs::seek_mode whence = fs::seek_set) override;
virtual u64 Tell() const override;
virtual bool IsOpened() const override;
+2 -3
View File
@@ -20,11 +20,10 @@ bool vfsFileBase::Open(const std::string& path, u32 mode)
return true;
}
bool vfsFileBase::Close()
void vfsFileBase::Close()
{
m_path = "";
return vfsStream::Close();
vfsStream::Close();
}
std::string vfsFileBase::GetPath() const
+1 -1
View File
@@ -16,7 +16,7 @@ public:
virtual ~vfsFileBase() override;
virtual bool Open(const std::string& path, u32 mode);
virtual bool Close() override;
virtual void Close() override;
virtual bool IsOpened() const override { return !m_path.empty(); }
std::string GetPath() const;
+1 -1
View File
@@ -20,7 +20,7 @@ bool vfsLocalDir::Open(const std::string& path)
std::string name;
fs::stat_t file_info;
while (m_dir.read(name, file_info))
while (m_dir.read(name, file_info) && name.size())
{
m_entries.emplace_back();
+6 -5
View File
@@ -12,9 +12,10 @@ bool vfsLocalFile::Open(const std::string& path, u32 mode)
return m_file.open(path, mode) && vfsFileBase::Open(path, mode);
}
bool vfsLocalFile::Close()
void vfsLocalFile::Close()
{
return m_file.close() && vfsFileBase::Close();
m_file.close();
vfsFileBase::Close();
}
u64 vfsLocalFile::GetSize() const
@@ -32,14 +33,14 @@ u64 vfsLocalFile::Read(void* dst, u64 size)
return m_file.read(dst, size);
}
u64 vfsLocalFile::Seek(s64 offset, fsm mode)
u64 vfsLocalFile::Seek(s64 offset, fs::seek_mode whence)
{
return m_file.seek(offset, mode);
return m_file.seek(offset, whence);
}
u64 vfsLocalFile::Tell() const
{
return m_file.seek(0, fsm::cur);
return m_file.seek(0, fs::seek_cur);
}
bool vfsLocalFile::IsOpened() const
+2 -2
View File
@@ -11,14 +11,14 @@ public:
vfsLocalFile(vfsDevice* device);
virtual bool Open(const std::string& path, u32 mode = fom::read) override;
virtual bool Close() override;
virtual void Close() override;
virtual u64 GetSize() const override;
virtual u64 Write(const void* src, u64 size) override;
virtual u64 Read(void* dst, u64 size) override;
virtual u64 Seek(s64 offset, fsm seek_mode = fsm::begin) override;
virtual u64 Seek(s64 offset, fs::seek_mode whence = fs::seek_set) override;
virtual u64 Tell() const override;
virtual bool IsOpened() const override;
+31 -5
View File
@@ -9,28 +9,54 @@ struct vfsStream
Close();
}
virtual bool Close()
virtual void Close()
{
return true;
}
virtual u64 GetSize() const = 0;
virtual u64 Write(const void* src, u64 count) = 0;
template<typename T> force_inline bool SWrite(const T& data, u64 count = sizeof(T))
template<typename T>
force_inline bool SWrite(const T& data, u64 count = sizeof(T))
{
return Write(&data, count) == count;
}
virtual u64 Read(void* dst, u64 count) = 0;
template<typename T> force_inline bool SRead(T& data, u64 count = sizeof(T))
template<typename T>
force_inline bool SRead(T& data, u64 count = sizeof(T))
{
return Read(&data, count) == count;
}
virtual u64 Seek(s64 offset, fsm seek_mode = fsm::begin) = 0;
template<typename T>
bool VWrite(const std::vector<T>& vec)
{
return IsOpened() && Write(vec.data(), vec.size() * sizeof(T)) == vec.size() * sizeof(T);
}
template<typename T>
std::vector<T> VRead()
{
std::vector<T> result;
if (IsOpened() == false)
{
return result;
}
result.resize(GetSize() / sizeof(T));
if (Seek(0) == -1 || Read(result.data(), result.size() * sizeof(T)) != result.size() * sizeof(T))
{
result.clear();
}
return result;
}
virtual u64 Seek(s64 offset, fs::seek_mode whence = fs::seek_set) = 0;
virtual u64 Tell() const = 0;
+6 -6
View File
@@ -31,16 +31,16 @@ public:
virtual u64 Read(void* dst, u64 count) override;
virtual u64 Seek(s64 offset, fsm seek_mode = fsm::begin) override
virtual u64 Seek(s64 offset, fs::seek_mode whence) override
{
switch (seek_mode)
switch (whence)
{
case fsm::begin: return m_pos = offset;
case fsm::cur: return m_pos += offset;
case fsm::end: return m_pos = m_size + offset;
case fs::seek_set: return m_pos = offset;
case fs::seek_cur: return m_pos += offset;
case fs::seek_end: return m_pos = m_size + offset;
}
throw EXCEPTION("Unknown seek_mode (0x%x)", seek_mode);
throw EXCEPTION("Unknown seek_mode (0x%x)", whence);
}
virtual u64 Tell() const override
+7 -7
View File
@@ -787,16 +787,16 @@ u64 vfsHDD::Read(void* dst, u64 size)
return m_file.Read(dst, size); // ???
}
u64 vfsHDD::Seek(s64 offset, fsm seek_mode)
u64 vfsHDD::Seek(s64 offset, fs::seek_mode whence)
{
switch (seek_mode)
switch (whence)
{
case fsm::begin: return m_file.Seek(offset);
case fsm::cur: return m_file.Seek(Tell() + offset);
case fsm::end: return m_file.Seek(m_file.GetSize() + offset);
case fs::seek_set: return m_file.Seek(offset);
case fs::seek_cur: return m_file.Seek(Tell() + offset);
case fs::seek_end: return m_file.Seek(m_file.GetSize() + offset);
}
throw EXCEPTION("Unknown seek_mode(0x%x)", seek_mode);
throw EXCEPTION("Unknown whence (0x%x)", whence);
}
u64 vfsHDD::Tell() const
@@ -817,4 +817,4 @@ bool vfsHDD::IsOpened() const
u64 vfsHDD::GetSize() const
{
return m_file.GetSize();
}
}
+1 -1
View File
@@ -196,7 +196,7 @@ public:
virtual u64 Read(void* dst, u64 count) override;
virtual u64 Seek(s64 offset, fsm seek_mode = fsm::begin) override;
virtual u64 Seek(s64 offset, fs::seek_mode whence = fs::seek_set) override;
virtual u64 Tell() const override;
+1 -5
View File
@@ -15,7 +15,6 @@
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
/* OS X uses MAP_ANON instead of MAP_ANONYMOUS */
#ifndef MAP_ANONYMOUS
@@ -239,13 +238,10 @@ namespace vm
catch (...)
{
// capture any exception possibly thrown by predicate
pred = [exception = std::current_exception()]
pred = [exception = std::current_exception()]() -> bool
{
// new predicate will throw the captured exception from the original thread
std::rethrow_exception(exception);
// dummy return value, remove when std::rethrow_exception gains [[noreturn]] attribute in MSVC
return true;
};
}
+1 -1
View File
@@ -213,7 +213,7 @@ namespace vm
// Convert pointer-to-member to a vm address compatible offset
template<typename MT, typename T> inline u32 get_offset(MT T::*const member_ptr)
{
return static_cast<u32>(reinterpret_cast<std::uintptr_t>(&(reinterpret_cast<T*>(0ull)->*member_ptr)));
return static_cast<u32>(reinterpret_cast<std::uintptr_t>(&reinterpret_cast<char const volatile&>(reinterpret_cast<T*>(0ull)->*member_ptr)));
}
template<typename T> struct cast_ptr
+16 -16
View File
@@ -46,7 +46,7 @@ namespace vm
// get vm pointer to a struct member with array subscription
template<typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>> _ptr_base<ET> ptr(MT T2::*const mptr, u32 index) const
{
return{ VM_CAST(m_addr) + get_offset(mptr) + sizeof32(ET) * index, vm::addr };
return{ VM_CAST(m_addr) + get_offset(mptr) + SIZE_32(ET) * index, vm::addr };
}
// get vm reference to a struct member
@@ -58,7 +58,7 @@ namespace vm
// get vm reference to a struct member with array subscription
template<typename MT, typename T2, typename ET = std::remove_extent_t<MT>, typename = if_comparable_t<T, T2>> _ref_base<ET> ref(MT T2::*const mptr, u32 index) const
{
return{ VM_CAST(m_addr) + get_offset(mptr) + sizeof32(ET) * index, vm::addr };
return{ VM_CAST(m_addr) + get_offset(mptr) + SIZE_32(ET) * index, vm::addr };
}
// get vm reference
@@ -98,7 +98,7 @@ namespace vm
{
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: operator[] is not available for void pointers");
return *static_cast<T*>(vm::base(VM_CAST(m_addr) + sizeof32(T) * index));
return *static_cast<T*>(vm::base(VM_CAST(m_addr) + SIZE_32(T) * index));
}
// enable only the conversions which are originally possible between pointer types
@@ -128,7 +128,7 @@ namespace vm
{
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: aligned() is not available for void pointers");
return aligned(alignof32(T));
return aligned(ALIGN_32(T));
}
// Test address for arbitrary alignment: (addr & (align - 1)) != 0
@@ -143,7 +143,7 @@ namespace vm
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: operator++ is not available for void pointers");
const addr_type result = m_addr;
m_addr = VM_CAST(m_addr) + sizeof32(T);
m_addr = VM_CAST(m_addr) + SIZE_32(T);
return{ result, vm::addr };
}
@@ -152,7 +152,7 @@ namespace vm
{
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: operator++ is not available for void pointers");
m_addr = VM_CAST(m_addr) + sizeof32(T);
m_addr = VM_CAST(m_addr) + SIZE_32(T);
return *this;
}
@@ -162,7 +162,7 @@ namespace vm
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: operator-- is not available for void pointers");
const addr_type result = m_addr;
m_addr = VM_CAST(m_addr) - sizeof32(T);
m_addr = VM_CAST(m_addr) - SIZE_32(T);
return{ result, vm::addr };
}
@@ -171,7 +171,7 @@ namespace vm
{
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: operator-- is not available for void pointers");
m_addr = VM_CAST(m_addr) - sizeof32(T);
m_addr = VM_CAST(m_addr) - SIZE_32(T);
return *this;
}
@@ -179,7 +179,7 @@ namespace vm
{
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: operator+= is not available for void pointers");
m_addr = VM_CAST(m_addr) + count * sizeof32(T);
m_addr = VM_CAST(m_addr) + count * SIZE_32(T);
return *this;
}
@@ -187,7 +187,7 @@ namespace vm
{
static_assert(!std::is_void<T>::value, "vm::_ptr_base<> error: operator-= is not available for void pointers");
m_addr = VM_CAST(m_addr) - count * sizeof32(T);
m_addr = VM_CAST(m_addr) - count * SIZE_32(T);
return *this;
}
};
@@ -350,13 +350,13 @@ namespace vm
// Call wait_op() for specified vm pointer
template<typename T, typename AT, typename F, typename... Args> inline auto wait_op(named_thread_t& thread, const _ptr_base<T, AT>& ptr, F pred, Args&&... args) -> decltype(static_cast<void>(pred(args...)))
{
return wait_op(thread, ptr.addr(), sizeof32(T), std::move(pred), std::forward<Args>(args)...);
return wait_op(thread, ptr.addr(), SIZE_32(T), std::move(pred), std::forward<Args>(args)...);
}
// Call notify_at() for specified vm pointer
template<typename T, typename AT> inline void notify_at(const vm::_ptr_base<T, AT>& ptr)
{
return notify_at(ptr.addr(), sizeof32(T));
return notify_at(ptr.addr(), SIZE_32(T));
}
}
@@ -375,19 +375,19 @@ template<typename T, typename AT> inline std::enable_if_t<std::is_object<T>::val
// addition operator for vm::_ptr_base (pointer + integer)
template<typename T, typename AT> inline std::enable_if_t<std::is_object<T>::value, vm::_ptr_base<T>> operator +(const vm::_ptr_base<T, AT>& ptr, u32 count)
{
return{ VM_CAST(ptr.addr()) + count * sizeof32(T), vm::addr };
return{ VM_CAST(ptr.addr()) + count * SIZE_32(T), vm::addr };
}
// addition operator for vm::_ptr_base (integer + pointer)
template<typename T, typename AT> inline std::enable_if_t<std::is_object<T>::value, vm::_ptr_base<T>> operator +(u32 count, const vm::_ptr_base<T, AT>& ptr)
{
return{ VM_CAST(ptr.addr()) + count * sizeof32(T), vm::addr };
return{ VM_CAST(ptr.addr()) + count * SIZE_32(T), vm::addr };
}
// subtraction operator for vm::_ptr_base (pointer - integer)
template<typename T, typename AT> inline std::enable_if_t<std::is_object<T>::value, vm::_ptr_base<T>> operator -(const vm::_ptr_base<T, AT>& ptr, u32 count)
{
return{ VM_CAST(ptr.addr()) - count * sizeof32(T), vm::addr };
return{ VM_CAST(ptr.addr()) - count * SIZE_32(T), vm::addr };
}
// pointer difference operator for vm::_ptr_base
@@ -397,7 +397,7 @@ template<typename T1, typename AT1, typename T2, typename AT2> inline std::enabl
std::is_same<std::remove_cv_t<T1>, std::remove_cv_t<T2>>::value,
s32> operator -(const vm::_ptr_base<T1, AT1>& left, const vm::_ptr_base<T2, AT2>& right)
{
return static_cast<s32>(VM_CAST(left.addr()) - VM_CAST(right.addr())) / sizeof32(T1);
return static_cast<s32>(VM_CAST(left.addr()) - VM_CAST(right.addr())) / SIZE_32(T1);
}
// comparison operator for vm::_ptr_base (pointer1 == pointer2)
+8 -8
View File
@@ -103,7 +103,7 @@ namespace vm
public:
// Call the constructor with specified arguments
template<typename... Args, typename = std::enable_if_t<std::is_constructible<T, Args...>::value>> _var_base(Args&&... args)
: pointer(A::alloc(sizeof32(T), alignof32(T)), vm::addr)
: pointer(A::alloc(SIZE_32(T), ALIGN_32(T)), vm::addr)
{
#include "restore_new.h"
new(pointer::get_ptr()) T(std::forward<Args>(args)...);
@@ -118,7 +118,7 @@ namespace vm
pointer::get_ptr()->~T();
// Deallocate memory
A::dealloc(pointer::addr(), sizeof32(T));
A::dealloc(pointer::addr(), SIZE_32(T));
}
// Remove operator []
@@ -135,7 +135,7 @@ namespace vm
public:
// Call the default constructor for each element
_var_base(u32 count)
: pointer(A::alloc(sizeof32(T) * count, alignof32(T)), vm::addr)
: pointer(A::alloc(SIZE_32(T) * count, ALIGN_32(T)), vm::addr)
, m_count(count)
{
#include "restore_new.h"
@@ -145,7 +145,7 @@ namespace vm
// Call the constructor for each element using [it, it + count)
template<typename T2> _var_base(u32 count, T2 it)
: pointer(A::alloc(sizeof32(T) * count, alignof32(T)), vm::addr)
: pointer(A::alloc(SIZE_32(T) * count, ALIGN_32(T)), vm::addr)
, m_count(count)
{
#include "restore_new.h"
@@ -161,7 +161,7 @@ namespace vm
for (u32 i = m_count - 1; ~i; i--) pointer::operator [](i).~T();
// Deallocate memory
A::dealloc(pointer::addr(), sizeof32(T) * m_count);
A::dealloc(pointer::addr(), SIZE_32(T) * m_count);
}
u32 get_count() const
@@ -188,7 +188,7 @@ namespace vm
public:
// Call the default constructor for each element
_var_base()
: pointer(A::alloc(sizeof32(T) * N, alignof32(T)), vm::addr)
: pointer(A::alloc(SIZE_32(T) * N, ALIGN_32(T)), vm::addr)
{
#include "restore_new.h"
new(pointer::get_ptr()) T[N]();
@@ -197,7 +197,7 @@ namespace vm
// Call the constructor for each element using array
template<typename T2> _var_base(const T2(&array)[N])
: pointer(A::alloc(sizeof32(T) * N, alignof32(T)), vm::addr)
: pointer(A::alloc(SIZE_32(T) * N, ALIGN_32(T)), vm::addr)
{
#include "restore_new.h"
for (u32 i = 0; i < N; i++) new(pointer::get_ptr() + i) T(array[i]);
@@ -212,7 +212,7 @@ namespace vm
for (u32 i = N - 1; ~i; i--) pointer::operator [](i).~T();
// Deallocate memory
A::dealloc(pointer::addr(), sizeof32(T) * N);
A::dealloc(pointer::addr(), SIZE_32(T) * N);
}
constexpr u32 get_count() const
+8 -4
View File
@@ -309,7 +309,7 @@ public:
m_arb_shader += fmt::format("#%d ", i) + param_type + param_name + param_semantic + param_const + "\n";
offset += sizeof32(CgBinaryParameter);
offset += SIZE_32(CgBinaryParameter);
}
m_arb_shader += "\n";
@@ -334,7 +334,9 @@ public:
u32 size;
u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0);
std::vector<texture_dimension> td;
GLFragmentDecompilerThread(m_glsl_shader, param_array, ptr + vmprog.ucode, size, ctrl, td).Task();
RSXFragmentProgram prog;
prog.size = 0, prog.addr = vm::base(ptr + vmprog.ucode), prog.offset = 0, prog.ctrl = ctrl;
GLFragmentDecompilerThread(m_glsl_shader, param_array, prog, size).Task();
vm::close();
}
}
@@ -364,7 +366,7 @@ public:
m_arb_shader += fmt::format("#%d ", i) + param_type + param_name + param_semantic + param_const + "\n";
offset += sizeof32(CgBinaryParameter);
offset += SIZE_32(CgBinaryParameter);
}
m_arb_shader += "\n";
@@ -383,7 +385,9 @@ public:
}
TaskVP();
GLVertexDecompilerThread(m_data, m_glsl_shader, param_array).Task();
RSXVertexProgram prog;
prog.data = m_data;
GLVertexDecompilerThread(prog, m_glsl_shader, param_array).Task();
}
}
+2 -2
View File
@@ -60,7 +60,7 @@ std::string CgBinaryDisasm::GetDSTDisasm(bool isSca)
default:
if (d3.dst > 15)
LOG_ERROR(RSX, fmt::format("dst index out of range: %u", d3.dst));
LOG_ERROR(RSX, "dst index out of range: %u", d3.dst);
ret += fmt::format("o[%d]", d3.dst) + GetVecMaskDisasm();
break;
@@ -94,7 +94,7 @@ std::string CgBinaryDisasm::GetSRCDisasm(const u32 n)
break;
default:
LOG_ERROR(RSX, fmt::format("Bad src%u reg type: %d", n, u32{ src[n].reg_type }));
LOG_ERROR(RSX, "Bad src%u reg type: %d", n, u32{ src[n].reg_type });
Emu.Pause();
break;
}
+277 -148
View File
@@ -5,34 +5,54 @@
#define MIN2(x, y) ((x) < (y)) ? (x) : (y)
#define MAX2(x, y) ((x) > (y)) ? (x) : (y)
namespace
{
/**
* Convert CMP vector to RGBA16.
* A vector in CMP (compressed) format is stored as X11Y11Z10 and has a W component of 1.
* X11 and Y11 channels are int between -1024 and 1023 interpreted as -1.f, 1.f
* Z10 is int between -512 and 511 interpreted as -1.f, 1.f
*/
std::array<u16, 4> decode_cmp_vector(u32 encoded_vector)
{
u16 Z = encoded_vector >> 22;
Z = Z << 6;
u16 Y = (encoded_vector >> 11) & 0x7FF;
Y = Y << 5;
u16 X = encoded_vector & 0x7FF;
X = X << 5;
return{ X, Y, Z, 1 };
}
}
// FIXME: these functions shouldn't access rsx::method_registers (global)
void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_t index, const rsx::data_array_format_info &vertex_array_desc)
{
assert(vertex_array_desc.size > 0);
if (vertex_array_desc.frequency > 1)
LOG_ERROR(RSX, "%s: frequency is not null (%d, index=%d)", __FUNCTION__, vertex_array_desc.frequency, index);
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 address = rsx::get_address(offset & 0x7fffffff, offset >> 31);
u32 type_size = rsx::get_vertex_type_size(vertex_array_desc.type);
u32 element_size = type_size * vertex_array_desc.size;
Expects(vertex_array_desc.size > 0);
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_ARRAY_OFFSET + index];
u32 address = base_offset + rsx::get_address(offset & 0x7fffffff, offset >> 31);
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_array_desc.type, vertex_array_desc.size);
u32 base_index = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX];
for (u32 i = 0; i < count; ++i)
{
auto src = vm::ps3::_ptr<const u8>(address + base_offset + vertex_array_desc.stride * (first + i + base_index));
auto src = vm::ps3::_ptr<const u8>(address + vertex_array_desc.stride * (first + i + base_index));
u8* dst = (u8*)buffer + i * element_size;
switch (type_size)
switch (vertex_array_desc.type)
{
case 1:
case rsx::vertex_base_type::ub:
memcpy(dst, src, vertex_array_desc.size);
break;
case 2:
case rsx::vertex_base_type::s1:
case rsx::vertex_base_type::sf:
{
auto* c_src = (const be_t<u16>*)src;
u16* c_dst = (u16*)dst;
@@ -41,10 +61,14 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
{
*c_dst++ = *c_src++;
}
if (vertex_array_desc.size * sizeof(u16) < element_size)
*c_dst++ = 0x3c00;
break;
}
case 4:
case rsx::vertex_base_type::f:
case rsx::vertex_base_type::s32k:
case rsx::vertex_base_type::ub256:
{
auto* c_src = (const be_t<u32>*)src;
u32* c_dst = (u32*)dst;
@@ -55,137 +79,186 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
}
break;
}
case rsx::vertex_base_type::cmp:
{
auto* c_src = (const be_t<u32>*)src;
const auto& decoded_vector = decode_cmp_vector(*c_src);
u16* c_dst = (u16*)dst;
c_dst[0] = decoded_vector[0];
c_dst[1] = decoded_vector[1];
c_dst[2] = decoded_vector[2];
c_dst[3] = decoded_vector[3];
break;
}
}
}
}
namespace
{
template<typename IndexType>
void uploadAsIt(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index)
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)
{
for (u32 i = 0; i < indexCount; ++i)
T min_index = -1;
T max_index = 0;
Expects(dst.size_bytes() >= src.size_bytes());
size_t dst_idx = 0;
for (T index : src)
{
IndexType index = vm::ps3::_ref<IndexType>(address + i * sizeof(IndexType));
if (is_primitive_restart_enabled && index == (IndexType)primitive_restart_index)
index = (IndexType)-1;
(IndexType&)dst[i * sizeof(IndexType)] = index;
if (is_primitive_restart_enabled && index == (IndexType)-1) // Cut
continue;
max_index = MAX2(max_index, index);
min_index = MIN2(min_index, index);
if (is_primitive_restart_enabled && index == primitive_restart_index)
{
index = -1;
}
else
{
max_index = MAX2(max_index, index);
min_index = MIN2(min_index, index);
}
dst[dst_idx++] = index;
}
return std::make_tuple(min_index, max_index);
}
// FIXME: expanded primitive type may not support primitive restart correctly
template<typename IndexType>
void expandIndexedTriangleFan(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index)
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)
{
for (unsigned i = 0; i < indexCount - 2; i++)
T min_index = -1;
T max_index = 0;
Expects(dst.size() >= 3 * (src.size() - 2));
const T index0 = src[0];
if (!is_primitive_restart_enabled || index0 != -1) // Cut
{
IndexType index0 = vm::ps3::_ref<IndexType>(address);
if (index0 == (IndexType)primitive_restart_index)
index0 = (IndexType)-1;
IndexType index1 = vm::ps3::_ref<IndexType>(address + (i + 2 - 1) * sizeof(IndexType));
if (index1 == (IndexType)primitive_restart_index)
index1 = (IndexType)-1;
IndexType index2 = vm::ps3::_ref<IndexType>(address + (i + 2) * sizeof(IndexType));
if (index2 == (IndexType)primitive_restart_index)
index2 = (IndexType)-1;
min_index = MIN2(min_index, index0);
max_index = MAX2(max_index, index0);
}
(IndexType&)dst[(3 * i) * sizeof(IndexType)] = index0;
(IndexType&)dst[(3 * i + 1) * sizeof(IndexType)] = index1;
(IndexType&)dst[(3 * i + 2) * sizeof(IndexType)] = index2;
if (!is_primitive_restart_enabled || index0 != (IndexType)-1) // Cut
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)
{
min_index = MIN2(min_index, index0);
max_index = MAX2(max_index, index0);
index1 = -1;
}
if (!is_primitive_restart_enabled || index1 != (IndexType)-1) // Cut
else
{
min_index = MIN2(min_index, index1);
max_index = MAX2(max_index, index1);
}
if (!is_primitive_restart_enabled || index2 != (IndexType)-1) // Cut
T index2 = tri_indexes[1];
if (is_primitive_restart_enabled && index2 == primitive_restart_index)
{
index2 = -1;
}
else
{
min_index = MIN2(min_index, index2);
max_index = MAX2(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);
}
template<typename IndexType>
void expandIndexedQuads(char *dst, u32 address, size_t indexCount, bool is_primitive_restart_enabled, u32 primitive_restart_index, u32 &min_index, u32 &max_index)
// 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)
{
for (unsigned i = 0; i < indexCount / 4; i++)
T min_index = -1;
T max_index = 0;
Expects(4 * dst.size_bytes() >= 6 * src.size_bytes());
size_t dst_idx = 0;
while (!src.empty())
{
IndexType index0 = vm::ps3::_ref<IndexType>(address + 4 * i * sizeof(IndexType));
if (is_primitive_restart_enabled && index0 == (IndexType)primitive_restart_index)
index0 = (IndexType)-1;
IndexType index1 = vm::ps3::_ref<IndexType>(address + (4 * i + 1) * sizeof(IndexType));
if (is_primitive_restart_enabled && index1 == (IndexType)primitive_restart_index)
index1 = (IndexType)-1;
IndexType index2 = vm::ps3::_ref<IndexType>(address + (4 * i + 2) * sizeof(IndexType));
if (is_primitive_restart_enabled && index2 == (IndexType)primitive_restart_index)
index2 = (IndexType)-1;
IndexType index3 = vm::ps3::_ref<IndexType>(address + (4 * i + 3) * sizeof(IndexType));
if (is_primitive_restart_enabled &&index3 == (IndexType)primitive_restart_index)
index3 = (IndexType)-1;
// First triangle
(IndexType&)dst[(6 * i) * sizeof(IndexType)] = index0;
(IndexType&)dst[(6 * i + 1) * sizeof(IndexType)] = index1;
(IndexType&)dst[(6 * i + 2) * sizeof(IndexType)] = index2;
// Second triangle
(IndexType&)dst[(6 * i + 3) * sizeof(IndexType)] = index2;
(IndexType&)dst[(6 * i + 4) * sizeof(IndexType)] = index3;
(IndexType&)dst[(6 * i + 5) * sizeof(IndexType)] = index0;
if (!is_primitive_restart_enabled || index0 != (IndexType)-1) // Cut
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)
{
index0 = -1;
}
else
{
min_index = MIN2(min_index, index0);
max_index = MAX2(max_index, index0);
}
if (!is_primitive_restart_enabled || index1 != (IndexType)-1) // Cut
T index1 = quad_indexes[1];
if (is_primitive_restart_enabled && index1 == primitive_restart_index)
{
index1 = -1;
}
else
{
min_index = MIN2(min_index, index1);
max_index = MAX2(max_index, index1);
}
if (!is_primitive_restart_enabled || index2 != (IndexType)-1) // Cut
T index2 = quad_indexes[2];
if (is_primitive_restart_enabled && index2 == primitive_restart_index)
{
index2 = -1;
}
else
{
min_index = MIN2(min_index, index2);
max_index = MAX2(max_index, index2);
}
if (!is_primitive_restart_enabled || index3 != (IndexType)-1) // Cut
T index3 = quad_indexes[3];
if (is_primitive_restart_enabled &&index3 == primitive_restart_index)
{
index3 = -1;
}
else
{
min_index = MIN2(min_index, index3);
max_index = MAX2(max_index, index3);
}
// 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;
src = src.subspan(4);
}
return std::make_tuple(min_index, max_index);
}
}
// Only handle quads and triangle fan now
bool is_primitive_native(unsigned m_draw_mode)
bool is_primitive_native(rsx::primitive_type draw_mode)
{
switch (m_draw_mode)
switch (draw_mode)
{
default:
case CELL_GCM_PRIMITIVE_POINTS:
case CELL_GCM_PRIMITIVE_LINES:
case CELL_GCM_PRIMITIVE_LINE_LOOP:
case CELL_GCM_PRIMITIVE_LINE_STRIP:
case CELL_GCM_PRIMITIVE_TRIANGLES:
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
case rsx::primitive_type::points:
case rsx::primitive_type::lines:
case rsx::primitive_type::line_loop:
case rsx::primitive_type::line_strip:
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
case rsx::primitive_type::quad_strip:
return true;
case CELL_GCM_PRIMITIVE_POLYGON:
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
case CELL_GCM_PRIMITIVE_QUADS:
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
case rsx::primitive_type::quads:
return false;
}
throw new EXCEPTION("Wrong primitive type");
}
/** We assume that polygon is convex in polygon mode (constraints in OpenGL)
@@ -193,41 +266,41 @@ bool is_primitive_native(unsigned m_draw_mode)
* see http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/polygon-triangulation-r3334
*/
size_t get_index_count(unsigned m_draw_mode, unsigned initial_index_count)
size_t get_index_count(rsx::primitive_type draw_mode, unsigned initial_index_count)
{
// Index count
if (is_primitive_native(m_draw_mode))
if (is_primitive_native(draw_mode))
return initial_index_count;
switch (m_draw_mode)
switch (draw_mode)
{
case CELL_GCM_PRIMITIVE_POLYGON:
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
return (initial_index_count - 2) * 3;
case CELL_GCM_PRIMITIVE_QUADS:
case rsx::primitive_type::quads:
return (6 * initial_index_count) / 4;
default:
return 0;
}
}
size_t get_index_type_size(u32 type)
size_t get_index_type_size(rsx::index_array_type type)
{
switch (type)
{
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: return 2;
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: return 4;
default: return 0;
case rsx::index_array_type::u16: return sizeof(u16);
case rsx::index_array_type::u32: return sizeof(u32);
}
throw new EXCEPTION("Wrong index type");
}
void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst, unsigned draw_mode, unsigned first, unsigned count)
void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst, rsx::primitive_type draw_mode, unsigned first, unsigned count)
{
unsigned short *typedDst = (unsigned short *)(dst);
switch (draw_mode)
{
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
case CELL_GCM_PRIMITIVE_POLYGON:
case rsx::primitive_type::triangle_fan:
case rsx::primitive_type::polygon:
for (unsigned i = 0; i < (count - 2); i++)
{
typedDst[3 * i] = first;
@@ -235,7 +308,7 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
typedDst[3 * i + 2] = i + 2;
}
return;
case CELL_GCM_PRIMITIVE_QUADS:
case rsx::primitive_type::quads:
for (unsigned i = 0; i < count / 4; i++)
{
// First triangle
@@ -248,62 +321,118 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
typedDst[6 * i + 5] = 4 * i + first;
}
return;
case rsx::primitive_type::points:
case rsx::primitive_type::lines:
case rsx::primitive_type::line_loop:
case rsx::primitive_type::line_strip:
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
case rsx::primitive_type::quad_strip:
throw new EXCEPTION("Native primitive type doesn't require expansion");
}
}
void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned first, unsigned count, unsigned &min_index, unsigned &max_index)
// 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, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_INDEX_ARRAY_ADDRESS], rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] & 0xf);
u32 type = rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4;
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
u32 type_size = type == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32 ? sizeof(u32) : sizeof(u16);
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
Expects(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
u32 base_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
u32 base_index = 0;//rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX];
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
u32 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
switch (m_draw_mode)
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
{
case CELL_GCM_PRIMITIVE_POINTS:
case CELL_GCM_PRIMITIVE_LINES:
case CELL_GCM_PRIMITIVE_LINE_LOOP:
case CELL_GCM_PRIMITIVE_LINE_STRIP:
case CELL_GCM_PRIMITIVE_TRIANGLES:
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP:
case CELL_GCM_PRIMITIVE_QUAD_STRIP:
case CELL_GCM_PRIMITIVE_POLYGON:
switch (type)
{
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
uploadAsIt<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
return;
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
uploadAsIt<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
return;
}
return;
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN:
switch (type)
{
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
expandIndexedTriangleFan<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
return;
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
expandIndexedTriangleFan<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
return;
}
case CELL_GCM_PRIMITIVE_QUADS:
switch (type)
{
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32:
expandIndexedQuads<u32>(dst, address + (first + base_index) * sizeof(u32), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
return;
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16:
expandIndexedQuads<u16>(dst, address + (first + base_index) * sizeof(u16), count, is_primitive_restart_enabled, primitive_restart_index, min_index, max_index);
return;
}
const std::tuple<u32, u32> &range = first_count_arguments[i];
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
Expects(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
}
u32 first = std::get<0>(first_count_arguments.front());
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
auto ptr = vm::ps3::_ptr<const T>(address + first * type_size);
switch (draw_mode)
{
case rsx::primitive_type::points:
case rsx::primitive_type::lines:
case rsx::primitive_type::line_loop:
case rsx::primitive_type::line_strip:
case rsx::primitive_type::triangles:
case rsx::primitive_type::triangle_strip:
case rsx::primitive_type::quad_strip:
return upload_untouched<T>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
return expand_indexed_triangle_fan<T>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
case rsx::primitive_type::quads:
return expand_indexed_quads<T>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
}
throw new EXCEPTION("Unknow draw mode");
}
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<u32, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
return write_index_array_data_to_buffer_impl(dst, draw_mode, first_count_arguments);
}
std::tuple<u16, u16> write_index_array_data_to_buffer(gsl::span<u16, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
return write_index_array_data_to_buffer_impl(dst, draw_mode, first_count_arguments);
}
std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_INDEX_ARRAY_ADDRESS], rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] & 0xf);
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
u32 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
{
const std::tuple<u32, u32> &range = first_count_arguments[i];
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
Expects(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
}
u32 first = std::get<0>(first_count_arguments.front());
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
auto ptr = vm::ps3::_ptr<const u32>(address + first * type_size);
return upload_untouched<u32>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
}
std::tuple<u16, u16> write_index_array_data_to_buffer_untouched(gsl::span<u16, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments)
{
u32 address = rsx::get_address(rsx::method_registers[NV4097_SET_INDEX_ARRAY_ADDRESS], rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] & 0xf);
rsx::index_array_type type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
u32 type_size = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
u16 primitive_restart_index = rsx::method_registers[NV4097_SET_RESTART_INDEX];
// Disjoint first_counts ranges not supported atm
for (int i = 0; i < first_count_arguments.size() - 1; i++)
{
const std::tuple<u32, u32> &range = first_count_arguments[i];
const std::tuple<u32, u32> &next_range = first_count_arguments[i + 1];
Expects(std::get<0>(range) + std::get<1>(range) == std::get<0>(next_range));
}
u32 first = std::get<0>(first_count_arguments.front());
u32 count = std::get<0>(first_count_arguments.back()) + std::get<1>(first_count_arguments.back()) - first;
auto ptr = vm::ps3::_ptr<const u16>(address + first * type_size);
return upload_untouched<u16>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
}
void stream_vector(void *dst, u32 x, u32 y, u32 z, u32 w)
+13 -15
View File
@@ -3,15 +3,6 @@
#include "Emu/Memory/vm.h"
#include "../RSXThread.h"
struct VertexBufferFormat
{
std::pair<size_t, size_t> range;
std::vector<size_t> attributeId;
size_t elementCount;
size_t stride;
};
/**
* Write count vertex attributes from index array buffer starting at first, using vertex_array_desc
*/
@@ -20,29 +11,36 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
/*
* If primitive mode is not supported and need to be emulated (using an index buffer) returns false.
*/
bool is_primitive_native(unsigned m_draw_mode);
bool is_primitive_native(rsx::primitive_type m_draw_mode);
/**
* Returns a fixed index count for emulated primitive, otherwise returns initial_index_count
*/
size_t get_index_count(unsigned m_draw_mode, unsigned initial_index_count);
size_t get_index_count(rsx::primitive_type m_draw_mode, unsigned initial_index_count);
/**
* Returns index type size in byte
*/
size_t get_index_type_size(u32 type);
size_t get_index_type_size(rsx::index_array_type type);
/**
* Write count indexes starting at first to dst buffer.
* Write count indexes using (first, first + count) ranges.
* Returns min/max index found during the process.
* The function expands index buffer for non native primitive type.
*/
void write_index_array_data_to_buffer(char* dst, unsigned m_draw_mode, unsigned first, unsigned count, unsigned &min_index, unsigned &max_index);
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<u32, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments);
std::tuple<u16, u16> write_index_array_data_to_buffer(gsl::span<u16, gsl::dynamic_range> dst, rsx::primitive_type draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments);
/**
* Doesn't expand index
*/
std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments);
std::tuple<u16, u16> write_index_array_data_to_buffer_untouched(gsl::span<u16, gsl::dynamic_range> dst, const std::vector<std::pair<u32, u32> > &first_count_arguments);
/**
* Write index data needed to emulate non indexed non native primitive mode.
*/
void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst, unsigned m_draw_mode, unsigned first, unsigned count);
void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst, rsx::primitive_type draw_mode, unsigned first, unsigned count);
/**
* Stream a 128 bits vector to dst.
@@ -4,13 +4,12 @@
#include "FragmentProgramDecompiler.h"
FragmentProgramDecompiler::FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions) :
m_addr(addr),
FragmentProgramDecompiler::FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size) :
m_prog(prog),
m_size(size),
m_const_index(0),
m_location(0),
m_ctrl(ctrl),
m_texture_dimensions(texture_dimensions)
m_ctrl(prog.ctrl)
{
m_size = 0;
}
@@ -114,7 +113,7 @@ std::string FragmentProgramDecompiler::AddConst()
return name;
}
auto data = vm::ps3::ptr<u32>::make(m_addr + m_size + 4 * sizeof32(u32));
auto data = (be_t<u32>*) ((char*)m_prog.addr + m_size + 4 * SIZE_32(u32));
m_offset = 2 * 4 * sizeof(u32);
u32 x = GetData(data[0]);
@@ -128,7 +127,23 @@ std::string FragmentProgramDecompiler::AddConst()
std::string FragmentProgramDecompiler::AddTex()
{
return m_parr.AddParam(PF_PARAM_UNIFORM, (m_texture_dimensions[dst.tex_num] == texture_dimension::texture_dimension_cubemap) ? "samplerCube" : "sampler2D", std::string("tex") + std::to_string(dst.tex_num));
std::string sampler;
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case texture_dimension::texture_dimension_1d:
sampler = "sampler1D";
break;
case texture_dimension::texture_dimension_cubemap:
sampler = "samplerCube";
break;
case texture_dimension::texture_dimension_2d:
sampler = "sampler2D";
break;
case texture_dimension::texture_dimension_3d:
sampler = "sampler3D";
break;
}
return m_parr.AddParam(PF_PARAM_UNIFORM, sampler, std::string("tex") + std::to_string(dst.tex_num));
}
std::string FragmentProgramDecompiler::Format(const std::string& code)
@@ -259,7 +274,7 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
{
static const std::string reg_table[] =
{
"gl_Position",
"gl_FragCoord",
"diff_color", "spec_color",
"fogc",
"tc0", "tc1", "tc2", "tc3", "tc4", "tc5", "tc6", "tc7", "tc8", "tc9",
@@ -340,8 +355,10 @@ bool FragmentProgramDecompiler::handle_sct(u32 opcode)
switch (opcode)
{
case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); return true;
case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); return true;
case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1).xxxx)"); return true;
case RSX_FP_OPCODE_DIV: SetDst("($0 / $1.xxxx)"); return true;
// Note: DIVSQ is not IEEE compliant. divsq(0, 0) is 0 (Super Puzzle Fighter II Turbo HD Remix).
// sqrt(x, 0) might be equal to some big value (in absolute) whose sign is sign(x) but it has to be proven.
case RSX_FP_OPCODE_DIVSQ: SetDst("divsq_legacy($0, $1)"); return true;
case RSX_FP_OPCODE_DP2: SetDst(getFunction(FUNCTION::FUNCTION_DP2)); return true;
case RSX_FP_OPCODE_DP3: SetDst(getFunction(FUNCTION::FUNCTION_DP3)); return true;
case RSX_FP_OPCODE_DP4: SetDst(getFunction(FUNCTION::FUNCTION_DP4)); return true;
@@ -351,8 +368,11 @@ bool FragmentProgramDecompiler::handle_sct(u32 opcode)
case RSX_FP_OPCODE_MIN: SetDst("min($0, $1)"); return true;
case RSX_FP_OPCODE_MOV: SetDst("$0"); return true;
case RSX_FP_OPCODE_MUL: SetDst("($0 * $1)"); return true;
case RSX_FP_OPCODE_RCP: SetDst("1.0 / $0"); return true;
case RSX_FP_OPCODE_RSQ: SetDst("1.f / sqrt($0)"); return true;
// Note: It's higly likely that RCP is not IEEE compliant but a game that uses rcp(0) has to be found
case RSX_FP_OPCODE_RCP: SetDst("rcp_legacy($0)"); return true;
// Note: RSQ is not IEEE compliant. rsq(0) is some big number (Silent Hill 3 HD)
// It is not know what happens if 0 is negative.
case RSX_FP_OPCODE_RSQ: SetDst("rsq_legacy($0)"); return true;
case RSX_FP_OPCODE_SEQ: SetDst(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SEQ, "$0", "$1") + ")"); return true;
case RSX_FP_OPCODE_SFL: SetDst(getFunction(FUNCTION::FUNCTION_SFL)); return true;
case RSX_FP_OPCODE_SGE: SetDst(getFloatTypeName(4) + "(" + compareFunction(COMPARE::FUNCTION_SGE, "$0", "$1") + ")"); return true;
@@ -371,8 +391,10 @@ bool FragmentProgramDecompiler::handle_scb(u32 opcode)
{
case RSX_FP_OPCODE_ADD: SetDst("($0 + $1)"); return true;
case RSX_FP_OPCODE_COS: SetDst("cos($0.xxxx)"); return true;
case RSX_FP_OPCODE_DIV: SetDst("($0 / $1)"); return true;
case RSX_FP_OPCODE_DIVSQ: SetDst("($0 / sqrt($1).xxxx)"); return true;
case RSX_FP_OPCODE_DIV: SetDst("($0 / $1.xxxx)"); return true;
// Note: DIVSQ is not IEEE compliant. sqrt(0, 0) is 0 (Super Puzzle Fighter II Turbo HD Remix).
// sqrt(x, 0) might be equal to some big value (in absolute) whose sign is sign(x) but it has to be proven.
case RSX_FP_OPCODE_DIVSQ: SetDst("divsq_legacy($0, sqrt($1).xxxx)"); return true;
case RSX_FP_OPCODE_DP2: SetDst(getFunction(FUNCTION::FUNCTION_DP2)); return true;
case RSX_FP_OPCODE_DP3: SetDst(getFunction(FUNCTION::FUNCTION_DP3)); return true;
case RSX_FP_OPCODE_DP4: SetDst(getFunction(FUNCTION::FUNCTION_DP4)); return true;
@@ -382,7 +404,7 @@ bool FragmentProgramDecompiler::handle_scb(u32 opcode)
case RSX_FP_OPCODE_EX2: SetDst("exp2($0.xxxx)"); return true;
case RSX_FP_OPCODE_FLR: SetDst("floor($0)"); return true;
case RSX_FP_OPCODE_FRC: SetDst(getFunction(FUNCTION::FUNCTION_FRACT)); return true;
case RSX_FP_OPCODE_LIT: SetDst(getFloatTypeName(4) + "(1.0, $0.x, ($0.x > 0.0 ? exp($0.w * log2($0.y)) : 0.0), 1.0)"); return true;
case RSX_FP_OPCODE_LIT: SetDst("lit_legacy($0)"); return true;
case RSX_FP_OPCODE_LIF: SetDst(getFloatTypeName(4) + "(1.0, $0.y, ($0.y > 0 ? pow(2.0, $0.w) : 0.0), 1.0)"); return true;
case RSX_FP_OPCODE_LRP: LOG_ERROR(RSX, "Unimplemented SCB instruction: LRP"); return true; // TODO: Is this in the right category?
case RSX_FP_OPCODE_LG2: SetDst("log2($0.xxxx)"); return true;
@@ -418,42 +440,60 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
case RSX_FP_OPCODE_NRM: SetDst("normalize($0)"); return true;
case RSX_FP_OPCODE_BEM: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: BEM"); return true;
case RSX_FP_OPCODE_TEX:
if (dst.tex_num >= m_texture_dimensions.size())
switch (m_prog.get_texture_dimension(dst.tex_num))
{
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE));
case texture_dimension::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D));
return true;
}
switch (m_texture_dimensions[dst.tex_num])
{
case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE));
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D));
return true;
case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE));
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE));
return true;
case texture_dimension::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D));
return true;
}
return false;
case RSX_FP_OPCODE_TEXBEM: SetDst("texture($t, $0.xy, $1.x)"); return true;
case RSX_FP_OPCODE_TXP:
if (dst.tex_num >= m_texture_dimensions.size())
switch (m_prog.get_texture_dimension(dst.tex_num))
{
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ));
case texture_dimension::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ));
return true;
}
switch (m_texture_dimensions[dst.tex_num])
{
case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ));
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ));
return true;
case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ));
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ));
return true;
case texture_dimension::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ));
return true;
}
return false;
case RSX_FP_OPCODE_TXPBEM: SetDst("textureProj($t, $0.xyz, $1.x)"); return true;
case RSX_FP_OPCODE_TXD: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: TXD"); return true;
case RSX_FP_OPCODE_TXB: SetDst("texture($t, $0.xy, $1.x)"); return true;
case RSX_FP_OPCODE_TXL: SetDst("textureLod($t, $0.xy, $1.x)"); return true;
case RSX_FP_OPCODE_TXL:
switch (m_prog.get_texture_dimension(dst.tex_num))
{
case texture_dimension::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD));
return true;
case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD));
return true;
case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD));
return true;
case texture_dimension::texture_dimension_3d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD));
return true;
}
return false;
case RSX_FP_OPCODE_UP2: SetDst("unpackSnorm2x16($0)"); return true; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478))
case RSX_FP_OPCODE_UP4: SetDst("unpackSnorm4x8($0)"); return true; // TODO: More testing (Sonic The Hedgehog (NPUB-30442/NPEB-00478))
case RSX_FP_OPCODE_UP16: LOG_ERROR(RSX, "Unimplemented TEX_SRB instruction: UP16"); return true;
@@ -465,7 +505,7 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
std::string FragmentProgramDecompiler::Decompile()
{
auto data = vm::ps3::ptr<u32>::make(m_addr);
auto data = (be_t<u32>*) m_prog.addr;
m_size = 0;
m_location = 0;
m_loop_count = 0;
@@ -25,9 +25,7 @@ class FragmentProgramDecompiler
SRC2 src2;
std::string main;
u32 m_addr;
u32& m_size;
const std::vector<texture_dimension> m_texture_dimensions;
u32 m_const_index;
u32 m_offset;
u32 m_location;
@@ -76,6 +74,7 @@ class FragmentProgramDecompiler
*/
bool handle_tex_srb(u32 opcode);
protected:
const RSXFragmentProgram &m_prog;
u32 m_ctrl;
/** returns the type name of float vectors.
*/
@@ -113,6 +112,8 @@ protected:
virtual void insertMainEnd(std::stringstream &OS) = 0;
public:
ParamArray m_parr;
FragmentProgramDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions);
FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size);
FragmentProgramDecompiler(const FragmentProgramDecompiler&) = delete;
FragmentProgramDecompiler(FragmentProgramDecompiler&&) = delete;
std::string Decompile();
};
+132
View File
@@ -0,0 +1,132 @@
#include "stdafx.h"
#include "ProgramStateCache.h"
using namespace program_hash_util;
size_t vertex_program_hash::operator()(const RSXVertexProgram &program) const
{
// 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL;
const qword *instbuffer = (const qword*)program.data.data();
size_t instIndex = 0;
bool end = false;
for (unsigned i = 0; i < program.data.size() / 4; i++)
{
const qword inst = instbuffer[instIndex];
hash ^= inst.dword[0];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
hash ^= inst.dword[1];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
instIndex++;
}
return hash;
}
bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const
{
if (binary1.output_mask != binary2.output_mask)
return false;
if (binary1.rsx_vertex_inputs != binary2.rsx_vertex_inputs)
return false;
if (binary1.data.size() != binary2.data.size()) return false;
const qword *instBuffer1 = (const qword*)binary1.data.data();
const qword *instBuffer2 = (const qword*)binary2.data.data();
size_t instIndex = 0;
for (unsigned i = 0; i < binary1.data.size() / 4; i++)
{
const qword& inst1 = instBuffer1[instIndex];
const qword& inst2 = instBuffer2[instIndex];
if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1])
return false;
instIndex++;
}
return true;
}
bool fragment_program_utils::is_constant(u32 sourceOperand)
{
return ((sourceOperand >> 8) & 0x3) == 2;
}
size_t fragment_program_utils::get_fragment_program_ucode_size(void *ptr)
{
const qword *instBuffer = (const qword*)ptr;
size_t instIndex = 0;
while (true)
{
const qword& inst = instBuffer[instIndex];
bool isSRC0Constant = is_constant(inst.word[1]);
bool isSRC1Constant = is_constant(inst.word[2]);
bool isSRC2Constant = is_constant(inst.word[3]);
bool end = (inst.word[0] >> 8) & 0x1;
if (isSRC0Constant || isSRC1Constant || isSRC2Constant)
{
instIndex += 2;
if (end)
return instIndex * 4 * 4;
continue;
}
instIndex++;
if (end)
return (instIndex)* 4 * 4;
}
}
size_t fragment_program_hash::operator()(const RSXFragmentProgram& program) const
{
// 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL;
const qword *instbuffer = (const qword*)program.addr;
size_t instIndex = 0;
while (true)
{
const qword& inst = instbuffer[instIndex];
hash ^= inst.dword[0];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
hash ^= inst.dword[1];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
instIndex++;
// Skip constants
if (fragment_program_utils::is_constant(inst.word[1]) ||
fragment_program_utils::is_constant(inst.word[2]) ||
fragment_program_utils::is_constant(inst.word[3]))
instIndex++;
bool end = (inst.word[0] >> 8) & 0x1;
if (end)
return hash;
}
return 0;
}
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
{
if (binary1.texture_dimensions != binary2.texture_dimensions || binary1.unnormalized_coords != binary2.unnormalized_coords ||
binary1.height != binary2.height || binary1.origin_mode != binary2.origin_mode || binary1.pixel_center_mode != binary2.pixel_center_mode ||
binary1.back_color_diffuse_output != binary2.back_color_diffuse_output || binary1.back_color_specular_output != binary2.back_color_specular_output ||
binary1.front_back_color_enabled != binary2.front_back_color_enabled || binary1.alpha_func != binary2.alpha_func)
return false;
const qword *instBuffer1 = (const qword*)binary1.addr;
const qword *instBuffer2 = (const qword*)binary2.addr;
size_t instIndex = 0;
while (true)
{
const qword& inst1 = instBuffer1[instIndex];
const qword& inst2 = instBuffer2[instIndex];
if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1])
return false;
instIndex++;
// Skip constants
if (fragment_program_utils::is_constant(inst1.word[1]) ||
fragment_program_utils::is_constant(inst1.word[2]) ||
fragment_program_utils::is_constant(inst1.word[3]))
instIndex++;
bool end = ((inst1.word[0] >> 8) & 0x1) && ((inst2.word[0] >> 8) & 0x1);
if (end)
return true;
}
}
+126 -243
View File
@@ -2,6 +2,7 @@
#include "Emu/RSX/RSXFragmentProgram.h"
#include "Emu/RSX/RSXVertexProgram.h"
#include "Emu/Memory/vm.h"
enum class SHADER_TYPE
@@ -10,7 +11,7 @@ enum class SHADER_TYPE
SHADER_TYPE_FRAGMENT
};
namespace ProgramHashUtil
namespace program_hash_util
{
// Based on
// https://github.com/AlexAltea/nucleus/blob/master/nucleus/gpu/rsx_pgraph.cpp
@@ -20,142 +21,34 @@ namespace ProgramHashUtil
u32 word[4];
};
struct HashVertexProgram
struct vertex_program_hash
{
size_t operator()(const std::vector<u32> &program) const
{
// 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL;
const qword *instbuffer = (const qword*)program.data();
size_t instIndex = 0;
bool end = false;
for (unsigned i = 0; i < program.size() / 4; i++)
{
const qword inst = instbuffer[instIndex];
hash ^= inst.dword[0];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
hash ^= inst.dword[1];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
instIndex++;
}
return hash;
}
size_t operator()(const RSXVertexProgram &program) const;
};
struct VertexProgramCompare
struct vertex_program_compare
{
bool operator()(const std::vector<u32> &binary1, const std::vector<u32> &binary2) const
{
if (binary1.size() != binary2.size()) return false;
const qword *instBuffer1 = (const qword*)binary1.data();
const qword *instBuffer2 = (const qword*)binary2.data();
size_t instIndex = 0;
for (unsigned i = 0; i < binary1.size() / 4; i++)
{
const qword& inst1 = instBuffer1[instIndex];
const qword& inst2 = instBuffer2[instIndex];
if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1])
return false;
instIndex++;
}
return true;
}
bool operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const;
};
struct FragmentProgramUtil
struct fragment_program_utils
{
/**
* returns true if the given source Operand is a constant
*/
static bool isConstant(u32 sourceOperand)
{
return ((sourceOperand >> 8) & 0x3) == 2;
}
static bool is_constant(u32 sourceOperand);
static
size_t getFPBinarySize(void *ptr)
{
const qword *instBuffer = (const qword*)ptr;
size_t instIndex = 0;
while (true)
{
const qword& inst = instBuffer[instIndex];
bool isSRC0Constant = isConstant(inst.word[1]);
bool isSRC1Constant = isConstant(inst.word[2]);
bool isSRC2Constant = isConstant(inst.word[3]);
bool end = (inst.word[0] >> 8) & 0x1;
if (isSRC0Constant || isSRC1Constant || isSRC2Constant)
{
instIndex += 2;
if (end)
return instIndex * 4 * 4;
continue;
}
instIndex++;
if (end)
return (instIndex)* 4 * 4;
}
}
static size_t get_fragment_program_ucode_size(void *ptr);
};
struct HashFragmentProgram
struct fragment_program_hash
{
size_t operator()(const void *program) const
{
// 64-bit Fowler/Noll/Vo FNV-1a hash code
size_t hash = 0xCBF29CE484222325ULL;
const qword *instbuffer = (const qword*)program;
size_t instIndex = 0;
while (true)
{
const qword& inst = instbuffer[instIndex];
hash ^= inst.dword[0];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
hash ^= inst.dword[1];
hash += (hash << 1) + (hash << 4) + (hash << 5) + (hash << 7) + (hash << 8) + (hash << 40);
instIndex++;
// Skip constants
if (FragmentProgramUtil::isConstant(inst.word[1]) ||
FragmentProgramUtil::isConstant(inst.word[2]) ||
FragmentProgramUtil::isConstant(inst.word[3]))
instIndex++;
bool end = (inst.word[0] >> 8) & 0x1;
if (end)
return hash;
}
return 0;
}
size_t operator()(const RSXFragmentProgram &program) const;
};
struct FragmentProgramCompare
struct fragment_program_compare
{
bool operator()(const void *binary1, const void *binary2) const
{
const qword *instBuffer1 = (const qword*)binary1;
const qword *instBuffer2 = (const qword*)binary2;
size_t instIndex = 0;
while (true)
{
const qword& inst1 = instBuffer1[instIndex];
const qword& inst2 = instBuffer2[instIndex];
if (inst1.dword[0] != inst2.dword[0] || inst1.dword[1] != inst2.dword[1])
return false;
instIndex++;
// Skip constants
if (FragmentProgramUtil::isConstant(inst1.word[1]) ||
FragmentProgramUtil::isConstant(inst1.word[2]) ||
FragmentProgramUtil::isConstant(inst1.word[3]))
instIndex++;
bool end = ((inst1.word[0] >> 8) & 0x1) && ((inst2.word[0] >> 8) & 0x1);
if (end)
return true;
}
}
bool operator()(const RSXFragmentProgram &binary1, const RSXFragmentProgram &binary2) const;
};
}
@@ -170,193 +63,183 @@ namespace ProgramHashUtil
* - a typedef PipelineProperties to a type that encapsulate various state info relevant to program compilation (alpha test, primitive type,...)
* - a typedef ExtraData type that will be passed to the buildProgram function.
* It should also contains the following function member :
* - static void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID);
* - static void RecompileVertexProgram(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID);
* - static PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData);
* - void DeleteProgram(PipelineData *ptr);
* - static void recompile_fragment_program(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID);
* - static void recompile_vertex_program(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID);
* - static PipelineData build_program(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData);
*/
template<typename BackendTraits>
class ProgramStateCache
template<typename backend_traits>
class program_state_cache
{
private:
typedef std::unordered_map<std::vector<u32>, typename BackendTraits::VertexProgramData, ProgramHashUtil::HashVertexProgram, ProgramHashUtil::VertexProgramCompare> binary2VS;
typedef std::unordered_map<void *, typename BackendTraits::FragmentProgramData, ProgramHashUtil::HashFragmentProgram, ProgramHashUtil::FragmentProgramCompare> binary2FS;
binary2VS m_cacheVS;
binary2FS m_cacheFS;
using pipeline_storage_type = typename backend_traits::pipeline_storage_type;
using pipeline_properties = typename backend_traits::pipeline_properties;
using vertex_program_type = typename backend_traits::vertex_program_type;
using fragment_program_type = typename backend_traits::fragment_program_type;
size_t m_currentShaderId;
std::vector<size_t> dummyFragmentConstantCache;
using binary_to_vertex_program = std::unordered_map<RSXVertexProgram, vertex_program_type, program_hash_util::vertex_program_hash, program_hash_util::vertex_program_compare> ;
using binary_to_fragment_program = std::unordered_map<RSXFragmentProgram, fragment_program_type, program_hash_util::fragment_program_hash, program_hash_util::fragment_program_compare>;
struct PSOKey
struct pipeline_key
{
u32 vpIdx;
u32 fpIdx;
typename BackendTraits::PipelineProperties properties;
u32 vertex_program_id;
u32 fragment_program_id;
pipeline_properties properties;
};
struct PSOKeyHash
struct pipeline_key_hash
{
size_t operator()(const PSOKey &key) const
size_t operator()(const pipeline_key &key) const
{
size_t hashValue = 0;
hashValue ^= std::hash<unsigned>()(key.vpIdx);
hashValue ^= std::hash<unsigned>()(key.fpIdx);
hashValue ^= std::hash<typename BackendTraits::PipelineProperties>()(key.properties);
hashValue ^= std::hash<unsigned>()(key.vertex_program_id);
hashValue ^= std::hash<unsigned>()(key.fragment_program_id);
hashValue ^= std::hash<pipeline_properties>()(key.properties);
return hashValue;
}
};
struct PSOKeyCompare
struct pipeline_key_compare
{
size_t operator()(const PSOKey &key1, const PSOKey &key2) const
bool operator()(const pipeline_key &key1, const pipeline_key &key2) const
{
return (key1.vpIdx == key2.vpIdx) && (key1.fpIdx == key2.fpIdx) && (key1.properties == key2.properties);
return (key1.vertex_program_id == key2.vertex_program_id) && (key1.fragment_program_id == key2.fragment_program_id) && (key1.properties == key2.properties);
}
};
std::unordered_map<PSOKey, typename BackendTraits::PipelineData*, PSOKeyHash, PSOKeyCompare> m_cachePSO;
private:
size_t m_next_id = 0;
binary_to_vertex_program m_vertex_shader_cache;
binary_to_fragment_program m_fragment_shader_cache;
std::unordered_map <pipeline_key, pipeline_storage_type, pipeline_key_hash, pipeline_key_compare> m_storage;
typename BackendTraits::FragmentProgramData& SearchFp(RSXFragmentProgram* rsx_fp, bool& found)
/// bool here to inform that the program was preexisting.
std::tuple<const vertex_program_type&, bool> search_vertex_program(const RSXVertexProgram& rsx_vp)
{
typename binary2FS::iterator It = m_cacheFS.find(vm::base(rsx_fp->addr));
if (It != m_cacheFS.end())
const auto& I = m_vertex_shader_cache.find(rsx_vp);
if (I != m_vertex_shader_cache.end())
{
found = true;
return It->second;
return std::forward_as_tuple(I->second, true);
}
found = false;
LOG_WARNING(RSX, "FP not found in buffer!");
size_t actualFPSize = ProgramHashUtil::FragmentProgramUtil::getFPBinarySize(vm::base(rsx_fp->addr));
void *fpShadowCopy = malloc(actualFPSize);
std::memcpy(fpShadowCopy, vm::base(rsx_fp->addr), actualFPSize);
typename BackendTraits::FragmentProgramData &newShader = m_cacheFS[fpShadowCopy];
BackendTraits::RecompileFragmentProgram(rsx_fp, newShader, m_currentShaderId++);
LOG_NOTICE(RSX, "VP not found in buffer!");
vertex_program_type& new_shader = m_vertex_shader_cache[rsx_vp];
backend_traits::recompile_vertex_program(rsx_vp, new_shader, m_next_id++);
return newShader;
return std::forward_as_tuple(new_shader, false);
}
typename BackendTraits::VertexProgramData& SearchVp(RSXVertexProgram* rsx_vp, bool &found)
/// bool here to inform that the program was preexisting.
std::tuple<const fragment_program_type&, bool> search_fragment_program(const RSXFragmentProgram& rsx_fp)
{
typename binary2VS::iterator It = m_cacheVS.find(rsx_vp->data);
if (It != m_cacheVS.end())
const auto& I = m_fragment_shader_cache.find(rsx_fp);
if (I != m_fragment_shader_cache.end())
{
found = true;
return It->second;
return std::forward_as_tuple(I->second, true);
}
found = false;
LOG_WARNING(RSX, "VP not found in buffer!");
typename BackendTraits::VertexProgramData& newShader = m_cacheVS[rsx_vp->data];
BackendTraits::RecompileVertexProgram(rsx_vp, newShader, m_currentShaderId++);
LOG_NOTICE(RSX, "FP not found in buffer!");
size_t fragment_program_size = program_hash_util::fragment_program_utils::get_fragment_program_ucode_size(rsx_fp.addr);
gsl::not_null<void*> fragment_program_ucode_copy = malloc(fragment_program_size);
std::memcpy(fragment_program_ucode_copy, rsx_fp.addr, fragment_program_size);
RSXFragmentProgram new_fp_key = rsx_fp;
new_fp_key.addr = fragment_program_ucode_copy;
fragment_program_type &new_shader = m_fragment_shader_cache[new_fp_key];
backend_traits::recompile_fragment_program(rsx_fp, new_shader, m_next_id++);
return newShader;
}
typename BackendTraits::PipelineData *GetProg(const PSOKey &psoKey) const
{
typename std::unordered_map<PSOKey, typename BackendTraits::PipelineData *, PSOKeyHash, PSOKeyCompare>::const_iterator It = m_cachePSO.find(psoKey);
if (It == m_cachePSO.end())
return nullptr;
return It->second;
}
void Add(typename BackendTraits::PipelineData *prog, const PSOKey& PSOKey)
{
m_cachePSO.insert(std::make_pair(PSOKey, prog));
return std::forward_as_tuple(new_shader, false);
}
public:
ProgramStateCache() : m_currentShaderId(0) {}
~ProgramStateCache()
program_state_cache() = default;
~program_state_cache()
{
clear();
for (auto& pair : m_fragment_shader_cache)
{
free(pair.first.addr);
}
};
const vertex_program_type& get_transform_program(const RSXVertexProgram& rsx_vp) const
{
auto I = m_vertex_shader_cache.find(rsx_vp);
if (I != m_vertex_shader_cache.end())
return I->second;
throw new EXCEPTION("Trying to get unknow transform program");
}
const typename BackendTraits::VertexProgramData* get_transform_program(const RSXVertexProgram& rsx_vp) const
const fragment_program_type& get_shader_program(const RSXFragmentProgram& rsx_fp) const
{
typename binary2VS::const_iterator It = m_cacheVS.find(rsx_vp.data);
if (It == m_cacheVS.end())
return nullptr;
return &It->second;
auto I = m_fragment_shader_cache.find(rsx_fp);
if (I != m_fragment_shader_cache.end())
return I->second;
throw new EXCEPTION("Trying to get unknow shader program");
}
const typename BackendTraits::FragmentProgramData* get_shader_program(const RSXFragmentProgram& rsx_fp) const
{
typename binary2FS::const_iterator It = m_cacheFS.find(vm::base(rsx_fp.addr));
if (It == m_cacheFS.end())
return nullptr;
return &It->second;
}
void clear()
{
for (auto pair : m_cachePSO)
BackendTraits::DeleteProgram(pair.second);
m_cachePSO.clear();
for (auto pair : m_cacheFS)
free(pair.first);
m_cacheFS.clear();
}
typename BackendTraits::PipelineData *getGraphicPipelineState(
RSXVertexProgram *vertexShader,
RSXFragmentProgram *fragmentShader,
const typename BackendTraits::PipelineProperties &pipelineProperties,
const typename BackendTraits::ExtraData& extraData
template<typename... Args>
pipeline_storage_type& getGraphicPipelineState(
const RSXVertexProgram& vertexShader,
const RSXFragmentProgram& fragmentShader,
const pipeline_properties& pipelineProperties,
Args&& ...args
)
{
typename BackendTraits::PipelineData *result = nullptr;
bool fpFound, vpFound;
typename BackendTraits::VertexProgramData &vertexProg = SearchVp(vertexShader, vpFound);
typename BackendTraits::FragmentProgramData &fragmentProg = SearchFp(fragmentShader, fpFound);
// TODO : use tie and implicit variable declaration syntax with c++17
const auto &vp_search = search_vertex_program(vertexShader);
const auto &fp_search = search_fragment_program(fragmentShader);
const vertex_program_type &vertex_program = std::get<0>(vp_search);
const fragment_program_type &fragment_program = std::get<0>(fp_search);
bool already_existing_fragment_program = std::get<1>(fp_search);
bool already_existing_vertex_program = std::get<1>(vp_search);
if (fpFound && vpFound)
pipeline_key key = { vertex_program.id, fragment_program.id, pipelineProperties };
if (already_existing_fragment_program && already_existing_vertex_program)
{
result = GetProg({ vertexProg.id, fragmentProg.id, pipelineProperties });
const auto I = m_storage.find(key);
if (I != m_storage.end())
return I->second;
}
if (result != nullptr)
return result;
else
{
LOG_WARNING(RSX, "Add program :");
LOG_WARNING(RSX, "*** vp id = %d", vertexProg.id);
LOG_WARNING(RSX, "*** fp id = %d", fragmentProg.id);
LOG_NOTICE(RSX, "Add program :");
LOG_NOTICE(RSX, "*** vp id = %d", vertex_program.id);
LOG_NOTICE(RSX, "*** fp id = %d", fragment_program.id);
result = BackendTraits::BuildProgram(vertexProg, fragmentProg, pipelineProperties, extraData);
Add(result, { vertexProg.id, fragmentProg.id, pipelineProperties });
}
return result;
m_storage[key] = backend_traits::build_pipeline(vertex_program, fragment_program, pipelineProperties, std::forward<Args>(args)...);
return m_storage[key];
}
size_t get_fragment_constants_buffer_size(const RSXFragmentProgram *fragmentShader) const
size_t get_fragment_constants_buffer_size(const RSXFragmentProgram &fragmentShader) const
{
typename binary2FS::const_iterator It = m_cacheFS.find(vm::base(fragmentShader->addr));
if (It != m_cacheFS.end())
return It->second.FragmentConstantOffsetCache.size() * 4 * sizeof(float);
const auto I = m_fragment_shader_cache.find(fragmentShader);
if (I != m_fragment_shader_cache.end())
return I->second.FragmentConstantOffsetCache.size() * 4 * sizeof(float);
LOG_ERROR(RSX, "Can't retrieve constant offset cache");
return 0;
}
void fill_fragment_constans_buffer(void *buffer, const RSXFragmentProgram *fragment_program) const
void fill_fragment_constans_buffer(gsl::span<f32, gsl::dynamic_range> dst_buffer, const RSXFragmentProgram &fragment_program) const
{
typename binary2FS::const_iterator It = m_cacheFS.find(vm::base(fragment_program->addr));
if (It == m_cacheFS.end())
const auto I = m_fragment_shader_cache.find(fragment_program);
if (I == m_fragment_shader_cache.end())
return;
__m128i mask = _mm_set_epi8(0xE, 0xF, 0xC, 0xD,
0xA, 0xB, 0x8, 0x9,
0x6, 0x7, 0x4, 0x5,
0x2, 0x3, 0x0, 0x1);
Expects(dst_buffer.size_bytes() >= gsl::narrow<int>(I->second.FragmentConstantOffsetCache.size()) * 16);
size_t offset = 0;
for (size_t offset_in_fragment_program : It->second.FragmentConstantOffsetCache)
for (size_t offset_in_fragment_program : I->second.FragmentConstantOffsetCache)
{
void *data = vm::base(fragment_program->addr + (u32)offset_in_fragment_program);
void *data = (char*)fragment_program.addr + (u32)offset_in_fragment_program;
const __m128i &vector = _mm_loadu_si128((__m128i*)data);
const __m128i &shuffled_vector = _mm_shuffle_epi8(vector, mask);
_mm_stream_si128((__m128i*)((char*)buffer + offset), shuffled_vector);
offset += 4 * sizeof(u32);
_mm_stream_si128((__m128i*)dst_buffer.subspan(offset, 4).data(), shuffled_vector);
offset += sizeof(f32);
}
}
void clear()
{
m_storage.clear();
}
};
+12 -4
View File
@@ -13,10 +13,18 @@ enum class FUNCTION {
FUNCTION_FRACT,
FUNCTION_DFDX,
FUNCTION_DFDY,
FUNCTION_TEXTURE_SAMPLE,
FUNCTION_TEXTURE_SAMPLE_PROJ,
FUNCTION_TEXTURE_CUBE_SAMPLE,
FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ,
FUNCTION_TEXTURE_SAMPLE1D,
FUNCTION_TEXTURE_SAMPLE1D_PROJ,
FUNCTION_TEXTURE_SAMPLE1D_LOD,
FUNCTION_TEXTURE_SAMPLE2D,
FUNCTION_TEXTURE_SAMPLE2D_PROJ,
FUNCTION_TEXTURE_SAMPLE2D_LOD,
FUNCTION_TEXTURE_SAMPLECUBE,
FUNCTION_TEXTURE_SAMPLECUBE_PROJ,
FUNCTION_TEXTURE_SAMPLECUBE_LOD,
FUNCTION_TEXTURE_SAMPLE3D,
FUNCTION_TEXTURE_SAMPLE3D_PROJ,
FUNCTION_TEXTURE_SAMPLE3D_LOD,
};
enum class COMPARE {
+54 -35
View File
@@ -14,9 +14,9 @@ namespace
struct texel_rgba
{
template<size_t block_size>
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block)
{
for (unsigned row = 0; row < row_count; row++)
for (unsigned row = 0; row < row_count * depth; row++)
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * src_pitch_in_block * block_size, width_in_block * block_size);
}
};
@@ -28,13 +28,13 @@ struct texel_rgba
struct texel_16b_swizzled
{
template<size_t block_size>
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block)
{
u16 *castedSrc = static_cast<u16*>(src), *castedDst = static_cast<u16*>(dst);
std::unique_ptr<u16[]> temp_swizzled(new u16[row_count * width_in_block]);
rsx::convert_linear_swizzle<u16>(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true);
for (unsigned row = 0; row < row_count; row++)
for (unsigned row = 0; row < row_count * depth; row++)
for (int j = 0; j < width_in_block; j++)
{
u16 tmp = temp_swizzled[row * src_pitch_in_block + j];
@@ -49,14 +49,14 @@ struct texel_16b_swizzled
struct texel_rgba_swizzled
{
template<size_t block_size>
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block)
{
u32 *castedSrc, *castedDst;
castedSrc = (u32*)src;
castedDst = (u32*)dst ;
std::unique_ptr<u32[]> temp_swizzled(new u32[src_pitch_in_block * row_count]);
rsx::convert_linear_swizzle<u32>(castedSrc, temp_swizzled.get(), src_pitch_in_block, row_count, true);
for (unsigned row = 0; row < row_count; row++)
for (unsigned row = 0; row < row_count * depth; row++)
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)temp_swizzled.get() + row * src_pitch_in_block * block_size, width_in_block * block_size);
}
};
@@ -67,9 +67,9 @@ struct texel_rgba_swizzled
*/
struct texel_bc_format {
template<size_t block_size>
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block)
{
for (unsigned row = 0; row < row_count; row++)
for (unsigned row = 0; row < row_count * depth; row++)
memcpy((char*)dst + row * dst_pitch_in_block * block_size, (char*)src + row * src_pitch_in_block * block_size, width_in_block * block_size);
}
};
@@ -79,11 +79,11 @@ struct texel_bc_format {
*/
struct texel_16b_format {
template<size_t block_size>
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block)
{
unsigned short *castedDst = (unsigned short *)dst, *castedSrc = (unsigned short *)src;
for (unsigned row = 0; row < row_count; row++)
for (unsigned row = 0; row < row_count * depth; row++)
for (int j = 0; j < width_in_block; j++)
{
u16 tmp = castedSrc[row * src_pitch_in_block + j];
@@ -97,10 +97,10 @@ struct texel_16b_format {
*/
struct texel_16bX4_format {
template<size_t block_size>
static void copy_mipmap_level(void *dst, void *src, size_t row_count, size_t width_in_block, size_t dst_pitch_in_block, size_t src_pitch_in_block)
static void copy_mipmap_level(void *dst, void *src, u16 row_count, u16 width_in_block, u16 depth, size_t dst_pitch_in_block, size_t src_pitch_in_block)
{
unsigned short *casted_dst = (unsigned short *)dst, *casted_src = (unsigned short *)src;
for (unsigned row = 0; row < row_count; row++)
for (unsigned row = 0; row < row_count * depth; row++)
for (int j = 0; j < width_in_block * 4; j++)
{
u16 tmp = casted_src[row * src_pitch_in_block * 4 + j];
@@ -124,13 +124,13 @@ struct texel_16bX4_format {
* mipmap level (to allow same code for packed/non packed texels)
*/
template <typename T, bool padded_row, size_t block_size_in_bytes, size_t block_edge_in_texel>
std::vector<MipmapLevelInfo> copy_texture_data(void *dst, const void *src, size_t width_in_texel, size_t height_in_texel, size_t depth, size_t mipmap_count)
std::vector<MipmapLevelInfo> copy_texture_data(void *dst, const void *src, u16 width_in_texel, u16 height_in_texel, u16 depth, u8 layer_count, u16 mipmap_count)
{
std::vector<MipmapLevelInfo> Result;
size_t offsetInDst = 0, offsetInSrc = 0;
size_t texture_height_in_block = (height_in_texel + block_edge_in_texel - 1) / block_edge_in_texel;
size_t texture_width_in_block = (width_in_texel + block_edge_in_texel - 1) / block_edge_in_texel;
for (unsigned depth_level = 0; depth_level < depth; depth_level++)
for (unsigned layer = 0; layer < layer_count; layer++)
{
size_t miplevel_height_in_block = texture_height_in_block, miplevel_width_in_block = texture_width_in_block;
for (unsigned mip_level = 0; mip_level < mipmap_count; mip_level++)
@@ -141,18 +141,19 @@ std::vector<MipmapLevelInfo> copy_texture_data(void *dst, const void *src, size_
currentMipmapLevelInfo.offset = offsetInDst;
currentMipmapLevelInfo.height = miplevel_height_in_block * block_edge_in_texel;
currentMipmapLevelInfo.width = miplevel_width_in_block * block_edge_in_texel;
currentMipmapLevelInfo.depth = depth;
currentMipmapLevelInfo.rowPitch = dst_pitch * block_size_in_bytes;
Result.push_back(currentMipmapLevelInfo);
if (!padded_row)
{
T::template copy_mipmap_level<block_size_in_bytes>((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, dst_pitch, miplevel_width_in_block);
offsetInSrc += miplevel_height_in_block * miplevel_width_in_block * block_size_in_bytes;
T::template copy_mipmap_level<block_size_in_bytes>((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, depth, dst_pitch, miplevel_width_in_block);
offsetInSrc += miplevel_height_in_block * miplevel_width_in_block * block_size_in_bytes * depth;
}
else
{
T::template copy_mipmap_level<block_size_in_bytes>((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, dst_pitch, texture_width_in_block);
offsetInSrc += miplevel_height_in_block * texture_width_in_block * block_size_in_bytes;
T::template copy_mipmap_level<block_size_in_bytes>((char*)dst + offsetInDst, (char*)src + offsetInSrc, miplevel_height_in_block, miplevel_width_in_block, depth, dst_pitch, texture_width_in_block);
offsetInSrc += miplevel_height_in_block * texture_width_in_block * block_size_in_bytes * depth;
}
offsetInDst += align(miplevel_height_in_block * dst_pitch * block_size_in_bytes, 512);
miplevel_height_in_block = MAX2(miplevel_height_in_block / 2, 1);
@@ -265,10 +266,28 @@ size_t get_placed_texture_storage_size(const rsx::texture &texture, size_t rowPi
std::vector<MipmapLevelInfo> upload_placed_texture(const rsx::texture &texture, size_t rowPitchAlignement, void* textureData)
{
size_t w = texture.width(), h = texture.height();
size_t depth = texture.depth();
if (depth == 0) depth = 1;
if (texture.cubemap()) depth *= 6;
u16 w = texture.width(), h = texture.height();
u16 depth;
u8 layer;
if (texture.dimension() == 1)
{
depth = 1;
layer = 1;
h = 1;
}
else if (texture.dimension() == 2)
{
depth = 1;
layer = texture.cubemap() ? 6 : 1;
}
else if (texture.dimension() == 3)
{
depth = texture.depth();
layer = 1;
}
else
throw EXCEPTION("Unsupported texture dimension %d", texture.dimension());
int format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
@@ -281,37 +300,37 @@ std::vector<MipmapLevelInfo> upload_placed_texture(const rsx::texture &texture,
{
case CELL_GCM_TEXTURE_A8R8G8B8:
if (is_swizzled)
return copy_texture_data<texel_rgba_swizzled, false, 4, 1>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_rgba_swizzled, false, 4, 1>(textureData, pixels, w, h, depth, layer, texture.mipmap());
else
return copy_texture_data<texel_rgba, true, 4, 1>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_rgba, true, 4, 1>(textureData, pixels, w, h, depth, layer, texture.mipmap());
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
if (is_swizzled)
return copy_texture_data<texel_16b_swizzled, false, 2, 1>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_16b_swizzled, false, 2, 1>(textureData, pixels, w, h, depth, layer, texture.mipmap());
else
return copy_texture_data<texel_16b_format, true, 2, 1>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_16b_format, true, 2, 1>(textureData, pixels, w, h, depth, layer, texture.mipmap());
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return copy_texture_data<texel_16bX4_format, true, 8, 1>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_16bX4_format, true, 8, 1>(textureData, pixels, w, h, depth, layer, texture.mipmap());
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
if (is_swizzled)
return copy_texture_data<texel_bc_format, false, 8, 4>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_bc_format, false, 8, 4>(textureData, pixels, w, h, depth, layer, texture.mipmap());
else
return copy_texture_data<texel_bc_format, true, 8, 4>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_bc_format, true, 8, 4>(textureData, pixels, w, h, depth, layer, texture.mipmap());
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
if (is_swizzled)
return copy_texture_data<texel_bc_format, false, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_bc_format, false, 16, 4>(textureData, pixels, w, h, depth, layer, texture.mipmap());
else
return copy_texture_data<texel_bc_format, true, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_bc_format, true, 16, 4>(textureData, pixels, w, h, depth, layer, texture.mipmap());
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
if (is_swizzled)
return copy_texture_data<texel_bc_format, false, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_bc_format, false, 16, 4>(textureData, pixels, w, h, depth, layer, texture.mipmap());
else
return copy_texture_data<texel_bc_format, true, 16, 4>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_bc_format, true, 16, 4>(textureData, pixels, w, h, depth, layer, texture.mipmap());
case CELL_GCM_TEXTURE_B8:
return copy_texture_data<texel_rgba, true, 1, 1>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_rgba, true, 1, 1>(textureData, pixels, w, h, depth, layer, texture.mipmap());
default:
return copy_texture_data<texel_rgba, true, 4, 1>(textureData, pixels, w, h, depth, texture.mipmap());
return copy_texture_data<texel_rgba, true, 4, 1>(textureData, pixels, w, h, depth, layer, texture.mipmap());
}
}
+4 -3
View File
@@ -5,9 +5,10 @@
struct MipmapLevelInfo
{
size_t offset;
size_t width;
size_t height;
size_t rowPitch;
u16 width;
u16 height;
u16 depth;
u16 rowPitch;
};
/**
@@ -47,7 +47,7 @@ std::string VertexProgramDecompiler::GetDST(bool isSca)
default:
if (d3.dst > 15)
LOG_ERROR(RSX, fmt::format("dst index out of range: %u", d3.dst));
LOG_ERROR(RSX, "dst index out of range: %u", d3.dst);
ret += m_parr.AddParam(PF_PARAM_NONE, getFloatTypeName(4), std::string("dst_reg") + std::to_string(d3.dst), d3.dst == 0 ? getFloatTypeName(4) + "(0.0f, 0.0f, 0.0f, 1.0f)" : getFloatTypeName(4) + "(0.0, 0.0, 0.0, 0.0)");
break;
}
@@ -91,7 +91,7 @@ std::string VertexProgramDecompiler::GetSRC(const u32 n)
break;
default:
LOG_ERROR(RSX, fmt::format("Bad src%u reg type: %d", n, u32{ src[n].reg_type }));
LOG_ERROR(RSX, "Bad src%u reg type: %d", n, u32{ src[n].reg_type });
Emu.Pause();
break;
}
@@ -435,8 +435,8 @@ std::string VertexProgramDecompiler::BuildCode()
return OS.str();
}
VertexProgramDecompiler::VertexProgramDecompiler(std::vector<u32>& data) :
m_data(data)
VertexProgramDecompiler::VertexProgramDecompiler(const RSXVertexProgram& prog) :
m_data(prog.data)
{
m_funcs.emplace_back();
m_funcs[0].offset = 0;
@@ -562,10 +562,10 @@ std::string VertexProgramDecompiler::Decompile()
case RSX_SCA_OPCODE_MOV: SetDSTSca("$s"); break;
case RSX_SCA_OPCODE_RCP: SetDSTSca("(1.0 / $s)"); break;
case RSX_SCA_OPCODE_RCC: SetDSTSca("clamp(1.0 / $s, 5.42101e-20, 1.884467e19)"); break;
case RSX_SCA_OPCODE_RSQ: SetDSTSca("(1.f / sqrt($s))"); break;
case RSX_SCA_OPCODE_RSQ: SetDSTSca("rsq_legacy($s)"); break;
case RSX_SCA_OPCODE_EXP: SetDSTSca("exp($s)"); break;
case RSX_SCA_OPCODE_LOG: SetDSTSca("log($s)"); break;
case RSX_SCA_OPCODE_LIT: SetDSTSca(getFloatTypeName(4) + "(1.0, $s.x, ($s.x > 0.0 ? exp($s.w * log2($s.y)) : 0.0), 1.0)"); break;
case RSX_SCA_OPCODE_LIT: SetDSTSca("lit_legacy($s)"); break;
case RSX_SCA_OPCODE_BRA:
{
AddCode("$if ($cond)");
@@ -619,7 +619,7 @@ std::string VertexProgramDecompiler::Decompile()
// works like BRI but shorter (RET o[1].x(TR);)
AddCode("$ifcond return;");
break;
case RSX_SCA_OPCODE_LG2: SetDSTSca("log2($s)"); break;
case RSX_SCA_OPCODE_LG2: SetDSTSca("log2_legacy($s)"); break;
case RSX_SCA_OPCODE_EX2: SetDSTSca("exp2($s)"); break;
case RSX_SCA_OPCODE_SIN: SetDSTSca("sin($s)"); break;
case RSX_SCA_OPCODE_COS: SetDSTSca("cos($s)"); break;
@@ -57,7 +57,7 @@ struct VertexProgramDecompiler
//wxString main;
std::vector<u32>& m_data;
const std::vector<u32>& m_data;
ParamArray m_parr;
std::string GetMask(bool is_sca);
@@ -124,6 +124,6 @@ protected:
*/
virtual void insertMainEnd(std::stringstream &OS) = 0;
public:
VertexProgramDecompiler(std::vector<u32>& data);
VertexProgramDecompiler(const RSXVertexProgram& prog);
std::string Decompile();
};
+66
View File
@@ -0,0 +1,66 @@
#include "stdafx.h"
#include "surface_store.h"
namespace rsx
{
namespace utility
{
std::vector<u8> get_rtt_indexes(surface_target color_target)
{
switch (color_target)
{
case surface_target::none: return{};
case surface_target::surface_a: return{ 0 };
case surface_target::surface_b: return{ 1 };
case surface_target::surfaces_a_b: return{ 0, 1 };
case surface_target::surfaces_a_b_c: return{ 0, 1, 2 };
case surface_target::surfaces_a_b_c_d: return{ 0, 1, 2, 3 };
}
throw EXCEPTION("Wrong color_target");
}
size_t get_aligned_pitch(surface_color_format format, u32 width)
{
switch (format)
{
case surface_color_format::b8: return align(width, 256);
case surface_color_format::g8b8:
case surface_color_format::x1r5g5b5_o1r5g5b5:
case surface_color_format::x1r5g5b5_z1r5g5b5:
case surface_color_format::r5g6b5: return align(width * 2, 256);
case surface_color_format::a8b8g8r8:
case surface_color_format::x8b8g8r8_o8b8g8r8:
case surface_color_format::x8b8g8r8_z8b8g8r8:
case surface_color_format::x8r8g8b8_o8r8g8b8:
case surface_color_format::x8r8g8b8_z8r8g8b8:
case surface_color_format::x32:
case surface_color_format::a8r8g8b8: return align(width * 4, 256);
case surface_color_format::w16z16y16x16: return align(width * 8, 256);
case surface_color_format::w32z32y32x32: return align(width * 16, 256);
}
throw EXCEPTION("Unknow color surface format");
}
size_t get_packed_pitch(surface_color_format format, u32 width)
{
switch (format)
{
case surface_color_format::b8: return width;
case surface_color_format::g8b8:
case surface_color_format::x1r5g5b5_o1r5g5b5:
case surface_color_format::x1r5g5b5_z1r5g5b5:
case surface_color_format::r5g6b5: return width * 2;
case surface_color_format::a8b8g8r8:
case surface_color_format::x8b8g8r8_o8b8g8r8:
case surface_color_format::x8b8g8r8_z8b8g8r8:
case surface_color_format::x8r8g8b8_o8r8g8b8:
case surface_color_format::x8r8g8b8_z8r8g8b8:
case surface_color_format::x32:
case surface_color_format::a8r8g8b8: return width * 4;
case surface_color_format::w16z16y16x16: return width * 8;
case surface_color_format::w32z32y32x32: return width * 16;
}
throw EXCEPTION("Unknow color surface format");
}
}
}
+348
View File
@@ -0,0 +1,348 @@
#pragma once
#include <gsl.h>
#include "../GCM.h"
namespace rsx
{
namespace utility
{
std::vector<u8> get_rtt_indexes(surface_target color_target);
size_t get_aligned_pitch(surface_color_format format, u32 width);
size_t get_packed_pitch(surface_color_format format, u32 width);
}
/**
* Helper for surface (ie color and depth stencil render target) management.
* It handles surface creation and storage. Backend should only retrieve pointer to surface.
* It provides 2 methods get_texture_from_*_if_applicable that should be used when an app
* wants to sample a previous surface.
* Please note that the backend is still responsible for creating framebuffer/descriptors
* and need to inform surface_store everytime surface format/size/addresses change.
*
* Since it's a template it requires a trait with the followings:
* - type surface_storage_type which is a structure containing texture.
* - type surface_type which is a pointer to storage_type or a reference.
* - type command_list_type that can be void for backend without command list
* - type download_buffer_object used by issue_download_command and map_downloaded_buffer functions to handle sync
*
* - a member function static surface_type(const surface_storage_type&) that returns underlying surface pointer from a storage type.
* - 2 member functions static surface_storage_type create_new_surface(u32 address, Surface_color_format/Surface_depth_format format, size_t width, size_t height,...)
* used to create a new surface_storage_type holding surface from passed parameters.
* - a member function static prepare_rtt_for_drawing(command_list, surface_type) that makes a sampleable surface a color render target one.
* - a member function static prepare_rtt_for_drawing(command_list, surface_type) that makes a render target surface a sampleable one.
* - a member function static prepare_ds_for_drawing that does the same for depth stencil surface.
* - a member function static prepare_ds_for_sampling that does the same for depth stencil surface.
* - a member function static bool rtt_has_format_width_height(const surface_storage_type&, Surface_color_format surface_color_format, size_t width, size_t height)
* that checks if the given surface has the given format and size
* - a member function static bool ds_has_format_width_height that does the same for ds
* - a member function static download_buffer_object issue_download_command(surface_type, Surface_color_format color_format, size_t width, size_t height,...)
* that generates command to download the given surface to some mappable buffer.
* - a member function static issue_depth_download_command that does the same for depth surface
* - a member function static issue_stencil_download_command that does the same for stencil surface
* - a member function gsl::span<const gsl::byte> map_downloaded_buffer(download_buffer_object, ...) that maps a download_buffer_object
* - a member function static unmap_downloaded_buffer that unmaps it.
*/
template<typename Traits>
struct surface_store
{
template<typename T, typename U>
void copy_pitched_src_to_dst(gsl::span<T> dest, gsl::span<const U> src, size_t src_pitch_in_bytes, size_t width, size_t height)
{
for (int row = 0; row < height; row++)
{
for (unsigned col = 0; col < width; col++)
dest[col] = src[col];
src = src.subspan(src_pitch_in_bytes / sizeof(U));
dest = dest.subspan(width);
}
}
private:
using surface_storage_type = typename Traits::surface_storage_type;
using surface_type = typename Traits::surface_type;
using command_list_type = typename Traits::command_list_type;
using download_buffer_object = typename Traits::download_buffer_object;
std::unordered_map<u32, surface_storage_type> m_render_targets_storage = {};
std::unordered_map<u32, surface_storage_type> m_depth_stencil_storage = {};
public:
std::array<std::tuple<u32, surface_type>, 4> m_bound_render_targets = {};
std::tuple<u32, surface_type> m_bound_depth_stencil = {};
std::list<surface_storage_type> invalidated_resources;
surface_store() = default;
~surface_store() = default;
surface_store(const surface_store&) = delete;
private:
/**
* If render target already exists at address, issue state change operation on cmdList.
* Otherwise create one with width, height, clearColor info.
* returns the corresponding render target resource.
*/
template <typename ...Args>
gsl::not_null<surface_type> bind_address_as_render_targets(
command_list_type command_list,
u32 address,
surface_color_format color_format, size_t width, size_t height,
Args&&... extra_params)
{
auto It = m_render_targets_storage.find(address);
// TODO: Fix corner cases
// This doesn't take overlapping surface(s) into account.
// Invalidated surface(s) should also copy their content to the new resources.
if (It != m_render_targets_storage.end())
{
surface_storage_type &rtt = It->second;
if (Traits::rtt_has_format_width_height(rtt, color_format, width, height))
{
Traits::prepare_rtt_for_drawing(command_list, Traits::get(rtt));
return Traits::get(rtt);
}
invalidated_resources.push_back(std::move(rtt));
m_render_targets_storage.erase(address);
}
m_render_targets_storage[address] = Traits::create_new_surface(address, color_format, width, height, std::forward<Args>(extra_params)...);
return Traits::get(m_render_targets_storage[address]);
}
template <typename ...Args>
gsl::not_null<surface_type> bind_address_as_depth_stencil(
command_list_type command_list,
u32 address,
surface_depth_format depth_format, size_t width, size_t height,
Args&&... extra_params)
{
auto It = m_depth_stencil_storage.find(address);
if (It != m_depth_stencil_storage.end())
{
surface_storage_type &ds = It->second;
if (Traits::ds_has_format_width_height(ds, depth_format, width, height))
{
Traits::prepare_ds_for_drawing(command_list, Traits::get(ds));
return Traits::get(ds);
}
invalidated_resources.push_back(std::move(ds));
m_depth_stencil_storage.erase(address);
}
m_depth_stencil_storage[address] = Traits::create_new_surface(address, depth_format, width, height, std::forward<Args>(extra_params)...);
return Traits::get(m_depth_stencil_storage[address]);
}
public:
/**
* Update bound color and depth surface.
* Must be called everytime surface format, clip, or addresses changes.
*/
template <typename ...Args>
void prepare_render_target(
command_list_type command_list,
u32 set_surface_format_reg,
u32 clip_horizontal_reg, u32 clip_vertical_reg,
surface_target set_surface_target,
const std::array<u32, 4> &surface_addresses, u32 address_z,
Args&&... extra_params)
{
u32 clip_width = clip_horizontal_reg >> 16;
u32 clip_height = clip_vertical_reg >> 16;
u32 clip_x = clip_horizontal_reg;
u32 clip_y = clip_vertical_reg;
surface_color_format color_format = to_surface_color_format(set_surface_format_reg & 0x1f);
surface_depth_format depth_format = to_surface_depth_format((set_surface_format_reg >> 5) & 0x7);
// Make previous RTTs sampleable
for (std::tuple<u32, surface_type> &rtt : m_bound_render_targets)
{
if (std::get<1>(rtt) != nullptr)
Traits::prepare_rtt_for_sampling(command_list, std::get<1>(rtt));
rtt = std::make_tuple(0, nullptr);
}
// Create/Reuse requested rtts
for (u8 surface_index : utility::get_rtt_indexes(set_surface_target))
{
if (surface_addresses[surface_index] == 0)
continue;
m_bound_render_targets[surface_index] = std::make_tuple(surface_addresses[surface_index],
bind_address_as_render_targets(command_list, surface_addresses[surface_index], color_format, clip_width, clip_height, std::forward<Args>(extra_params)...));
}
// Same for depth buffer
if (std::get<1>(m_bound_depth_stencil) != nullptr)
Traits::prepare_ds_for_sampling(command_list, std::get<1>(m_bound_depth_stencil));
m_bound_depth_stencil = std::make_tuple(0, nullptr);
if (!address_z)
return;
m_bound_depth_stencil = std::make_tuple(address_z,
bind_address_as_depth_stencil(command_list, address_z, depth_format, clip_width, clip_height, std::forward<Args>(extra_params)...));
}
/**
* Search for given address in stored color surface and returns it if size/format match.
* Return an empty surface_type otherwise.
*/
surface_type get_texture_from_render_target_if_applicable(u32 address)
{
// TODO: Handle texture that overlaps one (or several) surface.
// Handle texture conversion
// FIXME: Disgaea 3 loading screen seems to use a subset of a surface. It's not properly handled here.
// Note: not const because conversions/resolve/... can happen
auto It = m_render_targets_storage.find(address);
if (It != m_render_targets_storage.end())
return Traits::get(It->second);
return surface_type();
}
/**
* Search for given address in stored depth stencil surface and returns it if size/format match.
* Return an empty surface_type otherwise.
*/
surface_type get_texture_from_depth_stencil_if_applicable(u32 address)
{
// TODO: Same as above although there wasn't any game using corner case for DS yet.
auto It = m_depth_stencil_storage.find(address);
if (It != m_depth_stencil_storage.end())
return Traits::get(It->second);
return surface_type();
}
/**
* Get bound color surface raw data.
*/
template <typename... Args>
std::array<std::vector<gsl::byte>, 4> get_render_targets_data(
surface_color_format color_format, size_t width, size_t height,
Args&& ...args
)
{
std::array<download_buffer_object, 4> download_data = {};
// Issue download commands
for (int i = 0; i < 4; i++)
{
if (std::get<0>(m_bound_render_targets[i]) == 0)
continue;
surface_type surface_resource = std::get<1>(m_bound_render_targets[i]);
download_data[i] = std::move(
Traits::issue_download_command(surface_resource, color_format, width, height, std::forward<Args&&>(args)...)
);
}
std::array<std::vector<gsl::byte>, 4> result = {};
// Sync and copy data
for (int i = 0; i < 4; i++)
{
if (std::get<0>(m_bound_render_targets[i]) == 0)
continue;
gsl::span<const gsl::byte> raw_src = Traits::map_downloaded_buffer(download_data[i], std::forward<Args&&>(args)...);
size_t src_pitch = utility::get_aligned_pitch(color_format, gsl::narrow<u32>(width));
size_t dst_pitch = utility::get_packed_pitch(color_format, gsl::narrow<u32>(width));
result[i].resize(dst_pitch * height);
// Note: MSVC + GSL doesn't support span<byte> -> span<T> for non const span atm
// thus manual conversion
switch (color_format)
{
case surface_color_format::a8b8g8r8:
case surface_color_format::x8b8g8r8_o8b8g8r8:
case surface_color_format::x8b8g8r8_z8b8g8r8:
case surface_color_format::a8r8g8b8:
case surface_color_format::x8r8g8b8_o8r8g8b8:
case surface_color_format::x8r8g8b8_z8r8g8b8:
case surface_color_format::x32:
{
gsl::span<be_t<u32>> dst_span{ (be_t<u32>*)result[i].data(), gsl::narrow<int>(dst_pitch * width / sizeof(be_t<u32>)) };
copy_pitched_src_to_dst(dst_span, gsl::as_span<const u32>(raw_src), src_pitch, width, height);
break;
}
case surface_color_format::b8:
{
gsl::span<u8> dst_span{ (u8*)result[i].data(), gsl::narrow<int>(dst_pitch * width / sizeof(u8)) };
copy_pitched_src_to_dst(dst_span, gsl::as_span<const u8>(raw_src), src_pitch, width, height);
break;
}
case surface_color_format::g8b8:
case surface_color_format::r5g6b5:
case surface_color_format::x1r5g5b5_o1r5g5b5:
case surface_color_format::x1r5g5b5_z1r5g5b5:
{
gsl::span<be_t<u16>> dst_span{ (be_t<u16>*)result[i].data(), gsl::narrow<int>(dst_pitch * width / sizeof(be_t<u16>)) };
copy_pitched_src_to_dst(dst_span, gsl::as_span<const u16>(raw_src), src_pitch, width, height);
break;
}
// Note : may require some big endian swap
case surface_color_format::w32z32y32x32:
{
gsl::span<u128> dst_span{ (u128*)result[i].data(), gsl::narrow<int>(dst_pitch * width / sizeof(u128)) };
copy_pitched_src_to_dst(dst_span, gsl::as_span<const u128>(raw_src), src_pitch, width, height);
break;
}
case surface_color_format::w16z16y16x16:
{
gsl::span<u64> dst_span{ (u64*)result[i].data(), gsl::narrow<int>(dst_pitch * width / sizeof(u64)) };
copy_pitched_src_to_dst(dst_span, gsl::as_span<const u64>(raw_src), src_pitch, width, height);
break;
}
}
Traits::unmap_downloaded_buffer(download_data[i], std::forward<Args&&>(args)...);
}
return result;
}
/**
* Get bound color surface raw data.
*/
template <typename... Args>
std::array<std::vector<gsl::byte>, 2> get_depth_stencil_data(
surface_depth_format depth_format, size_t width, size_t height,
Args&& ...args
)
{
std::array<std::vector<gsl::byte>, 2> result = {};
if (std::get<0>(m_bound_depth_stencil) == 0)
return result;
size_t row_pitch = align(width * 4, 256);
download_buffer_object stencil_data = {};
download_buffer_object depth_data = Traits::issue_depth_download_command(std::get<1>(m_bound_depth_stencil), depth_format, width, height, std::forward<Args&&>(args)...);
if (depth_format == surface_depth_format::z24s8)
stencil_data = std::move(Traits::issue_stencil_download_command(std::get<1>(m_bound_depth_stencil), width, height, std::forward<Args&&>(args)...));
gsl::span<const gsl::byte> depth_buffer_raw_src = Traits::map_downloaded_buffer(depth_data, std::forward<Args&&>(args)...);
if (depth_format == surface_depth_format::z16)
{
result[0].resize(width * height * 2);
gsl::span<u16> dest{ (u16*)result[0].data(), gsl::narrow<int>(width * height) };
copy_pitched_src_to_dst(dest, gsl::as_span<const u16>(depth_buffer_raw_src), row_pitch, width, height);
}
if (depth_format == surface_depth_format::z24s8)
{
result[0].resize(width * height * 4);
gsl::span<u32> dest{ (u32*)result[0].data(), gsl::narrow<int>(width * height) };
copy_pitched_src_to_dst(dest, gsl::as_span<const u32>(depth_buffer_raw_src), row_pitch, width, height);
}
Traits::unmap_downloaded_buffer(depth_data, std::forward<Args&&>(args)...);
if (depth_format == surface_depth_format::z16)
return result;
gsl::span<const gsl::byte> stencil_buffer_raw_src = Traits::map_downloaded_buffer(stencil_data, std::forward<Args&&>(args)...);
result[1].resize(width * height);
gsl::span<u8> dest{ (u8*)result[1].data(), gsl::narrow<int>(width * height) };
copy_pitched_src_to_dst(dest, gsl::as_span<const u8>(stencil_buffer_raw_src), align(width, 256), width, height);
Traits::unmap_downloaded_buffer(stencil_data, std::forward<Args&&>(args)...);
return result;
}
};
}
+207 -222
View File
@@ -10,43 +10,73 @@
namespace
{
/**
*
*/
D3D12_GPU_VIRTUAL_ADDRESS createVertexBuffer(const rsx::data_array_format_info &vertex_array_desc, const std::vector<u8> &vertex_data, ID3D12Device *device, data_heap<ID3D12Resource, 65536> &vertex_index_heap)
{
size_t buffer_size = vertex_data.size();
assert(vertex_index_heap.can_alloc(buffer_size));
size_t heap_offset = vertex_index_heap.alloc(buffer_size);
UINT get_component_mapping_from_vector_size(u8 size)
{
switch (size)
{
case 1:
return D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1);
case 2:
return D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1);
case 3:
return D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_1,
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_2,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_1);
case 4:
return D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
}
throw EXCEPTION("Wrong vector size %d", size);
}
void *buffer;
CHECK_HRESULT(vertex_index_heap.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), (void**)&buffer));
void *bufferMap = (char*)buffer + heap_offset;
memcpy(bufferMap, vertex_data.data(), vertex_data.size());
vertex_index_heap.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
return vertex_index_heap.m_heap->GetGPUVirtualAddress() + heap_offset;
u32 get_vertex_count(const std::vector<std::pair<u32, u32> > first_count_commands)
{
u32 vertex_count = 0;
for (const auto &pair : first_count_commands)
vertex_count += pair.second;
return vertex_count;
}
D3D12_SHADER_RESOURCE_VIEW_DESC get_vertex_attribute_srv(const rsx::data_array_format_info &info, UINT64 offset_in_vertex_buffers_buffer, UINT buffer_size)
{
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
D3D12_SHADER_RESOURCE_VIEW_DESC vertex_buffer_view = {
get_vertex_attribute_format(info.type, info.size),
D3D12_SRV_DIMENSION_BUFFER,
get_component_mapping_from_vector_size(info.size)
};
vertex_buffer_view.Buffer.FirstElement = offset_in_vertex_buffers_buffer / element_size;
vertex_buffer_view.Buffer.NumElements = buffer_size / element_size;
return vertex_buffer_view;
}
template<int N>
UINT64 get_next_multiple_of(UINT64 val)
{
UINT64 divided_val = (val + N - 1) / N;
return divided_val * N;
}
}
}
void D3D12GSRender::load_vertex_data(u32 first, u32 count)
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> D3D12GSRender::upload_vertex_attributes(
const std::vector<std::pair<u32, u32> > &vertex_ranges,
gsl::not_null<ID3D12GraphicsCommandList*> command_list)
{
m_first_count_pairs.emplace_back(std::make_pair(first, count));
vertex_draw_count += count;
}
std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::upload_vertex_attributes(const std::vector<std::pair<u32, u32> > &vertex_ranges)
{
std::vector<D3D12_VERTEX_BUFFER_VIEW> vertex_buffer_views;
m_IASet.clear();
size_t input_slot = 0;
size_t vertex_count = 0;
for (const auto &pair : vertex_ranges)
vertex_count += pair.second;
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_views;
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertex_buffer_data.Get(), D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER, D3D12_RESOURCE_STATE_COPY_DEST));
u32 vertex_count = get_vertex_count(vertex_ranges);
size_t offset_in_vertex_buffers_buffer = 0;
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
for (int index = 0; index < rsx::limits::vertex_count; ++index)
@@ -60,221 +90,184 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::upload_vertex_attributes(co
// Active vertex array
const rsx::data_array_format_info &info = vertex_arrays_info[index];
u32 type_size = rsx::get_vertex_type_size(info.type);
u32 element_size = type_size * info.size;
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
UINT buffer_size = element_size * vertex_count;
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
size_t buffer_size = element_size * vertex_count;
assert(m_vertex_index_data.can_alloc(buffer_size));
size_t heap_offset = m_vertex_index_data.alloc(buffer_size);
void *buffer;
CHECK_HRESULT(m_vertex_index_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), (void**)&buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
for (const auto &range : vertex_ranges)
{
write_vertex_array_data_to_buffer(mapped_buffer, range.first, range.second, index, info);
mapped_buffer = (char*)mapped_buffer + range.second * element_size;
}
m_vertex_index_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view =
{
m_vertex_index_data.m_heap->GetGPUVirtualAddress() + heap_offset,
(UINT)buffer_size,
(UINT)element_size
};
vertex_buffer_views.push_back(vertex_buffer_view);
command_list->CopyBufferRegion(m_vertex_buffer_data.Get(), offset_in_vertex_buffers_buffer, m_buffer_data.get_heap(), heap_offset, buffer_size);
m_timers.m_buffer_upload_size += buffer_size;
vertex_buffer_views.emplace_back(get_vertex_attribute_srv(info, offset_in_vertex_buffers_buffer, buffer_size));
offset_in_vertex_buffers_buffer = get_next_multiple_of<48>(offset_in_vertex_buffers_buffer + buffer_size); // 48 is multiple of 2, 4, 6, 8, 12, 16
m_timers.buffer_upload_size += buffer_size;
D3D12_INPUT_ELEMENT_DESC IAElement = {};
IAElement.SemanticName = "TEXCOORD";
IAElement.SemanticIndex = (UINT)index;
IAElement.InputSlot = (UINT)input_slot++;
IAElement.Format = get_vertex_attribute_format(info.type, info.size);
IAElement.AlignedByteOffset = 0;
IAElement.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
IAElement.InstanceDataStepRate = 0;
m_IASet.push_back(IAElement);
}
else if (register_vertex_info[index].size > 0)
{
// In register vertex attribute
const rsx::data_array_format_info &info = register_vertex_info[index];
const std::vector<u8> &data = register_vertex_data[index];
u32 type_size = rsx::get_vertex_type_size(info.type);
u32 element_size = type_size * info.size;
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
UINT buffer_size = gsl::narrow<UINT>(data.size());
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
size_t buffer_size = data.size();
assert(m_vertex_index_data.can_alloc(buffer_size));
size_t heap_offset = m_vertex_index_data.alloc(buffer_size);
void *buffer;
CHECK_HRESULT(m_vertex_index_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), (void**)&buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
memcpy(mapped_buffer, data.data(), data.size());
m_vertex_index_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view = {
m_vertex_index_data.m_heap->GetGPUVirtualAddress() + heap_offset,
(UINT)buffer_size,
(UINT)element_size
};
vertex_buffer_views.push_back(vertex_buffer_view);
command_list->CopyBufferRegion(m_vertex_buffer_data.Get(), offset_in_vertex_buffers_buffer, m_buffer_data.get_heap(), heap_offset, buffer_size);
D3D12_INPUT_ELEMENT_DESC IAElement = {};
IAElement.SemanticName = "TEXCOORD";
IAElement.SemanticIndex = (UINT)index;
IAElement.InputSlot = (UINT)input_slot++;
IAElement.Format = get_vertex_attribute_format(info.type, info.size);
IAElement.AlignedByteOffset = 0;
IAElement.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA;
IAElement.InstanceDataStepRate = 1;
m_IASet.push_back(IAElement);
vertex_buffer_views.emplace_back(get_vertex_attribute_srv(info, offset_in_vertex_buffers_buffer, buffer_size));
offset_in_vertex_buffers_buffer = get_next_multiple_of<48>(offset_in_vertex_buffers_buffer + buffer_size); // 48 is multiple of 2, 4, 6, 8, 12, 16
}
}
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertex_buffer_data.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER));
return vertex_buffer_views;
}
void D3D12GSRender::load_vertex_index_data(u32 first, u32 count)
namespace
{
std::tuple<std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>, size_t> upload_inlined_vertex_array(
gsl::span<const rsx::data_array_format_info, 16> vertex_attribute_infos,
gsl::span<const gsl::byte> inlined_array_raw_data,
data_heap& ring_buffer_data,
ID3D12Resource* vertex_buffer_placement,
ID3D12GraphicsCommandList* command_list
)
{
// We can't rely on vertex_attribute_infos strides here so compute it
// assuming all attributes are packed
u32 stride = 0;
for (const auto &info : vertex_attribute_infos)
{
if (!info.size) // disabled
continue;
stride += rsx::get_vertex_type_size_on_host(info.type, info.size);
}
u32 element_count = gsl::narrow<u32>(inlined_array_raw_data.size_bytes()) / stride;
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> result;
UINT64 vertex_buffer_offset = 0;
for (const auto &info : vertex_attribute_infos)
{
if (!info.size) // disabled
continue;
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
UINT buffer_size = element_size * element_count;
size_t heap_offset = ring_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *mapped_buffer = ring_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
gsl::span<gsl::byte> dst = { (gsl::byte*)mapped_buffer, buffer_size };
for (u32 i = 0; i < element_count; i++)
{
auto subdst = dst.subspan(i * element_size, element_size);
auto subsrc = inlined_array_raw_data.subspan(i * stride, element_size);
if (info.type == rsx::vertex_base_type::ub && info.size == 4)
{
subdst[0] = subsrc[3];
subdst[1] = subsrc[2];
subdst[2] = subsrc[1];
subdst[3] = subsrc[0];
}
else
{
std::copy(subsrc.begin(), subsrc.end(), subdst.begin());
}
}
ring_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
command_list->CopyBufferRegion(vertex_buffer_placement, vertex_buffer_offset, ring_buffer_data.get_heap(), heap_offset, buffer_size);
result.emplace_back(get_vertex_attribute_srv(info, vertex_buffer_offset, buffer_size));
vertex_buffer_offset = get_next_multiple_of<48>(vertex_buffer_offset + buffer_size); // 48 is multiple of 2, 4, 6, 8, 12, 16
}
return std::make_tuple(result, element_count);
}
}
void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
{
assert(m_constants_data.can_alloc(256));
size_t heap_offset = m_constants_data.alloc(256);
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(256);
// Scale offset buffer
// Separate constant buffer
void *mapped_buffer;
CHECK_HRESULT(m_constants_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + 256), &mapped_buffer));
fill_scale_offset_data((char*)mapped_buffer + heap_offset);
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + 256));
fill_scale_offset_data(mapped_buffer);
int is_alpha_tested = !!(rsx::method_registers[NV4097_SET_ALPHA_TEST_ENABLE]);
float alpha_ref = (float&)rsx::method_registers[NV4097_SET_ALPHA_REF];
memcpy((char*)mapped_buffer + heap_offset + 16 * sizeof(float), &is_alpha_tested, sizeof(int));
memcpy((char*)mapped_buffer + heap_offset + 17 * sizeof(float), &alpha_ref, sizeof(float));
size_t tex_idx = 0;
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
{
if (!textures[i].enabled())
{
int is_unorm = false;
memcpy((char*)mapped_buffer + heap_offset + (18 + tex_idx++) * sizeof(int), &is_unorm, sizeof(int));
continue;
}
size_t w = textures[i].width(), h = textures[i].height();
// if (!w || !h) continue;
int is_unorm = (textures[i].format() & CELL_GCM_TEXTURE_UN);
memcpy((char*)mapped_buffer + heap_offset + (18 + tex_idx++) * sizeof(int), &is_unorm, sizeof(int));
}
m_constants_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + 256));
u8 alpha_ref_raw = (u8)(rsx::method_registers[NV4097_SET_ALPHA_REF] & 0xFF);
float alpha_ref = alpha_ref_raw / 255.f;
memcpy((char*)mapped_buffer + 16 * sizeof(float), &is_alpha_tested, sizeof(int));
memcpy((char*)mapped_buffer + 17 * sizeof(float), &alpha_ref, sizeof(float));
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 256));
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
m_constants_data.m_heap->GetGPUVirtualAddress() + heap_offset,
m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
256
};
m_device->CreateConstantBufferView(&constant_buffer_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)descriptorIndex, g_descriptor_stride_srv_cbv_uav));
.Offset((INT)descriptorIndex, m_descriptor_stride_srv_cbv_uav));
}
void D3D12GSRender::upload_and_bind_vertex_shader_constants(size_t descriptor_index)
{
size_t buffer_size = 512 * 4 * sizeof(float);
assert(m_constants_data.can_alloc(buffer_size));
size_t heap_offset = m_constants_data.alloc(buffer_size);
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *mapped_buffer;
CHECK_HRESULT(m_constants_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), &mapped_buffer));
fill_vertex_program_constants_data((char*)mapped_buffer + heap_offset);
m_constants_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
fill_vertex_program_constants_data(mapped_buffer);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
m_constants_data.m_heap->GetGPUVirtualAddress() + heap_offset,
m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
(UINT)buffer_size
};
m_device->CreateConstantBufferView(&constant_buffer_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)descriptor_index, g_descriptor_stride_srv_cbv_uav));
.Offset((INT)descriptor_index, m_descriptor_stride_srv_cbv_uav));
}
void D3D12GSRender::upload_and_bind_fragment_shader_constants(size_t descriptor_index)
{
// Get constant from fragment program
size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(&fragment_program);
size_t buffer_size = m_pso_cache.get_fragment_constants_buffer_size(m_fragment_program);
// Multiple of 256 never 0
buffer_size = (buffer_size + 255) & ~255;
assert(m_constants_data.can_alloc(buffer_size));
size_t heap_offset = m_constants_data.alloc(buffer_size);
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
size_t offset = 0;
void *mapped_buffer;
CHECK_HRESULT(m_constants_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), &mapped_buffer));
m_pso_cache.fill_fragment_constans_buffer((char*)mapped_buffer + heap_offset, &fragment_program);
m_constants_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
float *mapped_buffer = m_buffer_data.map<float>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
m_pso_cache.fill_fragment_constans_buffer({ mapped_buffer, gsl::narrow<int>(buffer_size) }, m_fragment_program);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
m_constants_data.m_heap->GetGPUVirtualAddress() + heap_offset,
m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
(UINT)buffer_size
};
m_device->CreateConstantBufferView(&constant_buffer_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)descriptor_index, g_descriptor_stride_srv_cbv_uav));
.Offset((INT)descriptor_index, m_descriptor_stride_srv_cbv_uav));
}
std::tuple<D3D12_VERTEX_BUFFER_VIEW, size_t> D3D12GSRender::upload_inlined_vertex_array()
{
UINT offset = 0;
m_IASet.clear();
// Bind attributes
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
const auto &info = vertex_arrays_info[index];
if (!info.size) // disabled
continue;
D3D12_INPUT_ELEMENT_DESC IAElement = {};
IAElement.SemanticName = "TEXCOORD";
IAElement.SemanticIndex = (UINT)index;
IAElement.InputSlot = 0;
IAElement.Format = get_vertex_attribute_format(info.type, info.size);
IAElement.AlignedByteOffset = offset;
IAElement.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
IAElement.InstanceDataStepRate = 0;
m_IASet.push_back(IAElement);
offset += rsx::get_vertex_type_size(info.type) * info.size;
}
// Copy inline buffer
size_t buffer_size = inline_vertex_array.size() * sizeof(int);
assert(m_vertex_index_data.can_alloc(buffer_size));
size_t heap_offset = m_vertex_index_data.alloc(buffer_size);
void *buffer;
CHECK_HRESULT(m_vertex_index_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), (void**)&buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
write_inline_array_to_buffer(mapped_buffer);
m_vertex_index_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view =
{
m_vertex_index_data.m_heap->GetGPUVirtualAddress() + heap_offset,
(UINT)buffer_size,
(UINT)offset
};
return std::make_tuple(vertex_buffer_view, (u32)buffer_size / offset);
}
std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> D3D12GSRender::generate_index_buffer_for_emulated_primitives_array(const std::vector<std::pair<u32, u32> > &vertex_ranges)
{
@@ -284,12 +277,9 @@ std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> D3D12GSRender::generate_index_buffer
// Alloc
size_t buffer_size = align(index_count * sizeof(u16), 64);
assert(m_vertex_index_data.can_alloc(buffer_size));
size_t heap_offset = m_vertex_index_data.alloc(buffer_size);
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *buffer;
CHECK_HRESULT(m_vertex_index_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), (void**)&buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
size_t first = 0;
for (const auto &pair : vertex_ranges)
{
@@ -298,9 +288,9 @@ std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> D3D12GSRender::generate_index_buffer
mapped_buffer = (char*)mapped_buffer + element_count * sizeof(u16);
first += pair.second;
}
m_vertex_index_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_INDEX_BUFFER_VIEW index_buffer_view = {
m_vertex_index_data.m_heap->GetGPUVirtualAddress() + heap_offset,
m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
(UINT)buffer_size,
DXGI_FORMAT_R16_UINT
};
@@ -308,84 +298,79 @@ std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> D3D12GSRender::generate_index_buffer
return std::make_tuple(index_buffer_view, index_count);
}
std::tuple<bool, size_t> D3D12GSRender::upload_and_set_vertex_index_data(ID3D12GraphicsCommandList *command_list)
std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC>> D3D12GSRender::upload_and_set_vertex_index_data(ID3D12GraphicsCommandList *command_list)
{
if (draw_command == Draw_command::draw_command_inlined_array)
if (draw_command == rsx::draw_command::inlined_array)
{
size_t vertex_count;
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view;
std::tie(vertex_buffer_view, vertex_count) = upload_inlined_vertex_array();
command_list->IASetVertexBuffers(0, (UINT)1, &vertex_buffer_view);
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_view;
std::tie(vertex_buffer_view, vertex_count) = upload_inlined_vertex_array(
vertex_arrays_info,
{ (const gsl::byte*) inline_vertex_array.data(), gsl::narrow<int>(inline_vertex_array.size() * sizeof(uint)) },
m_buffer_data, m_vertex_buffer_data.Get(), command_list);
if (is_primitive_native(draw_mode))
return std::make_tuple(false, vertex_count);
return std::make_tuple(false, vertex_count, vertex_buffer_view);
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
size_t index_count;
std::tie(index_buffer_view, index_count) = generate_index_buffer_for_emulated_primitives_array({ { 0, (u32)vertex_count } });
command_list->IASetIndexBuffer(&index_buffer_view);
return std::make_tuple(true, index_count);
return std::make_tuple(true, index_count, vertex_buffer_view);
}
if (draw_command == Draw_command::draw_command_array)
if (draw_command == rsx::draw_command::array)
{
const std::vector<D3D12_VERTEX_BUFFER_VIEW> &vertex_buffer_views = upload_vertex_attributes(m_first_count_pairs);
command_list->IASetVertexBuffers(0, (UINT)vertex_buffer_views.size(), vertex_buffer_views.data());
if (is_primitive_native(draw_mode))
{
// Index count
size_t vertex_count = 0;
for (const auto &pair : m_first_count_pairs)
vertex_count += pair.second;
return std::make_tuple(false, vertex_count);
size_t vertex_count = get_vertex_count(first_count_commands);
return std::make_tuple(false, vertex_count, upload_vertex_attributes(first_count_commands, command_list));
}
D3D12_INDEX_BUFFER_VIEW index_buffer_view;
size_t index_count;
std::tie(index_buffer_view, index_count) = generate_index_buffer_for_emulated_primitives_array(m_first_count_pairs);
std::tie(index_buffer_view, index_count) = generate_index_buffer_for_emulated_primitives_array(first_count_commands);
command_list->IASetIndexBuffer(&index_buffer_view);
return std::make_tuple(true, index_count);
return std::make_tuple(true, index_count, upload_vertex_attributes(first_count_commands, command_list));
}
assert(draw_command == Draw_command::draw_command_indexed);
u32 indexed_type = rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4;
size_t index_size = get_index_type_size(indexed_type);
assert(draw_command == rsx::draw_command::indexed);
// Index count
size_t index_count = 0;
for (const auto &pair : m_first_count_pairs)
index_count += get_index_count(draw_mode, pair.second);
size_t index_count = get_index_count(draw_mode, gsl::narrow<int>(get_vertex_count(first_count_commands)));
rsx::index_array_type indexed_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
size_t index_size = get_index_type_size(indexed_type);
// Alloc
size_t buffer_size = align(index_count * index_size, 64);
assert(m_vertex_index_data.can_alloc(buffer_size));
size_t heap_offset = m_vertex_index_data.alloc(buffer_size);
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *buffer;
CHECK_HRESULT(m_vertex_index_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), (void**)&buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
u32 min_index = (u32)-1, max_index = 0;
for (const auto &pair : m_first_count_pairs)
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
u32 min_index, max_index;
if (indexed_type == rsx::index_array_type::u16)
{
size_t element_count = get_index_count(draw_mode, pair.second);
write_index_array_data_to_buffer((char*)mapped_buffer, draw_mode, pair.first, pair.second, min_index, max_index);
mapped_buffer = (char*)mapped_buffer + element_count * index_size;
gsl::span<u16> dst = { (u16*)mapped_buffer, gsl::narrow<int>(buffer_size / index_size) };
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, draw_mode, first_count_commands);
}
m_vertex_index_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
if (indexed_type == rsx::index_array_type::u32)
{
gsl::span<u32> dst = { (u32*)mapped_buffer, gsl::narrow<int>(buffer_size / index_size) };
std::tie(min_index, max_index) = write_index_array_data_to_buffer(dst, draw_mode, first_count_commands);
}
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_INDEX_BUFFER_VIEW index_buffer_view = {
m_vertex_index_data.m_heap->GetGPUVirtualAddress() + heap_offset,
m_buffer_data.get_heap()->GetGPUVirtualAddress() + heap_offset,
(UINT)buffer_size,
get_index_type(indexed_type)
};
m_timers.m_buffer_upload_size += buffer_size;
m_timers.buffer_upload_size += buffer_size;
command_list->IASetIndexBuffer(&index_buffer_view);
const std::vector<D3D12_VERTEX_BUFFER_VIEW> &vertex_buffer_views = upload_vertex_attributes({ std::make_pair(0, max_index + 1) });
command_list->IASetVertexBuffers(0, (UINT)vertex_buffer_views.size(), vertex_buffer_views.data());
return std::make_tuple(true, index_count);
return std::make_tuple(true, index_count, upload_vertex_attributes({ std::make_pair(0, max_index + 1) }, command_list));
}
#endif
+57 -5
View File
@@ -42,14 +42,30 @@ std::string getFunctionImp(FUNCTION f)
return "float4(1., 1., 1., 1.)";
case FUNCTION::FUNCTION_FRACT:
return "frac($0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE:
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
return "$t.Sample($tsampler, $0.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
return "$t.Sample($tsampler, ($0.x / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
return "$t.SampleLevel($tsampler, $0.x, $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
return "$t.Sample($tsampler, $0.xy * $t_scale)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ:
return "$t.Sample($tsampler, ($0.xy / $0.z) * $t_scale)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE:
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
return "$t.Sample($tsampler, ($0.xy / $0.w) * $t_scale)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
return "$t.SampleLevel($tsampler, $0.xy * $t_scale, $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
return "$t.Sample($tsampler, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ:
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
return "$t.Sample($tsampler, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
return "$t.SampleLevel($tsampler, $0.xyz, $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D:
return "$t.Sample($tsampler, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_PROJ:
return "$t.Sample($tsampler, ($0.xyz / $0.w))";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE3D_LOD:
return "$t.SampleLevel($tsampler, $0.xyz, $1)";
case FUNCTION::FUNCTION_DFDX:
return "ddx($0)";
case FUNCTION::FUNCTION_DFDY:
@@ -77,4 +93,40 @@ std::string compareFunctionImp(COMPARE f, const std::string &Op0, const std::str
return "(" + Op0 + " != " + Op1 + ")";
}
}
void insert_d3d12_legacy_function(std::ostream& OS)
{
OS << "float4 divsq_legacy(float4 num, float4 denum)\n";
OS << "{\n";
OS << " return num / sqrt(max(denum.xxxx, 1.E-10));\n";
OS << "}\n";
OS << "float4 rcp_legacy(float4 denum)\n";
OS << "{\n";
OS << " return 1. / denum;\n";
OS << "}\n";
OS << "float4 rsq_legacy(float4 val)\n";
OS << "{\n";
OS << " return float(1.0 / sqrt(max(val.x, 1.E-10))).xxxx;\n";
OS << "}\n\n";
OS << "float4 log2_legacy(float4 val)\n";
OS << "{\n";
OS << " return log2(max(val.x, 1.E-10)).xxxx;\n";
OS << "}\n\n";
OS << "float4 lit_legacy(float4 val)";
OS << "{\n";
OS << " float4 clamped_val = val;\n";
OS << " clamped_val.x = max(val.x, 0);\n";
OS << " clamped_val.y = max(val.y, 0);\n";
OS << " float4 result;\n";
OS << " result.x = 1.0;\n";
OS << " result.w = 1.;\n";
OS << " result.y = clamped_val.x;\n";
OS << " result.z = clamped_val.x > 0.0 ? exp(clamped_val.w * log(max(clamped_val.y, 1.E-10))) : 0.0;\n";
OS << " return result;\n";
OS << "}\n\n";
}
#endif
@@ -5,3 +5,5 @@
std::string getFloatTypeNameImp(size_t elementCount);
std::string getFunctionImp(FUNCTION f);
std::string compareFunctionImp(COMPARE f, const std::string &Op0, const std::string &Op1);
void insert_d3d12_legacy_function(std::ostream&);
+64 -56
View File
@@ -248,6 +248,7 @@ namespace
{
case CELL_GCM_TEXTURE_NEAREST: return D3D12_FILTER_TYPE_POINT;
case CELL_GCM_TEXTURE_LINEAR: return D3D12_FILTER_TYPE_LINEAR;
case CELL_GCM_TEXTURE_CONVOLUTION_MAG: return D3D12_FILTER_TYPE_LINEAR;
}
throw EXCEPTION("Invalid mag filter (0x%x)", mag_filter);
}
@@ -261,92 +262,99 @@ D3D12_FILTER get_texture_filter(u8 min_filter, u8 mag_filter)
return D3D12_ENCODE_BASIC_FILTER(min, mag, mip, D3D12_FILTER_REDUCTION_TYPE_STANDARD);
}
D3D12_PRIMITIVE_TOPOLOGY get_primitive_topology(u8 draw_mode)
D3D12_PRIMITIVE_TOPOLOGY get_primitive_topology(rsx::primitive_type draw_mode)
{
switch (draw_mode)
{
case CELL_GCM_PRIMITIVE_POINTS: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
case CELL_GCM_PRIMITIVE_LINES: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
case CELL_GCM_PRIMITIVE_LINE_LOOP: return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
case CELL_GCM_PRIMITIVE_LINE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
case CELL_GCM_PRIMITIVE_TRIANGLES: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case CELL_GCM_PRIMITIVE_QUADS: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case CELL_GCM_PRIMITIVE_QUAD_STRIP: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case CELL_GCM_PRIMITIVE_POLYGON: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::points: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
case rsx::primitive_type::lines: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
case rsx::primitive_type::line_loop: return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
case rsx::primitive_type::line_strip: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
case rsx::primitive_type::triangles: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::triangle_strip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
case rsx::primitive_type::triangle_fan: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::quads: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::quad_strip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case rsx::primitive_type::polygon: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
}
throw EXCEPTION("Invalid draw mode (0x%x)", draw_mode);
}
D3D12_PRIMITIVE_TOPOLOGY_TYPE get_primitive_topology_type(u8 draw_mode)
D3D12_PRIMITIVE_TOPOLOGY_TYPE get_primitive_topology_type(rsx::primitive_type draw_mode)
{
switch (draw_mode)
{
case CELL_GCM_PRIMITIVE_POINTS: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
case CELL_GCM_PRIMITIVE_LINES: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case CELL_GCM_PRIMITIVE_LINE_STRIP: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case CELL_GCM_PRIMITIVE_TRIANGLES: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case CELL_GCM_PRIMITIVE_QUADS: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case CELL_GCM_PRIMITIVE_QUAD_STRIP: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case CELL_GCM_PRIMITIVE_POLYGON: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case CELL_GCM_PRIMITIVE_LINE_LOOP: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case rsx::primitive_type::points: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
case rsx::primitive_type::lines: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case rsx::primitive_type::line_strip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case rsx::primitive_type::triangles: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case rsx::primitive_type::triangle_strip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case rsx::primitive_type::triangle_fan: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case rsx::primitive_type::quads: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case rsx::primitive_type::quad_strip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case rsx::primitive_type::polygon: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case rsx::primitive_type::line_loop: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
}
throw EXCEPTION("Invalid or unsupported draw mode (0x%x)", draw_mode);
}
DXGI_FORMAT get_color_surface_format(u8 format)
DXGI_FORMAT get_color_surface_format(rsx::surface_color_format format)
{
switch (format)
{
case CELL_GCM_SURFACE_R5G6B5: return DXGI_FORMAT_B5G6R5_UNORM;
case CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8: return DXGI_FORMAT_B8G8R8X8_UNORM; //BIT.TRIP Runner2 use this
case CELL_GCM_SURFACE_A8R8G8B8: return DXGI_FORMAT_R8G8B8A8_UNORM;
case CELL_GCM_SURFACE_F_W16Z16Y16X16: return DXGI_FORMAT_R16G16B16A16_FLOAT;
case CELL_GCM_SURFACE_F_X32: return DXGI_FORMAT_R32_FLOAT;
case CELL_GCM_SURFACE_A8B8G8R8: return DXGI_FORMAT_R8G8B8A8_UNORM;
case rsx::surface_color_format::r5g6b5: return DXGI_FORMAT_B5G6R5_UNORM;
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
return DXGI_FORMAT_B8G8R8X8_UNORM; //BIT.TRIP Runner2 use this
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::a8r8g8b8: return DXGI_FORMAT_R8G8B8A8_UNORM;
case rsx::surface_color_format::b8: return DXGI_FORMAT_R8_UNORM;
case rsx::surface_color_format::g8b8: return DXGI_FORMAT_R8G8_UNORM;
case rsx::surface_color_format::w16z16y16x16: return DXGI_FORMAT_R16G16B16A16_FLOAT;
case rsx::surface_color_format::w32z32y32x32: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case rsx::surface_color_format::x32: return DXGI_FORMAT_R32_FLOAT;
}
throw EXCEPTION("Invalid format (0x%x)", format);
}
DXGI_FORMAT get_depth_stencil_surface_format(u8 format)
DXGI_FORMAT get_depth_stencil_surface_format(rsx::surface_depth_format format)
{
switch (format)
{
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_D16_UNORM;
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
case rsx::surface_depth_format::z16: return DXGI_FORMAT_D16_UNORM;
case rsx::surface_depth_format::z24s8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
}
throw EXCEPTION("Invalid format (0x%x)", format);
}
DXGI_FORMAT get_depth_stencil_surface_clear_format(u8 format)
DXGI_FORMAT get_depth_stencil_surface_clear_format(rsx::surface_depth_format format)
{
switch (format)
{
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_D16_UNORM;
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
case rsx::surface_depth_format::z16: return DXGI_FORMAT_D16_UNORM;
case rsx::surface_depth_format::z24s8: return DXGI_FORMAT_D24_UNORM_S8_UINT;
}
throw EXCEPTION("Invalid format (0x%x)", format);
}
DXGI_FORMAT get_depth_stencil_typeless_surface_format(u8 format)
DXGI_FORMAT get_depth_stencil_typeless_surface_format(rsx::surface_depth_format format)
{
switch (format)
{
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_R16_TYPELESS;
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_R24G8_TYPELESS;
case rsx::surface_depth_format::z16: return DXGI_FORMAT_R16_TYPELESS;
case rsx::surface_depth_format::z24s8: return DXGI_FORMAT_R24G8_TYPELESS;
}
throw EXCEPTION("Invalid format (0x%x)", format);
}
DXGI_FORMAT get_depth_samplable_surface_format(u8 format)
DXGI_FORMAT get_depth_samplable_surface_format(rsx::surface_depth_format format)
{
switch (format)
{
case CELL_GCM_SURFACE_Z16: return DXGI_FORMAT_R16_FLOAT;
case CELL_GCM_SURFACE_Z24S8: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
case rsx::surface_depth_format::z16: return DXGI_FORMAT_R16_UNORM;
case rsx::surface_depth_format::z24s8: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
}
throw EXCEPTION("Invalid format (0x%x)", format);
}
@@ -362,21 +370,21 @@ BOOL get_front_face_ccw(u32 ffv)
throw EXCEPTION("Invalid front face value (0x%x)", ffv);
}
DXGI_FORMAT get_index_type(u8 index_type)
DXGI_FORMAT get_index_type(rsx::index_array_type index_type)
{
switch (index_type)
{
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: return DXGI_FORMAT_R16_UINT;
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: return DXGI_FORMAT_R32_UINT;
case rsx::index_array_type::u16: return DXGI_FORMAT_R16_UINT;
case rsx::index_array_type::u32: return DXGI_FORMAT_R32_UINT;
}
throw EXCEPTION("Invalid index_type (0x%x)", index_type);
}
DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
DXGI_FORMAT get_vertex_attribute_format(rsx::vertex_base_type type, u8 size)
{
switch (type)
{
case CELL_GCM_VERTEX_S1:
case rsx::vertex_base_type::s1:
{
switch (size)
{
@@ -387,7 +395,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_F:
case rsx::vertex_base_type::f:
{
switch (size)
{
@@ -398,7 +406,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_SF:
case rsx::vertex_base_type::sf:
{
switch (size)
{
@@ -409,7 +417,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_UB:
case rsx::vertex_base_type::ub:
{
switch (size)
{
@@ -420,7 +428,7 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_S32K:
case rsx::vertex_base_type::s32k:
{
switch (size)
{
@@ -431,18 +439,18 @@ DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size)
}
break;
}
case CELL_GCM_VERTEX_CMP:
case rsx::vertex_base_type::cmp:
{
switch (size)
{
case 1: return DXGI_FORMAT_R32_FLOAT;
case 2: return DXGI_FORMAT_R32G32_FLOAT;
case 3: return DXGI_FORMAT_R32G32B32_FLOAT;
case 4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case 1: return DXGI_FORMAT_R16G16B16A16_SNORM;
case 2:
case 3:
case 4: throw EXCEPTION("Unsupported CMP vertex format with size > 1");
}
break;
}
case CELL_GCM_VERTEX_UB256:
case rsx::vertex_base_type::ub256:
{
switch (size)
{
+9 -9
View File
@@ -56,37 +56,37 @@ D3D12_FILTER get_texture_filter(u8 min_filter, u8 mag_filter);
/**
* Convert draw mode to D3D12_PRIMITIVE_TOPOLOGY
*/
D3D12_PRIMITIVE_TOPOLOGY get_primitive_topology(u8 draw_mode);
D3D12_PRIMITIVE_TOPOLOGY get_primitive_topology(rsx::primitive_type draw_mode);
/**
* Convert draw mode to D3D12_PRIMITIVE_TOPOLOGY_TYPE
*/
D3D12_PRIMITIVE_TOPOLOGY_TYPE get_primitive_topology_type(u8 draw_mode);
D3D12_PRIMITIVE_TOPOLOGY_TYPE get_primitive_topology_type(rsx::primitive_type draw_mode);
/**
* Convert color surface format to DXGI_FORMAT
*/
DXGI_FORMAT get_color_surface_format(u8 format);
DXGI_FORMAT get_color_surface_format(rsx::surface_color_format format);
/**
* Convert depth stencil surface format to DXGI_FORMAT
*/
DXGI_FORMAT get_depth_stencil_surface_format(u8 format);
DXGI_FORMAT get_depth_stencil_surface_format(rsx::surface_depth_format format);
/**
*Convert depth stencil surface format to DXGI_FORMAT suited for clear value
*/
DXGI_FORMAT get_depth_stencil_surface_clear_format(u8 format);
DXGI_FORMAT get_depth_stencil_surface_clear_format(rsx::surface_depth_format format);
/**
* Convert depth surface format to a typeless DXGI_FORMAT
*/
DXGI_FORMAT get_depth_stencil_typeless_surface_format(u8 format);
DXGI_FORMAT get_depth_stencil_typeless_surface_format(rsx::surface_depth_format format);
/**
* Convert depth surface format to a DXGI_FORMAT that can be depth sampled
*/
DXGI_FORMAT get_depth_samplable_surface_format(u8 format);
DXGI_FORMAT get_depth_samplable_surface_format(rsx::surface_depth_format format);
/**
* Convert front face value to bool value telling wheter front face is counterclockwise or not
@@ -96,12 +96,12 @@ BOOL get_front_face_ccw(u32 set_front_face_value);
/**
* Convert index type to DXGI_FORMAT
*/
DXGI_FORMAT get_index_type(u8 index_type);
DXGI_FORMAT get_index_type(rsx::index_array_type index_type);
/**
* Convert vertex attribute format and size to DXGI_FORMAT
*/
DXGI_FORMAT get_vertex_attribute_format(u8 type, u8 size);
DXGI_FORMAT get_vertex_attribute_format(rsx::vertex_base_type type, u8 size);
/**
* Convert scissor register value to D3D12_RECT
@@ -6,8 +6,8 @@
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
D3D12FragmentDecompiler::D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions) :
FragmentProgramDecompiler(addr, size, ctrl, texture_dimensions)
D3D12FragmentDecompiler::D3D12FragmentDecompiler(const RSXFragmentProgram &prog, u32& size) :
FragmentProgramDecompiler(prog, size)
{
}
@@ -39,22 +39,6 @@ void D3D12FragmentDecompiler::insertHeader(std::stringstream & OS)
OS << " float4x4 scaleOffsetMat;" << std::endl;
OS << " int isAlphaTested;" << std::endl;
OS << " float alphaRef;" << std::endl;
OS << " int tex0_is_unorm;" << std::endl;
OS << " int tex1_is_unorm;" << std::endl;
OS << " int tex2_is_unorm;" << std::endl;
OS << " int tex3_is_unorm;" << std::endl;
OS << " int tex4_is_unorm;" << std::endl;
OS << " int tex5_is_unorm;" << std::endl;
OS << " int tex6_is_unorm;" << std::endl;
OS << " int tex7_is_unorm;" << std::endl;
OS << " int tex8_is_unorm;" << std::endl;
OS << " int tex9_is_unorm;" << std::endl;
OS << " int tex10_is_unorm;" << std::endl;
OS << " int tex11_is_unorm;" << std::endl;
OS << " int tex12_is_unorm;" << std::endl;
OS << " int tex13_is_unorm;" << std::endl;
OS << " int tex14_is_unorm;" << std::endl;
OS << " int tex15_is_unorm;" << std::endl;
OS << "};" << std::endl;
}
@@ -107,32 +91,50 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
{
OS << "cbuffer CONSTANT : register(b2)" << std::endl;
OS << "{" << std::endl;
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM])
for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM])
{
if (PT.type == "sampler2D" || PT.type == "samplerCube")
if (PT.type == "sampler1D" || PT.type == "sampler2D" || PT.type == "samplerCube" || PT.type == "sampler3D")
continue;
for (ParamItem PI : PT.items)
for (const ParamItem &PI : PT.items)
OS << " " << PT.type << " " << PI.name << ";" << std::endl;
}
OS << "};" << std::endl << std::endl;
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM])
for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM])
{
if (PT.type == "sampler2D")
if (PT.type == "sampler1D")
{
for (ParamItem PI : PT.items)
for (const ParamItem &PI : PT.items)
{
size_t textureIndex = atoi(PI.name.data() + 3);
OS << "Texture2D " << PI.name << " : register(t" << textureIndex << ");" << std::endl;
OS << "Texture1D " << PI.name << " : register(t" << textureIndex + 16 << ");" << std::endl;
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
}
}
else if (PT.type == "sampler2D")
{
for (const ParamItem &PI : PT.items)
{
size_t textureIndex = atoi(PI.name.data() + 3);
OS << "Texture2D " << PI.name << " : register(t" << textureIndex + 16 << ");" << std::endl;
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
}
}
else if (PT.type == "sampler3D")
{
for (const ParamItem &PI : PT.items)
{
size_t textureIndex = atoi(PI.name.data() + 3);
OS << "Texture3D " << PI.name << " : register(t" << textureIndex + 16 << ");" << std::endl;
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
}
}
else if (PT.type == "samplerCube")
{
for (ParamItem PI : PT.items)
for (const ParamItem &PI : PT.items)
{
size_t textureIndex = atoi(PI.name.data() + 3);
OS << "TextureCube " << PI.name << " : register(t" << textureIndex << ");" << std::endl;
OS << "TextureCube " << PI.name << " : register(t" << textureIndex + 16 << ");" << std::endl;
OS << "sampler " << PI.name << "sampler : register(s" << textureIndex << ");" << std::endl;
}
}
@@ -141,39 +143,64 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
{
insert_d3d12_legacy_function(OS);
const std::set<std::string> output_value =
{
"r0", "r1", "r2", "r3", "r4",
"h0", "h4", "h6", "h8"
"h0", "h2", "h4", "h6", "h8"
};
OS << "void ps_impl(PixelInput In, inout float4 r0, inout float4 h0, inout float4 r1, inout float4 r2, inout float4 h4, inout float4 r3, inout float4 h6, inout float4 r4, inout float4 h8)" << std::endl;
OS << "void ps_impl(bool is_front_face, PixelInput In, inout float4 r0, inout float4 h0, inout float4 r1, inout float4 h2, inout float4 r2, inout float4 h4, inout float4 r3, inout float4 h6, inout float4 r4, inout float4 h8)" << std::endl;
OS << "{" << std::endl;
for (ParamType PT : m_parr.params[PF_PARAM_IN])
for (const ParamType &PT : m_parr.params[PF_PARAM_IN])
{
for (ParamItem PI : PT.items)
for (const ParamItem &PI : PT.items)
{
if (m_prog.front_back_color_enabled)
{
if (PI.name == "spec_color" && m_prog.back_color_specular_output)
{
OS << " float4 spec_color = is_front_face ? In.dst_reg4 : In.spec_color;\n";
continue;
}
if (PI.name == "diff_color" && m_prog.back_color_diffuse_output)
{
OS << " float4 diff_color = is_front_face ? In.dst_reg3 : In.diff_color;\n";
continue;
}
}
OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";" << std::endl;
}
}
// A bit unclean, but works.
OS << " " << "float4 gl_Position = In.Position;" << std::endl;
OS << " " << "float4 gl_FragCoord = In.Position;" << std::endl;
if (m_prog.origin_mode == rsx::window_origin::bottom)
OS << " gl_FragCoord.y = (" << std::to_string(m_prog.height) << " - gl_FragCoord.y);\n";
// Declare output
for (ParamType PT : m_parr.params[PF_PARAM_NONE])
for (const ParamType &PT : m_parr.params[PF_PARAM_NONE])
{
for (ParamItem PI : PT.items)
for (const ParamItem &PI : PT.items)
if (output_value.find(PI.name) == output_value.end())
OS << " " << PT.type << " " << PI.name << " = float4(0., 0., 0., 0.);" << std::endl;
}
// Declare texture coordinate scaling component (to handle unormalized texture coordinates)
for (ParamType PT : m_parr.params[PF_PARAM_UNIFORM])
for (const ParamType &PT : m_parr.params[PF_PARAM_UNIFORM])
{
if (PT.type != "sampler2D")
continue;
for (const ParamItem& PI : PT.items)
{
size_t textureIndex = atoi(PI.name.data() + 3);
bool is_unorm = !!(m_prog.unnormalized_coords & (1 << textureIndex));
if (!is_unorm)
{
OS << " float2 " << PI.name << "_scale = float2(1., 1.);" << std::endl;
continue;
}
OS << " float2 " << PI.name << "_dim;" << std::endl;
OS << " " << PI.name << ".GetDimensions(" << PI.name << "_dim.x, " << PI.name << "_dim.y);" << std::endl;
OS << " float2 " << PI.name << "_scale = (!!" << PI.name << "_is_unorm) ? float2(1., 1.) / " << PI.name << "_dim : float2(1., 1.);" << std::endl;
OS << " float2 " << PI.name << "_scale = float2(1., 1.) / " << PI.name << "_dim;" << std::endl;
}
}
}
@@ -182,7 +209,7 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS)
{
OS << "}" << std::endl;
OS << std::endl;
OS << "PixelOutput main(PixelInput In)" << std::endl;
OS << "PixelOutput main(PixelInput In, bool is_front_face : SV_IsFrontFace)" << std::endl;
OS << "{" << std::endl;
OS << " float4 r0 = float4(0., 0., 0., 0.);" << std::endl;
OS << " float4 r1 = float4(0., 0., 0., 0.);" << std::endl;
@@ -194,7 +221,7 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS)
OS << " float4 h4 = float4(0., 0., 0., 0.);" << std::endl;
OS << " float4 h6 = float4(0., 0., 0., 0.);" << std::endl;
OS << " float4 h8 = float4(0., 0., 0., 0.);" << std::endl;
OS << " ps_impl(In, r0, h0, r1, r2, h4, r3, h6, r4, h8);" << std::endl;
OS << " ps_impl(is_front_face, In, r0, h0, r1, h2, r2, h4, r3, h6, r4, h8);" << std::endl;
const std::pair<std::string, std::string> table[] =
{
@@ -204,21 +231,52 @@ void D3D12FragmentDecompiler::insertMainEnd(std::stringstream & OS)
{ "ocol3", m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS ? "r4" : "h8" },
};
size_t num_output = 0;
std::string first_output_name;
OS << " PixelOutput Out = (PixelOutput)0;" << std::endl;
for (int i = 0; i < sizeof(table) / sizeof(*table); ++i)
{
if (m_parr.HasParam(PF_PARAM_NONE, "float4", table[i].second))
{
OS << " Out." << table[i].first << " = " << table[i].second << ";" << std::endl;
num_output++;
if (first_output_name.empty()) first_output_name = table[i].first;
}
}
if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
OS << " Out.depth = " << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "r1.z;" : "h0.z;") << std::endl;
{
/**
* Note: Naruto Shippuden : Ultimate Ninja Storm 2 sets CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS in a shader
* but it writes depth in r1.z and not h2.z.
* Maybe there's a different flag for depth ?
*/
// OS << " Out.depth = " << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "r1.z;" : "h2.z;") << std::endl;
OS << " Out.depth = r1.z;\n";
}
// Shaders don't always output colors (for instance if they write to depth only)
if (num_output > 0)
OS << " if (isAlphaTested && Out.ocol0.a <= alphaRef) discard;" << std::endl;
if (!first_output_name.empty())
{
switch (m_prog.alpha_func)
{
case rsx::comparaison_function::equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a != alphaRef) discard;\n";
break;
case rsx::comparaison_function::not_equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a == alphaRef) discard;\n";
break;
case rsx::comparaison_function::less_or_equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a > alphaRef) discard;\n";
break;
case rsx::comparaison_function::less:
OS << " if (isAlphaTested && Out." << first_output_name << ".a >= alphaRef) discard;\n";
break;
case rsx::comparaison_function::greater:
OS << " if (isAlphaTested && Out." << first_output_name << ".a <= alphaRef) discard;\n";
break;
case rsx::comparaison_function::greater_or_equal:
OS << " if (isAlphaTested && Out." << first_output_name << ".a < alphaRef) discard;\n";
break;
}
}
OS << " return Out;" << std::endl;
OS << "}" << std::endl;
}
@@ -20,5 +20,5 @@ protected:
virtual void insertMainStart(std::stringstream &OS) override;
virtual void insertMainEnd(std::stringstream &OS) override;
public:
D3D12FragmentDecompiler(u32 addr, u32& size, u32 ctrl, const std::vector<texture_dimension> &texture_dimensions);
D3D12FragmentDecompiler(const RSXFragmentProgram &prog, u32& size);
};
+169 -140
View File
@@ -58,17 +58,15 @@ void wait_for_command_queue(ID3D12Device *device, ID3D12CommandQueue *command_qu
}
}
void D3D12GSRender::Shader::Release()
void D3D12GSRender::shader::release()
{
m_PSO->Release();
m_rootSignature->Release();
m_vertexBuffer->Release();
m_textureDescriptorHeap->Release();
m_samplerDescriptorHeap->Release();
pso->Release();
root_signature->Release();
vertex_buffer->Release();
texture_descriptor_heap->Release();
sampler_descriptor_heap->Release();
}
extern std::function<bool(u32 addr)> gfxHandler;
bool D3D12GSRender::invalidate_address(u32 addr)
{
bool result = false;
@@ -87,19 +85,8 @@ D3D12DLLManagement::~D3D12DLLManagement()
}
D3D12GSRender::D3D12GSRender()
: GSRender(frame_type::DX12), m_d3d12_lib(), m_current_pso(nullptr)
: GSRender(frame_type::DX12), m_d3d12_lib(), m_current_pso({})
{
m_previous_address_a = 0;
m_previous_address_b = 0;
m_previous_address_c = 0;
m_previous_address_d = 0;
m_previous_address_z = 0;
gfxHandler = [this](u32 addr) {
bool result = invalidate_address(addr);
if (result)
LOG_WARNING(RSX, "Reporting Cell writing to 0x%x", addr);
return result;
};
if (rpcs3::config.rsx.d3d12.debug_output.value())
{
Microsoft::WRL::ComPtr<ID3D12Debug> debugInterface;
@@ -118,10 +105,10 @@ D3D12GSRender::D3D12GSRender()
D3D12_COMMAND_QUEUE_DESC graphic_queue_desc = { D3D12_COMMAND_LIST_TYPE_DIRECT };
CHECK_HRESULT(m_device->CreateCommandQueue(&graphic_queue_desc, IID_PPV_ARGS(m_command_queue.GetAddressOf())));
g_descriptor_stride_srv_cbv_uav = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
g_descriptor_stride_dsv = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
g_descriptor_stride_rtv = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
g_descriptor_stride_samplers = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
m_descriptor_stride_srv_cbv_uav = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
m_descriptor_stride_dsv = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_DSV);
m_descriptor_stride_rtv = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
m_descriptor_stride_samplers = m_device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
// Create swap chain and put them in a descriptor heap as rendertarget
DXGI_SWAP_CHAIN_DESC swap_chain = {};
@@ -148,33 +135,43 @@ D3D12GSRender::D3D12GSRender()
m_device->CreateRenderTargetView(m_backbuffer[1].Get(), &renter_target_view_desc, m_backbuffer_descriptor_heap[1]->GetCPUDescriptorHandleForHeapStart());
// Common root signatures
for (unsigned texture_count = 0; texture_count < 17; texture_count++)
for (int vertex_buffer_count = 0; vertex_buffer_count < 17; vertex_buffer_count++) // Some app (naruto ultimate ninja storm 2) uses a shader without inputs...
{
CD3DX12_DESCRIPTOR_RANGE descriptorRange[] =
for (unsigned texture_count = 0; texture_count < 17; texture_count++)
{
// Scale Offset data
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0),
// Constants
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 2, 1),
// Textures
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, texture_count, 0),
// Samplers
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, texture_count, 0),
};
CD3DX12_ROOT_PARAMETER RP[2];
RP[0].InitAsDescriptorTable((texture_count > 0) ? 3 : 2, &descriptorRange[0]);
RP[1].InitAsDescriptorTable(1, &descriptorRange[3]);
CD3DX12_DESCRIPTOR_RANGE descriptorRange[] =
{
// Vertex buffer
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, vertex_buffer_count, 0),
// Scale Offset data
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 1, 0),
// Constants
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 2, 1),
// Textures
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, texture_count, 16),
// Samplers
CD3DX12_DESCRIPTOR_RANGE(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, texture_count, 0),
};
CD3DX12_ROOT_PARAMETER RP[2];
UINT cbv_srv_uav_descriptor_size = 4;
if (texture_count == 0)
cbv_srv_uav_descriptor_size -= 1;
if (vertex_buffer_count == 0)
cbv_srv_uav_descriptor_size -= 1;
RP[0].InitAsDescriptorTable(cbv_srv_uav_descriptor_size, (vertex_buffer_count > 0) ? &descriptorRange[0] : &descriptorRange[1]);
RP[1].InitAsDescriptorTable(1, &descriptorRange[4]);
Microsoft::WRL::ComPtr<ID3DBlob> rootSignatureBlob;
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
CHECK_HRESULT(wrapD3D12SerializeRootSignature(
&CD3DX12_ROOT_SIGNATURE_DESC((texture_count > 0) ? 2 : 1, RP, 0, 0, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),
D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob));
Microsoft::WRL::ComPtr<ID3DBlob> rootSignatureBlob;
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
CHECK_HRESULT(wrapD3D12SerializeRootSignature(
&CD3DX12_ROOT_SIGNATURE_DESC((texture_count > 0) ? 2 : 1, RP, 0, 0),
D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob));
m_device->CreateRootSignature(0,
rootSignatureBlob->GetBufferPointer(),
rootSignatureBlob->GetBufferSize(),
IID_PPV_ARGS(m_root_signatures[texture_count].GetAddressOf()));
m_device->CreateRootSignature(0,
rootSignatureBlob->GetBufferPointer(),
rootSignatureBlob->GetBufferSize(),
IID_PPV_ARGS(m_root_signatures[texture_count][vertex_buffer_count].GetAddressOf()));
}
}
m_per_frame_storage[0].init(m_device.Get());
@@ -182,8 +179,8 @@ D3D12GSRender::D3D12GSRender()
m_per_frame_storage[1].init(m_device.Get());
m_per_frame_storage[1].reset();
initConvertShader();
m_output_scaling_pass.Init(m_device.Get(), m_command_queue.Get());
init_convert_shader();
m_output_scaling_pass.init(m_device.Get(), m_command_queue.Get());
CHECK_HRESULT(
m_device->CreateCommittedResource(
@@ -195,14 +192,20 @@ D3D12GSRender::D3D12GSRender()
IID_PPV_ARGS(&m_dummy_texture))
);
m_readback_resources.init(m_device.Get(), 1024 * 1024 * 128, D3D12_HEAP_TYPE_READBACK, D3D12_RESOURCE_STATE_COPY_DEST);
m_uav_heap.init(m_device.Get(), 1024 * 1024 * 128, D3D12_HEAP_TYPE_DEFAULT, D3D12_HEAP_FLAG_ALLOW_ONLY_NON_RT_DS_TEXTURES);
m_rtts.init(m_device.Get());
m_readback_resources.init(m_device.Get(), 1024 * 1024 * 128, D3D12_HEAP_TYPE_READBACK, D3D12_RESOURCE_STATE_COPY_DEST);
m_buffer_data.init(m_device.Get(), 1024 * 1024 * 896, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ);
m_constants_data.init(m_device.Get(), 1024 * 1024 * 64, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ);
m_vertex_index_data.init(m_device.Get(), 1024 * 1024 * 384, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ);
m_texture_upload_data.init(m_device.Get(), 1024 * 1024 * 512, D3D12_HEAP_TYPE_UPLOAD, D3D12_RESOURCE_STATE_GENERIC_READ);
CHECK_HRESULT(
m_device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(1024 * 1024 * 16),
D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER,
nullptr,
IID_PPV_ARGS(m_vertex_buffer_data.GetAddressOf())
)
);
if (rpcs3::config.rsx.d3d12.overlay.value())
init_d2d_structures();
@@ -214,18 +217,12 @@ D3D12GSRender::~D3D12GSRender()
m_texture_cache.unprotect_all();
gfxHandler = [this](u32) { return false; };
m_constants_data.release();
m_vertex_index_data.release();
m_texture_upload_data.release();
m_uav_heap.m_heap->Release();
m_readback_resources.m_heap->Release();
m_dummy_texture->Release();
m_convertPSO->Release();
m_convertRootSignature->Release();
m_convert_pso->Release();
m_convert_root_signature->Release();
m_per_frame_storage[0].release();
m_per_frame_storage[1].release();
m_output_scaling_pass.Release();
m_output_scaling_pass.release();
release_d2d_structures();
}
@@ -261,68 +258,93 @@ void D3D12GSRender::end()
prepare_render_targets(get_current_resource_storage().command_list.Get());
std::chrono::time_point<std::chrono::system_clock> rtt_duration_end = std::chrono::system_clock::now();
m_timers.m_prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count();
m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count();
std::chrono::time_point<std::chrono::system_clock> vertex_index_duration_start = std::chrono::system_clock::now();
size_t currentDescriptorIndex = get_current_resource_storage().descriptors_heap_index;
size_t vertex_count;
bool indexed_draw;
std::tie(indexed_draw, vertex_count) = upload_and_set_vertex_index_data(get_current_resource_storage().command_list.Get());
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> vertex_buffer_views;
std::tie(indexed_draw, vertex_count, vertex_buffer_views) = upload_and_set_vertex_index_data(get_current_resource_storage().command_list.Get());
size_t vertex_buffer_count = vertex_buffer_views.size();
std::chrono::time_point<std::chrono::system_clock> vertex_index_duration_end = std::chrono::system_clock::now();
m_timers.m_vertex_index_duration += std::chrono::duration_cast<std::chrono::microseconds>(vertex_index_duration_end - vertex_index_duration_start).count();
m_timers.vertex_index_duration += std::chrono::duration_cast<std::chrono::microseconds>(vertex_index_duration_end - vertex_index_duration_start).count();
std::chrono::time_point<std::chrono::system_clock> program_load_start = std::chrono::system_clock::now();
load_program();
std::chrono::time_point<std::chrono::system_clock> program_load_end = std::chrono::system_clock::now();
m_timers.m_program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count();
m_timers.program_load_duration += std::chrono::duration_cast<std::chrono::microseconds>(program_load_end - program_load_start).count();
get_current_resource_storage().command_list->SetGraphicsRootSignature(m_root_signatures[std::get<2>(*m_current_pso)].Get());
get_current_resource_storage().command_list->SetGraphicsRootSignature(m_root_signatures[std::get<2>(m_current_pso)][vertex_buffer_count].Get());
get_current_resource_storage().command_list->OMSetStencilRef(rsx::method_registers[NV4097_SET_STENCIL_FUNC_REF]);
std::chrono::time_point<std::chrono::system_clock> constants_duration_start = std::chrono::system_clock::now();
size_t currentDescriptorIndex = get_current_resource_storage().descriptors_heap_index;
INT offset = 0;
for (const auto view : vertex_buffer_views)
{
m_device->CreateShaderResourceView(m_vertex_buffer_data.Get(), &view,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)currentDescriptorIndex + offset++, m_descriptor_stride_srv_cbv_uav));
}
// Constants
upload_and_bind_scale_offset_matrix(currentDescriptorIndex);
upload_and_bind_vertex_shader_constants(currentDescriptorIndex + 1);
upload_and_bind_fragment_shader_constants(currentDescriptorIndex + 2);
upload_and_bind_scale_offset_matrix(currentDescriptorIndex + vertex_buffer_count);
upload_and_bind_vertex_shader_constants(currentDescriptorIndex + 1 + vertex_buffer_count);
upload_and_bind_fragment_shader_constants(currentDescriptorIndex + 2 + vertex_buffer_count);
std::chrono::time_point<std::chrono::system_clock> constants_duration_end = std::chrono::system_clock::now();
m_timers.m_constants_duration += std::chrono::duration_cast<std::chrono::microseconds>(constants_duration_end - constants_duration_start).count();
m_timers.constants_duration += std::chrono::duration_cast<std::chrono::microseconds>(constants_duration_end - constants_duration_start).count();
get_current_resource_storage().command_list->SetPipelineState(std::get<0>(*m_current_pso));
get_current_resource_storage().command_list->SetPipelineState(std::get<0>(m_current_pso).Get());
std::chrono::time_point<std::chrono::system_clock> texture_duration_start = std::chrono::system_clock::now();
if (std::get<2>(*m_current_pso) > 0)
size_t texture_count = std::get<2>(m_current_pso);
if (texture_count > 0)
{
upload_and_bind_textures(get_current_resource_storage().command_list.Get(), currentDescriptorIndex + 3, std::get<2>(*m_current_pso) > 0);
upload_and_bind_textures(get_current_resource_storage().command_list.Get(), texture_count);
for (unsigned i = 0; i < texture_count; i++)
{
ID3D12Resource *tex_resource;
D3D12_SHADER_RESOURCE_VIEW_DESC srv;
std::tie(tex_resource, srv) = m_current_shader_resources[i];
m_device->CreateShaderResourceView(tex_resource, &srv,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)currentDescriptorIndex + 3 + (INT)vertex_buffer_count + (INT)i, m_descriptor_stride_srv_cbv_uav)
);
m_device->CreateSampler(&m_current_samplers[i],
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart())
.Offset((UINT)get_current_resource_storage().current_sampler_index + (UINT)i, m_descriptor_stride_samplers));
}
get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0,
CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
.Offset((INT)currentDescriptorIndex, g_descriptor_stride_srv_cbv_uav)
.Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav)
);
get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(1,
CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetGPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().current_sampler_index, g_descriptor_stride_samplers)
.Offset((INT)get_current_resource_storage().current_sampler_index, m_descriptor_stride_samplers)
);
get_current_resource_storage().current_sampler_index += std::get<2>(*m_current_pso);
get_current_resource_storage().descriptors_heap_index += std::get<2>(*m_current_pso) + 3;
get_current_resource_storage().current_sampler_index += std::get<2>(m_current_pso);
get_current_resource_storage().descriptors_heap_index += std::get<2>(m_current_pso) + 3 + vertex_buffer_count;
}
else
{
get_current_resource_storage().command_list->SetDescriptorHeaps(1, get_current_resource_storage().descriptors_heap.GetAddressOf());
get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0,
CD3DX12_GPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetGPUDescriptorHandleForHeapStart())
.Offset((INT)currentDescriptorIndex, g_descriptor_stride_srv_cbv_uav)
.Offset((INT)currentDescriptorIndex, m_descriptor_stride_srv_cbv_uav)
);
get_current_resource_storage().descriptors_heap_index += 3;
get_current_resource_storage().descriptors_heap_index += 3 + vertex_buffer_count;
}
std::chrono::time_point<std::chrono::system_clock> texture_duration_end = std::chrono::system_clock::now();
m_timers.m_texture_duration += std::chrono::duration_cast<std::chrono::microseconds>(texture_duration_end - texture_duration_start).count();
m_timers.texture_duration += std::chrono::duration_cast<std::chrono::microseconds>(texture_duration_end - texture_duration_start).count();
set_rtt_and_ds(get_current_resource_storage().command_list.Get());
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
@@ -348,10 +370,9 @@ void D3D12GSRender::end()
else
get_current_resource_storage().command_list->DrawInstanced((UINT)vertex_count, 1, 0, 0);
vertex_index_array.clear();
std::chrono::time_point<std::chrono::system_clock> end_duration = std::chrono::system_clock::now();
m_timers.m_draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count();
m_timers.m_draw_calls_count++;
m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count();
m_timers.draw_calls_count++;
if (rpcs3::config.rsx.d3d12.debug_output.value())
{
@@ -359,26 +380,25 @@ void D3D12GSRender::end()
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
get_current_resource_storage().set_new_command_list();
}
m_first_count_pairs.clear();
thread::end();
}
namespace
{
bool is_flip_surface_in_global_memory(u32 color_target)
bool is_flip_surface_in_global_memory(rsx::surface_target color_target)
{
switch (color_target)
{
case CELL_GCM_SURFACE_TARGET_0:
case CELL_GCM_SURFACE_TARGET_1:
case CELL_GCM_SURFACE_TARGET_MRT1:
case CELL_GCM_SURFACE_TARGET_MRT2:
case CELL_GCM_SURFACE_TARGET_MRT3:
case rsx::surface_target::surface_a:
case rsx::surface_target::surface_b:
case rsx::surface_target::surfaces_a_b:
case rsx::surface_target::surfaces_a_b_c:
case rsx::surface_target::surfaces_a_b_c_d:
return true;
case CELL_GCM_SURFACE_TARGET_NONE:
case rsx::surface_target::none:
return false;
}
throw EXCEPTION("Wrong color_target (%u)", color_target);
throw EXCEPTION("Wrong color_target");
}
}
@@ -387,7 +407,7 @@ void D3D12GSRender::flip(int buffer)
ID3D12Resource *resource_to_flip;
float viewport_w, viewport_h;
if (!is_flip_surface_in_global_memory(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
if (!is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
{
resource_storage &storage = get_current_resource_storage();
assert(storage.ram_framebuffer == nullptr);
@@ -405,15 +425,12 @@ void D3D12GSRender::flip(int buffer)
row_pitch = align(w * 4, 256);
size_t texture_size = row_pitch * h; // * 4 for mipmap levels
assert(m_texture_upload_data.can_alloc(texture_size));
size_t heap_offset = m_texture_upload_data.alloc(texture_size);
size_t heap_offset = m_buffer_data.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(texture_size);
void *buffer;
CHECK_HRESULT(m_texture_upload_data.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + texture_size), &buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
void *mapped_buffer = m_buffer_data.map<void>(heap_offset);
for (unsigned row = 0; row < h; row++)
memcpy((char*)mapped_buffer + row * row_pitch, (char*)src_buffer + row * w * 4, w * 4);
m_texture_upload_data.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + texture_size));
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + texture_size));
offset = heap_offset;
}
@@ -428,7 +445,7 @@ void D3D12GSRender::flip(int buffer)
)
);
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(storage.ram_framebuffer.Get(), 0), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(m_texture_upload_data.m_heap, { offset, { DXGI_FORMAT_R8G8B8A8_UNORM, (UINT)w, (UINT)h, 1, (UINT)row_pitch } }), nullptr);
&CD3DX12_TEXTURE_COPY_LOCATION(m_buffer_data.get_heap(), { offset, { DXGI_FORMAT_R8G8B8A8_UNORM, (UINT)w, (UINT)h, 1, (UINT)row_pitch } }), nullptr);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(storage.ram_framebuffer.Get(), D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));
resource_to_flip = storage.ram_framebuffer.Get();
@@ -436,15 +453,15 @@ void D3D12GSRender::flip(int buffer)
}
else
{
if (m_rtts.bound_render_targets[0] != nullptr)
if (std::get<1>(m_rtts.m_bound_render_targets[0]) != nullptr)
{
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[0], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
resource_to_flip = m_rtts.bound_render_targets[0];
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[0]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[0]);
}
else if (m_rtts.bound_render_targets[1] != nullptr)
else if (std::get<1>(m_rtts.m_bound_render_targets[1]) != nullptr)
{
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[1], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
resource_to_flip = m_rtts.bound_render_targets[1];
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_render_targets[1]), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
resource_to_flip = std::get<1>(m_rtts.m_bound_render_targets[1]);
}
else
resource_to_flip = nullptr;
@@ -471,15 +488,15 @@ void D3D12GSRender::flip(int buffer)
(LONG)m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()]->GetDesc().Height,
};
get_current_resource_storage().command_list->RSSetScissorRects(1, &box);
get_current_resource_storage().command_list->SetGraphicsRootSignature(m_output_scaling_pass.m_rootSignature);
get_current_resource_storage().command_list->SetPipelineState(m_output_scaling_pass.m_PSO);
get_current_resource_storage().command_list->SetGraphicsRootSignature(m_output_scaling_pass.root_signature);
get_current_resource_storage().command_list->SetPipelineState(m_output_scaling_pass.pso);
D3D12_SHADER_RESOURCE_VIEW_DESC shader_resource_view_desc = {};
// FIXME: Not always true
shader_resource_view_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
shader_resource_view_desc.Texture2D.MipLevels = 1;
if (is_flip_surface_in_global_memory(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
else
shader_resource_view_desc.Shader4ComponentMapping = D3D12_ENCODE_SHADER_4_COMPONENT_MAPPING(
@@ -489,7 +506,7 @@ void D3D12GSRender::flip(int buffer)
D3D12_SHADER_COMPONENT_MAPPING_FROM_MEMORY_COMPONENT_0
);
m_device->CreateShaderResourceView(resource_to_flip, &shader_resource_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.m_textureDescriptorHeap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), g_descriptor_stride_srv_cbv_uav));
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.texture_descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_srv_cbv_uav));
D3D12_SAMPLER_DESC sampler_desc = {};
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_LINEAR_MIP_POINT;
@@ -497,24 +514,24 @@ void D3D12GSRender::flip(int buffer)
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
m_device->CreateSampler(&sampler_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.m_samplerDescriptorHeap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), g_descriptor_stride_samplers));
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.sampler_descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_samplers));
ID3D12DescriptorHeap *descriptors_heaps[] =
{
m_output_scaling_pass.m_textureDescriptorHeap,
m_output_scaling_pass.m_samplerDescriptorHeap
m_output_scaling_pass.texture_descriptor_heap,
m_output_scaling_pass.sampler_descriptor_heap
};
get_current_resource_storage().command_list->SetDescriptorHeaps(2, descriptors_heaps);
get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(0,
CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.m_textureDescriptorHeap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), g_descriptor_stride_srv_cbv_uav));
CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.texture_descriptor_heap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_srv_cbv_uav));
get_current_resource_storage().command_list->SetGraphicsRootDescriptorTable(1,
CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.m_samplerDescriptorHeap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), g_descriptor_stride_samplers));
CD3DX12_GPU_DESCRIPTOR_HANDLE(m_output_scaling_pass.sampler_descriptor_heap->GetGPUDescriptorHandleForHeapStart()).Offset(m_swap_chain->GetCurrentBackBufferIndex(), m_descriptor_stride_samplers));
get_current_resource_storage().command_list->OMSetRenderTargets(1,
&CD3DX12_CPU_DESCRIPTOR_HANDLE(m_backbuffer_descriptor_heap[m_swap_chain->GetCurrentBackBufferIndex()]->GetCPUDescriptorHandleForHeapStart()),
true, nullptr);
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view = {};
vertex_buffer_view.BufferLocation = m_output_scaling_pass.m_vertexBuffer->GetGPUVirtualAddress();
vertex_buffer_view.BufferLocation = m_output_scaling_pass.vertex_buffer->GetGPUVirtualAddress();
vertex_buffer_view.StrideInBytes = 4 * sizeof(float);
vertex_buffer_view.SizeInBytes = 16 * sizeof(float);
get_current_resource_storage().command_list->IASetVertexBuffers(0, 1, &vertex_buffer_view);
@@ -524,7 +541,7 @@ void D3D12GSRender::flip(int buffer)
if (!rpcs3::config.rsx.d3d12.overlay.value())
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_backbuffer[m_swap_chain->GetCurrentBackBufferIndex()].Get(), D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
if (is_flip_surface_in_global_memory(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]) && resource_to_flip != nullptr)
if (is_flip_surface_in_global_memory(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])) && resource_to_flip != nullptr)
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(resource_to_flip, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
@@ -546,15 +563,14 @@ void D3D12GSRender::flip(int buffer)
storage.fence_value++;
storage.in_use = true;
storage.dirty_textures.merge(m_rtts.invalidated_resources);
m_rtts.invalidated_resources.clear();
// Get the put pos - 1. This way after cleaning we can set the get ptr to
// this value, allowing heap to proceed even if we cleant before allocating
// a new value (that's the reason of the -1)
storage.constants_heap_get_pos = m_constants_data.get_current_put_pos_minus_one();
storage.vertex_index_heap_get_pos = m_vertex_index_data.get_current_put_pos_minus_one();
storage.texture_upload_heap_get_pos = m_texture_upload_data.get_current_put_pos_minus_one();
storage.buffer_heap_get_pos = m_buffer_data.get_current_put_pos_minus_one();
storage.readback_heap_get_pos = m_readback_resources.get_current_put_pos_minus_one();
storage.uav_heap_get_pos = m_uav_heap.get_current_put_pos_minus_one();
// Now get ready for next frame
resource_storage &new_storage = get_current_resource_storage();
@@ -562,31 +578,44 @@ void D3D12GSRender::flip(int buffer)
new_storage.wait_and_clean();
if (new_storage.in_use)
{
m_constants_data.m_get_pos = new_storage.constants_heap_get_pos;
m_vertex_index_data.m_get_pos = new_storage.vertex_index_heap_get_pos;
m_texture_upload_data.m_get_pos = new_storage.texture_upload_heap_get_pos;
m_buffer_data.m_get_pos = new_storage.buffer_heap_get_pos;
m_readback_resources.m_get_pos = new_storage.readback_heap_get_pos;
m_uav_heap.m_get_pos = new_storage.uav_heap_get_pos;
}
m_frame->flip(nullptr);
std::chrono::time_point<std::chrono::system_clock> flip_end = std::chrono::system_clock::now();
m_timers.m_flip_duration += std::chrono::duration_cast<std::chrono::microseconds>(flip_end - flip_start).count();
m_timers.flip_duration += std::chrono::duration_cast<std::chrono::microseconds>(flip_end - flip_start).count();
}
bool D3D12GSRender::on_access_violation(u32 address, bool is_writing)
{
if (!is_writing)
{
return false;
}
if (invalidate_address(address))
{
LOG_WARNING(RSX, "Reporting Cell writing to 0x%x", address);
return true;
}
return false;
}
void D3D12GSRender::reset_timer()
{
m_timers.m_draw_calls_count = 0;
m_timers.m_draw_calls_duration = 0;
m_timers.m_prepare_rtt_duration = 0;
m_timers.m_vertex_index_duration = 0;
m_timers.m_buffer_upload_size = 0;
m_timers.m_program_load_duration = 0;
m_timers.m_constants_duration = 0;
m_timers.m_texture_duration = 0;
m_timers.m_flip_duration = 0;
m_timers.draw_calls_count = 0;
m_timers.draw_calls_duration = 0;
m_timers.prepare_rtt_duration = 0;
m_timers.vertex_index_duration = 0;
m_timers.buffer_upload_size = 0;
m_timers.program_load_duration = 0;
m_timers.constants_duration = 0;
m_timers.texture_duration = 0;
m_timers.flip_duration = 0;
}
resource_storage& D3D12GSRender::get_current_resource_storage()
+46 -58
View File
@@ -56,7 +56,7 @@ private:
ComPtr<ID3D12Resource> m_backbuffer[2];
ComPtr<ID3D12DescriptorHeap> m_backbuffer_descriptor_heap[2];
// m_rootSignatures[N] is RS with N texture/sample
ComPtr<ID3D12RootSignature> m_root_signatures[17];
ComPtr<ID3D12RootSignature> m_root_signatures[17][17]; // indexed by [texture count][vertex count]
// TODO: Use a tree structure to parse more efficiently
data_cache m_texture_cache;
@@ -64,89 +64,81 @@ private:
rsx::surface_info m_surface;
RSXVertexProgram vertex_program;
RSXFragmentProgram fragment_program;
RSXVertexProgram m_vertex_program;
RSXFragmentProgram m_fragment_program;
PipelineStateObjectCache m_pso_cache;
std::tuple<ID3D12PipelineState *, std::vector<size_t>, size_t> *m_current_pso;
std::tuple<ComPtr<ID3D12PipelineState>, size_t, size_t> m_current_pso;
struct
{
size_t m_draw_calls_duration;
size_t m_draw_calls_count;
size_t m_prepare_rtt_duration;
size_t m_vertex_index_duration;
size_t m_buffer_upload_size;
size_t m_program_load_duration;
size_t m_constants_duration;
size_t m_texture_duration;
size_t m_flip_duration;
size_t draw_calls_duration;
size_t draw_calls_count;
size_t prepare_rtt_duration;
size_t vertex_index_duration;
size_t buffer_upload_size;
size_t program_load_duration;
size_t constants_duration;
size_t texture_duration;
size_t flip_duration;
} m_timers;
void reset_timer();
struct Shader
struct shader
{
ID3D12PipelineState *m_PSO;
ID3D12RootSignature *m_rootSignature;
ID3D12Resource *m_vertexBuffer;
ID3D12DescriptorHeap *m_textureDescriptorHeap;
ID3D12DescriptorHeap *m_samplerDescriptorHeap;
void Init(ID3D12Device *device, ID3D12CommandQueue *gfxcommandqueue);
void Release();
ID3D12PipelineState *pso;
ID3D12RootSignature *root_signature;
ID3D12Resource *vertex_buffer;
ID3D12DescriptorHeap *texture_descriptor_heap;
ID3D12DescriptorHeap *sampler_descriptor_heap;
void init(ID3D12Device *device, ID3D12CommandQueue *gfx_command_queue);
void release();
};
/**
* Stores data related to the scaling pass that turns internal
* render targets into presented buffers.
*/
Shader m_output_scaling_pass;
shader m_output_scaling_pass;
/**
* Data used when depth buffer is converted to uchar textures.
*/
ID3D12PipelineState *m_convertPSO;
ID3D12RootSignature *m_convertRootSignature;
void initConvertShader();
ID3D12PipelineState *m_convert_pso;
ID3D12RootSignature *m_convert_root_signature;
void init_convert_shader();
resource_storage m_per_frame_storage[2];
resource_storage &get_current_resource_storage();
resource_storage &get_non_current_resource_storage();
// Constants storage
data_heap<ID3D12Resource, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT> m_constants_data;
// Vertex storage
data_heap<ID3D12Resource, D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT> m_vertex_index_data;
// Texture storage
data_heap<ID3D12Resource, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT> m_texture_upload_data;
data_heap<ID3D12Heap, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT> m_uav_heap;
data_heap<ID3D12Resource, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT> m_readback_resources;
// Textures, constants, index and vertex buffers storage
data_heap m_buffer_data;
data_heap m_readback_resources;
ComPtr<ID3D12Resource> m_vertex_buffer_data;
render_targets m_rtts;
rsx::render_targets m_rtts;
std::vector<D3D12_INPUT_ELEMENT_DESC> m_IASet;
INT g_descriptor_stride_srv_cbv_uav;
INT g_descriptor_stride_dsv;
INT g_descriptor_stride_rtv;
INT g_descriptor_stride_samplers;
INT m_descriptor_stride_srv_cbv_uav;
INT m_descriptor_stride_dsv;
INT m_descriptor_stride_rtv;
INT m_descriptor_stride_samplers;
// Used to fill unused texture slot
ID3D12Resource *m_dummy_texture;
// Store previous fbo addresses to detect RTT config changes.
u32 m_previous_address_a;
u32 m_previous_address_b;
u32 m_previous_address_c;
u32 m_previous_address_d;
u32 m_previous_address_z;
// Currently used shader resources / samplers descriptor
std::array<std::tuple<ID3D12Resource*, D3D12_SHADER_RESOURCE_VIEW_DESC>, 16> m_current_shader_resources = {};
std::array<D3D12_SAMPLER_DESC, 16> m_current_samplers = {};
public:
D3D12GSRender();
virtual ~D3D12GSRender();
private:
void init_d2d_structures();
void release_d2d_structures();
bool load_program();
void load_program();
void set_rtt_and_ds(ID3D12GraphicsCommandList *command_list);
@@ -155,17 +147,15 @@ private:
* Non native primitive type are emulated by index buffers expansion.
* Returns whether the draw call is indexed or not and the vertex count to draw.
*/
std::tuple<bool, size_t> upload_and_set_vertex_index_data(ID3D12GraphicsCommandList *command_list);
std::tuple<bool, size_t, std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> > upload_and_set_vertex_index_data(ID3D12GraphicsCommandList *command_list);
std::vector<std::pair<u32, u32> > m_first_count_pairs;
/**
* Upload all enabled vertex attributes for vertex in ranges described by vertex_ranges.
* A range in vertex_range is a pair whose first element is the index of the beginning of the
* range, and whose second element is the number of vertex in this range.
*/
std::vector<D3D12_VERTEX_BUFFER_VIEW> upload_vertex_attributes(const std::vector<std::pair<u32, u32> > &vertex_ranges);
std::tuple<D3D12_VERTEX_BUFFER_VIEW, size_t> upload_inlined_vertex_array();
std::vector<D3D12_SHADER_RESOURCE_VIEW_DESC> upload_vertex_attributes(const std::vector<std::pair<u32, u32> > &vertex_ranges,
gsl::not_null<ID3D12GraphicsCommandList*> command_list);
std::tuple<D3D12_INDEX_BUFFER_VIEW, size_t> generate_index_buffer_for_emulated_primitives_array(const std::vector<std::pair<u32, u32> > &vertex_ranges);
@@ -178,7 +168,7 @@ private:
* Create necessary resource view/sampler descriptors in the per frame storage struct.
* If the count of enabled texture is below texture_count, fills with dummy texture and sampler.
*/
void upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t descriptor_index, size_t texture_count);
void upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t texture_count);
/**
* Creates render target if necessary.
@@ -206,11 +196,9 @@ protected:
virtual void end() override;
virtual void flip(int buffer) override;
virtual void load_vertex_data(u32 first, u32 count) override;
virtual void load_vertex_index_data(u32 first, u32 count) override;
virtual bool on_access_violation(u32 address, bool is_writing) override;
virtual void copy_render_targets_to_memory(void *buffer, u8 rtt) override;
virtual void copy_depth_buffer_to_memory(void *buffer) override;
virtual void copy_stencil_buffer_to_memory(void *buffer) 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;
virtual std::pair<std::string, std::string> get_programs() const override;
};
+6 -5
View File
@@ -4,18 +4,19 @@
#include "D3D12MemoryHelpers.h"
void data_cache::store_and_protect_data(u64 key, u32 start, size_t size, u8 format, size_t w, size_t h, size_t m, ComPtr<ID3D12Resource> data)
void data_cache::store_and_protect_data(u64 key, u32 start, size_t size, u8 format, size_t w, size_t h, size_t d, size_t m, ComPtr<ID3D12Resource> data)
{
std::lock_guard<std::mutex> lock(m_mut);
m_address_to_data[key] = std::make_pair(texture_entry(format, w, h, m), data);
m_address_to_data[key] = std::make_pair(texture_entry(format, w, h, d, m), data);
protect_data(key, start, size);
}
void data_cache::protect_data(u64 key, u32 start, size_t size)
{
/// align start to 4096 byte
u32 protected_range_start = align(start, 4096);
u32 protected_range_size = (u32)align(size, 4096);
static const u32 memory_page_size = 4096;
u32 protected_range_start = start & ~(memory_page_size - 1);
u32 protected_range_size = (u32)align(size, memory_page_size);
m_protected_ranges.push_back(std::make_tuple(key, protected_range_start, protected_range_size));
vm::page_protect(protected_range_start, protected_range_size, 0, 0, vm::page_writable);
}
@@ -105,7 +106,7 @@ void resource_storage::init(ID3D12Device *device)
CHECK_HRESULT(m_device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, command_allocator.Get(), nullptr, IID_PPV_ARGS(command_list.GetAddressOf())));
CHECK_HRESULT(command_list->Close());
D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 10000, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE };
D3D12_DESCRIPTOR_HEAP_DESC descriptor_heap_desc = { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, 50000, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE };
CHECK_HRESULT(device->CreateDescriptorHeap(&descriptor_heap_desc, IID_PPV_ARGS(&descriptors_heap)));
D3D12_DESCRIPTOR_HEAP_DESC sampler_heap_desc = { D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER , 2048, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE };
+90 -79
View File
@@ -3,48 +3,6 @@
#include "d3dx12.h"
template<typename T>
struct init_heap
{
static T* init(ID3D12Device *device, size_t heapSize, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags);
};
template<>
struct init_heap<ID3D12Heap>
{
static ID3D12Heap* init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_HEAP_FLAGS flags)
{
ID3D12Heap *result;
D3D12_HEAP_DESC heap_desc = {};
heap_desc.SizeInBytes = heap_size;
heap_desc.Properties.Type = type;
heap_desc.Flags = flags;
CHECK_HRESULT(device->CreateHeap(&heap_desc, IID_PPV_ARGS(&result)));
return result;
}
};
template<>
struct init_heap<ID3D12Resource>
{
static ID3D12Resource* init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_RESOURCE_STATES state)
{
ID3D12Resource *result;
D3D12_HEAP_PROPERTIES heap_properties = {};
heap_properties.Type = type;
CHECK_HRESULT(device->CreateCommittedResource(&heap_properties,
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(heap_size),
state,
nullptr,
IID_PPV_ARGS(&result))
);
return result;
}
};
/**
* Wrapper around a ID3D12Resource or a ID3D12Heap.
* Acts as a ring buffer : hold a get and put pointers,
@@ -52,43 +10,30 @@ struct init_heap<ID3D12Resource>
* and get is used as beginning of in use data space.
* This wrapper checks that put pointer doesn't cross get one.
*/
template<typename T, size_t alignment>
struct data_heap
class data_heap
{
T *m_heap;
size_t m_size;
size_t m_put_pos; // Start of free space
size_t m_get_pos; // End of free space
template <typename... arg_type>
void init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, arg_type... args)
{
m_size = heap_size;
m_heap = init_heap<T>::init(device, heap_size, type, args...);
m_put_pos = 0;
m_get_pos = heap_size - 1;
}
/**
* Does alloc cross get position ?
*/
template<int Alignement>
bool can_alloc(size_t size) const
{
size_t alloc_size = align(size, alignment);
if (m_put_pos + alloc_size < m_size)
size_t alloc_size = align(size, Alignement);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
// range before get
if (m_put_pos + alloc_size < m_get_pos)
if (aligned_put_pos + alloc_size < m_get_pos)
return true;
// range after get
if (m_put_pos > m_get_pos)
if (aligned_put_pos > m_get_pos)
return true;
return false;
}
else
{
// ..]....[..get..
if (m_put_pos < m_get_pos)
if (aligned_put_pos < m_get_pos)
return false;
// ..get..]...[...
// Actually all resources extending beyond heap space starts at 0
@@ -98,15 +43,45 @@ struct data_heap
}
}
size_t m_size;
size_t m_put_pos; // Start of free space
ComPtr<ID3D12Resource> m_heap;
public:
data_heap() = default;
~data_heap() = default;
data_heap(const data_heap&) = delete;
data_heap(data_heap&&) = delete;
size_t m_get_pos; // End of free space
template <typename... arg_type>
void init(ID3D12Device *device, size_t heap_size, D3D12_HEAP_TYPE type, D3D12_RESOURCE_STATES state)
{
m_size = heap_size;
m_put_pos = 0;
m_get_pos = heap_size - 1;
D3D12_HEAP_PROPERTIES heap_properties = {};
heap_properties.Type = type;
CHECK_HRESULT(device->CreateCommittedResource(&heap_properties,
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(heap_size),
state,
nullptr,
IID_PPV_ARGS(m_heap.GetAddressOf()))
);
}
template<int Alignement>
size_t alloc(size_t size)
{
assert(can_alloc(size));
size_t alloc_size = align(size, alignment);
if (m_put_pos + alloc_size < m_size)
if (!can_alloc<Alignement>(size)) throw EXCEPTION("Working buffer not big enough");
size_t alloc_size = align(size, Alignement);
size_t aligned_put_pos = align(m_put_pos, Alignement);
if (aligned_put_pos + alloc_size < m_size)
{
size_t old_put_pos = m_put_pos;
m_put_pos += alloc_size;
return old_put_pos;
m_put_pos = aligned_put_pos + alloc_size;
return aligned_put_pos;
}
else
{
@@ -115,9 +90,37 @@ struct data_heap
}
}
void release()
template<typename T>
T* map(const D3D12_RANGE &range)
{
m_heap->Release();
void *buffer;
CHECK_HRESULT(m_heap->Map(0, &range, &buffer));
void *mapped_buffer = (char*)buffer + range.Begin;
return static_cast<T*>(mapped_buffer);
}
template<typename T>
T* map(size_t heap_offset)
{
void *buffer;
CHECK_HRESULT(m_heap->Map(0, nullptr, &buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
return static_cast<T*>(mapped_buffer);
}
void unmap(const D3D12_RANGE &range)
{
m_heap->Unmap(0, &range);
}
void unmap()
{
m_heap->Unmap(0, nullptr);
}
ID3D12Resource* get_heap()
{
return m_heap.Get();
}
/**
@@ -136,16 +139,17 @@ struct texture_entry
size_t m_width;
size_t m_height;
size_t m_mipmap;
size_t m_depth;
texture_entry() : m_format(0), m_width(0), m_height(0), m_is_dirty(true)
texture_entry() : m_format(0), m_width(0), m_height(0), m_depth(0), m_is_dirty(true)
{}
texture_entry(u8 f, size_t w, size_t h, size_t m) : m_format(f), m_width(w), m_height(h), m_is_dirty(false)
texture_entry(u8 f, size_t w, size_t h, size_t d, size_t m) : m_format(f), m_width(w), m_height(h), m_depth(d), m_is_dirty(false), m_mipmap(m)
{}
bool operator==(const texture_entry &other)
{
return (m_format == other.m_format && m_width == other.m_width && m_height == other.m_height);
return (m_format == other.m_format && m_width == other.m_width && m_height == other.m_height && m_mipmap == other.m_mipmap && m_depth == other.m_depth);
}
};
@@ -165,7 +169,12 @@ private:
std::unordered_map<u64, std::pair<texture_entry, ComPtr<ID3D12Resource>> > m_address_to_data; // Storage
std::list <std::tuple<u64, u32, u32> > m_protected_ranges; // address, start of protected range, size of protected range
public:
void store_and_protect_data(u64 key, u32 start, size_t size, u8 format, size_t w, size_t h, size_t m, ComPtr<ID3D12Resource> data);
data_cache() = default;
~data_cache() = default;
data_cache(const data_cache&) = delete;
data_cache(data_cache&&) = delete;
void store_and_protect_data(u64 key, u32 start, size_t size, u8 format, size_t w, size_t h, size_t d, size_t m, ComPtr<ID3D12Resource> data);
/**
* Make memory from start to start + size write protected.
@@ -196,6 +205,11 @@ public:
*/
struct resource_storage
{
resource_storage() = default;
~resource_storage() = default;
resource_storage(const resource_storage&) = delete;
resource_storage(resource_storage&&) = delete;
bool in_use; // False until command list has been populated at least once
ComPtr<ID3D12Fence> frame_finished_fence;
UINT64 fence_value;
@@ -230,11 +244,8 @@ struct resource_storage
* This means newer resources shouldn't allocate memory crossing this position
* until the frame rendering is over.
*/
size_t constants_heap_get_pos;
size_t vertex_index_heap_get_pos;
size_t texture_upload_heap_get_pos;
size_t buffer_heap_get_pos;
size_t readback_heap_get_pos;
size_t uav_heap_get_pos;
void reset();
void init(ID3D12Device *device);
+14 -14
View File
@@ -152,21 +152,21 @@ void D3D12GSRender::release_d2d_structures()
void D3D12GSRender::render_overlay()
{
D2D1_SIZE_F rtSize = g_d2d_render_targets[m_swap_chain->GetCurrentBackBufferIndex()]->GetSize();
std::wstring duration = L"Draw duration : " + std::to_wstring(m_timers.m_draw_calls_duration) + L" us";
float vtxIdxPercent = (float)m_timers.m_vertex_index_duration / (float)m_timers.m_draw_calls_duration;
std::wstring vertexIndexDuration = L"Vtx/Idx upload : " + std::to_wstring(m_timers.m_vertex_index_duration) + L" us (" + std::to_wstring(100.f * vtxIdxPercent) + L" %)";
std::wstring size = L"Upload size : " + std::to_wstring(m_timers.m_buffer_upload_size) + L" Bytes";
float texPercent = (float)m_timers.m_texture_duration / (float)m_timers.m_draw_calls_duration;
std::wstring texDuration = L"Textures : " + std::to_wstring(m_timers.m_texture_duration) + L" us (" + std::to_wstring(100.f * texPercent) + L" %)";
float programPercent = (float)m_timers.m_program_load_duration / (float)m_timers.m_draw_calls_duration;
std::wstring programDuration = L"Program : " + std::to_wstring(m_timers.m_program_load_duration) + L" us (" + std::to_wstring(100.f * programPercent) + L" %)";
float constantsPercent = (float)m_timers.m_constants_duration / (float)m_timers.m_draw_calls_duration;
std::wstring constantDuration = L"Constants : " + std::to_wstring(m_timers.m_constants_duration) + L" us (" + std::to_wstring(100.f * constantsPercent) + L" %)";
float rttPercent = (float)m_timers.m_prepare_rtt_duration / (float)m_timers.m_draw_calls_duration;
std::wstring rttDuration = L"RTT : " + std::to_wstring(m_timers.m_prepare_rtt_duration) + L" us (" + std::to_wstring(100.f * rttPercent) + L" %)";
std::wstring flipDuration = L"Flip : " + std::to_wstring(m_timers.m_flip_duration) + L" us";
std::wstring duration = L"Draw duration : " + std::to_wstring(m_timers.draw_calls_duration) + L" us";
float vtxIdxPercent = (float)m_timers.vertex_index_duration / (float)m_timers.draw_calls_duration;
std::wstring vertexIndexDuration = L"Vtx/Idx upload : " + std::to_wstring(m_timers.vertex_index_duration) + L" us (" + std::to_wstring(100.f * vtxIdxPercent) + L" %)";
std::wstring size = L"Upload size : " + std::to_wstring(m_timers.buffer_upload_size) + L" Bytes";
float texPercent = (float)m_timers.texture_duration / (float)m_timers.draw_calls_duration;
std::wstring texDuration = L"Textures : " + std::to_wstring(m_timers.texture_duration) + L" us (" + std::to_wstring(100.f * texPercent) + L" %)";
float programPercent = (float)m_timers.program_load_duration / (float)m_timers.draw_calls_duration;
std::wstring programDuration = L"Program : " + std::to_wstring(m_timers.program_load_duration) + L" us (" + std::to_wstring(100.f * programPercent) + L" %)";
float constantsPercent = (float)m_timers.constants_duration / (float)m_timers.draw_calls_duration;
std::wstring constantDuration = L"Constants : " + std::to_wstring(m_timers.constants_duration) + L" us (" + std::to_wstring(100.f * constantsPercent) + L" %)";
float rttPercent = (float)m_timers.prepare_rtt_duration / (float)m_timers.draw_calls_duration;
std::wstring rttDuration = L"RTT : " + std::to_wstring(m_timers.prepare_rtt_duration) + L" us (" + std::to_wstring(100.f * rttPercent) + L" %)";
std::wstring flipDuration = L"Flip : " + std::to_wstring(m_timers.flip_duration) + L" us";
std::wstring count = L"Draw count : " + std::to_wstring(m_timers.m_draw_calls_count);
std::wstring count = L"Draw count : " + std::to_wstring(m_timers.draw_calls_count);
draw_strings(rtSize, m_swap_chain->GetCurrentBackBufferIndex(),
{
duration,
+24 -44
View File
@@ -36,38 +36,10 @@ void Shader::Compile(const std::string &code, SHADER_TYPE st)
}
}
bool D3D12GSRender::load_program()
void D3D12GSRender::load_program()
{
u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
vertex_program.data.reserve((512 - transform_program_start) * 4);
for (int i = transform_program_start; i < 512; ++i)
{
vertex_program.data.resize((i - transform_program_start) * 4 + 4);
memcpy(vertex_program.data.data() + (i - transform_program_start) * 4, transform_program + i * 4, 4 * sizeof(u32));
D3 d3;
d3.HEX = transform_program[i * 4 + 3];
if (d3.end)
break;
}
u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
fragment_program.offset = shader_program & ~0x3;
fragment_program.addr = rsx::get_address(fragment_program.offset, (shader_program & 0x3) - 1);
fragment_program.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
fragment_program.texture_dimensions.clear();
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
{
if (!textures[i].enabled())
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d);
else if (textures[i].cubemap())
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_cubemap);
else
fragment_program.texture_dimensions.push_back(texture_dimension::texture_dimension_2d);
}
m_vertex_program = get_current_vertex_program();
m_fragment_program = get_current_fragment_program();
D3D12PipelineProperties prop = {};
prop.Topology = get_primitive_topology_type(draw_mode);
@@ -162,19 +134,19 @@ bool D3D12GSRender::load_program()
prop.DepthStencilFormat = get_depth_stencil_surface_format(m_surface.depth_format);
prop.RenderTargetsFormat = get_color_surface_format(m_surface.color_format);
switch (u32 color_target = rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])
switch (rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
{
case CELL_GCM_SURFACE_TARGET_0:
case CELL_GCM_SURFACE_TARGET_1:
case rsx::surface_target::surface_a:
case rsx::surface_target::surface_b:
prop.numMRT = 1;
break;
case CELL_GCM_SURFACE_TARGET_MRT1:
case rsx::surface_target::surfaces_a_b:
prop.numMRT = 2;
break;
case CELL_GCM_SURFACE_TARGET_MRT2:
case rsx::surface_target::surfaces_a_b_c:
prop.numMRT = 3;
break;
case CELL_GCM_SURFACE_TARGET_MRT3:
case rsx::surface_target::surfaces_a_b_c_d:
prop.numMRT = 4;
break;
default:
@@ -223,7 +195,7 @@ bool D3D12GSRender::load_program()
D3D12_CONSERVATIVE_RASTERIZATION_MODE_OFF,
};
prop.Rasterization = CD3D12_RASTERIZER_DESC;
if (rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE])
if (!!rsx::method_registers[NV4097_SET_CULL_FACE_ENABLE])
{
switch (rsx::method_registers[NV4097_SET_CULL_FACE])
{
@@ -251,17 +223,25 @@ bool D3D12GSRender::load_program()
for (unsigned i = 0; i < prop.numMRT; i++)
prop.Blend.RenderTarget[i].RenderTargetWriteMask = mask;
prop.IASet = m_IASet;
if (!!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE])
prop.CutValue = ((rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4) == CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32) ?
D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF : D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF;
{
rsx::index_array_type index_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
if (index_type == rsx::index_array_type::u32)
{
prop.CutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFFFFFF;
}
if (index_type == rsx::index_array_type::u16)
{
prop.CutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_0xFFFF;
}
}
m_current_pso = m_pso_cache.getGraphicPipelineState(&vertex_program, &fragment_program, prop, std::make_pair(m_device.Get(), m_root_signatures));
return m_current_pso != nullptr;
m_current_pso = m_pso_cache.getGraphicPipelineState(m_vertex_program, m_fragment_program, prop, m_device.Get(), m_root_signatures);
return;
}
std::pair<std::string, std::string> D3D12GSRender::get_programs() const
{
return std::make_pair(m_pso_cache.get_transform_program(vertex_program)->content, m_pso_cache.get_shader_program(fragment_program)->content);
return std::make_pair(m_pso_cache.get_transform_program(m_vertex_program).content, m_pso_cache.get_shader_program(m_fragment_program).content);
}
#endif
+29 -75
View File
@@ -10,7 +10,6 @@ struct D3D12PipelineProperties
D3D12_PRIMITIVE_TOPOLOGY_TYPE Topology;
DXGI_FORMAT DepthStencilFormat;
DXGI_FORMAT RenderTargetsFormat;
std::vector<D3D12_INPUT_ELEMENT_DESC> IASet;
D3D12_BLEND_DESC Blend;
unsigned numMRT : 3;
D3D12_DEPTH_STENCIL_DESC DepthStencil;
@@ -19,23 +18,6 @@ struct D3D12PipelineProperties
bool operator==(const D3D12PipelineProperties &in) const
{
if (IASet.size() != in.IASet.size())
return false;
for (unsigned i = 0; i < IASet.size(); i++)
{
const D3D12_INPUT_ELEMENT_DESC &a = IASet[i], &b = in.IASet[i];
if (a.AlignedByteOffset != b.AlignedByteOffset)
return false;
if (a.Format != b.Format)
return false;
if (a.InputSlot != b.InputSlot)
return false;
if (a.InstanceDataStepRate != b.InstanceDataStepRate)
return false;
if (a.SemanticIndex != b.SemanticIndex)
return false;
}
if (memcmp(&DepthStencil, &in.DepthStencil, sizeof(D3D12_DEPTH_STENCIL_DESC)))
return false;
if (memcmp(&Blend, &in.Blend, sizeof(D3D12_BLEND_DESC)))
@@ -85,14 +67,15 @@ public:
SHADER_TYPE_FRAGMENT
};
Shader() : bytecode(nullptr) {}
~Shader() {}
Shader() = default;
~Shader() = default;
Shader(const Shader &) = delete;
u32 id;
ComPtr<ID3DBlob> bytecode;
// For debugging
std::string content;
std::vector<size_t> vertex_shader_inputs;
size_t vertex_shader_input_count;
std::vector<size_t> FragmentConstantOffsetCache;
size_t m_textureCount;
@@ -117,36 +100,18 @@ bool has_attribute(size_t attribute, const std::vector<D3D12_INPUT_ELEMENT_DESC>
return false;
}
static
std::vector<D3D12_INPUT_ELEMENT_DESC> completes_IA_desc(const std::vector<D3D12_INPUT_ELEMENT_DESC> &desc, const std::vector<size_t> &inputs)
{
std::vector<D3D12_INPUT_ELEMENT_DESC> result(desc);
for (size_t attribute : inputs)
{
if (has_attribute(attribute, desc))
continue;
D3D12_INPUT_ELEMENT_DESC extra_ia_desc = {};
extra_ia_desc.SemanticIndex = (UINT)attribute;
extra_ia_desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT;
extra_ia_desc.SemanticName = "TEXCOORD";
extra_ia_desc.InputSlotClass = D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA;
result.push_back(extra_ia_desc);
}
return result;
}
struct D3D12Traits
{
typedef Shader VertexProgramData;
typedef Shader FragmentProgramData;
typedef std::tuple<ID3D12PipelineState *, std::vector<size_t>, size_t> PipelineData;
typedef D3D12PipelineProperties PipelineProperties;
typedef std::pair<ID3D12Device *, ComPtr<ID3D12RootSignature> *> ExtraData;
using vertex_program_type = Shader;
using fragment_program_type = Shader;
using pipeline_storage_type = std::tuple<ComPtr<ID3D12PipelineState>, size_t, size_t>;
using pipeline_properties = D3D12PipelineProperties;
static
void RecompileFragmentProgram(RSXFragmentProgram *RSXFP, FragmentProgramData& fragmentProgramData, size_t ID)
void recompile_fragment_program(const RSXFragmentProgram &RSXFP, fragment_program_type& fragmentProgramData, size_t ID)
{
D3D12FragmentDecompiler FS(RSXFP->addr, RSXFP->size, RSXFP->ctrl, RSXFP->texture_dimensions);
u32 size;
D3D12FragmentDecompiler FS(RSXFP, size);
const std::string &shader = FS.Decompile();
fragmentProgramData.Compile(shader, Shader::SHADER_TYPE::SHADER_TYPE_FRAGMENT);
fragmentProgramData.m_textureCount = 0;
@@ -154,7 +119,7 @@ struct D3D12Traits
{
for (const ParamItem PI : PT.items)
{
if (PT.type == "sampler2D" || PT.type == "samplerCube")
if (PT.type == "sampler1D" || PT.type == "sampler2D" || PT.type == "samplerCube" || PT.type == "sampler3D")
{
size_t texture_unit = atoi(PI.name.c_str() + 3);
fragmentProgramData.m_textureCount = std::max(texture_unit + 1, fragmentProgramData.m_textureCount);
@@ -165,40 +130,40 @@ struct D3D12Traits
}
}
fs::file(fs::get_config_dir() + "FragmentProgram" + std::to_string(ID) + ".hlsl", fom::rewrite) << shader;
fs::file(fs::get_config_dir() + "FragmentProgram" + std::to_string(ID) + ".hlsl", fom::rewrite).write(shader);
fragmentProgramData.id = (u32)ID;
}
static
void RecompileVertexProgram(RSXVertexProgram *RSXVP, VertexProgramData& vertexProgramData, size_t ID)
void recompile_vertex_program(const RSXVertexProgram &RSXVP, vertex_program_type& vertexProgramData, size_t ID)
{
D3D12VertexProgramDecompiler VS(RSXVP->data);
D3D12VertexProgramDecompiler VS(RSXVP);
std::string shaderCode = VS.Decompile();
vertexProgramData.Compile(shaderCode, Shader::SHADER_TYPE::SHADER_TYPE_VERTEX);
vertexProgramData.vertex_shader_inputs = VS.input_slots;
fs::file(fs::get_config_dir() + "VertexProgram" + std::to_string(ID) + ".hlsl", fom::rewrite) << shaderCode;
vertexProgramData.vertex_shader_input_count = RSXVP.rsx_vertex_inputs.size();
fs::file(fs::get_config_dir() + "VertexProgram" + std::to_string(ID) + ".hlsl", fom::rewrite).write(shaderCode);
vertexProgramData.id = (u32)ID;
}
static
PipelineData *BuildProgram(VertexProgramData &vertexProgramData, FragmentProgramData &fragmentProgramData, const PipelineProperties &pipelineProperties, const ExtraData& extraData)
pipeline_storage_type build_pipeline(
const vertex_program_type &vertexProgramData, const fragment_program_type &fragmentProgramData, const pipeline_properties &pipelineProperties,
ID3D12Device *device, gsl::span<ComPtr<ID3D12RootSignature>, 17, 17> root_signatures)
{
std::tuple<ID3D12PipelineState *, std::vector<size_t>, size_t> *result = new std::tuple<ID3D12PipelineState *, std::vector<size_t>, size_t>();
std::tuple<ID3D12PipelineState *, std::vector<size_t>, size_t> result = {};
D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {};
if (vertexProgramData.bytecode == nullptr)
return nullptr;
throw new EXCEPTION("Vertex program compilation failure");
graphicPipelineStateDesc.VS.BytecodeLength = vertexProgramData.bytecode->GetBufferSize();
graphicPipelineStateDesc.VS.pShaderBytecode = vertexProgramData.bytecode->GetBufferPointer();
if (fragmentProgramData.bytecode == nullptr)
return nullptr;
throw new EXCEPTION("fragment program compilation failure");
graphicPipelineStateDesc.PS.BytecodeLength = fragmentProgramData.bytecode->GetBufferSize();
graphicPipelineStateDesc.PS.pShaderBytecode = fragmentProgramData.bytecode->GetBufferPointer();
graphicPipelineStateDesc.pRootSignature = extraData.second[fragmentProgramData.m_textureCount].Get();
std::get<2>(*result) = fragmentProgramData.m_textureCount;
graphicPipelineStateDesc.pRootSignature = root_signatures[fragmentProgramData.m_textureCount][vertexProgramData.vertex_shader_input_count].Get();
graphicPipelineStateDesc.BlendState = pipelineProperties.Blend;
graphicPipelineStateDesc.DepthStencilState = pipelineProperties.DepthStencil;
@@ -210,32 +175,21 @@ struct D3D12Traits
graphicPipelineStateDesc.RTVFormats[i] = pipelineProperties.RenderTargetsFormat;
graphicPipelineStateDesc.DSVFormat = pipelineProperties.DepthStencilFormat;
const std::vector<D3D12_INPUT_ELEMENT_DESC> &completed_IA_desc = completes_IA_desc(pipelineProperties.IASet, vertexProgramData.vertex_shader_inputs);
graphicPipelineStateDesc.InputLayout.pInputElementDescs = completed_IA_desc.data();
graphicPipelineStateDesc.InputLayout.NumElements = (UINT)completed_IA_desc.size();
graphicPipelineStateDesc.SampleDesc.Count = 1;
graphicPipelineStateDesc.SampleMask = UINT_MAX;
graphicPipelineStateDesc.NodeMask = 1;
graphicPipelineStateDesc.IBStripCutValue = pipelineProperties.CutValue;
CHECK_HRESULT(extraData.first->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(&std::get<0>(*result))));
std::get<1>(*result) = vertexProgramData.vertex_shader_inputs;
ComPtr<ID3D12PipelineState> pso;
CHECK_HRESULT(device->CreateGraphicsPipelineState(&graphicPipelineStateDesc, IID_PPV_ARGS(pso.GetAddressOf())));
std::wstring name = L"PSO_" + std::to_wstring(vertexProgramData.id) + L"_" + std::to_wstring(fragmentProgramData.id);
std::get<0>(*result)->SetName(name.c_str());
return result;
}
static
void DeleteProgram(PipelineData *ptr)
{
std::get<0>(*ptr)->Release();
delete ptr;
pso->SetName(name.c_str());
return std::make_tuple(pso, vertexProgramData.vertex_shader_input_count, fragmentProgramData.m_textureCount);
}
};
class PipelineStateObjectCache : public ProgramStateCache<D3D12Traits>
class PipelineStateObjectCache : public program_state_cache<D3D12Traits>
{
};
+144 -392
View File
@@ -13,33 +13,42 @@
#include "D3D12GSRender.h"
#include "D3D12Formats.h"
namespace
{
UINT get_num_rtt(u8 color_target)
u32 get_max_depth_value(rsx::surface_depth_format format)
{
switch (format)
{
case rsx::surface_depth_format::z16: return 0xFFFF;
case rsx::surface_depth_format::z24s8: return 0xFFFFFF;
}
throw EXCEPTION("Unknow depth format");
}
UINT get_num_rtt(rsx::surface_target color_target)
{
switch (color_target)
{
case CELL_GCM_SURFACE_TARGET_NONE: return 0;
case CELL_GCM_SURFACE_TARGET_0:
case CELL_GCM_SURFACE_TARGET_1: return 1;
case CELL_GCM_SURFACE_TARGET_MRT1: return 2;
case CELL_GCM_SURFACE_TARGET_MRT2: return 3;
case CELL_GCM_SURFACE_TARGET_MRT3: return 4;
case rsx::surface_target::none: return 0;
case rsx::surface_target::surface_a:
case rsx::surface_target::surface_b: return 1;
case rsx::surface_target::surfaces_a_b: return 2;
case rsx::surface_target::surfaces_a_b_c: return 3;
case rsx::surface_target::surfaces_a_b_c_d: return 4;
}
throw EXCEPTION("Wrong color_target (%d)", color_target);
}
std::vector<u8> get_rtt_indexes(u8 color_target)
std::vector<u8> get_rtt_indexes(rsx::surface_target color_target)
{
switch (color_target)
{
case CELL_GCM_SURFACE_TARGET_NONE: return{};
case CELL_GCM_SURFACE_TARGET_0: return{ 0 };
case CELL_GCM_SURFACE_TARGET_1: return{ 1 };
case CELL_GCM_SURFACE_TARGET_MRT1: return{ 0, 1 };
case CELL_GCM_SURFACE_TARGET_MRT2: return{ 0, 1, 2 };
case CELL_GCM_SURFACE_TARGET_MRT3: return{ 0, 1, 2, 3 };
case rsx::surface_target::none: return{};
case rsx::surface_target::surface_a: return{ 0 };
case rsx::surface_target::surface_b: return{ 1 };
case rsx::surface_target::surfaces_a_b: return{ 0, 1 };
case rsx::surface_target::surfaces_a_b_c: return{ 0, 1, 2 };
case rsx::surface_target::surfaces_a_b_c_d: return{ 0, 1, 2, 3 };
}
throw EXCEPTION("Wrong color_target (%d)", color_target);
}
@@ -63,6 +72,50 @@ namespace
{
return register_value & 0xff;
}
size_t get_aligned_pitch(rsx::surface_color_format format, u32 width)
{
switch (format)
{
case rsx::surface_color_format::b8: return align(width, 256);
case rsx::surface_color_format::g8b8:
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
case rsx::surface_color_format::r5g6b5: return align(width * 2, 256);
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
case rsx::surface_color_format::x32:
case rsx::surface_color_format::a8r8g8b8: return align(width * 4, 256);
case rsx::surface_color_format::w16z16y16x16: return align(width * 8, 256);
case rsx::surface_color_format::w32z32y32x32: return align(width * 16, 256);
}
throw EXCEPTION("Unknow color surface format");
}
size_t get_packed_pitch(rsx::surface_color_format format, u32 width)
{
switch (format)
{
case rsx::surface_color_format::b8: return width;
case rsx::surface_color_format::g8b8:
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
case rsx::surface_color_format::r5g6b5: return width * 2;
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
case rsx::surface_color_format::x32:
case rsx::surface_color_format::a8r8g8b8: return width * 4;
case rsx::surface_color_format::w16z16y16x16: return width * 8;
case rsx::surface_color_format::w32z32y32x32: return width * 16;
}
throw EXCEPTION("Unknow color surface format");
}
}
void D3D12GSRender::clear_surface(u32 arg)
@@ -73,42 +126,38 @@ void D3D12GSRender::clear_surface(u32 arg)
prepare_render_targets(get_current_resource_storage().command_list.Get());
std::chrono::time_point<std::chrono::system_clock> rtt_duration_end = std::chrono::system_clock::now();
m_timers.m_prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count();
m_timers.prepare_rtt_duration += std::chrono::duration_cast<std::chrono::microseconds>(rtt_duration_end - rtt_duration_start).count();
if (arg & 0x1 || arg & 0x2)
{
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * g_descriptor_stride_rtv);
m_rtts.bind_depth_stencil(m_device.Get(), m_surface.depth_format, handle);
get_current_resource_storage().depth_stencil_descriptor_heap_index++;
if (arg & 0x1)
{
u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8;
u32 max_depth_value = m_surface.depth_format == CELL_GCM_SURFACE_Z16 ? 0x0000ffff : 0x00ffffff;
get_current_resource_storage().command_list->ClearDepthStencilView(handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0,
u32 max_depth_value = get_max_depth_value(m_surface.depth_format);
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_DEPTH, clear_depth / (float)max_depth_value, 0,
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
}
if (arg & 0x2)
get_current_resource_storage().command_list->ClearDepthStencilView(handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE]),
get_current_resource_storage().command_list->ClearDepthStencilView(m_rtts.current_ds_handle, D3D12_CLEAR_FLAG_STENCIL, 0.f, get_clear_stencil(rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE]),
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
}
if (arg & 0xF0)
{
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * g_descriptor_stride_rtv);
size_t rtt_index = m_rtts.bind_render_targets(m_device.Get(), m_surface.color_format, handle);
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle);
size_t rtt_index = get_num_rtt(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]));
get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;
for (unsigned i = 0; i < rtt_index; i++)
get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, g_descriptor_stride_rtv), get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]).data(),
get_current_resource_storage().command_list->ClearRenderTargetView(handle.Offset(i, m_descriptor_stride_rtv), get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]).data(),
1, &get_scissor(rsx::method_registers[NV4097_SET_SCISSOR_HORIZONTAL], rsx::method_registers[NV4097_SET_SCISSOR_VERTICAL]));
}
std::chrono::time_point<std::chrono::system_clock> end_duration = std::chrono::system_clock::now();
m_timers.m_draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count();
m_timers.m_draw_calls_count++;
m_timers.draw_calls_duration += std::chrono::duration_cast<std::chrono::microseconds>(end_duration - start_duration).count();
m_timers.draw_calls_count++;
if (rpcs3::config.rsx.d3d12.debug_output.value())
{
@@ -120,240 +169,65 @@ void D3D12GSRender::clear_surface(u32 arg)
void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlist)
{
// check if something has changed
u32 surface_format = rsx::method_registers[NV4097_SET_SURFACE_FORMAT];
u32 clip_horizontal = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL];
u32 clip_vertical = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL];
u32 clip_width = clip_horizontal >> 16;
u32 clip_height = clip_vertical >> 16;
u32 clip_x = clip_horizontal;
u32 clip_y = clip_vertical;
u32 context_dma_color[] =
{
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_A],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_B],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_C],
rsx::method_registers[NV4097_SET_CONTEXT_DMA_COLOR_D]
};
u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA];
u32 offset_color[] =
{
rsx::method_registers[NV4097_SET_SURFACE_COLOR_AOFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_BOFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_COFFSET],
rsx::method_registers[NV4097_SET_SURFACE_COLOR_DOFFSET]
};
u32 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET];
// FBO location has changed, previous data might be copied
u32 address_color[] =
{
rsx::get_address(offset_color[0], context_dma_color[0]),
rsx::get_address(offset_color[1], context_dma_color[1]),
rsx::get_address(offset_color[2], context_dma_color[2]),
rsx::get_address(offset_color[3], context_dma_color[3]),
};
u32 address_z = rsx::get_address(offset_zeta, m_context_dma_z);
// Exit early if there is no rtt changes
if (m_previous_address_a == address_color[0] &&
m_previous_address_b == address_color[1] &&
m_previous_address_c == address_color[2] &&
m_previous_address_d == address_color[3] &&
m_previous_address_z == address_z &&
m_surface.format == surface_format)
if (!m_rtts_dirty)
return;
m_rtts_dirty = false;
m_previous_address_a = address_color[0];
m_previous_address_b = address_color[1];
m_previous_address_c = address_color[2];
m_previous_address_d = address_color[3];
m_previous_address_z = address_z;
if (m_surface.format != surface_format)
{
m_surface.unpack(surface_format);
m_surface.width = clip_width;
m_surface.height = clip_height;
}
// Make previous RTTs sampleable
for (unsigned i = 0; i < 4; i++)
{
if (m_rtts.bound_render_targets[i] == nullptr)
continue;
copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_render_targets[i], D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
}
// Reset bound data
memset(m_rtts.bound_render_targets_address, 0, 4 * sizeof(u32));
memset(m_rtts.bound_render_targets, 0, 4 * sizeof(ID3D12Resource *));
// Create/Reuse requested rtts
std::array<float, 4> clear_color = get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]);
for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
{
ComPtr<ID3D12Resource> old_render_target_resource;
m_rtts.bound_render_targets[i] = m_rtts.bind_address_as_render_targets(m_device.Get(), copycmdlist, address_color[i], clip_width, clip_height, m_surface.color_format,
clear_color, old_render_target_resource);
if (old_render_target_resource)
get_current_resource_storage().dirty_textures.push_back(old_render_target_resource);
m_rtts.bound_render_targets_address[i] = address_color[i];
}
m_rtts.prepare_render_target(copycmdlist,
rsx::method_registers[NV4097_SET_SURFACE_FORMAT],
rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL], rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL],
rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]),
get_color_surface_addresses(), get_zeta_surface_address(),
m_device.Get(), clear_color, 1.f, 0);
// Same for depth buffer
if (m_rtts.bound_depth_stencil != nullptr)
copycmdlist->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
m_rtts.bound_depth_stencil = nullptr;
m_rtts.bound_depth_stencil_address = 0;
if (!address_z)
return;
ComPtr<ID3D12Resource> old_depth_stencil_resource;
ID3D12Resource *ds = m_rtts.bind_address_as_depth_stencil(m_device.Get(), copycmdlist, address_z, clip_width, clip_height, m_surface.depth_format, 1., 0, old_depth_stencil_resource);
if (old_depth_stencil_resource)
get_current_resource_storage().dirty_textures.push_back(old_depth_stencil_resource);
m_rtts.bound_depth_stencil_address = address_z;
m_rtts.bound_depth_stencil = ds;
}
size_t render_targets::bind_render_targets(ID3D12Device *device, u32 color_format, D3D12_CPU_DESCRIPTOR_HANDLE handle)
{
DXGI_FORMAT dxgi_format = get_color_surface_format(color_format);
// write descriptors
DXGI_FORMAT dxgi_format = get_color_surface_format(m_surface.color_format);
D3D12_RENDER_TARGET_VIEW_DESC rtt_view_desc = {};
rtt_view_desc.ViewDimension = D3D12_RTV_DIMENSION_TEXTURE2D;
rtt_view_desc.Format = dxgi_format;
m_rtts.current_rtts_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * m_descriptor_stride_rtv);
size_t rtt_index = 0;
for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
for (u8 i : get_rtt_indexes(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
{
if (bound_render_targets[i] == nullptr)
if (std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr)
continue;
device->CreateRenderTargetView(bound_render_targets[i], &rtt_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(handle).Offset((INT)rtt_index * g_descriptor_stride_rtv));
m_device->CreateRenderTargetView(std::get<1>(m_rtts.m_bound_render_targets[i]), &rtt_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle).Offset((INT)rtt_index * m_descriptor_stride_rtv));
rtt_index++;
}
return rtt_index;
}
get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;
size_t render_targets::bind_depth_stencil(ID3D12Device *device, u32 depth_format, D3D12_CPU_DESCRIPTOR_HANDLE handle)
{
if (!bound_depth_stencil)
return 0;
if (std::get<1>(m_rtts.m_bound_depth_stencil) == nullptr)
return;
m_rtts.current_ds_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * m_descriptor_stride_dsv);
get_current_resource_storage().depth_stencil_descriptor_heap_index += 1;
D3D12_DEPTH_STENCIL_VIEW_DESC depth_stencil_view_desc = {};
depth_stencil_view_desc.Format = get_depth_stencil_surface_format(depth_format);
depth_stencil_view_desc.Format = get_depth_stencil_surface_format(m_surface.depth_format);
depth_stencil_view_desc.ViewDimension = D3D12_DSV_DIMENSION_TEXTURE2D;
device->CreateDepthStencilView(bound_depth_stencil, &depth_stencil_view_desc, handle);
return 1;
m_device->CreateDepthStencilView(std::get<1>(m_rtts.m_bound_depth_stencil), &depth_stencil_view_desc, m_rtts.current_ds_handle);
}
void D3D12GSRender::set_rtt_and_ds(ID3D12GraphicsCommandList *command_list)
{
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().render_targets_descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().render_targets_descriptors_heap_index * g_descriptor_stride_rtv);
size_t num_rtt = m_rtts.bind_render_targets(m_device.Get(), m_surface.color_format, handle);
get_current_resource_storage().render_targets_descriptors_heap_index += num_rtt;
CD3DX12_CPU_DESCRIPTOR_HANDLE depth_stencil_handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().depth_stencil_descriptor_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().depth_stencil_descriptor_heap_index * g_descriptor_stride_rtv);
size_t num_ds = m_rtts.bind_depth_stencil(m_device.Get(), m_surface.depth_format, depth_stencil_handle);
get_current_resource_storage().depth_stencil_descriptor_heap_index += num_ds;
command_list->OMSetRenderTargets((UINT)num_rtt, num_rtt > 0 ? &handle : nullptr, !!num_rtt,
num_ds > 0 ? &depth_stencil_handle : nullptr);
UINT num_rtt = get_num_rtt(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]));
D3D12_CPU_DESCRIPTOR_HANDLE* ds_handle = (std::get<1>(m_rtts.m_bound_depth_stencil) != nullptr) ? &m_rtts.current_ds_handle : nullptr;
command_list->OMSetRenderTargets((UINT)num_rtt, &m_rtts.current_rtts_handle, true, ds_handle);
}
ID3D12Resource *render_targets::bind_address_as_render_targets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address,
size_t width, size_t height, u8 surfaceColorFormat, const std::array<float, 4> &clear_color, ComPtr<ID3D12Resource> &dirtyRTT)
void rsx::render_targets::init(ID3D12Device *device)
{
DXGI_FORMAT dxgi_format = get_color_surface_format(surfaceColorFormat);
auto It = render_targets_storage.find(address);
// TODO: Check if format and size match
if (It != render_targets_storage.end())
{
ComPtr<ID3D12Resource> rtt;
rtt = It->second.Get();
if (rtt->GetDesc().Format == dxgi_format && rtt->GetDesc().Width == width && rtt->GetDesc().Height == height)
{
cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
return rtt.Get();
}
render_targets_storage.erase(address);
dirtyRTT = rtt;
}
ComPtr<ID3D12Resource> rtt;
LOG_WARNING(RSX, "Creating RTT");
D3D12_CLEAR_VALUE clear_color_value = {};
clear_color_value.Format = dxgi_format;
clear_color_value.Color[0] = clear_color[0];
clear_color_value.Color[1] = clear_color[1];
clear_color_value.Color[2] = clear_color[2];
clear_color_value.Color[3] = clear_color[3];
device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET),
D3D12_RESOURCE_STATE_RENDER_TARGET,
&clear_color_value,
IID_PPV_ARGS(rtt.GetAddressOf())
);
render_targets_storage[address] = rtt;
std::wstring name = L"rtt_@" + std::to_wstring(address);
rtt->SetName(name.c_str());
return rtt.Get();
}
ID3D12Resource * render_targets::bind_address_as_depth_stencil(ID3D12Device * device, ID3D12GraphicsCommandList * cmdList, u32 address, size_t width, size_t height, u8 surfaceDepthFormat, float depthClear, u8 stencilClear, ComPtr<ID3D12Resource> &dirtyDS)
{
auto It = depth_stencil_storage.find(address);
// TODO: Check if surface depth format match
if (It != depth_stencil_storage.end())
{
ComPtr<ID3D12Resource> ds = It->second;
if (ds->GetDesc().Width == width && ds->GetDesc().Height == height)
{
// set the resource as depth write
cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds.Get(), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
return ds.Get();
}
// If size doesn't match, remove ds from cache
depth_stencil_storage.erase(address);
dirtyDS = ds;
}
D3D12_CLEAR_VALUE clear_depth_value = {};
clear_depth_value.DepthStencil.Depth = depthClear;
DXGI_FORMAT dxgi_format = get_depth_stencil_typeless_surface_format(surfaceDepthFormat);
clear_depth_value.Format = get_depth_stencil_surface_clear_format(surfaceDepthFormat);
ComPtr<ID3D12Resource> new_depth_stencil;
device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
D3D12_RESOURCE_STATE_DEPTH_WRITE,
&clear_depth_value,
IID_PPV_ARGS(new_depth_stencil.GetAddressOf())
);
depth_stencil_storage[address] = new_depth_stencil;
std::wstring name = L"ds_@" + std::to_wstring(address);
new_depth_stencil->SetName(name.c_str());
return new_depth_stencil.Get();
}
void render_targets::init(ID3D12Device *device)//, u8 surfaceDepthFormat, size_t width, size_t height, float clearColor[4], float clearDepth)
{
memset(bound_render_targets_address, 0, 4 * sizeof(u32));
memset(bound_render_targets, 0, 4 * sizeof(ID3D12Resource*));
bound_depth_stencil = nullptr;
bound_depth_stencil_address = 0;
g_descriptor_stride_rtv = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
}
@@ -366,47 +240,32 @@ namespace
size_t download_to_readback_buffer(
ID3D12Device *device,
ID3D12GraphicsCommandList * command_list,
data_heap<ID3D12Resource, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT> &readback_heap,
data_heap &readback_heap,
ID3D12Resource * color_surface,
int color_surface_format
rsx::surface_color_format color_surface_format
)
{
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
DXGI_FORMAT dxgi_format = get_color_surface_format(color_surface_format);
size_t row_pitch;
switch (color_surface_format)
{
case CELL_GCM_SURFACE_R5G6B5:
row_pitch = align(clip_w * 2, 256);
break;
case CELL_GCM_SURFACE_A8R8G8B8:
row_pitch = align(clip_w * 4, 256);
break;
case CELL_GCM_SURFACE_F_W16Z16Y16X16:
row_pitch = align(clip_w * 8, 256);
break;
}
size_t row_pitch = get_aligned_pitch(color_surface_format, clip_w);
size_t buffer_size = row_pitch * clip_h;
assert(readback_heap.can_alloc(buffer_size));
size_t heap_offset = readback_heap.alloc(buffer_size);
size_t heap_offset = readback_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(color_surface, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE));
command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.m_heap, { heap_offset, { dxgi_format, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.get_heap(), { heap_offset, { dxgi_format, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(color_surface, 0), nullptr);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(color_surface, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET));
return heap_offset;
}
void copy_readback_buffer_to_dest(void *dest, data_heap<ID3D12Resource, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT> &readback_heap, size_t offset_in_heap, size_t dst_pitch, size_t src_pitch, size_t height)
void copy_readback_buffer_to_dest(void *dest, data_heap &readback_heap, size_t offset_in_heap, size_t dst_pitch, size_t src_pitch, size_t height)
{
void *buffer;
// TODO: Use exact range
CHECK_HRESULT(readback_heap.m_heap->Map(0, nullptr, &buffer));
void *mapped_buffer = (char*)buffer + offset_in_heap;
void *mapped_buffer = readback_heap.map<void>(offset_in_heap);
for (unsigned row = 0; row < height; row++)
{
u32 *casted_dest = (u32*)((char*)dest + row * dst_pitch);
@@ -414,7 +273,7 @@ namespace
for (unsigned col = 0; col < src_pitch / 4; col++)
*casted_dest++ = se_storage<u32>::swap(*casted_src++);
}
readback_heap.m_heap->Unmap(0, nullptr);
readback_heap.unmap();
}
void wait_for_command_queue(ID3D12Device *device, ID3D12CommandQueue *command_queue)
@@ -429,6 +288,8 @@ namespace
}
}
void D3D12GSRender::copy_render_target_to_dma_location()
{
// Add all buffer write
@@ -474,13 +335,11 @@ void D3D12GSRender::copy_render_target_to_dma_location()
if (m_context_dma_z && rpcs3::state.config.rsx.opengl.write_depth_buffer)
{
size_t uav_size = clip_w * clip_h * 2;
assert(m_uav_heap.can_alloc(uav_size));
size_t heap_offset = m_uav_heap.alloc(uav_size);
CHECK_HRESULT(
m_device->CreatePlacedResource(
m_uav_heap.m_heap,
heap_offset,
m_device->CreateCommittedResource(
&D3D12_HEAP_PROPERTIES{D3D12_HEAP_TYPE_DEFAULT},
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R8_UNORM, clip_w, clip_h, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_UNORDERED_ACCESS),
D3D12_RESOURCE_STATE_UNORDERED_ACCESS,
nullptr,
@@ -497,31 +356,31 @@ void D3D12GSRender::copy_render_target_to_dma_location()
shader_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
shader_resource_view_desc.Texture2D.MipLevels = 1;
shader_resource_view_desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
m_device->CreateShaderResourceView(m_rtts.bound_depth_stencil, &shader_resource_view_desc,
m_device->CreateShaderResourceView(std::get<1>(m_rtts.m_bound_depth_stencil), &shader_resource_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart()));
D3D12_UNORDERED_ACCESS_VIEW_DESC uav_desc = {};
uav_desc.Format = DXGI_FORMAT_R8_UNORM;
uav_desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
m_device->CreateUnorderedAccessView(depth_format_conversion_buffer.Get(), nullptr, &uav_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(1, g_descriptor_stride_srv_cbv_uav));
CD3DX12_CPU_DESCRIPTOR_HANDLE(descriptor_heap->GetCPUDescriptorHandleForHeapStart()).Offset(1, m_descriptor_stride_srv_cbv_uav));
// Convert
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
get_current_resource_storage().command_list->SetPipelineState(m_convertPSO);
get_current_resource_storage().command_list->SetComputeRootSignature(m_convertRootSignature);
get_current_resource_storage().command_list->SetPipelineState(m_convert_pso);
get_current_resource_storage().command_list->SetComputeRootSignature(m_convert_root_signature);
get_current_resource_storage().command_list->SetDescriptorHeaps(1, descriptor_heap.GetAddressOf());
get_current_resource_storage().command_list->SetComputeRootDescriptorTable(0, descriptor_heap->GetGPUDescriptorHandleForHeapStart());
get_current_resource_storage().command_list->Dispatch(clip_w / 8, clip_h / 8, 1);
D3D12_RESOURCE_BARRIER barriers[] =
{
CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE),
CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_bound_depth_stencil), D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE),
CD3DX12_RESOURCE_BARRIER::UAV(depth_format_conversion_buffer.Get()),
};
get_current_resource_storage().command_list->ResourceBarrier(2, barriers);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(depth_format_conversion_buffer.Get(), D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_COPY_SOURCE));
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.m_heap, { depth_buffer_offset_in_heap,{ DXGI_FORMAT_R8_UNORM, (UINT)clip_w, (UINT)clip_h, 1, (UINT)depth_row_pitch } }), 0, 0, 0,
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.get_heap(), { depth_buffer_offset_in_heap,{ DXGI_FORMAT_R8_UNORM, (UINT)clip_w, (UINT)clip_h, 1, (UINT)depth_row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(depth_format_conversion_buffer.Get(), 0), nullptr);
invalidate_address(address_z);
@@ -532,11 +391,11 @@ void D3D12GSRender::copy_render_target_to_dma_location()
size_t color_buffer_offset_in_heap[4];
if (rpcs3::state.config.rsx.opengl.write_color_buffers)
{
for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
for (u8 i : get_rtt_indexes(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
{
if (!address_color[i])
continue;
color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[i], m_surface.color_format);
color_buffer_offset_in_heap[i] = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, std::get<1>(m_rtts.m_bound_render_targets[i]), m_surface.color_format);
invalidate_address(address_color[i]);
need_transfer = true;
}
@@ -555,10 +414,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
{
auto ptr = vm::base(address_z);
char *depth_buffer = (char*)ptr;
void *buffer;
// TODO: Use exact range
CHECK_HRESULT(m_readback_resources.m_heap->Map(0, nullptr, &buffer));
unsigned char *mapped_buffer = (unsigned char*)buffer + depth_buffer_offset_in_heap;
u8 *mapped_buffer = m_readback_resources.map<u8>(depth_buffer_offset_in_heap);
for (unsigned row = 0; row < (unsigned)clip_h; row++)
{
@@ -571,28 +427,14 @@ void D3D12GSRender::copy_render_target_to_dma_location()
depth_buffer[4 * (row * clip_w + i) + 3] = c;
}
}
m_readback_resources.m_heap->Unmap(0, nullptr);
}
size_t srcPitch, dstPitch;
switch (m_surface.color_format)
{
case CELL_GCM_SURFACE_R5G6B5:
srcPitch = align(clip_w * 2, 256);
dstPitch = clip_w * 2;
break;
case CELL_GCM_SURFACE_A8R8G8B8:
srcPitch = align(clip_w * 4, 256);
dstPitch = clip_w * 4;
break;
case CELL_GCM_SURFACE_F_W16Z16Y16X16:
srcPitch = align(clip_w * 8, 256);
dstPitch = clip_w * 8;
break;
m_readback_resources.unmap();
}
if (rpcs3::state.config.rsx.opengl.write_color_buffers)
{
size_t srcPitch = get_aligned_pitch(m_surface.color_format, clip_w);
size_t dstPitch = get_packed_pitch(m_surface.color_format, clip_w);
void *dest_buffer[] =
{
vm::base(address_color[0]),
@@ -601,7 +443,7 @@ void D3D12GSRender::copy_render_target_to_dma_location()
vm::base(address_color[3]),
};
for (u8 i : get_rtt_indexes(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]))
for (u8 i : get_rtt_indexes(rsx::to_surface_target(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET])))
{
if (!address_color[i])
continue;
@@ -611,111 +453,21 @@ void D3D12GSRender::copy_render_target_to_dma_location()
}
void D3D12GSRender::copy_render_targets_to_memory(void *buffer, u8 rtt)
std::array<std::vector<gsl::byte>, 4> D3D12GSRender::copy_render_targets_to_memory()
{
size_t heap_offset = download_to_readback_buffer(m_device.Get(), get_current_resource_storage().command_list.Get(), m_readback_resources, m_rtts.bound_render_targets[rtt], m_surface.color_format);
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
get_current_resource_storage().set_new_command_list();
wait_for_command_queue(m_device.Get(), m_command_queue.Get());
m_readback_resources.m_get_pos = m_readback_resources.get_current_put_pos_minus_one();
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
size_t srcPitch, dstPitch;
switch (m_surface.color_format)
{
case CELL_GCM_SURFACE_R5G6B5:
srcPitch = align(clip_w * 2, 256);
dstPitch = clip_w * 2;
break;
case CELL_GCM_SURFACE_A8R8G8B8:
srcPitch = align(clip_w * 4, 256);
dstPitch = clip_w * 4;
break;
case CELL_GCM_SURFACE_F_W16Z16Y16X16:
srcPitch = align(clip_w * 8, 256);
dstPitch = clip_w * 8;
break;
}
copy_readback_buffer_to_dest(buffer, m_readback_resources, heap_offset, srcPitch, dstPitch, clip_h);
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
return m_rtts.get_render_targets_data(surface.color_format, clip_w, clip_h, m_device.Get(), m_command_queue.Get(), m_readback_resources, get_current_resource_storage());
}
void D3D12GSRender::copy_depth_buffer_to_memory(void *buffer)
std::array<std::vector<gsl::byte>, 2> D3D12GSRender::copy_depth_stencil_buffer_to_memory()
{
unsigned clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
unsigned clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
size_t row_pitch = align(clip_w * 4, 256);
size_t buffer_size = row_pitch * clip_h;
assert(m_readback_resources.can_alloc(buffer_size));
size_t heap_offset = m_readback_resources.alloc(buffer_size);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.m_heap, { heap_offset,{ DXGI_FORMAT_R32_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(m_rtts.bound_depth_stencil, 0), nullptr);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
get_current_resource_storage().set_new_command_list();
wait_for_command_queue(m_device.Get(), m_command_queue.Get());
m_readback_resources.m_get_pos = m_readback_resources.get_current_put_pos_minus_one();
void *temp_buffer;
CHECK_HRESULT(m_readback_resources.m_heap->Map(0, nullptr, &temp_buffer));
void *mapped_buffer = (char*)temp_buffer + heap_offset;
for (unsigned row = 0; row < clip_h; row++)
{
u32 *casted_dest = (u32*)((char*)buffer + row * clip_w * 4);
u32 *casted_src = (u32*)((char*)mapped_buffer + row * row_pitch);
for (unsigned col = 0; col < row_pitch / 4; col++)
*casted_dest++ = *casted_src++;
}
m_readback_resources.m_heap->Unmap(0, nullptr);
int clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
int clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
return m_rtts.get_depth_stencil_data(surface.depth_format, clip_w, clip_h, m_device.Get(), m_command_queue.Get(), m_readback_resources, get_current_resource_storage());
}
void D3D12GSRender::copy_stencil_buffer_to_memory(void *buffer)
{
unsigned clip_w = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL] >> 16;
unsigned clip_h = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL] >> 16;
size_t row_pitch = align(clip_w * 4, 256);
size_t buffer_size = row_pitch * clip_h;
assert(m_readback_resources.can_alloc(buffer_size));
size_t heap_offset = m_readback_resources.alloc(buffer_size);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.m_heap, { heap_offset, { DXGI_FORMAT_R8_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(m_rtts.bound_depth_stencil, 1), nullptr);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_rtts.bound_depth_stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
CHECK_HRESULT(get_current_resource_storage().command_list->Close());
m_command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)get_current_resource_storage().command_list.GetAddressOf());
get_current_resource_storage().set_new_command_list();
wait_for_command_queue(m_device.Get(), m_command_queue.Get());
m_readback_resources.m_get_pos = m_readback_resources.get_current_put_pos_minus_one();
void *temp_buffer;
CHECK_HRESULT(m_readback_resources.m_heap->Map(0, nullptr, &temp_buffer));
void *mapped_buffer = (char*)temp_buffer + heap_offset;
for (unsigned row = 0; row < clip_h; row++)
{
char *casted_dest = (char*)buffer + row * clip_w;
char *casted_src = (char*)mapped_buffer + row * row_pitch;
for (unsigned col = 0; col < row_pitch; col++)
*casted_dest++ = *casted_src++;
}
m_readback_resources.m_heap->Unmap(0, nullptr);
}
#endif
+256 -20
View File
@@ -1,31 +1,267 @@
#pragma once
#include <utility>
#include <d3d12.h>
#include "d3dx12.h"
struct render_targets
#include "D3D12Formats.h"
#include "D3D12MemoryHelpers.h"
#include "../Common/surface_store.h"
namespace rsx
{
struct render_target_traits
{
using surface_storage_type = ComPtr<ID3D12Resource>;
using surface_type = ID3D12Resource*;
using command_list_type = gsl::not_null<ID3D12GraphicsCommandList*>;
using download_buffer_object = std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE>; // heap offset, size, last_put_pos, fence, handle
static
ComPtr<ID3D12Resource> create_new_surface(
u32 address,
surface_color_format color_format, size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, const std::array<float, 4> &clear_color, float, u8)
{
DXGI_FORMAT dxgi_format = get_color_surface_format(color_format);
ComPtr<ID3D12Resource> rtt;
LOG_WARNING(RSX, "Creating RTT");
D3D12_CLEAR_VALUE clear_color_value = {};
clear_color_value.Format = dxgi_format;
clear_color_value.Color[0] = clear_color[0];
clear_color_value.Color[1] = clear_color[1];
clear_color_value.Color[2] = clear_color[2];
clear_color_value.Color[3] = clear_color[3];
device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET),
D3D12_RESOURCE_STATE_RENDER_TARGET,
&clear_color_value,
IID_PPV_ARGS(rtt.GetAddressOf())
);
std::wstring name = L"rtt_@" + std::to_wstring(address);
rtt->SetName(name.c_str());
return rtt;
}
static
void prepare_rtt_for_drawing(
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
ID3D12Resource* rtt)
{
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_RENDER_TARGET));
}
static
void prepare_rtt_for_sampling(
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
ID3D12Resource* rtt)
{
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_GENERIC_READ));
}
static
ComPtr<ID3D12Resource> create_new_surface(
u32 address,
surface_depth_format surfaceDepthFormat, size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, const std::array<float, 4>& , float clear_depth, u8 clear_stencil)
{
D3D12_CLEAR_VALUE clear_depth_value = {};
clear_depth_value.DepthStencil.Depth = clear_depth;
clear_depth_value.DepthStencil.Stencil = clear_stencil;
DXGI_FORMAT dxgi_format = get_depth_stencil_typeless_surface_format(surfaceDepthFormat);
clear_depth_value.Format = get_depth_stencil_surface_clear_format(surfaceDepthFormat);
ComPtr<ID3D12Resource> new_depth_stencil;
device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)width, (UINT)height, 1, 1, 1, 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL),
D3D12_RESOURCE_STATE_DEPTH_WRITE,
&clear_depth_value,
IID_PPV_ARGS(new_depth_stencil.GetAddressOf())
);
std::wstring name = L"ds_@" + std::to_wstring(address);
new_depth_stencil->SetName(name.c_str());
return new_depth_stencil;
}
static
void prepare_ds_for_drawing(
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
ID3D12Resource* ds)
{
// set the resource as depth write
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
}
static
void prepare_ds_for_sampling(
gsl::not_null<ID3D12GraphicsCommandList*> command_list,
ID3D12Resource* ds)
{
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
}
static
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_color_format surface_color_format, size_t width, size_t height)
{
DXGI_FORMAT dxgi_format = get_color_surface_format(surface_color_format);
return rtt->GetDesc().Format == dxgi_format && rtt->GetDesc().Width == width && rtt->GetDesc().Height == height;
}
static
bool ds_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, surface_depth_format surface_depth_stencil_format, size_t width, size_t height)
{
//TODO: Check format
return rtt->GetDesc().Width == width && rtt->GetDesc().Height == height;
}
static
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_download_command(
gsl::not_null<ID3D12Resource*> rtt,
surface_color_format color_format, size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store
)
{
ID3D12GraphicsCommandList* command_list = res_store.command_list.Get();
DXGI_FORMAT dxgi_format = get_color_surface_format(color_format);
size_t row_pitch = rsx::utility::get_aligned_pitch(color_format, gsl::narrow<u32>(width));
size_t buffer_size = row_pitch * height;
size_t heap_offset = readback_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE));
command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.get_heap(), { heap_offset,{ dxgi_format, (UINT)width, (UINT)height, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(rtt, 0), nullptr);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(rtt, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_RENDER_TARGET));
CHECK_HRESULT(command_list->Close());
command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)res_store.command_list.GetAddressOf());
res_store.set_new_command_list();
ComPtr<ID3D12Fence> fence;
CHECK_HRESULT(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(fence.GetAddressOf())));
HANDLE handle = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
fence->SetEventOnCompletion(1, handle);
command_queue->Signal(fence.Get(), 1);
return std::make_tuple(heap_offset, buffer_size, readback_heap.get_current_put_pos_minus_one(), fence, handle);
}
static
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_depth_download_command(
gsl::not_null<ID3D12Resource*> ds,
surface_depth_format depth_format, size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store
)
{
ID3D12GraphicsCommandList* command_list = res_store.command_list.Get();
DXGI_FORMAT dxgi_format = (depth_format == surface_depth_format::z24s8) ? DXGI_FORMAT_R32_TYPELESS : DXGI_FORMAT_R16_TYPELESS;
size_t row_pitch = align(width * 4, 256);
size_t buffer_size = row_pitch * height;
size_t heap_offset = readback_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.get_heap(), { heap_offset,{ dxgi_format, (UINT)width, (UINT)height, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(ds, 0), nullptr);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(ds, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
CHECK_HRESULT(command_list->Close());
command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)res_store.command_list.GetAddressOf());
res_store.set_new_command_list();
ComPtr<ID3D12Fence> fence;
CHECK_HRESULT(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(fence.GetAddressOf())));
HANDLE handle = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
fence->SetEventOnCompletion(1, handle);
command_queue->Signal(fence.Get(), 1);
return std::make_tuple(heap_offset, buffer_size, readback_heap.get_current_put_pos_minus_one(), fence, handle);
}
static
std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> issue_stencil_download_command(
gsl::not_null<ID3D12Resource*> stencil,
size_t width, size_t height,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store
)
{
ID3D12GraphicsCommandList* command_list = res_store.command_list.Get();
size_t row_pitch = align(width, 256);
size_t buffer_size = row_pitch * height;
size_t heap_offset = readback_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(stencil, D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_COPY_SOURCE));
command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(readback_heap.get_heap(), { heap_offset,{ DXGI_FORMAT_R8_TYPELESS, (UINT)width, (UINT)height, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(stencil, 1), nullptr);
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(stencil, D3D12_RESOURCE_STATE_COPY_SOURCE, D3D12_RESOURCE_STATE_DEPTH_WRITE));
CHECK_HRESULT(command_list->Close());
command_queue->ExecuteCommandLists(1, (ID3D12CommandList**)res_store.command_list.GetAddressOf());
res_store.set_new_command_list();
ComPtr<ID3D12Fence> fence;
CHECK_HRESULT(device->CreateFence(0, D3D12_FENCE_FLAG_NONE, IID_PPV_ARGS(fence.GetAddressOf())));
HANDLE handle = CreateEventEx(nullptr, FALSE, FALSE, EVENT_ALL_ACCESS);
fence->SetEventOnCompletion(1, handle);
command_queue->Signal(fence.Get(), 1);
return std::make_tuple(heap_offset, buffer_size, readback_heap.get_current_put_pos_minus_one(), fence, handle);
}
static
gsl::span<const gsl::byte> map_downloaded_buffer(const std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> &sync_data,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store)
{
size_t offset;
size_t buffer_size;
size_t current_put_pos_minus_one;
HANDLE handle;
std::tie(offset, buffer_size, current_put_pos_minus_one, std::ignore, handle) = sync_data;
WaitForSingleObjectEx(handle, INFINITE, FALSE);
CloseHandle(handle);
readback_heap.m_get_pos = current_put_pos_minus_one;
const gsl::byte *mapped_buffer = readback_heap.map<const gsl::byte>(CD3DX12_RANGE(offset, offset + buffer_size));
return { mapped_buffer , gsl::narrow<int>(buffer_size) };
}
static
void unmap_downloaded_buffer(const std::tuple<size_t, size_t, size_t, ComPtr<ID3D12Fence>, HANDLE> &sync_data,
gsl::not_null<ID3D12Device*> device, gsl::not_null<ID3D12CommandQueue*> command_queue, data_heap &readback_heap, resource_storage &res_store)
{
readback_heap.unmap();
}
static ID3D12Resource* get(const ComPtr<ID3D12Resource> &in)
{
return in.Get();
}
};
struct render_targets : public rsx::surface_store<render_target_traits>
{
INT g_descriptor_stride_rtv;
std::unordered_map<u32, ComPtr<ID3D12Resource> > render_targets_storage;
ID3D12Resource *bound_render_targets[4];
u32 bound_render_targets_address[4];
std::unordered_map<u32, ComPtr<ID3D12Resource> > depth_stencil_storage;
ID3D12Resource *bound_depth_stencil;
u32 bound_depth_stencil_address;
size_t bind_render_targets(ID3D12Device *, u32 color_format, D3D12_CPU_DESCRIPTOR_HANDLE);
size_t bind_depth_stencil(ID3D12Device *, u32 depth_format, D3D12_CPU_DESCRIPTOR_HANDLE);
/**
* If render target already exists at address, issue state change operation on cmdList.
* Otherwise create one with width, height, clearColor info.
* returns the corresponding render target resource.
*/
ID3D12Resource *bind_address_as_render_targets(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address,
size_t width, size_t height, u8 surfaceColorFormat, const std::array<float, 4> &clearColor, ComPtr<ID3D12Resource> &dirtyDS);
ID3D12Resource *bind_address_as_depth_stencil(ID3D12Device *device, ID3D12GraphicsCommandList *cmdList, u32 address,
size_t width, size_t height, u8 surfaceDepthFormat, float depthClear, u8 stencilClear, ComPtr<ID3D12Resource> &dirtyDS);
D3D12_CPU_DESCRIPTOR_HANDLE current_rtts_handle;
D3D12_CPU_DESCRIPTOR_HANDLE current_ds_handle;
void init(ID3D12Device *device);
};
}
+86 -69
View File
@@ -40,6 +40,31 @@ D3D12_SAMPLER_DESC get_sampler_desc(const rsx::texture &texture)
return samplerDesc;
}
namespace
{
CD3DX12_RESOURCE_DESC get_texture_description(const rsx::texture &texture)
{
const u8 format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
DXGI_FORMAT dxgi_format = get_texture_format(format);
if (texture.dimension() == 1) // 1D texture or cubemap
{
return CD3DX12_RESOURCE_DESC::Tex1D(dxgi_format, texture.width(), 1, texture.mipmap());
}
else if (texture.dimension() == 2) // 2D texture or cubemap
{
// if (texture.depth() < 2);
size_t depth = (texture.cubemap()) ? 6 : 1;
return CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, texture.width(), texture.height(), (UINT)depth, texture.mipmap());
}
else if (texture.dimension() == 3) // 3d texture
{
return CD3DX12_RESOURCE_DESC::Tex3D(dxgi_format, texture.width(), texture.height(), texture.depth(), texture.mipmap());
}
throw EXCEPTION("Unknow texture dimension");
}
}
/**
* Create a texture residing in default heap and generate uploads commands in commandList,
@@ -49,41 +74,32 @@ ComPtr<ID3D12Resource> upload_single_texture(
const rsx::texture &texture,
ID3D12Device *device,
ID3D12GraphicsCommandList *command_list,
data_heap<ID3D12Resource, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT> &texture_buffer_heap)
data_heap &texture_buffer_heap)
{
size_t w = texture.width(), h = texture.height();
size_t depth = texture.depth();
if (depth == 0) depth = 1;
if (texture.cubemap()) depth *= 6;
const u8 format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
DXGI_FORMAT dxgi_format = get_texture_format(format);
size_t buffer_size = get_placed_texture_storage_size(texture, 256);
assert(texture_buffer_heap.can_alloc(buffer_size));
size_t heap_offset = texture_buffer_heap.alloc(buffer_size);
size_t heap_offset = texture_buffer_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *buffer;
CHECK_HRESULT(texture_buffer_heap.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), &buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
void *mapped_buffer = texture_buffer_heap.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
std::vector<MipmapLevelInfo> mipInfos = upload_placed_texture(texture, 256, mapped_buffer);
texture_buffer_heap.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
texture_buffer_heap.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
ComPtr<ID3D12Resource> result;
CHECK_HRESULT(device->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Tex2D(dxgi_format, (UINT)w, (UINT)h, (UINT)depth, texture.mipmap()),
&get_texture_description(texture),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(result.GetAddressOf())
));
const u8 format = texture.format() & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
DXGI_FORMAT dxgi_format = get_texture_format(format);
size_t mip_level = 0;
for (const MipmapLevelInfo mli : mipInfos)
{
command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(result.Get(), (UINT)mip_level), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.m_heap, { heap_offset + mli.offset, { dxgi_format, (UINT)mli.width, (UINT)mli.height, 1, (UINT)mli.rowPitch } }), nullptr);
&CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.get_heap(), { heap_offset + mli.offset, { dxgi_format, (UINT)mli.width, (UINT)mli.height, (UINT)mli.depth, (UINT)mli.rowPitch } }), nullptr);
mip_level++;
}
@@ -97,7 +113,7 @@ ComPtr<ID3D12Resource> upload_single_texture(
void update_existing_texture(
const rsx::texture &texture,
ID3D12GraphicsCommandList *command_list,
data_heap<ID3D12Resource, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT> &texture_buffer_heap,
data_heap &texture_buffer_heap,
ID3D12Resource *existing_texture)
{
size_t w = texture.width(), h = texture.height();
@@ -106,34 +122,63 @@ void update_existing_texture(
DXGI_FORMAT dxgi_format = get_texture_format(format);
size_t buffer_size = get_placed_texture_storage_size(texture, 256);
assert(texture_buffer_heap.can_alloc(buffer_size));
size_t heap_offset = texture_buffer_heap.alloc(buffer_size);
size_t heap_offset = texture_buffer_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *buffer;
CHECK_HRESULT(texture_buffer_heap.m_heap->Map(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size), &buffer));
void *mapped_buffer = (char*)buffer + heap_offset;
void *mapped_buffer = texture_buffer_heap.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
std::vector<MipmapLevelInfo> mipInfos = upload_placed_texture(texture, 256, mapped_buffer);
texture_buffer_heap.m_heap->Unmap(0, &CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
texture_buffer_heap.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(existing_texture, D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_COPY_DEST));
size_t miplevel = 0;
for (const MipmapLevelInfo mli : mipInfos)
{
command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(existing_texture, (UINT)miplevel), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.m_heap, { heap_offset + mli.offset,{ dxgi_format, (UINT)mli.width, (UINT)mli.height, 1, (UINT)mli.rowPitch } }), nullptr);
&CD3DX12_TEXTURE_COPY_LOCATION(texture_buffer_heap.get_heap(), { heap_offset + mli.offset,{ dxgi_format, (UINT)mli.width, (UINT)mli.height, (UINT)mli.depth, (UINT)mli.rowPitch } }), nullptr);
miplevel++;
}
command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(existing_texture, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_GENERIC_READ));
}
D3D12_SHADER_RESOURCE_VIEW_DESC get_srv_descriptor_with_dimensions(const rsx::texture &tex)
{
D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = {};
if (tex.dimension() == 1)
{
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1D;
shared_resource_view_desc.Texture1D.MipLevels = tex.mipmap();
return shared_resource_view_desc;
}
if (tex.dimension() == 2)
{
if (tex.cubemap())
{
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
shared_resource_view_desc.TextureCube.MipLevels = tex.mipmap();
return shared_resource_view_desc;
}
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
shared_resource_view_desc.Texture2D.MipLevels = tex.mipmap();
return shared_resource_view_desc;
}
if (tex.dimension() == 3)
{
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D;
shared_resource_view_desc.Texture3D.MipLevels = tex.mipmap();
return shared_resource_view_desc;
}
throw EXCEPTION("Wrong texture dimension %d", tex.dimension());
}
}
void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t descriptor_index, size_t texture_count)
void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_list, size_t texture_count)
{
size_t used_texture = 0;
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
for (u32 i = 0; i < 16; ++i)
{
if (!m_textures_dirty[i])
continue;
m_textures_dirty[i] = false;
if (!textures[i].enabled())
{
// Now fill remaining texture slots with dummy texture/sampler
@@ -147,21 +192,14 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0,
D3D12_SHADER_COMPONENT_MAPPING_FORCE_VALUE_0);
m_device->CreateShaderResourceView(m_dummy_texture, &shader_resource_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)descriptor_index + (INT)used_texture, g_descriptor_stride_srv_cbv_uav)
);
m_current_shader_resources[i] = std::make_tuple(m_dummy_texture, shader_resource_view_desc);
D3D12_SAMPLER_DESC sampler_desc = {};
sampler_desc.Filter = D3D12_FILTER_MIN_MAG_MIP_POINT;
sampler_desc.AddressU = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
sampler_desc.AddressV = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
sampler_desc.AddressW = D3D12_TEXTURE_ADDRESS_MODE_WRAP;
m_device->CreateSampler(&sampler_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart())
.Offset((INT)get_current_resource_storage().current_sampler_index + (INT)used_texture, g_descriptor_stride_samplers)
);
used_texture++;
m_current_samplers[i] = sampler_desc;
continue;
}
size_t w = textures[i].width(), h = textures[i].height();
@@ -173,25 +211,22 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
bool is_swizzled = !(textures[i].format() & CELL_GCM_TEXTURE_LN);
ID3D12Resource *vram_texture;
std::unordered_map<u32, ComPtr<ID3D12Resource> >::const_iterator ItRTT = m_rtts.render_targets_storage.find(texaddr);
std::unordered_map<u32, ComPtr<ID3D12Resource> >::const_iterator ItDS = m_rtts.depth_stencil_storage.find(texaddr);
std::pair<texture_entry, ComPtr<ID3D12Resource> > *cached_texture = m_texture_cache.find_data_if_available(texaddr);
bool is_render_target = false, is_depth_stencil_texture = false;
if (ItRTT != m_rtts.render_targets_storage.end())
if (vram_texture = m_rtts.get_texture_from_render_target_if_applicable(texaddr))
{
vram_texture = ItRTT->second.Get();
is_render_target = true;
}
else if (ItDS != m_rtts.depth_stencil_storage.end())
else if (vram_texture = m_rtts.get_texture_from_depth_stencil_if_applicable(texaddr))
{
vram_texture = ItDS->second.Get();
is_depth_stencil_texture = true;
}
else if (cached_texture != nullptr && (cached_texture->first == texture_entry(format, w, h, textures[i].mipmap())))
else if (cached_texture != nullptr && (cached_texture->first == texture_entry(format, w, h, textures[i].depth(), textures[i].mipmap())))
{
if (cached_texture->first.m_is_dirty)
{
update_existing_texture(textures[i], command_list, m_texture_upload_data, cached_texture->second.Get());
update_existing_texture(textures[i], command_list, m_buffer_data, cached_texture->second.Get());
m_texture_cache.protect_data(texaddr, texaddr, get_texture_size(textures[i]));
}
vram_texture = cached_texture->second.Get();
@@ -200,24 +235,14 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
{
if (cached_texture != nullptr)
get_current_resource_storage().dirty_textures.push_back(m_texture_cache.remove_from_cache(texaddr));
ComPtr<ID3D12Resource> tex = upload_single_texture(textures[i], m_device.Get(), command_list, m_texture_upload_data);
ComPtr<ID3D12Resource> tex = upload_single_texture(textures[i], m_device.Get(), command_list, m_buffer_data);
std::wstring name = L"texture_@" + std::to_wstring(texaddr);
tex->SetName(name.c_str());
vram_texture = tex.Get();
m_texture_cache.store_and_protect_data(texaddr, texaddr, get_texture_size(textures[i]), format, w, h, textures[i].mipmap(), tex);
m_texture_cache.store_and_protect_data(texaddr, texaddr, get_texture_size(textures[i]), format, w, h, textures[i].depth(), textures[i].mipmap(), tex);
}
D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = {};
if (textures[i].cubemap())
{
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
shared_resource_view_desc.TextureCube.MipLevels = textures[i].mipmap();
}
else
{
shared_resource_view_desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
shared_resource_view_desc.Texture2D.MipLevels = textures[i].mipmap();
}
D3D12_SHADER_RESOURCE_VIEW_DESC shared_resource_view_desc = get_srv_descriptor_with_dimensions(textures[i]);
shared_resource_view_desc.Format = get_texture_format(format);
switch (format)
@@ -327,9 +352,7 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
break;
}
m_device->CreateShaderResourceView(vram_texture, &shared_resource_view_desc,
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().descriptors_heap->GetCPUDescriptorHandleForHeapStart())
.Offset((UINT)descriptor_index + (UINT)used_texture, g_descriptor_stride_srv_cbv_uav));
m_current_shader_resources[i] = std::make_tuple(vram_texture, shared_resource_view_desc);
if (get_current_resource_storage().current_sampler_index + 16 > 2048)
{
@@ -343,13 +366,7 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
};
command_list->SetDescriptorHeaps(2, descriptors);
}
m_device->CreateSampler(&get_sampler_desc(textures[i]),
CD3DX12_CPU_DESCRIPTOR_HANDLE(get_current_resource_storage().sampler_descriptor_heap[get_current_resource_storage().sampler_descriptors_heap_index]->GetCPUDescriptorHandleForHeapStart())
.Offset((UINT)get_current_resource_storage().current_sampler_index + (UINT)used_texture, g_descriptor_stride_samplers));
used_texture++;
m_current_samplers[i] = get_sampler_desc(textures[i]);
}
}
#endif
+20 -47
View File
@@ -28,12 +28,7 @@ std::pair<ID3DBlob *, ID3DBlob *> compileF32toU8CS()
ID3DBlob *bytecode;
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
HRESULT hr = wrapD3DCompile(shaderCode, strlen(shaderCode), "test", nullptr, nullptr, "main", "cs_5_0", 0, 0, &bytecode, errorBlob.GetAddressOf());
if (hr != S_OK)
{
const char *tmp = (const char*)errorBlob->GetBufferPointer();
LOG_ERROR(RSX, tmp);
}
CHECK_HRESULT(wrapD3DCompile(shaderCode, strlen(shaderCode), "test", nullptr, nullptr, "main", "cs_5_0", 0, 0, &bytecode, errorBlob.GetAddressOf()));
CD3DX12_DESCRIPTOR_RANGE descriptorRange[] =
{
// Textures
@@ -47,18 +42,12 @@ std::pair<ID3DBlob *, ID3DBlob *> compileF32toU8CS()
ID3DBlob *rootSignatureBlob;
hr = wrapD3D12SerializeRootSignature(&CD3DX12_ROOT_SIGNATURE_DESC(1, &RP), D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob);
if (hr != S_OK)
{
const char *tmp = (const char*)errorBlob->GetBufferPointer();
LOG_ERROR(RSX, tmp);
}
CHECK_HRESULT(wrapD3D12SerializeRootSignature(&CD3DX12_ROOT_SIGNATURE_DESC(1, &RP), D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob));
return std::make_pair(bytecode, rootSignatureBlob);
}
void D3D12GSRender::Shader::Init(ID3D12Device *device, ID3D12CommandQueue *gfxcommandqueue)
void D3D12GSRender::shader::init(ID3D12Device *device, ID3D12CommandQueue *gfx_command_queue)
{
const char *fsCode = STRINGIFY(
Texture2D InputTexture : register(t0); \n
@@ -78,12 +67,7 @@ void D3D12GSRender::Shader::Init(ID3D12Device *device, ID3D12CommandQueue *gfxco
Microsoft::WRL::ComPtr<ID3DBlob> fsBytecode;
Microsoft::WRL::ComPtr<ID3DBlob> errorBlob;
HRESULT hr = wrapD3DCompile(fsCode, strlen(fsCode), "test", nullptr, nullptr, "main", "ps_5_0", 0, 0, &fsBytecode, errorBlob.GetAddressOf());
if (hr != S_OK)
{
const char *tmp = (const char*)errorBlob->GetBufferPointer();
LOG_ERROR(RSX, tmp);
}
CHECK_HRESULT(wrapD3DCompile(fsCode, strlen(fsCode), "test", nullptr, nullptr, "main", "ps_5_0", 0, 0, &fsBytecode, errorBlob.GetAddressOf()));
const char *vsCode = STRINGIFY(
struct VertexInput \n
@@ -108,12 +92,7 @@ void D3D12GSRender::Shader::Init(ID3D12Device *device, ID3D12CommandQueue *gfxco
);
Microsoft::WRL::ComPtr<ID3DBlob> vsBytecode;
hr = wrapD3DCompile(vsCode, strlen(vsCode), "test", nullptr, nullptr, "main", "vs_5_0", 0, 0, &vsBytecode, errorBlob.GetAddressOf());
if (hr != S_OK)
{
const char *tmp = (const char*)errorBlob->GetBufferPointer();
LOG_ERROR(RSX, tmp);
}
CHECK_HRESULT(wrapD3DCompile(vsCode, strlen(vsCode), "test", nullptr, nullptr, "main", "vs_5_0", 0, 0, &vsBytecode, errorBlob.GetAddressOf()));
D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {};
psoDesc.PS.BytecodeLength = fsBytecode->GetBufferSize();
@@ -163,28 +142,22 @@ void D3D12GSRender::Shader::Init(ID3D12Device *device, ID3D12CommandQueue *gfxco
Microsoft::WRL::ComPtr<ID3DBlob> rootSignatureBlob;
hr = wrapD3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob);
if (hr != S_OK)
{
const char *tmp = (const char*)errorBlob->GetBufferPointer();
LOG_ERROR(RSX, tmp);
}
CHECK_HRESULT(wrapD3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob));
CHECK_HRESULT(device->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&root_signature)));
hr = device->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature));
psoDesc.pRootSignature = m_rootSignature;
psoDesc.pRootSignature = root_signature;
psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL;
CHECK_HRESULT(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_PSO)));
CHECK_HRESULT(device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&pso)));
D3D12_DESCRIPTOR_HEAP_DESC textureHeapDesc = { D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV , 2, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE };
CHECK_HRESULT(
device->CreateDescriptorHeap(&textureHeapDesc, IID_PPV_ARGS(&m_textureDescriptorHeap))
device->CreateDescriptorHeap(&textureHeapDesc, IID_PPV_ARGS(&texture_descriptor_heap))
);
D3D12_DESCRIPTOR_HEAP_DESC samplerHeapDesc = { D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER , 2, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE };
CHECK_HRESULT(
device->CreateDescriptorHeap(&samplerHeapDesc, IID_PPV_ARGS(&m_samplerDescriptorHeap))
device->CreateDescriptorHeap(&samplerHeapDesc, IID_PPV_ARGS(&sampler_descriptor_heap))
);
ComPtr<ID3D12Fence> fence;
@@ -224,37 +197,37 @@ void D3D12GSRender::Shader::Init(ID3D12Device *device, ID3D12CommandQueue *gfxco
&CD3DX12_RESOURCE_DESC::Buffer(16 * sizeof(float)),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr,
IID_PPV_ARGS(&m_vertexBuffer)
IID_PPV_ARGS(&vertex_buffer)
));
D3D12_SUBRESOURCE_DATA vertexData = { reinterpret_cast<BYTE*>(quadVertex), 16 * sizeof(float), 1 };
UpdateSubresources(cmdList.Get(), m_vertexBuffer, intermediateBuffer.Get(), 0, 0, 1, &vertexData);
cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(m_vertexBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER));
UpdateSubresources(cmdList.Get(), vertex_buffer, intermediateBuffer.Get(), 0, 0, 1, &vertexData);
cmdList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(vertex_buffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER));
CHECK_HRESULT(cmdList->Close());
gfxcommandqueue->ExecuteCommandLists(1, CommandListCast(cmdList.GetAddressOf()));
gfx_command_queue->ExecuteCommandLists(1, CommandListCast(cmdList.GetAddressOf()));
// Now wait until upload has completed
gfxcommandqueue->Signal(fence.Get(), 1);
gfx_command_queue->Signal(fence.Get(), 1);
WaitForSingleObjectEx(handle, INFINITE, FALSE);
CloseHandle(handle);
}
void D3D12GSRender::initConvertShader()
void D3D12GSRender::init_convert_shader()
{
const auto &p = compileF32toU8CS();
CHECK_HRESULT(
m_device->CreateRootSignature(0, p.second->GetBufferPointer(), p.second->GetBufferSize(), IID_PPV_ARGS(&m_convertRootSignature))
m_device->CreateRootSignature(0, p.second->GetBufferPointer(), p.second->GetBufferSize(), IID_PPV_ARGS(&m_convert_root_signature))
);
D3D12_COMPUTE_PIPELINE_STATE_DESC computePipelineStateDesc = {};
computePipelineStateDesc.CS.BytecodeLength = p.first->GetBufferSize();
computePipelineStateDesc.CS.pShaderBytecode = p.first->GetBufferPointer();
computePipelineStateDesc.pRootSignature = m_convertRootSignature;
computePipelineStateDesc.pRootSignature = m_convert_root_signature;
CHECK_HRESULT(
m_device->CreateComputePipelineState(&computePipelineStateDesc, IID_PPV_ARGS(&m_convertPSO))
m_device->CreateComputePipelineState(&computePipelineStateDesc, IID_PPV_ARGS(&m_convert_pso))
);
p.first->Release();
@@ -33,39 +33,43 @@ void D3D12VertexProgramDecompiler::insertHeader(std::stringstream &OS)
OS << " float4x4 scaleOffsetMat;" << std::endl;
OS << " int isAlphaTested;" << std::endl;
OS << " float alphaRef;" << std::endl;
OS << " int tex0_is_unorm;" << std::endl;
OS << " int tex1_is_unorm;" << std::endl;
OS << " int tex2_is_unorm;" << std::endl;
OS << " int tex3_is_unorm;" << std::endl;
OS << " int tex4_is_unorm;" << std::endl;
OS << " int tex5_is_unorm;" << std::endl;
OS << " int tex6_is_unorm;" << std::endl;
OS << " int tex7_is_unorm;" << std::endl;
OS << " int tex8_is_unorm;" << std::endl;
OS << " int tex9_is_unorm;" << std::endl;
OS << " int tex10_is_unorm;" << std::endl;
OS << " int tex11_is_unorm;" << std::endl;
OS << " int tex12_is_unorm;" << std::endl;
OS << " int tex13_is_unorm;" << std::endl;
OS << " int tex14_is_unorm;" << std::endl;
OS << " int tex15_is_unorm;" << std::endl;
OS << "};" << std::endl;
}
namespace
{
bool declare_input(std::stringstream & OS, const std::tuple<size_t, std::string> &attribute, const std::vector<rsx_vertex_input> &inputs, size_t reg)
{
for (const auto &real_input : inputs)
{
if (static_cast<size_t>(real_input.location) != std::get<0>(attribute))
continue;
OS << "Buffer<float4> " << std::get<1>(attribute) << "_buffer : register(t" << reg++ << ");\n";
return true;
}
return false;
}
}
void D3D12VertexProgramDecompiler::insertInputs(std::stringstream & OS, const std::vector<ParamType>& inputs)
{
OS << "struct VertexInput" << std::endl;
OS << "{" << std::endl;
std::vector<std::tuple<size_t, std::string>> input_data;
for (const ParamType PT : inputs)
{
for (const ParamItem &PI : PT.items)
{
OS << " " << PT.type << " " << PI.name << ": TEXCOORD" << PI.location << ";" << std::endl;
input_slots.push_back(PI.location);
input_data.push_back(std::make_tuple(PI.location, PI.name));
}
}
OS << "};" << std::endl;
std::sort(input_data.begin(), input_data.end());
size_t t_register = 0;
for (const auto &attribute : input_data)
{
if (declare_input(OS, attribute, rsx_vertex_program.rsx_vertex_inputs, t_register))
t_register++;
}
}
void D3D12VertexProgramDecompiler::insertConstants(std::stringstream & OS, const std::vector<ParamType> & constants)
@@ -140,9 +144,41 @@ static const reg_info reg_table[] =
{ "tc8", true, "dst_reg15", "", false },
};
namespace
{
void add_input(std::stringstream & OS, const ParamItem &PI, const std::vector<rsx_vertex_input> &inputs)
{
for (const auto &real_input : inputs)
{
if (real_input.location != PI.location)
continue;
if (!real_input.is_array)
{
OS << " float4 " << PI.name << " = " << PI.name << "_buffer[0];\n";
return;
}
if (real_input.frequency > 1)
{
if (real_input.is_modulo)
{
OS << " float4 " << PI.name << " = " << PI.name << "_buffer[vertex_id % " << real_input.frequency << "];\n";
return;
}
OS << " float4 " << PI.name << " = " << PI.name << "_buffer[vertex_id / " << real_input.frequency << "];\n";
return;
}
OS << " float4 " << PI.name << " = " << PI.name << "_buffer[vertex_id];\n";
return;
}
OS << " float4 " << PI.name << " = float4(0., 0., 0., 1.);\n";
}
}
void D3D12VertexProgramDecompiler::insertMainStart(std::stringstream & OS)
{
OS << "PixelInput main(VertexInput In)" << std::endl;
insert_d3d12_legacy_function(OS);
OS << "PixelInput main(uint vertex_id : SV_VertexID)" << std::endl;
OS << "{" << std::endl;
// Declare inside main function
@@ -162,7 +198,9 @@ void D3D12VertexProgramDecompiler::insertMainStart(std::stringstream & OS)
for (const ParamType PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem &PI : PT.items)
OS << " " << PT.type << " " << PI.name << " = In." << PI.name << ";" << std::endl;
{
add_input(OS, PI, rsx_vertex_program.rsx_vertex_inputs);
}
}
}
@@ -181,8 +219,8 @@ void D3D12VertexProgramDecompiler::insertMainEnd(std::stringstream & OS)
OS << "}" << std::endl;
}
D3D12VertexProgramDecompiler::D3D12VertexProgramDecompiler(std::vector<u32>& data) :
VertexProgramDecompiler(data)
D3D12VertexProgramDecompiler::D3D12VertexProgramDecompiler(const RSXVertexProgram &prog) :
VertexProgramDecompiler(prog), rsx_vertex_program(prog)
{
}
#endif
@@ -18,7 +18,8 @@ protected:
virtual void insertOutputs(std::stringstream &OS, const std::vector<ParamType> &outputs);
virtual void insertMainStart(std::stringstream &OS);
virtual void insertMainEnd(std::stringstream &OS);
const RSXVertexProgram &rsx_vertex_program;
public:
std::vector<size_t> input_slots;
D3D12VertexProgramDecompiler(std::vector<u32>& data);
D3D12VertexProgramDecompiler(const RSXVertexProgram &prog);
};
+271 -50
View File
@@ -719,6 +719,156 @@ namespace
};
}
rsx::vertex_base_type rsx::to_vertex_base_type(u8 in)
{
switch (in)
{
case 1: return rsx::vertex_base_type::s1;
case 2: return rsx::vertex_base_type::f;
case 3: return rsx::vertex_base_type::sf;
case 4: return rsx::vertex_base_type::ub;
case 5: return rsx::vertex_base_type::s32k;
case 6: return rsx::vertex_base_type::cmp;
case 7: return rsx::vertex_base_type::ub256;
}
throw new EXCEPTION("Unknow vertex base type %d", in);
}
rsx::index_array_type rsx::to_index_array_type(u8 in)
{
switch (in)
{
case 0: return rsx::index_array_type::u32;
case 1: return rsx::index_array_type::u16;
}
throw new EXCEPTION("Unknown index array type %d", in);
}
rsx::primitive_type rsx::to_primitive_type(u8 in)
{
switch (in)
{
case 1: return rsx::primitive_type::points;
case 2: return rsx::primitive_type::lines;
case 3: return rsx::primitive_type::line_loop;
case 4: return rsx::primitive_type::line_strip;
case 5: return rsx::primitive_type::triangles;
case 6: return rsx::primitive_type::triangle_strip;
case 7: return rsx::primitive_type::triangle_fan;
case 8: return rsx::primitive_type::quads;
case 9: return rsx::primitive_type::quad_strip;
case 10: return rsx::primitive_type::polygon;
}
throw new EXCEPTION("Unknow primitive type %d", in);
}
enum
{
CELL_GCM_WINDOW_ORIGIN_TOP = 0,
CELL_GCM_WINDOW_ORIGIN_BOTTOM = 1,
CELL_GCM_WINDOW_PIXEL_CENTER_HALF = 0,
CELL_GCM_WINDOW_PIXEL_CENTER_INTEGER = 1,
};
rsx::window_origin rsx::to_window_origin(u8 in)
{
switch (in)
{
case CELL_GCM_WINDOW_ORIGIN_TOP: return rsx::window_origin::top;
case CELL_GCM_WINDOW_ORIGIN_BOTTOM: return rsx::window_origin::bottom;
}
throw EXCEPTION("Unknow window origin modifier %x", in);
}
rsx::window_pixel_center rsx::to_window_pixel_center(u8 in)
{
switch (in)
{
case CELL_GCM_WINDOW_PIXEL_CENTER_HALF: return rsx::window_pixel_center::half;
case CELL_GCM_WINDOW_PIXEL_CENTER_INTEGER: return rsx::window_pixel_center::integer;
}
throw EXCEPTION("Unknow window pixel center %x", in);
}
rsx::comparaison_function rsx::to_comparaison_function(u16 in)
{
switch (in)
{
case CELL_GCM_NEVER: return rsx::comparaison_function::never;
case CELL_GCM_LESS: return rsx::comparaison_function::less;
case CELL_GCM_EQUAL: return rsx::comparaison_function::equal;
case CELL_GCM_LEQUAL: return rsx::comparaison_function::less_or_equal;
case CELL_GCM_GREATER: return rsx::comparaison_function::greater;
case CELL_GCM_NOTEQUAL: return rsx::comparaison_function::not_equal;
case CELL_GCM_GEQUAL: return rsx::comparaison_function::greater_or_equal;
case CELL_GCM_ALWAYS: return rsx::comparaison_function::always;
}
throw EXCEPTION("Wrong comparaison function %x", in);
}
enum
{
// Surface Target
CELL_GCM_SURFACE_TARGET_NONE = 0,
CELL_GCM_SURFACE_TARGET_0 = 1,
CELL_GCM_SURFACE_TARGET_1 = 2,
CELL_GCM_SURFACE_TARGET_MRT1 = 0x13,
CELL_GCM_SURFACE_TARGET_MRT2 = 0x17,
CELL_GCM_SURFACE_TARGET_MRT3 = 0x1f,
// Surface Depth
CELL_GCM_SURFACE_Z16 = 1,
CELL_GCM_SURFACE_Z24S8 = 2,
// Surface Antialias
CELL_GCM_SURFACE_CENTER_1 = 0,
CELL_GCM_SURFACE_DIAGONAL_CENTERED_2 = 3,
CELL_GCM_SURFACE_SQUARE_CENTERED_4 = 4,
CELL_GCM_SURFACE_SQUARE_ROTATED_4 = 5,
// Surface format
CELL_GCM_SURFACE_X1R5G5B5_Z1R5G5B5 = 1,
CELL_GCM_SURFACE_X1R5G5B5_O1R5G5B5 = 2,
CELL_GCM_SURFACE_R5G6B5 = 3,
CELL_GCM_SURFACE_X8R8G8B8_Z8R8G8B8 = 4,
CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8 = 5,
CELL_GCM_SURFACE_A8R8G8B8 = 8,
CELL_GCM_SURFACE_B8 = 9,
CELL_GCM_SURFACE_G8B8 = 10,
CELL_GCM_SURFACE_F_W16Z16Y16X16 = 11,
CELL_GCM_SURFACE_F_W32Z32Y32X32 = 12,
CELL_GCM_SURFACE_F_X32 = 13,
CELL_GCM_SURFACE_X8B8G8R8_Z8B8G8R8 = 14,
CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8 = 15,
CELL_GCM_SURFACE_A8B8G8R8 = 16,
};
rsx::surface_target rsx::to_surface_target(u8 in)
{
switch (in)
{
case CELL_GCM_SURFACE_TARGET_NONE: return rsx::surface_target::none;
case CELL_GCM_SURFACE_TARGET_0: return rsx::surface_target::surface_a;
case CELL_GCM_SURFACE_TARGET_1: return rsx::surface_target::surface_b;
case CELL_GCM_SURFACE_TARGET_MRT1: return rsx::surface_target::surfaces_a_b;
case CELL_GCM_SURFACE_TARGET_MRT2: return rsx::surface_target::surfaces_a_b_c;
case CELL_GCM_SURFACE_TARGET_MRT3: return rsx::surface_target::surfaces_a_b_c_d;
}
throw EXCEPTION("Unknow surface target %x", in);
}
rsx::surface_depth_format rsx::to_surface_depth_format(u8 in)
{
switch (in)
{
case CELL_GCM_SURFACE_Z16: return rsx::surface_depth_format::z16;
case CELL_GCM_SURFACE_Z24S8: return rsx::surface_depth_format::z24s8;
}
throw EXCEPTION("Unknow surface depth format %x", in);
}
std::string rsx::get_method_name(const u32 id)
{
auto found = methods.find(id);
@@ -730,6 +880,40 @@ std::string rsx::get_method_name(const u32 id)
return fmt::format("unknown/illegal method [0x%08x]", id);
}
rsx::surface_antialiasing rsx::to_surface_antialiasing(u8 in)
{
switch (in)
{
case CELL_GCM_SURFACE_CENTER_1: return rsx::surface_antialiasing::center_1_sample;
case CELL_GCM_SURFACE_DIAGONAL_CENTERED_2: return rsx::surface_antialiasing::diagonal_centered_2_samples;
case CELL_GCM_SURFACE_SQUARE_CENTERED_4: return rsx::surface_antialiasing::square_centered_4_samples;
case CELL_GCM_SURFACE_SQUARE_ROTATED_4: return rsx::surface_antialiasing::square_rotated_4_samples;
}
throw EXCEPTION("unknow surface antialiasing format %x", in);
}
rsx::surface_color_format rsx::to_surface_color_format(u8 in)
{
switch (in)
{
case CELL_GCM_SURFACE_X1R5G5B5_Z1R5G5B5: return rsx::surface_color_format::x1r5g5b5_z1r5g5b5;
case CELL_GCM_SURFACE_X1R5G5B5_O1R5G5B5: return rsx::surface_color_format::x1r5g5b5_o1r5g5b5;
case CELL_GCM_SURFACE_R5G6B5: return rsx::surface_color_format::r5g6b5;
case CELL_GCM_SURFACE_X8R8G8B8_Z8R8G8B8: return rsx::surface_color_format::x8r8g8b8_z8r8g8b8;
case CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8: return rsx::surface_color_format::x8r8g8b8_o8r8g8b8;
case CELL_GCM_SURFACE_A8R8G8B8: return rsx::surface_color_format::a8r8g8b8;
case CELL_GCM_SURFACE_B8: return rsx::surface_color_format::b8;
case CELL_GCM_SURFACE_G8B8: return rsx::surface_color_format::g8b8;
case CELL_GCM_SURFACE_F_W16Z16Y16X16: return rsx::surface_color_format::w16z16y16x16;
case CELL_GCM_SURFACE_F_W32Z32Y32X32: return rsx::surface_color_format::w32z32y32x32;
case CELL_GCM_SURFACE_F_X32: return rsx::surface_color_format::x32;
case CELL_GCM_SURFACE_X8B8G8R8_Z8B8G8R8: return rsx::surface_color_format::x8b8g8r8_z8b8g8r8;
case CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8: return rsx::surface_color_format::x8b8g8r8_o8b8g8r8;
case CELL_GCM_SURFACE_A8B8G8R8: return rsx::surface_color_format::a8b8g8r8;
}
throw EXCEPTION("unknow surface color format %x", in);
}
// Various parameter pretty printing function
namespace
{
@@ -813,18 +997,18 @@ namespace
std::string get_primitive_mode(u8 draw_mode)
{
switch (draw_mode)
switch (rsx::to_primitive_type(draw_mode))
{
case CELL_GCM_PRIMITIVE_POINTS: return "Points";
case CELL_GCM_PRIMITIVE_LINES: return "Lines";
case CELL_GCM_PRIMITIVE_LINE_LOOP: return "Line_loop";
case CELL_GCM_PRIMITIVE_LINE_STRIP: return "Line_strip";
case CELL_GCM_PRIMITIVE_TRIANGLES: return "Triangles";
case CELL_GCM_PRIMITIVE_TRIANGLE_STRIP: return "Triangle_strip";
case CELL_GCM_PRIMITIVE_TRIANGLE_FAN: return "Triangle_fan";
case CELL_GCM_PRIMITIVE_QUADS: return "Quads";
case CELL_GCM_PRIMITIVE_QUAD_STRIP: return "Quad_strip";
case CELL_GCM_PRIMITIVE_POLYGON: return "Polygon";
case rsx::primitive_type::points: return "Points";
case rsx::primitive_type::lines: return "Lines";
case rsx::primitive_type::line_loop: return "Line_loop";
case rsx::primitive_type::line_strip: return "Line_strip";
case rsx::primitive_type::triangles: return "Triangles";
case rsx::primitive_type::triangle_strip: return "Triangle_strip";
case rsx::primitive_type::triangle_fan: return "Triangle_fan";
case rsx::primitive_type::quads: return "Quads";
case rsx::primitive_type::quad_strip: return "Quad_strip";
case rsx::primitive_type::polygon: return "Polygon";
}
return "Error";
}
@@ -849,46 +1033,58 @@ namespace
std::string depth_stencil_surface_format(u32 format)
{
switch (format)
switch (rsx::to_surface_depth_format(format))
{
case CELL_GCM_SURFACE_Z16: return "CELL_GCM_SURFACE_Z16";
case CELL_GCM_SURFACE_Z24S8: return "CELL_GCM_SURFACE_Z24S8";
case rsx::surface_depth_format::z16: return "CELL_GCM_SURFACE_Z16";
case rsx::surface_depth_format::z24s8: return "CELL_GCM_SURFACE_Z24S8";
}
return "Error";
}
std::string color_surface_format(u32 format)
std::string surface_antialiasing(u8 format)
{
switch (format)
switch (rsx::to_surface_antialiasing(format))
{
case CELL_GCM_SURFACE_X1R5G5B5_Z1R5G5B5: return "CELL_GCM_SURFACE_X1R5G5B5_Z1R5G5B5";
case CELL_GCM_SURFACE_X1R5G5B5_O1R5G5B5: return "CELL_GCM_SURFACE_X1R5G5B5_O1R5G5B5";
case CELL_GCM_SURFACE_R5G6B5: return "CELL_GCM_SURFACE_R5G6B5";
case CELL_GCM_SURFACE_X8R8G8B8_Z8R8G8B8: return "CELL_GCM_SURFACE_X8R8G8B8_Z8R8G8B8";
case CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8: return "CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8";
case CELL_GCM_SURFACE_A8R8G8B8: return "CELL_GCM_SURFACE_A8R8G8B8";
case CELL_GCM_SURFACE_B8: return "CELL_GCM_SURFACE_B8";
case CELL_GCM_SURFACE_G8B8: return "CELL_GCM_SURFACE_G8B8";
case CELL_GCM_SURFACE_F_W16Z16Y16X16: return "CELL_GCM_SURFACE_F_W16Z16Y16X16";
case CELL_GCM_SURFACE_F_W32Z32Y32X32: return "CELL_GCM_SURFACE_F_W32Z32Y32X32";
case CELL_GCM_SURFACE_F_X32: return "CELL_GCM_SURFACE_F_X32";
case CELL_GCM_SURFACE_X8B8G8R8_Z8B8G8R8: return "CELL_GCM_SURFACE_X8B8G8R8_Z8B8G8R8";
case CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8: return "CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8";
case CELL_GCM_SURFACE_A8B8G8R8: return "CELL_GCM_SURFACE_A8B8G8R8";
case rsx::surface_antialiasing::center_1_sample: return "1 sample centered";
case rsx::surface_antialiasing::diagonal_centered_2_samples: return "2 samples diagonal centered";
case rsx::surface_antialiasing::square_centered_4_samples: return "4 samples square centered";
case rsx::surface_antialiasing::square_rotated_4_samples: return "4 samples diagonal rotated";
}
return "Error";
}
std::string surface_color_format(u32 format)
{
switch (rsx::to_surface_color_format(format))
{
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5: return "CELL_GCM_SURFACE_X1R5G5B5_Z1R5G5B5";
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5: return "CELL_GCM_SURFACE_X1R5G5B5_O1R5G5B5";
case rsx::surface_color_format::r5g6b5 : return "CELL_GCM_SURFACE_R5G6B5";
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8: return "CELL_GCM_SURFACE_X8R8G8B8_Z8R8G8B8";
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8: return "CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8";
case rsx::surface_color_format::a8r8g8b8: return "CELL_GCM_SURFACE_A8R8G8B8";
case rsx::surface_color_format::b8: return "CELL_GCM_SURFACE_B8";
case rsx::surface_color_format::g8b8: return "CELL_GCM_SURFACE_G8B8";
case rsx::surface_color_format::w16z16y16x16: return "CELL_GCM_SURFACE_F_W16Z16Y16X16";
case rsx::surface_color_format::w32z32y32x32: return "CELL_GCM_SURFACE_F_W32Z32Y32X32";
case rsx::surface_color_format::x32: return "CELL_GCM_SURFACE_F_X32";
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8: return "CELL_GCM_SURFACE_X8B8G8R8_Z8B8G8R8";
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8: return "CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8";
case rsx::surface_color_format::a8b8g8r8: return "CELL_GCM_SURFACE_A8B8G8R8";
}
return "Error";
}
std::string surface_target(u32 target)
{
switch (target)
switch (rsx::to_surface_target(target))
{
case CELL_GCM_SURFACE_TARGET_NONE: return "none";
case CELL_GCM_SURFACE_TARGET_0: return "surface A";
case CELL_GCM_SURFACE_TARGET_1: return "surface B";
case CELL_GCM_SURFACE_TARGET_MRT1: return "surfaces A and B";
case CELL_GCM_SURFACE_TARGET_MRT2: return "surfaces A, B and C";
case CELL_GCM_SURFACE_TARGET_MRT3: return "surfaces A,B, C and D";
case rsx::surface_target::none: return "none";
case rsx::surface_target::surface_a: return "surface A";
case rsx::surface_target::surface_b: return "surface B";
case rsx::surface_target::surfaces_a_b: return "surfaces A and B";
case rsx::surface_target::surfaces_a_b_c: return "surfaces A, B and C";
case rsx::surface_target::surfaces_a_b_c_d: return "surfaces A,B, C and D";
}
return "Error";
}
@@ -926,17 +1122,16 @@ namespace
std::string get_vertex_attribute_format(u8 type)
{
switch (type)
switch (rsx::to_vertex_base_type(type))
{
case CELL_GCM_VERTEX_S1: return "Short";
case CELL_GCM_VERTEX_F: return "Float";
case CELL_GCM_VERTEX_SF: return "Half float";
case CELL_GCM_VERTEX_UB: return "Unsigned byte";
case CELL_GCM_VERTEX_S32K: return "Signed int";
case CELL_GCM_VERTEX_CMP: return "CMP";
case CELL_GCM_VERTEX_UB256: return "UB256";
case rsx::vertex_base_type::s1: return "Short";
case rsx::vertex_base_type::f: return "Float";
case rsx::vertex_base_type::sf: return "Half float";
case rsx::vertex_base_type::ub: return "Unsigned byte";
case rsx::vertex_base_type::s32k: return "Signed int";
case rsx::vertex_base_type::cmp: return "CMP";
case rsx::vertex_base_type::ub256: return "UB256";
}
return "Error";
}
std::string unpack_vertex_format(u32 arg)
@@ -953,10 +1148,10 @@ namespace
std::string index_type(u16 arg)
{
switch (arg)
switch (rsx::to_index_array_type(arg))
{
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_16: return "unsigned short";
case CELL_GCM_DRAW_INDEX_ARRAY_TYPE_32: return "unsigned int";
case rsx::index_array_type::u16: return "unsigned short";
case rsx::index_array_type::u32: return "unsigned int";
}
return "Error";
}
@@ -1227,6 +1422,31 @@ namespace
return result;
}
std::string origin_mode(u32 origin)
{
switch (rsx::to_window_origin(origin))
{
case rsx::window_origin::bottom: return "bottom";
case rsx::window_origin::top: return "top";
}
throw EXCEPTION("Wrong origin mode");
}
std::string pixel_center_mode(u32 in)
{
switch (rsx::to_window_pixel_center(in))
{
case rsx::window_pixel_center::half: return "half";
case rsx::window_pixel_center::integer: return "integer";
}
throw EXCEPTION("Wrong origin mode");
}
std::string shader_window(u32 arg)
{
return "Viewport: height = " + std::to_string(arg & 0xFFF) + " origin = " + origin_mode((arg >> 12) & 0xF) + " pixel center = " + pixel_center_mode((arg >> 16) & 0xF);
}
#define OPCODE_RANGE_1(opcode, increment, index, printing_function) \
{ (opcode) + (index) * (increment), [](u32 arg) -> std::string { return (printing_function)((index), arg); } },
@@ -1292,7 +1512,7 @@ namespace
{ NV4097_SET_SURFACE_PITCH_Z, [](u32 arg) -> std::string { return "Surface Zeta: Pitch = " + std::to_string(arg); } },
{ NV4097_SET_SURFACE_ZETA_OFFSET, [](u32 arg) -> std::string { return "Surface Zeta: Offset = " + ptr_to_string(arg); } },
{ NV4097_SET_CONTEXT_DMA_ZETA, [](u32 arg) -> std::string { return "Surface Zeta: DMA mode = " + dma_mode(arg);} },
{ NV4097_SET_SURFACE_FORMAT, [](u32 arg) -> std::string { return "Surface: Color format = " + color_surface_format(arg & 0x1F) + " DepthStencil format = " + depth_stencil_surface_format((arg >> 5) & 0x7) + " Anti aliasing =" + std::to_string((arg >> 12) & 0x7); } },
{ NV4097_SET_SURFACE_FORMAT, [](u32 arg) -> std::string { return "Surface: Color format = " + surface_color_format(arg & 0x1F) + " DepthStencil format = " + depth_stencil_surface_format((arg >> 5) & 0x7) + " Anti aliasing =" + surface_antialiasing((arg >> 12) & 0x7); } },
{ NV4097_SET_SURFACE_CLIP_HORIZONTAL, [](u32 arg) -> std::string { return "Surface: clip x = " + std::to_string(arg & 0xFFFF) + " width = " + std::to_string(arg >> 16); } },
{ NV4097_SET_SURFACE_CLIP_VERTICAL, [](u32 arg) -> std::string { return "Surface: clip y = " + std::to_string(arg & 0xFFFF) + " height = " + std::to_string(arg >> 16); } },
{ NV4097_SET_SURFACE_COLOR_TARGET, [](u32 arg) -> std::string { return "Surface: Targets " + surface_target(arg); } },
@@ -1325,6 +1545,7 @@ namespace
{ NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK, vertex_output_mask },
{ NV4097_SET_SHADER_CONTROL, shader_control },
{ NV4097_SET_ANTI_ALIASING_CONTROL, anti_aliasing_control },
{ NV4097_SET_SHADER_WINDOW, shader_window },
{ NV4097_SET_VERTEX_DATA_ARRAY_FORMAT, [](u32 arg) -> std::string { return "Vertex array 0: " + unpack_vertex_format(arg); } },
{ NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 1, [](u32 arg) -> std::string { return "Vertex array 1: " + unpack_vertex_format(arg); } },
{ NV4097_SET_VERTEX_DATA_ARRAY_FORMAT + 2, [](u32 arg) -> std::string { return "Vertex array 2: " + unpack_vertex_format(arg); } },

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