Compare commits

...

81 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
Anthony J. Bentley aa4fb80465 By definition, malloc() is available in stdlib.h. malloc.h is deprecated. 2015-12-20 03:20:48 -07:00
99 changed files with 4738 additions and 3010 deletions
+3
View File
@@ -22,3 +22,6 @@
[submodule "GSL"]
path = GSL
url = https://github.com/Microsoft/GSL.git
[submodule "libpng"]
path = libpng
url = https://github.com/RPCS3/libpng
+6 -3
View File
@@ -33,8 +33,10 @@ 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++-5" CC="gcc-5" CXXFLAGS="-Wno-format-security";
@@ -51,7 +53,7 @@ before_install:
fi;
before_script:
- git submodule update --init asmjit ffmpeg rsx_program_decompiler GSL
- 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,7 +75,7 @@ addons:
- cmake
- libopenal-dev
- freeglut3-dev
- libglew-dev
# - libglew-dev apt version is too old
- libc6-dev
- llvm-3.6
- llvm-3.6-dev
@@ -83,6 +85,7 @@ addons:
- 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")
+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;
+10
View File
@@ -199,6 +199,16 @@ namespace fs
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;
}
};
// TODO
+9 -10
View File
@@ -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);
+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 GSL
- 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%
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;..\GSL\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;..\GSL\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>
+42
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}
@@ -197,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
@@ -693,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
@@ -730,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
+10 -6
View File
@@ -112,6 +112,7 @@ ${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"
@@ -140,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")
@@ -185,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()
+29 -2
View File
@@ -17,18 +17,45 @@ struct vfsStream
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;
}
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;
+1 -1
View File
@@ -335,7 +335,7 @@ public:
u32 ctrl = (vmfprog.outputFromH0 ? 0 : 0x40) | (vmfprog.depthReplace ? 0xe : 0);
std::vector<texture_dimension> td;
RSXFragmentProgram prog;
prog.size = 0, prog.addr = ptr + vmprog.ucode, prog.offset = 0, prog.ctrl = ctrl;
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();
}
+64 -67
View File
@@ -30,32 +30,29 @@ namespace
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);
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 = rsx::get_address(offset & 0x7fffffff, offset >> 31);
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_offset = rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET];
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 (vertex_array_desc.type)
{
case Vertex_base_type::ub:
case rsx::vertex_base_type::ub:
memcpy(dst, src, vertex_array_desc.size);
break;
case Vertex_base_type::s1:
case Vertex_base_type::sf:
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;
@@ -65,13 +62,13 @@ 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++ = 0x3800;
*c_dst++ = 0x3c00;
break;
}
case Vertex_base_type::f:
case Vertex_base_type::s32k:
case Vertex_base_type::ub256:
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;
@@ -82,7 +79,7 @@ void write_vertex_array_data_to_buffer(void *buffer, u32 first, u32 count, size_
}
break;
}
case Vertex_base_type::cmp:
case rsx::vertex_base_type::cmp:
{
auto* c_src = (const be_t<u32>*)src;
const auto& decoded_vector = decode_cmp_vector(*c_src);
@@ -244,21 +241,21 @@ std::tuple<T, T> expand_indexed_quads(gsl::span<to_be_t<const T>> src, gsl::span
}
// Only handle quads and triangle fan now
bool is_primitive_native(Primitive_type m_draw_mode)
bool is_primitive_native(rsx::primitive_type draw_mode)
{
switch (m_draw_mode)
switch (draw_mode)
{
case Primitive_type::points:
case Primitive_type::lines:
case Primitive_type::line_loop:
case Primitive_type::line_strip:
case Primitive_type::triangles:
case Primitive_type::triangle_strip:
case Primitive_type::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 Primitive_type::polygon:
case Primitive_type::triangle_fan:
case Primitive_type::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");
@@ -269,41 +266,41 @@ bool is_primitive_native(Primitive_type m_draw_mode)
* see http://www.gamedev.net/page/resources/_/technical/graphics-programming-and-theory/polygon-triangulation-r3334
*/
size_t get_index_count(Primitive_type 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 Primitive_type::polygon:
case Primitive_type::triangle_fan:
case rsx::primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
return (initial_index_count - 2) * 3;
case Primitive_type::quads:
case rsx::primitive_type::quads:
return (6 * initial_index_count) / 4;
default:
return 0;
}
}
size_t get_index_type_size(Index_array_type type)
size_t get_index_type_size(rsx::index_array_type type)
{
switch (type)
{
case Index_array_type::unsigned_16b: return 2;
case Index_array_type::unsigned_32b: return 4;
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, Primitive_type 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 Primitive_type::triangle_fan:
case Primitive_type::polygon:
case rsx::primitive_type::triangle_fan:
case rsx::primitive_type::polygon:
for (unsigned i = 0; i < (count - 2); i++)
{
typedDst[3 * i] = first;
@@ -311,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 Primitive_type::quads:
case rsx::primitive_type::quads:
for (unsigned i = 0; i < count / 4; i++)
{
// First triangle
@@ -324,13 +321,13 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
typedDst[6 * i + 5] = 4 * i + first;
}
return;
case Primitive_type::points:
case Primitive_type::lines:
case Primitive_type::line_loop:
case Primitive_type::line_strip:
case Primitive_type::triangles:
case Primitive_type::triangle_strip:
case Primitive_type::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:
throw new EXCEPTION("Native primitive type doesn't require expansion");
}
}
@@ -338,14 +335,14 @@ void write_index_array_for_non_indexed_non_native_primitive_to_buffer(char* dst,
// 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, Primitive_type m_draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
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);
Index_array_type type = to_index_array_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 = gsl::narrow<u32>(get_index_type_size(type));
Expects(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_OFFSET] == 0);
Expects(rsx::method_registers[NV4097_SET_VERTEX_DATA_BASE_INDEX] == 0);
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
@@ -362,40 +359,40 @@ std::tuple<T, T> write_index_array_data_to_buffer_impl(gsl::span<T, gsl::dynamic
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 (m_draw_mode)
switch (draw_mode)
{
case Primitive_type::points:
case Primitive_type::lines:
case Primitive_type::line_loop:
case Primitive_type::line_strip:
case Primitive_type::triangles:
case Primitive_type::triangle_strip:
case Primitive_type::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 upload_untouched<T>({ ptr, count }, dst, is_primitive_restart_enabled, primitive_restart_index);
case Primitive_type::polygon:
case Primitive_type::triangle_fan:
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 Primitive_type::quads:
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, Primitive_type m_draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments)
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, m_draw_mode, 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, Primitive_type m_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)
{
return write_index_array_data_to_buffer_impl(dst, m_draw_mode, 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);
Index_array_type type = to_index_array_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 = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
@@ -418,7 +415,7 @@ std::tuple<u32, u32> write_index_array_data_to_buffer_untouched(gsl::span<u32, g
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);
Index_array_type type = to_index_array_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 = gsl::narrow<u32>(get_index_type_size(type));
bool is_primitive_restart_enabled = !!rsx::method_registers[NV4097_SET_RESTART_INDEX_ENABLE];
+6 -6
View File
@@ -11,25 +11,25 @@ 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(Primitive_type 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(Primitive_type 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(Index_array_type type);
size_t get_index_type_size(rsx::index_array_type type);
/**
* Write count indexes using (first, first + count) ranges.
* Returns min/max index found during the process.
* The function expands index buffer for non native primitive type.
*/
std::tuple<u32, u32> write_index_array_data_to_buffer(gsl::span<u32, gsl::dynamic_range> dst, Primitive_type m_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, Primitive_type m_draw_mode, const std::vector<std::pair<u32, u32> > &first_count_arguments);
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
@@ -40,7 +40,7 @@ std::tuple<u16, u16> write_index_array_data_to_buffer_untouched(gsl::span<u16, g
/**
* 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, Primitive_type 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.
@@ -5,12 +5,11 @@
#include "FragmentProgramDecompiler.h"
FragmentProgramDecompiler::FragmentProgramDecompiler(const RSXFragmentProgram &prog, u32& size) :
m_addr(prog.addr),
m_prog(prog),
m_size(size),
m_const_index(0),
m_location(0),
m_ctrl(prog.ctrl),
m_texture_dimensions(prog.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 * SIZE_32(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,7 +355,7 @@ 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_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;
@@ -376,7 +391,7 @@ 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_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;
@@ -389,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;
@@ -425,35 +440,37 @@ 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;
@@ -461,18 +478,19 @@ bool FragmentProgramDecompiler::handle_tex_srb(u32 opcode)
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:
if (dst.tex_num >= m_texture_dimensions.size())
switch (m_prog.get_texture_dimension(dst.tex_num))
{
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD));
case texture_dimension::texture_dimension_1d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD));
return true;
}
switch (m_texture_dimensions[dst.tex_num])
{
case texture_dimension::texture_dimension_2d:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD));
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD));
return true;
case texture_dimension::texture_dimension_cubemap:
SetDst(getFunction(FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD));
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;
@@ -487,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.
*/
+22 -13
View File
@@ -3,14 +3,14 @@
using namespace program_hash_util;
size_t vertex_program_hash::operator()(const std::vector<u32> &program) const
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();
const qword *instbuffer = (const qword*)program.data.data();
size_t instIndex = 0;
bool end = false;
for (unsigned i = 0; i < program.size() / 4; i++)
for (unsigned i = 0; i < program.data.size() / 4; i++)
{
const qword inst = instbuffer[instIndex];
hash ^= inst.dword[0];
@@ -22,13 +22,17 @@ size_t vertex_program_hash::operator()(const std::vector<u32> &program) const
return hash;
}
bool vertex_program_compare::operator()(const std::vector<u32> &binary1, const std::vector<u32> &binary2) const
bool vertex_program_compare::operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const
{
if (binary1.size() != binary2.size()) return false;
const qword *instBuffer1 = (const qword*)binary1.data();
const qword *instBuffer2 = (const qword*)binary2.data();
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.size() / 4; i++)
for (unsigned i = 0; i < binary1.data.size() / 4; i++)
{
const qword& inst1 = instBuffer1[instIndex];
const qword& inst2 = instBuffer2[instIndex];
@@ -70,11 +74,11 @@ size_t fragment_program_utils::get_fragment_program_ucode_size(void *ptr)
}
}
size_t fragment_program_hash::operator()(const void *program) const
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;
const qword *instbuffer = (const qword*)program.addr;
size_t instIndex = 0;
while (true)
{
@@ -97,10 +101,15 @@ size_t fragment_program_hash::operator()(const void *program) const
return 0;
}
bool fragment_program_compare::operator()(const void *binary1, const void *binary2) const
bool fragment_program_compare::operator()(const RSXFragmentProgram& binary1, const RSXFragmentProgram& binary2) const
{
const qword *instBuffer1 = (const qword*)binary1;
const qword *instBuffer2 = (const qword*)binary2;
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)
{
+32 -19
View File
@@ -23,12 +23,12 @@ namespace program_hash_util
struct vertex_program_hash
{
size_t operator()(const std::vector<u32> &program) const;
size_t operator()(const RSXVertexProgram &program) const;
};
struct vertex_program_compare
{
bool operator()(const std::vector<u32> &binary1, const std::vector<u32> &binary2) const;
bool operator()(const RSXVertexProgram &binary1, const RSXVertexProgram &binary2) const;
};
struct fragment_program_utils
@@ -43,12 +43,12 @@ namespace program_hash_util
struct fragment_program_hash
{
size_t operator()(const void *program) const;
size_t operator()(const RSXFragmentProgram &program) const;
};
struct fragment_program_compare
{
bool operator()(const void *binary1, const void *binary2) const;
bool operator()(const RSXFragmentProgram &binary1, const RSXFragmentProgram &binary2) const;
};
}
@@ -75,8 +75,8 @@ class program_state_cache
using vertex_program_type = typename backend_traits::vertex_program_type;
using fragment_program_type = typename backend_traits::fragment_program_type;
using binary_to_vertex_program = std::unordered_map<std::vector<u32>, vertex_program_type, program_hash_util::vertex_program_hash, program_hash_util::vertex_program_compare> ;
using binary_to_fragment_program = std::unordered_map<void *, fragment_program_type, program_hash_util::fragment_program_hash, program_hash_util::fragment_program_compare>;
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 pipeline_key
@@ -115,13 +115,13 @@ private:
/// bool here to inform that the program was preexisting.
std::tuple<const vertex_program_type&, bool> search_vertex_program(const RSXVertexProgram& rsx_vp)
{
const auto& I = m_vertex_shader_cache.find(rsx_vp.data);
const auto& I = m_vertex_shader_cache.find(rsx_vp);
if (I != m_vertex_shader_cache.end())
{
return std::forward_as_tuple(I->second, true);
}
LOG_NOTICE(RSX, "VP not found in buffer!");
vertex_program_type& new_shader = m_vertex_shader_cache[rsx_vp.data];
vertex_program_type& new_shader = m_vertex_shader_cache[rsx_vp];
backend_traits::recompile_vertex_program(rsx_vp, new_shader, m_next_id++);
return std::forward_as_tuple(new_shader, false);
@@ -130,16 +130,18 @@ private:
/// bool here to inform that the program was preexisting.
std::tuple<const fragment_program_type&, bool> search_fragment_program(const RSXFragmentProgram& rsx_fp)
{
const auto& I = m_fragment_shader_cache.find(vm::base(rsx_fp.addr));
const auto& I = m_fragment_shader_cache.find(rsx_fp);
if (I != m_fragment_shader_cache.end())
{
return std::forward_as_tuple(I->second, true);
}
LOG_NOTICE(RSX, "FP not found in buffer!");
size_t fragment_program_size = program_hash_util::fragment_program_utils::get_fragment_program_ucode_size(vm::base(rsx_fp.addr));
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, vm::base(rsx_fp.addr), fragment_program_size);
fragment_program_type &new_shader = m_fragment_shader_cache[fragment_program_ucode_copy];
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 std::forward_as_tuple(new_shader, false);
@@ -147,19 +149,25 @@ private:
public:
program_state_cache() = default;
~program_state_cache() = default;
~program_state_cache()
{
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.data);
if (I == m_vertex_shader_cache.end())
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 fragment_program_type& get_shader_program(const RSXFragmentProgram& rsx_fp) const
{
auto I = m_fragment_shader_cache.find(vm::base(rsx_fp.addr));
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");
@@ -200,7 +208,7 @@ public:
size_t get_fragment_constants_buffer_size(const RSXFragmentProgram &fragmentShader) const
{
const auto I = m_fragment_shader_cache.find(vm::base(fragmentShader.addr));
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");
@@ -209,7 +217,7 @@ public:
void fill_fragment_constans_buffer(gsl::span<f32, gsl::dynamic_range> dst_buffer, const RSXFragmentProgram &fragment_program) const
{
const auto I = m_fragment_shader_cache.find(vm::base(fragment_program.addr));
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,
@@ -222,11 +230,16 @@ public:
size_t offset = 0;
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*)dst_buffer.subspan(offset, 4).data(), shuffled_vector);
offset += sizeof(f32);
}
}
void clear()
{
m_storage.clear();
}
};
+12 -6
View File
@@ -13,12 +13,18 @@ enum class FUNCTION {
FUNCTION_FRACT,
FUNCTION_DFDX,
FUNCTION_DFDY,
FUNCTION_TEXTURE_SAMPLE,
FUNCTION_TEXTURE_SAMPLE_PROJ,
FUNCTION_TEXTURE_SAMPLE_LOD,
FUNCTION_TEXTURE_CUBE_SAMPLE,
FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ,
FUNCTION_TEXTURE_CUBE_SAMPLE_LOD,
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;
};
/**
@@ -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;
+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;
}
};
}
+168 -138
View File
@@ -8,19 +8,75 @@
#include "D3D12Formats.h"
#include "../rsx_methods.h"
std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::upload_vertex_attributes(const std::vector<std::pair<u32, u32> > &vertex_ranges)
namespace
{
std::vector<D3D12_VERTEX_BUFFER_VIEW> vertex_buffer_views;
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);
}
m_IASet.clear();
size_t input_slot = 0;
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;
}
size_t vertex_count = 0;
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;
}
for (const auto &pair : vertex_ranges)
vertex_count += pair.second;
template<int N>
UINT64 get_next_multiple_of(UINT64 val)
{
UINT64 divided_val = (val + N - 1) / N;
return divided_val * N;
}
}
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)
{
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)
@@ -35,8 +91,7 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::upload_vertex_attributes(co
const rsx::data_array_format_info &info = vertex_arrays_info[index];
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
size_t buffer_size = element_size * vertex_count;
UINT buffer_size = element_size * vertex_count;
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
@@ -47,64 +102,104 @@ std::vector<D3D12_VERTEX_BUFFER_VIEW> D3D12GSRender::upload_vertex_attributes(co
}
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view =
{
m_buffer_data.get_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 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
size_t buffer_size = data.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);
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
memcpy(mapped_buffer, data.data(), data.size());
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view = {
m_buffer_data.get_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;
}
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)
{
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(256);
@@ -114,25 +209,10 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
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];
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));
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 + (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 + (18 + tex_idx++) * sizeof(int), &is_unorm, sizeof(int));
}
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + 256));
D3D12_CONSTANT_BUFFER_VIEW_DESC constant_buffer_view_desc = {
@@ -141,7 +221,7 @@ void D3D12GSRender::upload_and_bind_scale_offset_matrix(size_t descriptorIndex)
};
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)
@@ -160,13 +240,13 @@ void D3D12GSRender::upload_and_bind_vertex_shader_constants(size_t descriptor_in
};
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;
@@ -174,7 +254,7 @@ void D3D12GSRender::upload_and_bind_fragment_shader_constants(size_t descriptor_
size_t offset = 0;
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) }, fragment_program);
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 = {
@@ -183,51 +263,11 @@ void D3D12GSRender::upload_and_bind_fragment_shader_constants(size_t descriptor_
};
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_on_host(info.type, info.size);
}
// Copy inline buffer
size_t buffer_size = inline_vertex_array.size() * sizeof(int);
size_t heap_offset = m_buffer_data.alloc<D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
write_inline_array_to_buffer(mapped_buffer);
m_buffer_data.unmap(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
D3D12_VERTEX_BUFFER_VIEW vertex_buffer_view =
{
m_buffer_data.get_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)
{
@@ -258,55 +298,48 @@ 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(first_count_commands);
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 : first_count_commands)
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(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);
assert(draw_command == rsx::draw_command::indexed);
// Index count
size_t index_count = 0;
for (const auto &pair : first_count_commands)
index_count += pair.second;
index_count = get_index_count(draw_mode, gsl::narrow<int>(index_count));
size_t index_count = get_index_count(draw_mode, gsl::narrow<int>(get_vertex_count(first_count_commands)));
Index_array_type indexed_type = to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
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
@@ -316,13 +349,13 @@ std::tuple<bool, size_t> D3D12GSRender::upload_and_set_vertex_index_data(ID3D12G
void *mapped_buffer = m_buffer_data.map<void>(CD3DX12_RANGE(heap_offset, heap_offset + buffer_size));
u32 min_index, max_index;
if (indexed_type == Index_array_type::unsigned_16b)
if (indexed_type == rsx::index_array_type::u16)
{
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);
}
if (indexed_type == Index_array_type::unsigned_32b)
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);
@@ -334,13 +367,10 @@ std::tuple<bool, size_t> D3D12GSRender::upload_and_set_vertex_index_data(ID3D12G
(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 -9
View File
@@ -42,18 +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_SAMPLE_LOD:
return "$t.SampleLevel($tsampler, ($0.xy / $0.z) * $t_scale, $1)";
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_CUBE_SAMPLE_LOD:
return "$t.SampleLevel($tsampler, ($0.xyz / $0.w), $1)";
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:
@@ -81,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&);
+59 -52
View File
@@ -262,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(Primitive_type draw_mode)
D3D12_PRIMITIVE_TOPOLOGY get_primitive_topology(rsx::primitive_type draw_mode)
{
switch (draw_mode)
{
case Primitive_type::points: return D3D_PRIMITIVE_TOPOLOGY_POINTLIST;
case Primitive_type::lines: return D3D_PRIMITIVE_TOPOLOGY_LINELIST;
case Primitive_type::line_loop: return D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ;
case Primitive_type::line_strip: return D3D_PRIMITIVE_TOPOLOGY_LINESTRIP;
case Primitive_type::triangles: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case Primitive_type::triangle_strip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP;
case Primitive_type::triangle_fan: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case Primitive_type::quads: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case Primitive_type::quad_strip: return D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
case Primitive_type::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(Primitive_type draw_mode)
D3D12_PRIMITIVE_TOPOLOGY_TYPE get_primitive_topology_type(rsx::primitive_type draw_mode)
{
switch (draw_mode)
{
case Primitive_type::points: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_POINT;
case Primitive_type::lines: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case Primitive_type::line_strip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_LINE;
case Primitive_type::triangles: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case Primitive_type::triangle_strip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case Primitive_type::triangle_fan: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case Primitive_type::quads: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case Primitive_type::quad_strip: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case Primitive_type::polygon: return D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
case Primitive_type::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);
}
@@ -363,21 +370,21 @@ BOOL get_front_face_ccw(u32 ffv)
throw EXCEPTION("Invalid front face value (0x%x)", ffv);
}
DXGI_FORMAT get_index_type(Index_array_type index_type)
DXGI_FORMAT get_index_type(rsx::index_array_type index_type)
{
switch (index_type)
{
case Index_array_type::unsigned_16b: return DXGI_FORMAT_R16_UINT;
case Index_array_type::unsigned_32b: 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(Vertex_base_type type, u8 size)
DXGI_FORMAT get_vertex_attribute_format(rsx::vertex_base_type type, u8 size)
{
switch (type)
{
case Vertex_base_type::s1:
case rsx::vertex_base_type::s1:
{
switch (size)
{
@@ -388,7 +395,7 @@ DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size)
}
break;
}
case Vertex_base_type::f:
case rsx::vertex_base_type::f:
{
switch (size)
{
@@ -399,7 +406,7 @@ DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size)
}
break;
}
case Vertex_base_type::sf:
case rsx::vertex_base_type::sf:
{
switch (size)
{
@@ -410,7 +417,7 @@ DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size)
}
break;
}
case Vertex_base_type::ub:
case rsx::vertex_base_type::ub:
{
switch (size)
{
@@ -421,7 +428,7 @@ DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size)
}
break;
}
case Vertex_base_type::s32k:
case rsx::vertex_base_type::s32k:
{
switch (size)
{
@@ -432,7 +439,7 @@ DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size)
}
break;
}
case Vertex_base_type::cmp:
case rsx::vertex_base_type::cmp:
{
switch (size)
{
@@ -443,7 +450,7 @@ DXGI_FORMAT get_vertex_attribute_format(Vertex_base_type type, u8 size)
}
break;
}
case Vertex_base_type::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(Primitive_type 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(Primitive_type 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(Index_array_type 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(Vertex_base_type type, u8 size);
DXGI_FORMAT get_vertex_attribute_format(rsx::vertex_base_type type, u8 size);
/**
* Convert scissor register value to D3D12_RECT
@@ -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,57 +143,64 @@ void D3D12FragmentDecompiler::insertConstants(std::stringstream & OS)
void D3D12FragmentDecompiler::insertMainStart(std::stringstream & OS)
{
// "lib" function
// 0.00001 is used as "some non zero very little number"
OS << "float4 divsq_legacy(float4 num, float4 denum)\n";
OS << "{\n";
OS << " return num / sqrt(max(denum.xxxx, 0.00001));\n";
OS << "}\n";
OS << "float4 rcp_legacy(float4 denum)\n";
OS << "{\n";
OS << " return 1. / denum;\n";
OS << "}\n";
OS << "float4 rsq_legacy(float4 denum)\n";
OS << "{\n";
OS << " return 1. / sqrt(max(denum, 0.00001));\n";
OS << "}\n";
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;
}
}
}
@@ -200,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;
@@ -212,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[] =
{
@@ -222,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;
}
+151 -98
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;
@@ -89,12 +87,6 @@ D3D12DLLManagement::~D3D12DLLManagement()
D3D12GSRender::D3D12GSRender()
: GSRender(frame_type::DX12), m_d3d12_lib(), m_current_pso({})
{
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;
@@ -113,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 = {};
@@ -143,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());
@@ -177,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(
@@ -194,6 +196,17 @@ D3D12GSRender::D3D12GSRender()
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);
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();
}
@@ -204,13 +217,12 @@ D3D12GSRender::~D3D12GSRender()
m_texture_cache.unprotect_all();
gfxHandler = [this](u32) { return false; };
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();
}
@@ -246,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());
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().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;
@@ -334,8 +371,8 @@ void D3D12GSRender::end()
get_current_resource_storage().command_list->DrawInstanced((UINT)vertex_count, 1, 0, 0);
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())
{
@@ -348,20 +385,20 @@ void D3D12GSRender::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");
}
}
@@ -370,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);
@@ -451,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(
@@ -469,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;
@@ -477,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);
@@ -504,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());
@@ -549,20 +586,36 @@ void D3D12GSRender::flip(int buffer)
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()
+43 -46
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,49 +64,49 @@ 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<ComPtr<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();
@@ -115,28 +115,25 @@ private:
// 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.
std::array<u32, 4> m_previous_color_address = {};
u32 m_previous_address_z = 0;
u32 m_previous_target = 0;
u32 m_previous_clip_horizontal = 0;
u32 m_previous_clip_vertical = 0;
// 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();
@@ -150,16 +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);
/**
* 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);
@@ -172,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.
@@ -200,8 +196,9 @@ protected:
virtual void end() override;
virtual void flip(int buffer) 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 bool on_access_violation(u32 address, bool is_writing) 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;
};
+3 -3
View File
@@ -4,10 +4,10 @@
#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);
}
@@ -106,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 };
+20 -4
View File
@@ -47,6 +47,11 @@ class data_heap
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>
@@ -134,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);
}
};
@@ -163,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.
@@ -194,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;
+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,
+14 -43
View File
@@ -38,36 +38,8 @@ void Shader::Compile(const std::string &code, SHADER_TYPE st)
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 @@ void 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 @@ void 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,26 +223,25 @@ void 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])
{
Index_array_type index_type = to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
if (index_type == Index_array_type::unsigned_32b)
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 == Index_array_type::unsigned_16b)
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, m_device.Get(), m_root_signatures);
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
+9 -49
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)))
@@ -93,7 +75,7 @@ public:
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;
@@ -118,29 +100,11 @@ 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
{
using vertex_program_type = Shader;
using fragment_program_type = Shader;
using pipeline_storage_type = std::tuple<ComPtr<ID3D12PipelineState>, std::vector<size_t>, size_t>;
using pipeline_storage_type = std::tuple<ComPtr<ID3D12PipelineState>, size_t, size_t>;
using pipeline_properties = D3D12PipelineProperties;
static
@@ -155,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);
@@ -176,15 +140,15 @@ struct D3D12Traits
D3D12VertexProgramDecompiler VS(RSXVP);
std::string shaderCode = VS.Decompile();
vertexProgramData.Compile(shaderCode, Shader::SHADER_TYPE::SHADER_TYPE_VERTEX);
vertexProgramData.vertex_shader_inputs = VS.input_slots;
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
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> root_signatures)
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 = {};
D3D12_GRAPHICS_PIPELINE_STATE_DESC graphicPipelineStateDesc = {};
@@ -199,7 +163,7 @@ struct D3D12Traits
graphicPipelineStateDesc.PS.BytecodeLength = fragmentProgramData.bytecode->GetBufferSize();
graphicPipelineStateDesc.PS.pShaderBytecode = fragmentProgramData.bytecode->GetBufferPointer();
graphicPipelineStateDesc.pRootSignature = root_signatures[fragmentProgramData.m_textureCount].Get();
graphicPipelineStateDesc.pRootSignature = root_signatures[fragmentProgramData.m_textureCount][vertexProgramData.vertex_shader_input_count].Get();
graphicPipelineStateDesc.BlendState = pipelineProperties.Blend;
graphicPipelineStateDesc.DepthStencilState = pipelineProperties.DepthStencil;
@@ -211,10 +175,6 @@ 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;
@@ -226,7 +186,7 @@ struct D3D12Traits
std::wstring name = L"PSO_" + std::to_wstring(vertexProgramData.id) + L"_" + std::to_wstring(fragmentProgramData.id);
pso->SetName(name.c_str());
return std::make_tuple(pso, vertexProgramData.vertex_shader_inputs, fragmentProgramData.m_textureCount);
return std::make_tuple(pso, vertexProgramData.vertex_shader_input_count, fragmentProgramData.m_textureCount);
}
};
+111 -202
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,7 +126,7 @@ 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)
{
@@ -82,7 +135,7 @@ void D3D12GSRender::clear_surface(u32 arg)
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;
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]));
}
@@ -95,16 +148,16 @@ void D3D12GSRender::clear_surface(u32 arg)
if (arg & 0xF0)
{
CD3DX12_CPU_DESCRIPTOR_HANDLE handle = CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle);
size_t rtt_index = get_num_rtt(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]);
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())
{
@@ -118,58 +171,23 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
{
// check if something has changed
u32 surface_format = rsx::method_registers[NV4097_SET_SURFACE_FORMAT];
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
std::array<u32, 4> 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);
u32 clip_h_reg = rsx::method_registers[NV4097_SET_SURFACE_CLIP_HORIZONTAL];
u32 clip_v_reg = rsx::method_registers[NV4097_SET_SURFACE_CLIP_VERTICAL];
u32 target_reg = rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET];
// Exit early if there is no rtt changes
if (m_previous_color_address == address_color &&
m_previous_address_z == address_z &&
m_surface.format == surface_format &&
m_previous_clip_horizontal == clip_h_reg &&
m_previous_clip_vertical == clip_v_reg &&
m_previous_target == target_reg)
if (!m_rtts_dirty)
return;
m_rtts_dirty = false;
m_previous_color_address = address_color;
m_previous_address_z = address_z;
m_previous_target = target_reg;
m_previous_clip_horizontal = clip_h_reg;
m_previous_clip_vertical = clip_v_reg;
if (m_surface.format != surface_format)
m_surface.unpack(surface_format);
std::array<float, 4> clear_color = get_clear_color(rsx::method_registers[NV4097_SET_COLOR_CLEAR_VALUE]);
m_rtts.prepare_render_target(copycmdlist, surface_format, clip_h_reg, clip_v_reg, target_reg, address_color, address_z, m_device.Get(), clear_color, 1.f, 0);
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);
// write descriptors
DXGI_FORMAT dxgi_format = get_color_surface_format(m_surface.color_format);
@@ -178,14 +196,14 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
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 * g_descriptor_stride_rtv);
.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 (std::get<1>(m_rtts.m_bound_render_targets[i]) == nullptr)
continue;
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 * g_descriptor_stride_rtv));
CD3DX12_CPU_DESCRIPTOR_HANDLE(m_rtts.current_rtts_handle).Offset((INT)rtt_index * m_descriptor_stride_rtv));
rtt_index++;
}
get_current_resource_storage().render_targets_descriptors_heap_index += rtt_index;
@@ -193,7 +211,7 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
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 * g_descriptor_stride_rtv);
.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(m_surface.depth_format);
@@ -203,13 +221,12 @@ void D3D12GSRender::prepare_render_targets(ID3D12GraphicsCommandList *copycmdlis
void D3D12GSRender::set_rtt_and_ds(ID3D12GraphicsCommandList *command_list)
{
UINT num_rtt = get_num_rtt(rsx::method_registers[NV4097_SET_SURFACE_COLOR_TARGET]);
D3D12_CPU_DESCRIPTOR_HANDLE* rtt_handle = (num_rtt > 0) ? &m_rtts.current_rtts_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, rtt_handle, true, ds_handle);
command_list->OMSetRenderTargets((UINT)num_rtt, &m_rtts.current_rtts_handle, true, ds_handle);
}
void render_targets::init(ID3D12Device *device)
void rsx::render_targets::init(ID3D12Device *device)
{
g_descriptor_stride_rtv = device->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_RTV);
}
@@ -225,26 +242,14 @@ namespace
ID3D12GraphicsCommandList * command_list,
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;
size_t heap_offset = readback_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
@@ -283,6 +288,8 @@ namespace
}
}
void D3D12GSRender::copy_render_target_to_dma_location()
{
// Add all buffer write
@@ -355,13 +362,13 @@ void D3D12GSRender::copy_render_target_to_dma_location()
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(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);
@@ -384,7 +391,7 @@ 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;
@@ -423,25 +430,11 @@ void D3D12GSRender::copy_render_target_to_dma_location()
m_readback_resources.unmap();
}
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;
}
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]),
@@ -450,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;
@@ -460,105 +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, std::get<1>(m_rtts.m_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;
size_t heap_offset = m_readback_resources.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
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_COPY_SOURCE));
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.get_heap(), { heap_offset,{ DXGI_FORMAT_R32_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(std::get<1>(m_rtts.m_bound_depth_stencil), 0), nullptr);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_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 *mapped_buffer = m_readback_resources.map<void>(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.unmap();
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;
size_t heap_offset = m_readback_resources.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
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_COPY_SOURCE));
get_current_resource_storage().command_list->CopyTextureRegion(&CD3DX12_TEXTURE_COPY_LOCATION(m_readback_resources.get_heap(), { heap_offset, { DXGI_FORMAT_R8_TYPELESS, (UINT)clip_w, (UINT)clip_h, 1, (UINT)row_pitch } }), 0, 0, 0,
&CD3DX12_TEXTURE_COPY_LOCATION(std::get<1>(m_rtts.m_bound_depth_stencil), 1), nullptr);
get_current_resource_storage().command_list->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(std::get<1>(m_rtts.m_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 *mapped_buffer = m_readback_resources.map<void>(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.unmap();
}
#endif
+138 -169
View File
@@ -5,185 +5,26 @@
#include "d3dx12.h"
#include "D3D12Formats.h"
#include <gsl.h>
#include "D3D12MemoryHelpers.h"
#include "../Common/surface_store.h"
namespace rsx
{
namespace
{
std::vector<u8> get_rtt_indexes(u8 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 };
}
throw EXCEPTION("Wrong color_target (%d)", color_target);
}
}
template<typename Traits>
struct surface_store
{
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;
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,
u8 surface_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, surface_color_format, width, height))
{
Traits::prepare_rtt_for_drawing(command_list, rtt.Get());
return rtt.Get();
}
invalidated_resources.push_back(std::move(rtt));
m_render_targets_storage.erase(address);
}
m_render_targets_storage[address] = Traits::create_new_render_target(address, surface_color_format, width, height, std::forward<Args>(extra_params)...);
return m_render_targets_storage[address].Get();
}
template <typename ...Args>
gsl::not_null<surface_type> bind_address_as_depth_stencil(
command_list_type command_list,
u32 address,
u8 surface_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, surface_depth_format, width, height))
{
Traits::prepare_ds_for_drawing(command_list, ds.Get());
return ds.Get();
}
invalidated_resources.push_back(std::move(ds));
m_depth_stencil_storage.erase(address);
}
m_depth_stencil_storage[address] = Traits::create_new_depth_stencil(address, surface_depth_format, width, height, std::forward<Args>(extra_params)...);
return m_depth_stencil_storage[address].Get();
}
public:
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,
u32 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;
rsx::surface_info surface = {};
surface.unpack(set_surface_format_reg);
// 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 : 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], surface.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, surface.depth_format, clip_width, clip_height, std::forward<Args>(extra_params)...));
}
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 It->second.Get();
return surface_type();
}
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 It->second.Get();
return surface_type();
}
};
}
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_render_target(
ComPtr<ID3D12Resource> create_new_surface(
u32 address,
u8 surface_color_format, size_t width, size_t height,
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(surface_color_format);
DXGI_FORMAT dxgi_format = get_color_surface_format(color_format);
ComPtr<ID3D12Resource> rtt;
LOG_WARNING(RSX, "Creating RTT");
@@ -226,9 +67,9 @@ struct render_target_traits
}
static
ComPtr<ID3D12Resource> create_new_depth_stencil(
ComPtr<ID3D12Resource> create_new_surface(
u32 address,
u8 surfaceDepthFormat, size_t width, size_t height,
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 = {};
@@ -272,18 +113,145 @@ struct render_target_traits
static
bool rtt_has_format_width_height(const ComPtr<ID3D12Resource> &rtt, u8 surface_color_format, size_t width, size_t height)
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, u8 surface_depth_stencil_format, size_t width, size_t height)
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>
@@ -296,3 +264,4 @@ struct render_targets : public rsx::surface_store<render_target_traits>
void init(ID3D12Device *device);
};
}
+73 -47
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,
@@ -51,14 +76,6 @@ ComPtr<ID3D12Resource> upload_single_texture(
ID3D12GraphicsCommandList *command_list,
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);
size_t heap_offset = texture_buffer_heap.alloc<D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT>(buffer_size);
@@ -70,17 +87,19 @@ ComPtr<ID3D12Resource> upload_single_texture(
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.get_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++;
}
@@ -114,20 +133,52 @@ void update_existing_texture(
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.get_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
@@ -141,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();
@@ -178,7 +222,7 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
{
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)
{
@@ -195,20 +239,10 @@ void D3D12GSRender::upload_and_bind_textures(ID3D12GraphicsCommandList *command_
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)
@@ -318,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)
{
@@ -334,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
+15 -15
View File
@@ -47,7 +47,7 @@ std::pair<ID3DBlob *, ID3DBlob *> compileF32toU8CS()
}
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
@@ -143,21 +143,21 @@ void D3D12GSRender::Shader::Init(ID3D12Device *device, ID3D12CommandQueue *gfxco
Microsoft::WRL::ComPtr<ID3DBlob> rootSignatureBlob;
CHECK_HRESULT(wrapD3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &rootSignatureBlob, &errorBlob));
CHECK_HRESULT(device->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature)));
CHECK_HRESULT(device->CreateRootSignature(0, rootSignatureBlob->GetBufferPointer(), rootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&root_signature)));
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;
@@ -197,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);
}
}
}
@@ -182,7 +220,7 @@ void D3D12VertexProgramDecompiler::insertMainEnd(std::stringstream & OS)
}
D3D12VertexProgramDecompiler::D3D12VertexProgramDecompiler(const RSXVertexProgram &prog) :
VertexProgramDecompiler(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(const RSXVertexProgram &prog);
};
+250 -71
View File
@@ -719,49 +719,156 @@ namespace
};
}
Vertex_base_type to_vertex_base_type(u8 in)
rsx::vertex_base_type rsx::to_vertex_base_type(u8 in)
{
switch (in)
{
case 1: return Vertex_base_type::s1;
case 2: return Vertex_base_type::f;
case 3: return Vertex_base_type::sf;
case 4: return Vertex_base_type::ub;
case 5: return Vertex_base_type::s32k;
case 6: return Vertex_base_type::cmp;
case 7: return Vertex_base_type::ub256;
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);
}
Index_array_type to_index_array_type(u8 in)
rsx::index_array_type rsx::to_index_array_type(u8 in)
{
switch (in)
{
case 0: return Index_array_type::unsigned_32b;
case 1: return Index_array_type::unsigned_16b;
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);
}
Primitive_type to_primitive_type(u8 in)
rsx::primitive_type rsx::to_primitive_type(u8 in)
{
switch (in)
{
case 1: return Primitive_type::points;
case 2: return Primitive_type::lines;
case 3: return Primitive_type::line_loop;
case 4: return Primitive_type::line_strip;
case 5: return Primitive_type::triangles;
case 6: return Primitive_type::triangle_strip;
case 7: return Primitive_type::triangle_fan;
case 8: return Primitive_type::quads;
case 9: return Primitive_type::quad_strip;
case 10: return Primitive_type::polygon;
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);
@@ -773,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
{
@@ -856,18 +997,18 @@ namespace
std::string get_primitive_mode(u8 draw_mode)
{
switch (to_primitive_type(draw_mode))
switch (rsx::to_primitive_type(draw_mode))
{
case Primitive_type::points: return "Points";
case Primitive_type::lines: return "Lines";
case Primitive_type::line_loop: return "Line_loop";
case Primitive_type::line_strip: return "Line_strip";
case Primitive_type::triangles: return "Triangles";
case Primitive_type::triangle_strip: return "Triangle_strip";
case Primitive_type::triangle_fan: return "Triangle_fan";
case Primitive_type::quads: return "Quads";
case Primitive_type::quad_strip: return "Quad_strip";
case Primitive_type::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";
}
@@ -892,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";
}
@@ -969,15 +1122,15 @@ namespace
std::string get_vertex_attribute_format(u8 type)
{
switch (to_vertex_base_type(type))
switch (rsx::to_vertex_base_type(type))
{
case Vertex_base_type::s1: return "Short";
case Vertex_base_type::f: return "Float";
case Vertex_base_type::sf: return "Half float";
case Vertex_base_type::ub: return "Unsigned byte";
case Vertex_base_type::s32k: return "Signed int";
case Vertex_base_type::cmp: return "CMP";
case Vertex_base_type::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";
}
}
@@ -995,10 +1148,10 @@ namespace
std::string index_type(u16 arg)
{
switch (to_index_array_type(arg))
switch (rsx::to_index_array_type(arg))
{
case Index_array_type::unsigned_16b: return "unsigned short";
case Index_array_type::unsigned_32b: return "unsigned int";
case rsx::index_array_type::u16: return "unsigned short";
case rsx::index_array_type::u32: return "unsigned int";
}
return "Error";
}
@@ -1269,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); } },
@@ -1334,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); } },
@@ -1367,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); } },
+113 -71
View File
@@ -23,42 +23,125 @@ enum
CELL_GCM_DISPLAY_FREQUENCY_DISABLE = 3,
};
enum class Vertex_base_type : u8
namespace rsx
{
s1, ///< signed byte
f, ///< float
sf, ///< half float
ub, ///< unsigned byte
s32k, ///< signed 32bits int
cmp, ///< compressed aka X11G11Z10 and always 1. W.
ub256,
};
enum class vertex_base_type : u8
{
s1, ///< signed byte
f, ///< float
sf, ///< half float
ub, ///< unsigned byte
s32k, ///< signed 32bits int
cmp, ///< compressed aka X11G11Z10 and always 1. W.
ub256,
};
Vertex_base_type to_vertex_base_type(u8 in);
vertex_base_type to_vertex_base_type(u8 in);
enum class Index_array_type : u8
{
unsigned_32b,
unsigned_16b,
};
enum class index_array_type : u8
{
u32,
u16,
};
Index_array_type to_index_array_type(u8 in);
index_array_type to_index_array_type(u8 in);
enum class Primitive_type : u8
{
points,
lines,
line_loop, // line strip with last end being joined with first end.
line_strip,
triangles,
triangle_strip,
triangle_fan, // like strip except that every triangle share the first vertex and one instead of 2 from previous triangle.
quads,
quad_strip,
polygon, // convex polygon
};
enum class primitive_type : u8
{
points,
lines,
line_loop, // line strip with last end being joined with first end.
line_strip,
triangles,
triangle_strip,
triangle_fan, // like strip except that every triangle share the first vertex and one instead of 2 from previous triangle.
quads,
quad_strip,
polygon, // convex polygon
};
Primitive_type to_primitive_type(u8 in);
primitive_type to_primitive_type(u8 in);
enum class surface_target : u8
{
none,
surface_a,
surface_b,
surfaces_a_b,
surfaces_a_b_c,
surfaces_a_b_c_d,
};
surface_target to_surface_target(u8 in);
enum class surface_depth_format : u8
{
z16, // unsigned 16 bits depth
z24s8, // unsigned 24 bits depth + 8 bits stencil
};
surface_depth_format to_surface_depth_format(u8 in);
enum class surface_antialiasing : u8
{
center_1_sample,
diagonal_centered_2_samples,
square_centered_4_samples,
square_rotated_4_samples,
};
surface_antialiasing to_surface_antialiasing(u8 in);
enum class surface_color_format : u8
{
x1r5g5b5_z1r5g5b5,
x1r5g5b5_o1r5g5b5,
r5g6b5,
x8r8g8b8_z8r8g8b8,
x8r8g8b8_o8r8g8b8,
a8r8g8b8,
b8,
g8b8,
w16z16y16x16,
w32z32y32x32,
x32,
x8b8g8r8_z8b8g8r8,
x8b8g8r8_o8b8g8r8,
a8b8g8r8,
};
surface_color_format to_surface_color_format(u8 in);
enum class window_origin : u8
{
top,
bottom
};
window_origin to_window_origin(u8 in);
enum class window_pixel_center : u8
{
half,
integer
};
window_pixel_center to_window_pixel_center(u8 in);
enum class comparaison_function : u8
{
never,
less,
equal,
less_or_equal,
greater,
not_equal,
greater_or_equal,
always
};
comparaison_function to_comparaison_function(u16 in);
}
enum
{
@@ -159,44 +242,9 @@ enum
// GCM Surface
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 type
CELL_GCM_SURFACE_PITCH = 1,
CELL_GCM_SURFACE_SWIZZLE = 2,
// 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,
};
enum
@@ -463,12 +511,6 @@ enum
CELL_GCM_TRUE = 1,
CELL_GCM_FALSE = 0,
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,
CELL_GCM_USER_CLIP_PLANE_DISABLE = 0,
CELL_GCM_USER_CLIP_PLANE_ENABLE_LT = 1,
CELL_GCM_USER_CLIP_PLANE_ENABLE_GE = 2,
+48 -6
View File
@@ -40,17 +40,23 @@ std::string getFunctionImpl(FUNCTION f)
return "vec4(1., 1., 1., 1.)";
case FUNCTION::FUNCTION_FRACT:
return "fract($0)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE:
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D:
return "texture($t, $0.x)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_PROJ:
return "textureProj($t, $0.x, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE1D_LOD:
return "textureLod($t, $0.x, $1)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D:
return "texture($t, $0.xy)";
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_PROJ:
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_PROJ:
return "textureProj($t, $0.xyz, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_SAMPLE_LOD:
case FUNCTION::FUNCTION_TEXTURE_SAMPLE2D_LOD:
return "textureLod($t, $0.xy, $1)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE:
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE:
return "texture($t, $0.xyz)";
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_PROJ:
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_PROJ:
return "textureProj($t, $0.xyzw, $1.x)"; // Note: $1.x is bias
case FUNCTION::FUNCTION_TEXTURE_CUBE_SAMPLE_LOD:
case FUNCTION::FUNCTION_TEXTURE_SAMPLECUBE_LOD:
return "textureLod($t, $0.xyz, $1)";
case FUNCTION::FUNCTION_DFDX:
return "dFdx($0)";
@@ -78,3 +84,39 @@ std::string compareFunctionImpl(COMPARE f, const std::string &Op0, const std::st
}
throw EXCEPTION("Unknow compare function");
}
void insert_glsl_legacy_function(std::ostream& OS)
{
OS << "vec4 divsq_legacy(vec4 num, vec4 denum)\n";
OS << "{\n";
OS << " return num / sqrt(max(denum.xxxx, 1.E-10));\n";
OS << "}\n";
OS << "vec4 rcp_legacy(vec4 denum)\n";
OS << "{\n";
OS << " return 1. / denum;\n";
OS << "}\n";
OS << "vec4 rsq_legacy(vec4 val)\n";
OS << "{\n";
OS << " return float(1.0 / sqrt(max(val.x, 1.E-10))).xxxx;\n";
OS << "}\n\n";
OS << "vec4 log2_legacy(vec4 val)\n";
OS << "{\n";
OS << " return log2(max(val.x, 1.E-10)).xxxx;\n";
OS << "}\n\n";
OS << "vec4 lit_legacy(vec4 val)";
OS << "{\n";
OS << " vec4 clamped_val = val;\n";
OS << " clamped_val.x = max(val.x, 0);\n";
OS << " clamped_val.y = max(val.y, 0);\n";
OS << " vec4 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";
}
+1
View File
@@ -4,3 +4,4 @@
std::string getFloatTypeNameImpl(size_t elementCount);
std::string getFunctionImpl(FUNCTION f);
std::string compareFunctionImpl(COMPARE f, const std::string &Op0, const std::string &Op1);
void insert_glsl_legacy_function(std::ostream& OS);
+34 -22
View File
@@ -61,22 +61,39 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
{
for (const ParamType& PT : m_parr.params[PF_PARAM_UNIFORM])
{
if (PT.type != "sampler2D")
if (PT.type != "sampler1D" &&
PT.type != "sampler2D" &&
PT.type != "sampler3D" &&
PT.type != "samplerCube")
continue;
for (const ParamItem& PI : PT.items)
OS << "uniform " << PT.type << " " << PI.name << ";" << std::endl;
for (const ParamItem& PI : PT.items)
{
std::string samplerType = PT.type;
int index = atoi(&PI.name.data()[3]);
if (m_prog.unnormalized_coords & (1 << index))
samplerType = "sampler2DRect";
OS << "uniform " << samplerType << " " << PI.name << ";" << std::endl;
}
}
OS << "layout(std140, binding = 2) uniform FragmentConstantsBuffer" << std::endl;
OS << "{" << std::endl;
for (const ParamType& PT : m_parr.params[PF_PARAM_UNIFORM])
{
if (PT.type == "sampler2D")
if (PT.type == "sampler1D" ||
PT.type == "sampler2D" ||
PT.type == "sampler3D" ||
PT.type == "samplerCube")
continue;
for (const ParamItem& PI : PT.items)
OS << " " << PT.type << " " << PI.name << ";" << std::endl;
OS << " " << PT.type << " " << PI.name << ";" << std::endl;
}
// A dummy value otherwise it's invalid to create an empty uniform buffer
OS << " vec4 void_value;" << std::endl;
OS << "};" << std::endl;
@@ -84,22 +101,7 @@ void GLFragmentDecompilerThread::insertConstants(std::stringstream & OS)
void GLFragmentDecompilerThread::insertMainStart(std::stringstream & OS)
{
// "lib" function
// 0.00001 is used as "some non zero very little number"
OS << "vec4 divsq_legacy(vec4 num, vec4 denum)\n";
OS << "{\n";
OS << " return num / sqrt(max(denum.xxxx, 0.00001));\n";
OS << "}\n";
OS << "vec4 rcp_legacy(vec4 denum)\n";
OS << "{\n";
OS << " return 1. / denum;\n";
OS << "}\n";
OS << "vec4 rsq_legacy(vec4 denum)\n";
OS << "{\n";
OS << " return 1. / sqrt(max(denum, 0.00001));\n";
OS << "}\n";
insert_glsl_legacy_function(OS);
OS << "void main ()" << std::endl;
OS << "{" << std::endl;
@@ -133,7 +135,17 @@ void GLFragmentDecompilerThread::insertMainEnd(std::stringstream & OS)
}
if (m_ctrl & CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT)
OS << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << 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 << ((m_ctrl & CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS) ? "\tgl_FragDepth = r1.z;\n" : "\tgl_FragDepth = h0.z;\n") << std::endl;
OS << " gl_FragDepth = r1.z;\n";
}
}
OS << "}" << std::endl;
}
+219 -136
View File
@@ -9,6 +9,48 @@
#define DUMP_VERTEX_DATA 0
namespace
{
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");
}
u8 get_pixel_size(rsx::surface_depth_format format)
{
switch (format)
{
case rsx::surface_depth_format::z16: return 2;
case rsx::surface_depth_format::z24s8: return 4;
}
throw EXCEPTION("Unknow depth format");
}
u32 to_gl_internal_type(rsx::vertex_base_type type, u8 size)
{
/**
* The buffer texture spec only allows fetches aligned to 8, 16, 32, etc...
* This rules out most 3-component formats, except for the 32-wide RGB32F, RGB32I, RGB32UI
*/
const u32 vec1_types[] = { GL_R16, GL_R32F, GL_R16F, GL_R8, GL_R32I, GL_R16F, GL_R8 };
const u32 vec2_types[] = { GL_RG16, GL_RG32F, GL_RG16F, GL_RG8, GL_RG32I, GL_RG16F, GL_RG8 };
const u32 vec3_types[] = { GL_RGBA16, GL_RGB32F, GL_RGBA16F, GL_RGBA8, GL_RGB32I, GL_RGBA16F, GL_RGBA8 }; //VEC3 COMPONENTS NOT SUPPORTED!
const u32 vec4_types[] = { GL_RGBA16, GL_RGBA32F, GL_RGBA16F, GL_RGBA8, GL_RGBA32I, GL_RGBA16F, GL_RGBA8 };
const u32* vec_selectors[] = { 0, vec1_types, vec2_types, vec3_types, vec4_types };
if (type > rsx::vertex_base_type::ub256)
throw EXCEPTION("OpenGL error: unknown vertex base type 0x%X.", (u32)type);
return vec_selectors[size][(int)type];
}
}
GLGSRender::GLGSRender() : GSRender(frame_type::OpenGL)
{
shaders_cache.load(rsx::shader_language::glsl);
@@ -97,7 +139,7 @@ void GLGSRender::begin()
__glcheck glBlendFuncSeparate(sfactor_rgb, dfactor_rgb, sfactor_a, dfactor_a);
if (m_surface.color_format == CELL_GCM_SURFACE_F_W16Z16Y16X16) //TODO: check another color formats
if (m_surface.color_format == rsx::surface_color_format::w16z16y16x16) //TODO: check another color formats
{
u32 blend_color = rsx::method_registers[NV4097_SET_BLEND_COLOR];
u32 blend_color2 = rsx::method_registers[NV4097_SET_BLEND_COLOR2];
@@ -295,33 +337,33 @@ void apply_attrib_array(gl::glsl::program& program, int location, const std::vec
namespace
{
gl::buffer_pointer::type gl_types(Vertex_base_type type)
gl::buffer_pointer::type gl_types(rsx::vertex_base_type type)
{
switch (type)
{
case Vertex_base_type::s1: return gl::buffer_pointer::type::s16;
case Vertex_base_type::f: return gl::buffer_pointer::type::f32;
case Vertex_base_type::sf: return gl::buffer_pointer::type::f16;
case Vertex_base_type::ub: return gl::buffer_pointer::type::u8;
case Vertex_base_type::s32k: return gl::buffer_pointer::type::s32;
case Vertex_base_type::cmp: return gl::buffer_pointer::type::s16; // Needs conversion
case Vertex_base_type::ub256: gl::buffer_pointer::type::u8;
case rsx::vertex_base_type::s1: return gl::buffer_pointer::type::s16;
case rsx::vertex_base_type::f: return gl::buffer_pointer::type::f32;
case rsx::vertex_base_type::sf: return gl::buffer_pointer::type::f16;
case rsx::vertex_base_type::ub: return gl::buffer_pointer::type::u8;
case rsx::vertex_base_type::s32k: return gl::buffer_pointer::type::s32;
case rsx::vertex_base_type::cmp: return gl::buffer_pointer::type::s16; // Needs conversion
case rsx::vertex_base_type::ub256: gl::buffer_pointer::type::u8;
}
throw EXCEPTION("unknow vertex type");
}
bool gl_normalized(Vertex_base_type type)
bool gl_normalized(rsx::vertex_base_type type)
{
switch (type)
{
case Vertex_base_type::s1:
case Vertex_base_type::ub:
case Vertex_base_type::cmp:
case rsx::vertex_base_type::s1:
case rsx::vertex_base_type::ub:
case rsx::vertex_base_type::cmp:
return true;
case Vertex_base_type::f:
case Vertex_base_type::sf:
case Vertex_base_type::ub256:
case Vertex_base_type::s32k:
case rsx::vertex_base_type::f:
case rsx::vertex_base_type::sf:
case rsx::vertex_base_type::ub256:
case rsx::vertex_base_type::s32k:
return false;
}
throw EXCEPTION("unknow vertex type");
@@ -352,6 +394,12 @@ void GLGSRender::end()
int location;
if (m_program->uniforms.has_location("tex" + std::to_string(i), &location))
{
u32 target = GL_TEXTURE_2D;
if (textures[i].format() & CELL_GCM_TEXTURE_UN)
target = GL_TEXTURE_RECTANGLE;
m_gl_textures[i].set_target(target);
__glcheck m_gl_textures[i].init(i, textures[i]);
glProgramUniform1i(m_program->id(), location, i);
}
@@ -374,14 +422,14 @@ void GLGSRender::end()
};
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
m_vao.bind();
std::vector<u8> vertex_index_array;
vertex_draw_count = 0;
u32 min_index, max_index;
if (draw_command == Draw_command::draw_command_indexed)
if (draw_command == rsx::draw_command::indexed)
{
Index_array_type type = to_index_array_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 = gsl::narrow<u32>(get_index_type_size(type));
for (const auto& first_count : first_count_commands)
{
@@ -392,17 +440,18 @@ void GLGSRender::end()
switch (type)
{
case Index_array_type::unsigned_32b:
case rsx::index_array_type::u32:
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u32>((u32*)vertex_index_array.data(), vertex_draw_count), first_count_commands);
break;
case Index_array_type::unsigned_16b:
case rsx::index_array_type::u16:
std::tie(min_index, max_index) = write_index_array_data_to_buffer_untouched(gsl::span<u16>((u16*)vertex_index_array.data(), vertex_draw_count), first_count_commands);
break;
}
}
if (draw_command == Draw_command::draw_command_inlined_array)
if (draw_command == rsx::draw_command::inlined_array)
{
vertex_arrays_data.resize(inline_vertex_array.size() * sizeof(u32));
write_inline_array_to_buffer(vertex_arrays_data.data());
u32 offset = 0;
for (int index = 0; index < rsx::limits::vertex_count; ++index)
@@ -413,17 +462,30 @@ void GLGSRender::end()
continue;
int location;
if (!m_program->attribs.has_location(reg_table[index], &location))
if (!m_program->uniforms.has_location(reg_table[index] + "_buffer", &location))
continue;
__glcheck m_program->attribs[location] =
(m_vao + offset)
.config(gl_types(vertex_info.type), vertex_info.size, gl_normalized(vertex_info.type));
const u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
const u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
const u32 data_size = element_size * vertex_draw_count;
auto &buffer = m_gl_attrib_buffers[index].buffer;
auto &texture = m_gl_attrib_buffers[index].texture;
buffer->data(data_size, nullptr);
buffer->sub_data(0, data_size, vertex_arrays_data.data()+offset);
//Attach buffer to texture
texture->copy_from(*buffer, gl_type);
//Link texture to uniform
m_program->uniforms.texture(location, index +rsx::limits::vertex_count, *texture);
offset += rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
}
}
if (draw_command == Draw_command::draw_command_array)
if (draw_command == rsx::draw_command::array)
{
for (const auto &first_count : first_count_commands)
{
@@ -431,7 +493,7 @@ void GLGSRender::end()
}
}
if (draw_command == Draw_command::draw_command_array || draw_command == Draw_command::draw_command_indexed)
if (draw_command == rsx::draw_command::array || draw_command == rsx::draw_command::indexed)
{
for (int index = 0; index < rsx::limits::vertex_count; ++index)
{
@@ -440,7 +502,7 @@ void GLGSRender::end()
continue;
int location;
if (!m_program->attribs.has_location(reg_table[index], &location))
if (!m_program->uniforms.has_location(reg_table[index]+"_buffer", &location))
continue;
if (vertex_arrays_info[index].size > 0)
@@ -452,7 +514,7 @@ void GLGSRender::end()
// Fill vertex_array
u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
vertex_array.resize(vertex_draw_count * element_size);
if (draw_command == Draw_command::draw_command_array)
if (draw_command == rsx::draw_command::array)
{
size_t offset = 0;
for (const auto &first_count : first_count_commands)
@@ -461,7 +523,7 @@ void GLGSRender::end()
offset += first_count.second * element_size;
}
}
if (draw_command == Draw_command::draw_command_indexed)
if (draw_command == rsx::draw_command::indexed)
{
vertex_array.resize((max_index + 1) * element_size);
write_vertex_array_data_to_buffer(vertex_array.data(), 0, max_index + 1, index, vertex_info);
@@ -472,29 +534,48 @@ void GLGSRender::end()
vertex_arrays_offsets[index] = gsl::narrow<u32>(position);
vertex_arrays_data.resize(position + size);
memcpy(vertex_arrays_data.data() + position, vertex_array.data(), size);
const u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
const u32 data_size = element_size * vertex_draw_count;
__glcheck m_program->attribs[location] =
(m_vao + vertex_arrays_offsets[index])
.config(gl_types(vertex_info.type), vertex_info.size, gl_normalized(vertex_info.type));
auto &buffer = m_gl_attrib_buffers[index].buffer;
auto &texture = m_gl_attrib_buffers[index].texture;
buffer->data(data_size, nullptr);
buffer->sub_data(0, data_size, vertex_array.data());
//Attach buffer to texture
texture->copy_from(*buffer, gl_type);
//Link texture to uniform
m_program->uniforms.texture(location, index + rsx::limits::vertex_count, *texture);
}
else if (register_vertex_info[index].size > 0)
{
//Untested!
auto &vertex_data = register_vertex_data[index];
auto &vertex_info = register_vertex_info[index];
switch (vertex_info.type)
{
case Vertex_base_type::f:
switch (register_vertex_info[index].size)
{
case 1: apply_attrib_array<f32, 1>(*m_program, location, vertex_data); break;
case 2: apply_attrib_array<f32, 2>(*m_program, location, vertex_data); break;
case 3: apply_attrib_array<f32, 3>(*m_program, location, vertex_data); break;
case 4: apply_attrib_array<f32, 4>(*m_program, location, vertex_data); break;
}
break;
case rsx::vertex_base_type::f:
{
const u32 element_size = rsx::get_vertex_type_size_on_host(vertex_info.type, vertex_info.size);
const u32 gl_type = to_gl_internal_type(vertex_info.type, vertex_info.size);
const size_t data_size = vertex_data.size();
auto &buffer = m_gl_attrib_buffers[index].buffer;
auto &texture = m_gl_attrib_buffers[index].texture;
buffer->data(data_size, nullptr);
buffer->sub_data(0, data_size, vertex_data.data());
//Attach buffer to texture
texture->copy_from(*buffer, gl_type);
//Link texture to uniform
m_program->uniforms.texture(location, index + rsx::limits::vertex_count, *texture);
break;
}
default:
LOG_ERROR(RSX, "bad non array vertex data format (type = %d, size = %d)", vertex_info.type, vertex_info.size);
break;
@@ -502,17 +583,28 @@ void GLGSRender::end()
}
}
}
m_vbo.data(vertex_arrays_data.size(), vertex_arrays_data.data());
if (draw_command == Draw_command::draw_command_indexed)
// glDraw* will fail without at least attrib0 defined if we are on compatibility profile
// Someone should really test AMD behaviour here, Nvidia is too permissive. There is no buffer currently bound, but on NV it works ok
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, false, 0, 0);
/**
* Validate fails if called right after linking a program because the VS and FS both use textures bound using different
* samplers. So far only sampler2D has been largely used, hiding the problem. This call shall also degrade performance further
* if used every draw call. Fixes shader validation issues on AMD.
*/
m_program->validate();
if (draw_command == rsx::draw_command::indexed)
{
m_ebo.data(vertex_index_array.size(), vertex_index_array.data());
Index_array_type indexed_type = to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
rsx::index_array_type indexed_type = rsx::to_index_array_type(rsx::method_registers[NV4097_SET_INDEX_ARRAY_DMA] >> 4);
if (indexed_type == Index_array_type::unsigned_32b)
if (indexed_type == rsx::index_array_type::u32)
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_INT, nullptr);
if (indexed_type == Index_array_type::unsigned_16b)
if (indexed_type == rsx::index_array_type::u16)
__glcheck glDrawElements(gl::draw_mode(draw_mode), vertex_draw_count, GL_UNSIGNED_SHORT, nullptr);
}
else
@@ -544,10 +636,10 @@ void GLGSRender::set_viewport()
u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
u8 shader_window_origin = (shader_window >> 12) & 0xf;
rsx::window_origin shader_window_origin = rsx::to_window_origin((shader_window >> 12) & 0xf);
//TODO
if (true || shader_window_origin == CELL_GCM_WINDOW_ORIGIN_BOTTOM)
if (true || shader_window_origin == rsx::window_origin::bottom)
{
__glcheck glViewport(viewport_x, viewport_y, viewport_w, viewport_h);
__glcheck glScissor(scissor_x, scissor_y, scissor_w, scissor_h);
@@ -586,14 +678,25 @@ void GLGSRender::on_init_thread()
m_vao.array_buffer = m_vbo;
m_vao.element_array_buffer = m_ebo;
for (texture_buffer_pair &attrib_buffer : m_gl_attrib_buffers)
{
gl::texture *&tex = attrib_buffer.texture;
tex = new gl::texture(gl::texture::target::textureBuffer);
tex->create();
tex->set_target(gl::texture::target::textureBuffer);
gl::buffer *&buf = attrib_buffer.buffer;
buf = new gl::buffer();
buf->create();
}
}
void GLGSRender::on_exit()
{
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
//if (m_program)
// m_program.remove();
m_prog_buffer.clear();
if (draw_fbo)
draw_fbo.remove();
@@ -627,6 +730,19 @@ void GLGSRender::on_exit()
if (m_fragment_constants_buffer)
m_fragment_constants_buffer.remove();
for (texture_buffer_pair &attrib_buffer : m_gl_attrib_buffers)
{
gl::texture *&tex = attrib_buffer.texture;
tex->remove();
delete tex;
tex = nullptr;
gl::buffer *&buf = attrib_buffer.buffer;
buf->remove();
delete buf;
buf = nullptr;
}
}
void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
@@ -654,8 +770,8 @@ void nv4097_clear_surface(u32 arg, GLGSRender* renderer)
if (arg & 0x1)
{
u32 surface_depth_format = (rsx::method_registers[NV4097_SET_SURFACE_FORMAT] >> 5) & 0x7;
u32 max_depth_value = surface_depth_format == CELL_GCM_SURFACE_Z16 ? 0x0000ffff : 0x00ffffff;
rsx::surface_depth_format surface_depth_format = rsx::to_surface_depth_format((rsx::method_registers[NV4097_SET_SURFACE_FORMAT] >> 5) & 0x7);
u32 max_depth_value = get_max_depth_value(surface_depth_format);
u32 clear_depth = rsx::method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] >> 8;
@@ -715,37 +831,8 @@ bool GLGSRender::do_method(u32 cmd, u32 arg)
bool GLGSRender::load_program()
{
#if 1
RSXVertexProgram vertex_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;
}
RSXFragmentProgram fragment_program;
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];
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);
}
RSXVertexProgram vertex_program = get_current_vertex_program();
RSXFragmentProgram fragment_program = get_current_fragment_program();
__glcheck m_program = &m_prog_buffer.getGraphicPipelineState(vertex_program, fragment_program, nullptr);
__glcheck m_program->use();
@@ -832,52 +919,52 @@ struct color_format
color_swizzle swizzle;
};
color_format surface_color_format_to_gl(int color_format)
color_format surface_color_format_to_gl(rsx::surface_color_format color_format)
{
//color format
switch (color_format)
{
case CELL_GCM_SURFACE_R5G6B5:
case rsx::surface_color_format::r5g6b5:
return{ gl::texture::type::ushort_5_6_5, gl::texture::format::bgr, false, 3, 2 };
case CELL_GCM_SURFACE_A8R8G8B8:
case rsx::surface_color_format::a8r8g8b8:
return{ gl::texture::type::uint_8_8_8_8, gl::texture::format::bgra, false, 4, 1 };
case CELL_GCM_SURFACE_X8R8G8B8_O8R8G8B8:
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
return{ gl::texture::type::uint_8_8_8_8, gl::texture::format::bgra, false, 4, 1,
{ gl::texture::channel::one, gl::texture::channel::r, gl::texture::channel::g, gl::texture::channel::b } };
case CELL_GCM_SURFACE_F_W16Z16Y16X16:
case rsx::surface_color_format::w16z16y16x16:
return{ gl::texture::type::f16, gl::texture::format::rgba, true, 4, 2 };
case CELL_GCM_SURFACE_F_W32Z32Y32X32:
case rsx::surface_color_format::w32z32y32x32:
return{ gl::texture::type::f32, gl::texture::format::rgba, true, 4, 4 };
case CELL_GCM_SURFACE_B8:
case CELL_GCM_SURFACE_X1R5G5B5_Z1R5G5B5:
case CELL_GCM_SURFACE_X1R5G5B5_O1R5G5B5:
case CELL_GCM_SURFACE_X8R8G8B8_Z8R8G8B8:
case CELL_GCM_SURFACE_G8B8:
case CELL_GCM_SURFACE_F_X32:
case CELL_GCM_SURFACE_X8B8G8R8_Z8B8G8R8:
case CELL_GCM_SURFACE_X8B8G8R8_O8B8G8R8:
case CELL_GCM_SURFACE_A8B8G8R8:
case rsx::surface_color_format::b8:
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
case rsx::surface_color_format::g8b8:
case rsx::surface_color_format::x32:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
case rsx::surface_color_format::a8b8g8r8:
default:
LOG_ERROR(RSX, "Surface color buffer: Unsupported surface color format (0x%x)", color_format);
return{ gl::texture::type::uint_8_8_8_8, gl::texture::format::bgra, false, 4, 1 };
}
}
std::pair<gl::texture::type, gl::texture::format> surface_depth_format_to_gl(int depth_format)
std::pair<gl::texture::type, gl::texture::format> surface_depth_format_to_gl(rsx::surface_depth_format depth_format)
{
switch (depth_format)
{
case CELL_GCM_SURFACE_Z16:
case rsx::surface_depth_format::z16:
return std::make_pair(gl::texture::type::ushort, gl::texture::format::depth);
default:
LOG_ERROR(RSX, "Surface depth buffer: Unsupported surface depth format (0x%x)", depth_format);
case CELL_GCM_SURFACE_Z24S8:
case rsx::surface_depth_format::z24s8:
return std::make_pair(gl::texture::type::uint_24_8, gl::texture::format::depth_stencil);
//return std::make_pair(gl::texture::type::f32, gl::texture::format::depth);
}
@@ -926,7 +1013,7 @@ void GLGSRender::init_buffers(bool skip_reading)
switch (m_surface.depth_format)
{
case CELL_GCM_SURFACE_Z16:
case rsx::surface_depth_format::z16:
{
__glcheck m_draw_tex_depth_stencil.config()
.size({ (int)m_surface.width, (int)m_surface.height })
@@ -938,7 +1025,7 @@ void GLGSRender::init_buffers(bool skip_reading)
break;
}
case CELL_GCM_SURFACE_Z24S8:
case rsx::surface_depth_format::z24s8:
{
__glcheck m_draw_tex_depth_stencil.config()
.size({ (int)m_surface.width, (int)m_surface.height })
@@ -950,9 +1037,6 @@ void GLGSRender::init_buffers(bool skip_reading)
break;
}
case 0:
break;
default:
{
LOG_ERROR(RSX, "Bad depth format! (%d)", m_surface.depth_format);
@@ -972,27 +1056,27 @@ void GLGSRender::init_buffers(bool skip_reading)
set_viewport();
switch (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_NONE: break;
case rsx::surface_target::none: break;
case CELL_GCM_SURFACE_TARGET_0:
case rsx::surface_target::surface_a:
__glcheck draw_fbo.draw_buffer(draw_fbo.color[0]);
break;
case CELL_GCM_SURFACE_TARGET_1:
case rsx::surface_target::surface_b:
__glcheck draw_fbo.draw_buffer(draw_fbo.color[1] );
break;
case CELL_GCM_SURFACE_TARGET_MRT1:
case rsx::surface_target::surfaces_a_b:
__glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1] });
break;
case CELL_GCM_SURFACE_TARGET_MRT2:
case rsx::surface_target::surfaces_a_b_c:
__glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2] });
break;
case CELL_GCM_SURFACE_TARGET_MRT3:
case rsx::surface_target::surfaces_a_b_c_d:
__glcheck draw_fbo.draw_buffers({ draw_fbo.color[0], draw_fbo.color[1], draw_fbo.color[2], draw_fbo.color[3] });
break;
@@ -1070,28 +1154,28 @@ void GLGSRender::read_buffers()
}
};
switch (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_NONE:
case rsx::surface_target::none:
break;
case CELL_GCM_SURFACE_TARGET_0:
case rsx::surface_target::surface_a:
read_color_buffers(0, 1);
break;
case CELL_GCM_SURFACE_TARGET_1:
case rsx::surface_target::surface_b:
read_color_buffers(1, 1);
break;
case CELL_GCM_SURFACE_TARGET_MRT1:
case rsx::surface_target::surfaces_a_b:
read_color_buffers(0, 2);
break;
case CELL_GCM_SURFACE_TARGET_MRT2:
case rsx::surface_target::surfaces_a_b_c:
read_color_buffers(0, 3);
break;
case CELL_GCM_SURFACE_TARGET_MRT3:
case rsx::surface_target::surfaces_a_b_c_d:
read_color_buffers(0, 4);
break;
}
@@ -1107,8 +1191,7 @@ void GLGSRender::read_buffers()
auto depth_format = surface_depth_format_to_gl(m_surface.depth_format);
int pixel_size = m_surface.depth_format == CELL_GCM_SURFACE_Z16 ? 2 : 4;
int pixel_size = get_pixel_size(m_surface.depth_format);
gl::buffer pbo_depth;
__glcheck pbo_depth.create(m_surface.width * m_surface.height * pixel_size);
@@ -1116,7 +1199,7 @@ void GLGSRender::read_buffers()
{
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
if (m_surface.depth_format == CELL_GCM_SURFACE_Z16)
if (m_surface.depth_format == rsx::surface_depth_format::z16)
{
u16 *dst = (u16*)pixels;
const be_t<u16>* src = vm::ps3::_ptr<u16>(depth_address);
@@ -1202,28 +1285,28 @@ void GLGSRender::write_buffers()
}
};
switch (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_NONE:
case rsx::surface_target::none:
break;
case CELL_GCM_SURFACE_TARGET_0:
case rsx::surface_target::surface_a:
write_color_buffers(0, 1);
break;
case CELL_GCM_SURFACE_TARGET_1:
case rsx::surface_target::surface_b:
write_color_buffers(1, 1);
break;
case CELL_GCM_SURFACE_TARGET_MRT1:
case rsx::surface_target::surfaces_a_b:
write_color_buffers(0, 2);
break;
case CELL_GCM_SURFACE_TARGET_MRT2:
case rsx::surface_target::surfaces_a_b_c:
write_color_buffers(0, 3);
break;
case CELL_GCM_SURFACE_TARGET_MRT3:
case rsx::surface_target::surfaces_a_b_c_d:
write_color_buffers(0, 4);
break;
}
@@ -1241,7 +1324,7 @@ void GLGSRender::write_buffers()
gl::buffer pbo_depth;
int pixel_size = m_surface.depth_format == CELL_GCM_SURFACE_Z16 ? 2 : 4;
int pixel_size = get_pixel_size(m_surface.depth_format);
__glcheck pbo_depth.create(m_surface.width * m_surface.height * pixel_size);
__glcheck m_draw_tex_depth_stencil.copy_to(pbo_depth, depth_format.second, depth_format.first);
@@ -1250,7 +1333,7 @@ void GLGSRender::write_buffers()
{
u32 depth_address = rsx::get_address(rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA]);
if (m_surface.depth_format == CELL_GCM_SURFACE_Z16)
if (m_surface.depth_format == rsx::surface_depth_format::z16)
{
const u16 *src = (const u16*)pixels;
be_t<u16>* dst = vm::ps3::_ptr<u16>(depth_address);
+7
View File
@@ -22,6 +22,13 @@ private:
rsx::surface_info m_surface;
struct texture_buffer_pair
{
gl::texture *texture;
gl::buffer *buffer;
}
m_gl_attrib_buffers[rsx::limits::vertex_count];
public:
gl::fbo draw_fbo;
+4
View File
@@ -166,6 +166,10 @@ OPENGL_PROC(PFNGLCHECKFRAMEBUFFERSTATUSPROC, CheckFramebufferStatus);
OPENGL_PROC(PFNGLBINDBUFFERBASEPROC, BindBufferBase);
//Texture Buffers
OPENGL_PROC(PFNGLTEXBUFFERPROC, TexBuffer);
OPENGL_PROC(PFNGLTEXTUREBUFFERRANGEEXTPROC, TextureBufferRangeEXT);
//KHR_debug
OPENGL_PROC(PFNGLDEBUGMESSAGECONTROLARBPROC, DebugMessageControlARB);
OPENGL_PROC(PFNGLDEBUGMESSAGEINSERTARBPROC, DebugMessageInsertARB);
+65 -3
View File
@@ -27,7 +27,7 @@ std::string GLVertexDecompilerThread::compareFunction(COMPARE f, const std::stri
void GLVertexDecompilerThread::insertHeader(std::stringstream &OS)
{
OS << "#version 420" << std::endl << std::endl;
OS << "#version 430" << std::endl << std::endl;
OS << "layout(std140, binding = 0) uniform ScaleOffsetBuffer" << std::endl;
OS << "{" << std::endl;
OS << " mat4 scaleOffsetMat;" << std::endl;
@@ -36,10 +36,33 @@ void GLVertexDecompilerThread::insertHeader(std::stringstream &OS)
void GLVertexDecompilerThread::insertInputs(std::stringstream & OS, const std::vector<ParamType>& inputs)
{
for (const ParamType PT : inputs)
std::vector<std::tuple<size_t, std::string>> input_data;
for (const ParamType &PT : inputs)
{
for (const ParamItem &PI : PT.items)
OS << /*"layout(location = " << PI.location << ") "*/ "in " << PT.type << " " << PI.name << ";" << std::endl;
{
input_data.push_back(std::make_tuple(PI.location, PI.name));
}
}
/**
* Its is important that the locations are in the order that vertex attributes are expected.
* If order is not adhered to, channels may be swapped leading to corruption
*/
std::sort(input_data.begin(), input_data.end());
int location = 1;
for (const std::tuple<size_t, std::string> item : input_data)
{
for (const ParamType &PT : inputs)
{
for (const ParamItem &PI : PT.items)
{
if (PI.name == std::get<1>(item))
OS << "layout(location=" << location++ << ")" << " uniform samplerBuffer" << " " << PI.name << "_buffer;" << std::endl;
}
}
}
}
@@ -101,9 +124,42 @@ void GLVertexDecompilerThread::insertOutputs(std::stringstream & OS, const std::
}
}
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 << " vec4 " << PI.name << " = texelFetch(" << PI.name << "_buffer, 0);" << std::endl;
return;
}
if (real_input.frequency > 1)
{
if (real_input.is_modulo)
{
OS << " vec4 " << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexID %" << real_input.frequency << ");" << std::endl;
return;
}
OS << " vec4 " << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexID /" << real_input.frequency << ");" << std::endl;
return;
}
OS << " vec4 " << PI.name << "= texelFetch(" << PI.name << "_buffer, gl_VertexID);" << std::endl;
return;
}
OS << " vec4 " << PI.name << " = vec4(0., 0., 0., 1.);" << std::endl;
}
void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS)
{
insert_glsl_legacy_function(OS);
OS << "void main()" << std::endl;
OS << "{" << std::endl;
@@ -118,6 +174,12 @@ void GLVertexDecompilerThread::insertMainStart(std::stringstream & OS)
OS << ";" << std::endl;
}
}
for (const ParamType &PT : m_parr.params[PF_PARAM_IN])
{
for (const ParamItem &PI : PT.items)
add_input(OS, PI, rsx_vertex_program.rsx_vertex_inputs);
}
}
void GLVertexDecompilerThread::insertMainEnd(std::stringstream & OS)
+3
View File
@@ -19,10 +19,13 @@ protected:
virtual void insertOutputs(std::stringstream &OS, const std::vector<ParamType> &outputs) override;
virtual void insertMainStart(std::stringstream &OS) override;
virtual void insertMainEnd(std::stringstream &OS) override;
const RSXVertexProgram &rsx_vertex_program;
public:
GLVertexDecompilerThread(const RSXVertexProgram &prog, std::string& shader, ParamArray& parr)
: VertexProgramDecompiler(prog)
, m_shader(shader)
, rsx_vertex_program(prog)
{
}
+24 -24
View File
@@ -5,20 +5,20 @@ namespace gl
{
const fbo screen{};
GLenum draw_mode(Primitive_type in)
GLenum draw_mode(rsx::primitive_type in)
{
switch (in)
{
case Primitive_type::points: return GL_POINTS;
case Primitive_type::lines: return GL_LINES;
case Primitive_type::line_loop: return GL_LINE_LOOP;
case Primitive_type::line_strip: return GL_LINE_STRIP;
case Primitive_type::triangles: return GL_TRIANGLES;
case Primitive_type::triangle_strip: return GL_TRIANGLE_STRIP;
case Primitive_type::triangle_fan: return GL_TRIANGLE_FAN;
case Primitive_type::quads: return GL_QUADS;
case Primitive_type::quad_strip: return GL_QUAD_STRIP;
case Primitive_type::polygon: return GL_POLYGON;
case rsx::primitive_type::points: return GL_POINTS;
case rsx::primitive_type::lines: return GL_LINES;
case rsx::primitive_type::line_loop: return GL_LINE_LOOP;
case rsx::primitive_type::line_strip: return GL_LINE_STRIP;
case rsx::primitive_type::triangles: return GL_TRIANGLES;
case rsx::primitive_type::triangle_strip: return GL_TRIANGLE_STRIP;
case rsx::primitive_type::triangle_fan: return GL_TRIANGLE_FAN;
case rsx::primitive_type::quads: return GL_QUADS;
case rsx::primitive_type::quad_strip: return GL_QUAD_STRIP;
case rsx::primitive_type::polygon: return GL_POLYGON;
}
throw new EXCEPTION("unknow primitive type");
}
@@ -97,74 +97,74 @@ namespace gl
__glcheck glDrawBuffers((GLsizei)ids.size(), ids.data());
}
void fbo::draw_arrays(Primitive_type mode, GLsizei count, GLint first) const
void fbo::draw_arrays(rsx::primitive_type mode, GLsizei count, GLint first) const
{
save_binding_state save(*this);
__glcheck glDrawArrays(draw_mode(mode), first, count);
}
void fbo::draw_arrays(const buffer& buffer, Primitive_type mode, GLsizei count, GLint first) const
void fbo::draw_arrays(const buffer& buffer, rsx::primitive_type mode, GLsizei count, GLint first) const
{
buffer.bind(buffer::target::array);
draw_arrays(mode, count, first);
}
void fbo::draw_arrays(const vao& buffer, Primitive_type mode, GLsizei count, GLint first) const
void fbo::draw_arrays(const vao& buffer, rsx::primitive_type mode, GLsizei count, GLint first) const
{
buffer.bind();
draw_arrays(mode, count, first);
}
void fbo::draw_elements(Primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const
void fbo::draw_elements(rsx::primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const
{
save_binding_state save(*this);
__glcheck glDrawElements(draw_mode(mode), count, (GLenum)type, indices);
}
void fbo::draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const
void fbo::draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const
{
buffer.bind(buffer::target::array);
__glcheck glDrawElements(draw_mode(mode), count, (GLenum)type, indices);
}
void fbo::draw_elements(Primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset) const
void fbo::draw_elements(rsx::primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset) const
{
indices.bind(buffer::target::element_array);
__glcheck glDrawElements(draw_mode(mode), count, (GLenum)type, (GLvoid*)indices_buffer_offset);
}
void fbo::draw_elements(const buffer& buffer_, Primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset) const
void fbo::draw_elements(const buffer& buffer_, rsx::primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset) const
{
buffer_.bind(buffer::target::array);
draw_elements(mode, count, type, indices, indices_buffer_offset);
}
void fbo::draw_elements(Primitive_type mode, GLsizei count, const GLubyte *indices) const
void fbo::draw_elements(rsx::primitive_type mode, GLsizei count, const GLubyte *indices) const
{
draw_elements(mode, count, indices_type::ubyte, indices);
}
void fbo::draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, const GLubyte *indices) const
void fbo::draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, const GLubyte *indices) const
{
draw_elements(buffer, mode, count, indices_type::ubyte, indices);
}
void fbo::draw_elements(Primitive_type mode, GLsizei count, const GLushort *indices) const
void fbo::draw_elements(rsx::primitive_type mode, GLsizei count, const GLushort *indices) const
{
draw_elements(mode, count, indices_type::ushort, indices);
}
void fbo::draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, const GLushort *indices) const
void fbo::draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, const GLushort *indices) const
{
draw_elements(buffer, mode, count, indices_type::ushort, indices);
}
void fbo::draw_elements(Primitive_type mode, GLsizei count, const GLuint *indices) const
void fbo::draw_elements(rsx::primitive_type mode, GLsizei count, const GLuint *indices) const
{
draw_elements(mode, count, indices_type::uint, indices);
}
void fbo::draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, const GLuint *indices) const
void fbo::draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, const GLuint *indices) const
{
draw_elements(buffer, mode, count, indices_type::uint, indices);
}
+43 -19
View File
@@ -830,7 +830,8 @@ namespace gl
{
texture1D = GL_TEXTURE_1D,
texture2D = GL_TEXTURE_2D,
texture3D = GL_TEXTURE_3D
texture3D = GL_TEXTURE_3D,
textureBuffer = GL_TEXTURE_BUFFER
};
enum class channel_type
@@ -863,9 +864,10 @@ namespace gl
GLenum pname;
switch (new_binding.get_target())
{
case target::texture1D: pname = GL_TEXTURE_1D_BINDING_EXT; break;
case target::texture2D: pname = GL_TEXTURE_2D_BINDING_EXT; break;
case target::texture3D: pname = GL_TEXTURE_3D_BINDING_EXT; break;
case target::texture1D: pname = GL_TEXTURE_BINDING_1D; break;
case target::texture2D: pname = GL_TEXTURE_BINDING_2D; break;
case target::texture3D: pname = GL_TEXTURE_BINDING_3D; break;
case target::textureBuffer: pname = GL_TEXTURE_BINDING_BUFFER; break;
}
glGetIntegerv(pname, &m_last_binding);
@@ -1131,6 +1133,29 @@ namespace gl
__glcheck glTexSubImage2D((GLenum)get_target(), level(), 0, 0, width(), height(), (GLenum)format, (GLenum)type, src);
}
void copy_from(buffer &buf, u32 gl_format_type, u32 offset, u32 length)
{
if (get_target() != target::textureBuffer)
throw EXCEPTION("OpenGL error: texture cannot copy from buffer");
if (!offset)
{
copy_from(buf, gl_format_type);
return;
}
if (glTextureBufferRangeEXT == nullptr)
throw EXCEPTION("OpenGL error: partial buffer access for textures is unsupported on your system");
__glcheck glTextureBufferRangeEXT(id(), (GLenum)target::textureBuffer, gl_format_type, buf.id(), offset, length);
}
void copy_from(buffer &buf, u32 gl_format_type)
{
save_binding_state save(*this);
__glcheck glTexBuffer((GLenum)target::textureBuffer, gl_format_type, buf.id());
}
void copy_from(const buffer& buf, texture::format format, texture::type type, class pixel_unpack_settings pixel_settings)
{
buffer::save_binding_state save_buffer(buffer::target::pixel_unpack, buf);
@@ -1380,7 +1405,7 @@ namespace gl
settings& border_color(color4f value);
};
GLenum draw_mode(Primitive_type in);
GLenum draw_mode(rsx::primitive_type in);
enum class indices_type
{
@@ -1523,20 +1548,20 @@ namespace gl
void draw_buffer(const attachment& buffer) const;
void draw_buffers(const std::initializer_list<attachment>& indexes) const;
void draw_arrays(Primitive_type mode, GLsizei count, GLint first = 0) const;
void draw_arrays(const buffer& buffer, Primitive_type mode, GLsizei count, GLint first = 0) const;
void draw_arrays(const vao& buffer, Primitive_type mode, GLsizei count, GLint first = 0) const;
void draw_arrays(rsx::primitive_type mode, GLsizei count, GLint first = 0) const;
void draw_arrays(const buffer& buffer, rsx::primitive_type mode, GLsizei count, GLint first = 0) const;
void draw_arrays(const vao& buffer, rsx::primitive_type mode, GLsizei count, GLint first = 0) const;
void draw_elements(Primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const;
void draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const;
void draw_elements(Primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset = 0) const;
void draw_elements(const buffer& buffer_, Primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset = 0) const;
void draw_elements(Primitive_type mode, GLsizei count, const GLubyte *indices) const;
void draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, const GLubyte *indices) const;
void draw_elements(Primitive_type mode, GLsizei count, const GLushort *indices) const;
void draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, const GLushort *indices) const;
void draw_elements(Primitive_type mode, GLsizei count, const GLuint *indices) const;
void draw_elements(const buffer& buffer, Primitive_type mode, GLsizei count, const GLuint *indices) const;
void draw_elements(rsx::primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const;
void draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, indices_type type, const GLvoid *indices) const;
void draw_elements(rsx::primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset = 0) const;
void draw_elements(const buffer& buffer_, rsx::primitive_type mode, GLsizei count, indices_type type, const buffer& indices, size_t indices_buffer_offset = 0) const;
void draw_elements(rsx::primitive_type mode, GLsizei count, const GLubyte *indices) const;
void draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, const GLubyte *indices) const;
void draw_elements(rsx::primitive_type mode, GLsizei count, const GLushort *indices) const;
void draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, const GLushort *indices) const;
void draw_elements(rsx::primitive_type mode, GLsizei count, const GLuint *indices) const;
void draw_elements(const buffer& buffer, rsx::primitive_type mode, GLsizei count, const GLuint *indices) const;
void clear(buffers buffers_) const;
void clear(buffers buffers_, color4f color_value, double depth_value, u8 stencil_value) const;
@@ -2071,7 +2096,6 @@ namespace gl
void make()
{
link();
validate();
}
uint id() const
+136 -160
View File
@@ -5,6 +5,7 @@
#include "../RSXThread.h"
#include "../RSXTexture.h"
#include "../rsx_utils.h"
#include "../Common/TextureUtils.h"
namespace rsx
{
@@ -89,6 +90,63 @@ namespace rsx
return 1.0f;
}
u16 texture::get_pitch_modifier(u32 format)
{
switch (format)
{
case CELL_GCM_TEXTURE_COMPRESSED_HILO8:
case CELL_GCM_TEXTURE_COMPRESSED_HILO_S8:
default:
LOG_ERROR(RSX, "Unimplemented Texture format : 0x%x", format);
return 0;
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
return 4;
case CELL_GCM_TEXTURE_B8:
return 1;
case CELL_GCM_TEXTURE_COMPRESSED_DXT1:
case CELL_GCM_TEXTURE_COMPRESSED_DXT23:
case CELL_GCM_TEXTURE_COMPRESSED_DXT45:
return 0;
case CELL_GCM_TEXTURE_A1R5G5B5:
case CELL_GCM_TEXTURE_A4R4G4B4:
case CELL_GCM_TEXTURE_R5G6B5:
case CELL_GCM_TEXTURE_G8B8:
case CELL_GCM_TEXTURE_R6G5B5:
case CELL_GCM_TEXTURE_DEPTH16:
case CELL_GCM_TEXTURE_DEPTH16_FLOAT:
case CELL_GCM_TEXTURE_X16:
case CELL_GCM_TEXTURE_R5G5B5A1:
case CELL_GCM_TEXTURE_D1R5G5B5:
return 2;
case CELL_GCM_TEXTURE_A8R8G8B8:
case CELL_GCM_TEXTURE_X32_FLOAT:
case CELL_GCM_TEXTURE_Y16_X16_FLOAT:
case CELL_GCM_TEXTURE_D8R8G8B8:
case CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
case CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
case CELL_GCM_TEXTURE_DEPTH24_D8:
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT:
case CELL_GCM_TEXTURE_Y16_X16:
return 4;
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT:
return 8;
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT:
return 16;
}
}
bool texture::mandates_expansion(u32 format)
{
/**
* If a texture behaves differently when uploaded directly vs when uploaded via texutils methods, it should be added here.
*/
if (format == CELL_GCM_TEXTURE_A1R5G5B5)
return true;
return false;
}
void texture::init(int index, rsx::texture& tex)
{
if (!m_id)
@@ -110,8 +168,6 @@ namespace rsx
u32 format = full_format & ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN);
bool is_swizzled = !!(~full_format & CELL_GCM_TEXTURE_LN);
const u8* pixels = vm::ps3::_ptr<u8>(texaddr);
u8 *unswizzledPixels;
static const GLint glRemapStandard[4] = { GL_ALPHA, GL_RED, GL_GREEN, GL_BLUE };
// NOTE: This must be in ARGB order in all forms below.
const GLint *glRemap = glRemapStandard;
@@ -119,14 +175,36 @@ namespace rsx
::gl::pixel_pack_settings().apply();
::gl::pixel_unpack_settings().apply();
u32 pitch = tex.pitch();
u32 aligned_pitch = tex.pitch();
size_t texture_data_sz = get_placed_texture_storage_size(tex, 256);
std::vector<u8> data_upload_buf(texture_data_sz);
u8* texture_data = data_upload_buf.data();
u32 block_sz = get_pitch_modifier(format);
if (is_swizzled || mandates_expansion(format))
{
aligned_pitch = align(aligned_pitch, 256);
upload_placed_texture(tex, 256, texture_data);
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
}
else
{
texture_data = vm::ps3::_ptr<u8>(texaddr);
}
if (block_sz)
aligned_pitch /= block_sz;
else
aligned_pitch = 0;
glPixelStorei(GL_UNPACK_ROW_LENGTH, aligned_pitch);
switch (format)
{
case CELL_GCM_TEXTURE_B8: // One 8-bit fixed-point number
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BLUE, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BLUE, GL_UNSIGNED_BYTE, texture_data);
static const GLint swizzleMaskB8[] = { GL_BLUE, GL_BLUE, GL_BLUE, GL_BLUE };
glRemap = swizzleMaskB8;
@@ -135,19 +213,13 @@ namespace rsx
case CELL_GCM_TEXTURE_A1R5G5B5:
{
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
// TODO: texture swizzling
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, texture_data);
break;
}
case CELL_GCM_TEXTURE_A4R4G4B4:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4, texture_data);
// We read it in as R4G4B4A4, so we need to remap each component.
static const GLint swizzleMaskA4R4G4B4[] = { GL_BLUE, GL_ALPHA, GL_RED, GL_GREEN };
@@ -157,67 +229,43 @@ namespace rsx
case CELL_GCM_TEXTURE_R5G6B5:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
LOG_WARNING(RSX, "CELL_GCM_R5G6B5 texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex.width(), tex.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, pixels);
glTexImage2D(m_target, 0, GL_RGB, tex.width(), tex.height(), 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, texture_data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
break;
}
case CELL_GCM_TEXTURE_A8R8G8B8:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
if (is_swizzled)
{
u32 *src, *dst;
u16 height = tex.height();
u16 width = tex.width();
unswizzledPixels = (u8*)malloc(width * height * 4);
src = (u32*)pixels;
dst = (u32*)unswizzledPixels;
if ((height & (height - 1)) || (width & (width - 1)))
{
LOG_ERROR(RSX, "Swizzle Texture: Width or height not power of 2! (h=%d,w=%d).", height, width);
}
rsx::convert_linear_swizzle<u32>(src, dst, width, height, true);
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, is_swizzled ? unswizzledPixels : pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, texture_data);
break;
}
case CELL_GCM_TEXTURE_COMPRESSED_DXT1: // Compressed 4x4 pixels into 8 bytes
{
u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 8;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.width(), tex.height(), 0, size, pixels);
glCompressedTexImage2D(m_target, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, tex.width(), tex.height(), 0, size, texture_data);
break;
}
case CELL_GCM_TEXTURE_COMPRESSED_DXT23: // Compressed 4x4 pixels into 16 bytes
{
u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.width(), tex.height(), 0, size, pixels);
glCompressedTexImage2D(m_target, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, tex.width(), tex.height(), 0, size, texture_data);
}
break;
case CELL_GCM_TEXTURE_COMPRESSED_DXT45: // Compressed 4x4 pixels into 16 bytes
{
u32 size = ((tex.width() + 3) / 4) * ((tex.height() + 3) / 4) * 16;
glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.width(), tex.height(), 0, size, pixels);
glCompressedTexImage2D(m_target, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, tex.width(), tex.height(), 0, size, texture_data);
break;
}
case CELL_GCM_TEXTURE_G8B8:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_BYTE, texture_data);
static const GLint swizzleMaskG8B8[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN };
glRemap = swizzleMaskG8B8;
@@ -226,60 +274,39 @@ namespace rsx
case CELL_GCM_TEXTURE_R6G5B5:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
// TODO: Probably need to actually unswizzle if is_swizzled.
const u32 numPixels = tex.width() * tex.height();
unswizzledPixels = (u8 *)malloc(numPixels * 4);
// TODO: Speed.
for (u32 i = 0; i < numPixels; ++i) {
u16 c = reinterpret_cast<const be_t<u16> *>(pixels)[i];
unswizzledPixels[i * 4 + 0] = convert_6_to_8((c >> 10) & 0x3F);
unswizzledPixels[i * 4 + 1] = convert_5_to_8((c >> 5) & 0x1F);
unswizzledPixels[i * 4 + 2] = convert_5_to_8((c >> 0) & 0x1F);
unswizzledPixels[i * 4 + 3] = 255;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
free(unswizzledPixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
break;
}
case CELL_GCM_TEXTURE_DEPTH24_D8: // 24-bit unsigned fixed-point number and 8 bits of garbage
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(m_target, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, texture_data);
break;
}
case CELL_GCM_TEXTURE_DEPTH24_D8_FLOAT: // 24-bit unsigned float and 8 bits of garbage
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
glTexImage2D(m_target, 0, GL_DEPTH_COMPONENT24, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, texture_data);
break;
}
case CELL_GCM_TEXTURE_DEPTH16: // 16-bit unsigned fixed-point number
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_SHORT, pixels);
glTexImage2D(m_target, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_SHORT, texture_data);
break;
}
case CELL_GCM_TEXTURE_DEPTH16_FLOAT: // 16-bit unsigned float
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, pixels);
glTexImage2D(m_target, 0, GL_DEPTH_COMPONENT16, tex.width(), tex.height(), 0, GL_DEPTH_COMPONENT, GL_FLOAT, texture_data);
break;
}
case CELL_GCM_TEXTURE_X16: // A 16-bit fixed-point number
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
LOG_WARNING(RSX, "CELL_GCM_X16 texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_UNSIGNED_SHORT, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_UNSIGNED_SHORT, texture_data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
static const GLint swizzleMaskX16[] = { GL_RED, GL_ONE, GL_RED, GL_ONE };
@@ -289,10 +316,11 @@ namespace rsx
case CELL_GCM_TEXTURE_Y16_X16: // Two 16-bit fixed-point numbers
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
LOG_WARNING(RSX, "CELL_GCM_Y16_X16 texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_SHORT, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_UNSIGNED_SHORT, texture_data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
static const GLint swizzleMaskX32_Y16_X16[] = { GL_GREEN, GL_RED, GL_GREEN, GL_RED };
glRemap = swizzleMaskX32_Y16_X16;
break;
@@ -300,35 +328,34 @@ namespace rsx
case CELL_GCM_TEXTURE_R5G5B5A1:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
LOG_WARNING(RSX, "CELL_GCM_R5G6B5A1 texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, texture_data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
break;
}
case CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT: // Four fp16 values
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 8);
LOG_WARNING(RSX, "CELL_GCM_W16_Z16_Y16_X16_FLOAT texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_HALF_FLOAT, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_HALF_FLOAT, texture_data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
break;
}
case CELL_GCM_TEXTURE_W32_Z32_Y32_X32_FLOAT: // Four fp32 values
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 16);
LOG_WARNING(RSX, "CELL_GCM_W32_Z32_Y32_X32_FLOAT texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_FLOAT, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_FLOAT, texture_data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
break;
}
case CELL_GCM_TEXTURE_X32_FLOAT: // One 32-bit floating-point number
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_FLOAT, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RED, GL_FLOAT, texture_data);
static const GLint swizzleMaskX32_FLOAT[] = { GL_RED, GL_ONE, GL_ONE, GL_ONE };
glRemap = swizzleMaskX32_FLOAT;
@@ -337,11 +364,11 @@ namespace rsx
case CELL_GCM_TEXTURE_D1R5G5B5:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 2);
LOG_WARNING(RSX, "CELL_GCM_D1R5G5B5 texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
// TODO: Texture swizzling
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, texture_data);
static const GLint swizzleMaskX32_D1R5G5B5[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
glRemap = swizzleMaskX32_D1R5G5B5;
@@ -352,8 +379,7 @@ namespace rsx
case CELL_GCM_TEXTURE_D8R8G8B8: // 8 bits of garbage and three unsigned 8-bit fixed-point numbers
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8, texture_data);
static const GLint swizzleMaskX32_D8R8G8B8[] = { GL_ONE, GL_RED, GL_GREEN, GL_BLUE };
glRemap = swizzleMaskX32_D8R8G8B8;
@@ -363,9 +389,9 @@ namespace rsx
case CELL_GCM_TEXTURE_Y16_X16_FLOAT: // Two fp16 values
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
LOG_WARNING(RSX, "CELL_GCM_Y16_X16_FLOAT texture. Watch out for corruption due to swapped color channels!");
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_HALF_FLOAT, pixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RG, GL_HALF_FLOAT, texture_data);
glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE);
static const GLint swizzleMaskX32_Y16_X16_FLOAT[] = { GL_RED, GL_GREEN, GL_RED, GL_GREEN };
@@ -374,54 +400,9 @@ namespace rsx
}
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_B8R8_G8R8:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
const u32 numPixels = tex.width() * tex.height();
unswizzledPixels = (u8 *)malloc(numPixels * 4);
// TODO: Speed.
for (u32 i = 0; i < numPixels; i += 2)
{
unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 3];
unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 2];
unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 0];
unswizzledPixels[i * 4 + 0 + 3] = 255;
// The second pixel is the same, except for red.
unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 1];
unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 2];
unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 0];
unswizzledPixels[i * 4 + 4 + 3] = 255;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
free(unswizzledPixels);
break;
}
case ~(CELL_GCM_TEXTURE_LN | CELL_GCM_TEXTURE_UN) & CELL_GCM_TEXTURE_COMPRESSED_R8B8_R8G8:
{
glPixelStorei(GL_UNPACK_ROW_LENGTH, pitch / 4);
const u32 numPixels = tex.width() * tex.height();
unswizzledPixels = (u8 *)malloc(numPixels * 4);
// TODO: Speed.
for (u32 i = 0; i < numPixels; i += 2)
{
unswizzledPixels[i * 4 + 0 + 0] = pixels[i * 2 + 2];
unswizzledPixels[i * 4 + 0 + 1] = pixels[i * 2 + 3];
unswizzledPixels[i * 4 + 0 + 2] = pixels[i * 2 + 1];
unswizzledPixels[i * 4 + 0 + 3] = 255;
// The second pixel is the same, except for red.
unswizzledPixels[i * 4 + 4 + 0] = pixels[i * 2 + 0];
unswizzledPixels[i * 4 + 4 + 1] = pixels[i * 2 + 3];
unswizzledPixels[i * 4 + 4 + 2] = pixels[i * 2 + 1];
unswizzledPixels[i * 4 + 4 + 3] = 255;
}
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, unswizzledPixels);
free(unswizzledPixels);
glTexImage2D(m_target, 0, GL_RGBA, tex.width(), tex.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_data);
break;
}
@@ -432,8 +413,8 @@ namespace rsx
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, tex.mipmap() - 1);
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, tex.mipmap() > 1);
glTexParameteri(m_target, GL_TEXTURE_MAX_LEVEL, tex.mipmap() - 1);
glTexParameteri(m_target, GL_GENERATE_MIPMAP, tex.mipmap() > 1);
if (format != CELL_GCM_TEXTURE_B8 && format != CELL_GCM_TEXTURE_X16 && format != CELL_GCM_TEXTURE_X32_FLOAT)
{
@@ -442,48 +423,43 @@ namespace rsx
u8 remap_g = (tex.remap() >> 4) & 0x3;
u8 remap_b = (tex.remap() >> 6) & 0x3;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[remap_a]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[remap_r]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[remap_g]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[remap_b]);
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_A, glRemap[0]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_R, glRemap[1]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_G, glRemap[2]);
glTexParameteri(m_target, GL_TEXTURE_SWIZZLE_B, glRemap[3]);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s()));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t()));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r()));
glTexParameteri(m_target, GL_TEXTURE_WRAP_S, gl_wrap(tex.wrap_s()));
glTexParameteri(m_target, GL_TEXTURE_WRAP_T, gl_wrap(tex.wrap_t()));
glTexParameteri(m_target, GL_TEXTURE_WRAP_R, gl_wrap(tex.wrap_r()));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]);
glTexParameteri(m_target, GL_TEXTURE_COMPARE_FUNC, gl_tex_zfunc[tex.zfunc()]);
glTexEnvi(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (GLint)tex.bias());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
glTexParameteri(m_target, GL_TEXTURE_MIN_LOD, (tex.min_lod() >> 8));
glTexParameteri(m_target, GL_TEXTURE_MAX_LOD, (tex.max_lod() >> 8));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_tex_min_filter[tex.min_filter()]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter[tex.mag_filter()]);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
if (is_swizzled && format == CELL_GCM_TEXTURE_A8R8G8B8)
{
free(unswizzledPixels);
}
glTexParameteri(m_target, GL_TEXTURE_MIN_FILTER, gl_tex_min_filter[tex.min_filter()]);
glTexParameteri(m_target, GL_TEXTURE_MAG_FILTER, gl_tex_mag_filter[tex.mag_filter()]);
glTexParameterf(m_target, GL_TEXTURE_MAX_ANISOTROPY_EXT, max_aniso(tex.max_aniso()));
}
void texture::bind()
{
glBindTexture(GL_TEXTURE_2D, m_id);
glBindTexture(m_target, m_id);
}
void texture::unbind()
{
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(m_target, 0);
}
void texture::remove()
+17
View File
@@ -1,3 +1,4 @@
#include "OpenGL.h"
namespace rsx
{
@@ -8,6 +9,7 @@ namespace rsx
class texture
{
u32 m_id = 0;
u32 m_target = GL_TEXTURE_2D;
public:
void create();
@@ -35,10 +37,25 @@ namespace rsx
}
void init(int index, rsx::texture& tex);
/**
* If a format is marked as mandating expansion, any request to have the data uploaded to the GPU shall require that the pixel data
* be decoded/expanded fully, regardless of whether the input is swizzled. This is because some formats behave differently when swizzled pixel data
* is decoded and when data is fed directly, usually byte order is not the same. Forcing decoding/expanding fixes this but slows performance.
*/
static bool mandates_expansion(u32 format);
/**
* The pitch modifier changes the pitch value supplied by the rsx::texture by supplying a suitable divisor or 0 if no change is needed.
* The modified value, if any, is then used to supply to GL the UNPACK_ROW_LENGTH for the texture data to be supplied.
*/
static u16 get_pitch_modifier(u32 format);
void bind();
void unbind();
void remove();
void set_target(u32 target) { m_target = target; }
u32 id() const;
};
}
+35 -6
View File
@@ -1,4 +1,5 @@
#pragma once
#include "GCM.h"
enum
{
@@ -204,26 +205,54 @@ static const std::string rsx_fp_op_names[] =
"NULL", "BRK", "CAL", "IFE", "LOOP", "REP", "RET"
};
enum class texture_dimension
enum class texture_dimension : u8
{
texture_dimension_2d,
texture_dimension_2d_array,
texture_dimension_cubemap,
texture_dimension_1d = 0,
texture_dimension_2d = 1,
texture_dimension_cubemap = 2,
texture_dimension_3d = 3,
};
struct RSXFragmentProgram
{
u32 size;
u32 addr;
void *addr;
u32 offset;
u32 ctrl;
std::vector<texture_dimension> texture_dimensions;
u16 unnormalized_coords;
rsx::comparaison_function alpha_func;
bool front_back_color_enabled : 1;
bool back_color_diffuse_output : 1;
bool back_color_specular_output : 1;
u32 texture_dimensions;
rsx::window_origin origin_mode;
rsx::window_pixel_center pixel_center_mode;
u16 height;
texture_dimension get_texture_dimension(u8 id) const
{
return (texture_dimension)((texture_dimensions >> (id * 2)) & 0x3);
}
void set_texture_dimension(const std::array<texture_dimension, 16> &dimensions)
{
size_t id = 0;
for (const texture_dimension &dim : dimensions)
{
texture_dimensions &= ~(0x3 << (id * 2));
u8 d = (u8)dim;
texture_dimensions |= ((d & 0x3) << (id * 2));
id++;
}
}
RSXFragmentProgram()
: size(0)
, addr(0)
, offset(0)
, ctrl(0)
, unnormalized_coords(0)
, texture_dimensions(0)
{
}
};
+4 -4
View File
@@ -202,12 +202,12 @@ namespace rsx
u16 texture::depth() const
{
return method_registers[NV4097_SET_TEXTURE_CONTROL3] >> 20;
return method_registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] >> 20;
}
u32 texture::pitch() const
{
return method_registers[NV4097_SET_TEXTURE_CONTROL3] & 0xfffff;
return method_registers[NV4097_SET_TEXTURE_CONTROL3 + m_index] & 0xfffff;
}
void vertex_texture::init(u8 index)
@@ -386,11 +386,11 @@ namespace rsx
u16 vertex_texture::depth() const
{
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3] >> 20;
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] >> 20;
}
u32 vertex_texture::pitch() const
{
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3] & 0xfffff;
return method_registers[NV4097_SET_VERTEX_TEXTURE_CONTROL3 + (m_index * 8)] & 0xfffff;
}
}
+219 -49
View File
@@ -19,6 +19,8 @@ frame_capture_data frame_debug;
namespace rsx
{
std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
std::string shaders_cache::path_to_root()
{
return fs::get_executable_dir() + "data/";
@@ -120,11 +122,11 @@ namespace rsx
return res;
}
u32 get_vertex_type_size_on_host(Vertex_base_type type, u32 size)
u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size)
{
switch (type)
{
case Vertex_base_type::s1:
case vertex_base_type::s1:
switch (size)
{
case 1:
@@ -135,8 +137,8 @@ namespace rsx
return sizeof(u16) * 4;
}
throw new EXCEPTION("Wrong vector size");
case Vertex_base_type::f: return sizeof(f32) * size;
case Vertex_base_type::sf:
case vertex_base_type::f: return sizeof(f32) * size;
case vertex_base_type::sf:
switch (size)
{
case 1:
@@ -147,7 +149,7 @@ namespace rsx
return sizeof(f16) * 4;
}
throw new EXCEPTION("Wrong vector size");
case Vertex_base_type::ub:
case vertex_base_type::ub:
switch (size)
{
case 1:
@@ -158,16 +160,16 @@ namespace rsx
return sizeof(u8) * 4;
}
throw new EXCEPTION("Wrong vector size");
case Vertex_base_type::s32k: return sizeof(u32) * size;
case Vertex_base_type::cmp: return sizeof(u16) * 4;
case Vertex_base_type::ub256: return sizeof(u8) * 4;
case vertex_base_type::s32k: return sizeof(u32) * size;
case vertex_base_type::cmp: return sizeof(u16) * 4;
case vertex_base_type::ub256: return sizeof(u8) * 4;
default:
throw new EXCEPTION("RSXVertexData::GetTypeSize: Bad vertex data type (%d)!", type);
return 0;
}
}
void tiled_region::write(const void *src, u32 width, u32 height, u32 pitch)
{
if (!tile)
@@ -270,50 +272,35 @@ namespace rsx
}
}
thread::thread()
{
g_access_violation_handler = [this](u32 address, bool is_writing)
{
return on_access_violation(address, is_writing);
};
m_rtts_dirty = true;
memset(m_textures_dirty, -1, sizeof(m_textures_dirty));
}
thread::~thread()
{
g_access_violation_handler = nullptr;
}
void thread::capture_frame(const std::string &name)
{
frame_capture_data::draw_state draw_state = {};
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 pitch = clip_w * 4;
std::vector<size_t> color_index_to_record;
switch (method_registers[NV4097_SET_SURFACE_COLOR_TARGET])
{
case CELL_GCM_SURFACE_TARGET_0:
color_index_to_record = { 0 };
break;
case CELL_GCM_SURFACE_TARGET_1:
color_index_to_record = { 1 };
break;
case CELL_GCM_SURFACE_TARGET_MRT1:
color_index_to_record = { 0, 1 };
break;
case CELL_GCM_SURFACE_TARGET_MRT2:
color_index_to_record = { 0, 1, 2 };
break;
case CELL_GCM_SURFACE_TARGET_MRT3:
color_index_to_record = { 0, 1, 2, 3 };
break;
}
for (size_t i : color_index_to_record)
{
draw_state.color_buffer[i].width = clip_w;
draw_state.color_buffer[i].height = clip_h;
draw_state.color_buffer[i].data.resize(pitch * clip_h);
copy_render_targets_to_memory(draw_state.color_buffer[i].data.data(), i);
}
if (get_address(method_registers[NV4097_SET_SURFACE_ZETA_OFFSET], method_registers[NV4097_SET_CONTEXT_DMA_ZETA]))
{
draw_state.depth.width = clip_w;
draw_state.depth.height = clip_h;
draw_state.depth.data.resize(clip_w * clip_h * 4);
copy_depth_buffer_to_memory(draw_state.depth.data.data());
draw_state.stencil.width = clip_w;
draw_state.stencil.height = clip_h;
draw_state.stencil.data.resize(clip_w * clip_h * 4);
copy_stencil_buffer_to_memory(draw_state.stencil.data.data());
}
rsx::surface_info surface = {};
surface.unpack(rsx::method_registers[NV4097_SET_SURFACE_FORMAT]);
draw_state.width = clip_w;
draw_state.height = clip_h;
draw_state.color_format = surface.color_format;
draw_state.color_buffer = std::move(copy_render_targets_to_memory());
draw_state.depth_format = surface.depth_format;
draw_state.depth_stencil = std::move(copy_depth_stencil_buffer_to_memory());
draw_state.programs = get_programs();
draw_state.name = name;
frame_debug.draw_calls.push_back(draw_state);
@@ -331,7 +318,10 @@ namespace rsx
if (capture_current_frame)
{
for (const auto &first_count : first_count_commands)
vertex_draw_count += first_count.second;
capture_frame("Draw " + std::to_string(vertex_draw_count));
vertex_draw_count = 0;
}
}
@@ -381,7 +371,7 @@ namespace rsx
if (put == get || !Emu.IsRunning())
{
std::this_thread::sleep_for(std::chrono::milliseconds(1)); // hack
do_internal_task();
continue;
}
@@ -510,7 +500,7 @@ namespace rsx
u32 element_size = rsx::get_vertex_type_size_on_host(info.type, info.size);
if (info.type == Vertex_base_type::ub && info.size == 4)
if (info.type == vertex_base_type::ub && info.size == 4)
{
dst[0] = src[3];
dst[1] = src[2];
@@ -534,6 +524,184 @@ namespace rsx
return get_system_time() * 1000;
}
void thread::do_internal_task()
{
if (m_internal_tasks.empty())
{
std::this_thread::sleep_for(1ms);
}
else
{
std::lock_guard<std::mutex> lock{ m_mtx_task };
internal_task_entry &front = m_internal_tasks.front();
if (front.callback())
{
front.promise.set_value();
m_internal_tasks.pop_front();
}
}
}
std::future<void> thread::add_internal_task(std::function<bool()> callback)
{
std::lock_guard<std::mutex> lock{ m_mtx_task };
m_internal_tasks.emplace_back(callback);
return m_internal_tasks.back().promise.get_future();
}
void thread::invoke(std::function<bool()> callback)
{
if (get_thread_ctrl() == thread_ctrl::get_current())
{
while (true)
{
if (callback())
{
break;
}
}
}
else
{
add_internal_task(callback).wait();
}
}
std::array<u32, 4> thread::get_color_surface_addresses() const
{
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 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]
};
return
{
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 thread::get_zeta_surface_address() const
{
u32 m_context_dma_z = rsx::method_registers[NV4097_SET_CONTEXT_DMA_ZETA];
u32 offset_zeta = rsx::method_registers[NV4097_SET_SURFACE_ZETA_OFFSET];
return rsx::get_address(offset_zeta, m_context_dma_z);
}
RSXVertexProgram thread::get_current_vertex_program() const
{
RSXVertexProgram result = {};
u32 transform_program_start = rsx::method_registers[NV4097_SET_TRANSFORM_PROGRAM_START];
result.data.reserve((512 - transform_program_start) * 4);
for (int i = transform_program_start; i < 512; ++i)
{
result.data.resize((i - transform_program_start) * 4 + 4);
memcpy(result.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;
}
result.output_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK];
u32 input_mask = rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_INPUT_MASK];
u32 modulo_mask = rsx::method_registers[NV4097_SET_FREQUENCY_DIVIDER_OPERATION];
result.rsx_vertex_inputs.clear();
for (u8 index = 0; index < rsx::limits::vertex_count; ++index)
{
bool enabled = !!(input_mask & (1 << index));
if (!enabled)
continue;
if (vertex_arrays_info[index].size > 0)
{
result.rsx_vertex_inputs.push_back(
{
index,
vertex_arrays_info[index].size,
vertex_arrays_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
true
}
);
}
else if (register_vertex_info[index].size > 0)
{
result.rsx_vertex_inputs.push_back(
{
index,
register_vertex_info[index].size,
register_vertex_info[index].frequency,
!!((modulo_mask >> index) & 0x1),
false
}
);
}
}
return result;
}
RSXFragmentProgram thread::get_current_fragment_program() const
{
RSXFragmentProgram result = {};
u32 shader_program = rsx::method_registers[NV4097_SET_SHADER_PROGRAM];
result.offset = shader_program & ~0x3;
result.addr = vm::base(rsx::get_address(result.offset, (shader_program & 0x3) - 1));
result.ctrl = rsx::method_registers[NV4097_SET_SHADER_CONTROL];
result.unnormalized_coords = 0;
result.front_back_color_enabled = !rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN];
result.back_color_diffuse_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKDIFFUSE);
result.back_color_specular_output = !!(rsx::method_registers[NV4097_SET_VERTEX_ATTRIB_OUTPUT_MASK] & CELL_GCM_ATTRIB_OUTPUT_MASK_BACKSPECULAR);
result.alpha_func = to_comparaison_function(rsx::method_registers[NV4097_SET_ALPHA_FUNC]);
u32 shader_window = rsx::method_registers[NV4097_SET_SHADER_WINDOW];
result.origin_mode = rsx::to_window_origin((shader_window >> 12) & 0xF);
result.pixel_center_mode = rsx::to_window_pixel_center((shader_window >> 16) & 0xF);
result.height = shader_window & 0xFFF;
std::array<texture_dimension, 16> texture_dimensions;
for (u32 i = 0; i < rsx::limits::textures_count; ++i)
{
if (!textures[i].enabled())
texture_dimensions[i] = texture_dimension::texture_dimension_2d;
else if (textures[i].dimension() == 1)
texture_dimensions[i] = texture_dimension::texture_dimension_1d;
else if (textures[i].dimension() == 2)
{
if (textures[i].cubemap())
texture_dimensions[i] = texture_dimension::texture_dimension_cubemap;
else
texture_dimensions[i] = texture_dimension::texture_dimension_2d;
}
else if (textures[i].dimension() == 3)
texture_dimensions[i] = texture_dimension::texture_dimension_3d;
else
throw EXCEPTION("Unable to determine texture dimension");
if (textures[i].enabled() && (textures[i].format() & CELL_GCM_TEXTURE_UN))
result.unnormalized_coords |= (1 << i);
}
result.set_texture_dimension(texture_dimensions);
return result;
}
void thread::reset()
{
//setup method registers
@@ -598,6 +766,8 @@ namespace rsx
method_registers[NV4097_SET_ZSTENCIL_CLEAR_VALUE] = 0xffffffff;
method_registers[NV4097_SET_CONTEXT_DMA_REPORT] = CELL_GCM_CONTEXT_DMA_TO_MEMORY_GET_REPORT;
rsx::method_registers[NV4097_SET_TWO_SIDE_LIGHT_EN] = true;
rsx::method_registers[NV4097_SET_ALPHA_FUNC] = CELL_GCM_ALWAYS;
// Reset vertex attrib array
for (int i = 0; i < limits::vertex_count; i++)
+61 -35
View File
@@ -15,19 +15,15 @@ extern u64 get_system_time();
struct frame_capture_data
{
struct buffer
{
std::vector<u8> data;
size_t width = 0, height = 0;
};
struct draw_state
{
std::string name;
std::pair<std::string, std::string> programs;
buffer color_buffer[4];
buffer depth;
buffer stencil;
size_t width = 0, height = 0;
rsx::surface_color_format color_format;
std::array<std::vector<gsl::byte>, 4> color_buffer;
rsx::surface_depth_format depth_format;
std::array<std::vector<gsl::byte>, 2> depth_stencil;
};
std::vector<std::pair<u32, u32> > command_queue;
std::vector<draw_state> draw_calls;
@@ -148,7 +144,7 @@ namespace rsx
static std::string path_to_root();
};
u32 get_vertex_type_size_on_host(Vertex_base_type type, u32 size);
u32 get_vertex_type_size_on_host(vertex_base_type type, u32 size);
u32 get_address(u32 offset, u32 location);
@@ -167,9 +163,9 @@ namespace rsx
{
u8 log2height;
u8 log2width;
u8 antialias;
u8 depth_format;
u8 color_format;
surface_antialiasing antialias;
surface_depth_format depth_format;
surface_color_format color_format;
u32 width;
u32 height;
@@ -181,9 +177,9 @@ namespace rsx
log2height = surface_format >> 24;
log2width = (surface_format >> 16) & 0xff;
antialias = (surface_format >> 12) & 0xf;
depth_format = (surface_format >> 5) & 0x7;
color_format = surface_format & 0x1f;
antialias = to_surface_antialiasing((surface_format >> 12) & 0xf);
depth_format = to_surface_depth_format((surface_format >> 5) & 0x7);
color_format = to_surface_color_format(surface_format & 0x1f);
width = 1 << (u32(log2width) + 1);
height = 1 << (u32(log2width) + 1);
@@ -195,7 +191,7 @@ namespace rsx
u16 frequency = 0;
u8 stride = 0;
u8 size = 0;
Vertex_base_type type = Vertex_base_type::f;
vertex_base_type type = vertex_base_type::f;
void unpack_array(u32 data_array_format)
{
@@ -206,6 +202,13 @@ namespace rsx
}
};
enum class draw_command
{
array,
inlined_array,
indexed,
};
class thread : public named_thread_t
{
protected:
@@ -260,6 +263,7 @@ namespace rsx
bool capture_current_frame = false;
void capture_frame(const std::string &name);
public:
u32 ioAddress, ioSize;
int flip_status;
@@ -275,21 +279,22 @@ namespace rsx
u32 ctxt_addr;
u32 report_main_addr;
u32 label_addr;
enum class Draw_command
{
draw_command_array,
draw_command_inlined_array,
draw_command_indexed,
} draw_command;
Primitive_type draw_mode;
rsx::draw_command draw_command;
primitive_type draw_mode;
u32 local_mem_addr, main_mem_addr;
bool strict_ordering[0x1000];
bool draw_inline_vertex_array;
std::vector<u32> inline_vertex_array;
bool m_rtts_dirty;
bool m_textures_dirty[16];
protected:
std::array<u32, 4> get_color_surface_addresses() const;
u32 get_zeta_surface_address() const;
RSXVertexProgram get_current_vertex_program() const;
RSXFragmentProgram get_current_fragment_program() const;
public:
u32 draw_array_count;
u32 draw_array_first;
@@ -307,7 +312,8 @@ namespace rsx
std::set<u32> m_used_gcm_commands;
protected:
virtual ~thread() {}
thread();
virtual ~thread();
virtual void on_task() override;
@@ -322,6 +328,27 @@ namespace rsx
virtual bool do_method(u32 cmd, u32 value) { return false; }
virtual void flip(int buffer) = 0;
virtual u64 timestamp() const;
virtual bool on_access_violation(u32 address, bool is_writing) { return false; }
private:
std::mutex m_mtx_task;
struct internal_task_entry
{
std::function<bool()> callback;
std::promise<void> promise;
internal_task_entry(std::function<bool()> callback) : callback(callback)
{
}
};
std::deque<internal_task_entry> m_internal_tasks;
void do_internal_task();
public:
std::future<void> add_internal_task(std::function<bool()> callback);
void invoke(std::function<bool()> callback);
/**
* Fill buffer with 4x4 scale offset matrix.
@@ -347,21 +374,20 @@ namespace rsx
* Copy rtt values to buffer.
* TODO: It's more efficient to combine multiple call of this function into one.
*/
virtual void copy_render_targets_to_memory(void *buffer, u8 rtt) {};
virtual std::array<std::vector<gsl::byte>, 4> copy_render_targets_to_memory() {
return std::array<std::vector<gsl::byte>, 4>();
};
/**
* Copy depth content to buffer.
* Copy depth and stencil content to buffers.
* TODO: It's more efficient to combine multiple call of this function into one.
*/
virtual void copy_depth_buffer_to_memory(void *buffer) {};
/**
* Copy stencil content to buffer.
* TODO: It's more efficient to combine multiple call of this function into one.
*/
virtual void copy_stencil_buffer_to_memory(void *buffer) {};
virtual std::array<std::vector<gsl::byte>, 2> copy_depth_stencil_buffer_to_memory() {
return std::array<std::vector<gsl::byte>, 2>();
};
virtual std::pair<std::string, std::string> get_programs() const { return std::make_pair("", ""); };
public:
void reset();
void init(const u32 ioAddress, const u32 ioSize, const u32 ctrlAddress, const u32 localAddress);
+16
View File
@@ -190,7 +190,23 @@ static const std::string rsx_vp_vec_op_names[] =
"SEQ", "SFL", "SGT", "SLE", "SNE", "STR", "SSG", "NULL", "NULL", "TXL"
};
struct rsx_vertex_input
{
u8 location; // between 0 and 15
u8 size; // between 1 and 4
u16 frequency;
bool is_modulo; // either modulo frequency or divide frequency
bool is_array; // false if "reg value"
bool operator==(const rsx_vertex_input other) const
{
return location == other.location && size == other.size && frequency == other.frequency && is_modulo == other.is_modulo && is_array == other.is_array;
}
};
struct RSXVertexProgram
{
std::vector<u32> data;
std::vector<rsx_vertex_input> rsx_vertex_inputs;
u32 output_mask;
};
+55 -8
View File
@@ -14,10 +14,10 @@ namespace rsx
rsx_method_t methods[0x10000 >> 2]{};
template<typename Type> struct vertex_data_type_from_element_type;
template<> struct vertex_data_type_from_element_type<float> { static const Vertex_base_type type = Vertex_base_type::f; };
template<> struct vertex_data_type_from_element_type<f16> { static const Vertex_base_type type = Vertex_base_type::sf; };
template<> struct vertex_data_type_from_element_type<u8> { static const Vertex_base_type type = Vertex_base_type::ub; };
template<> struct vertex_data_type_from_element_type<u16> { static const Vertex_base_type type = Vertex_base_type::s1; };
template<> struct vertex_data_type_from_element_type<float> { static const vertex_base_type type = vertex_base_type::f; };
template<> struct vertex_data_type_from_element_type<f16> { static const vertex_base_type type = vertex_base_type::sf; };
template<> struct vertex_data_type_from_element_type<u8> { static const vertex_base_type type = vertex_base_type::ub; };
template<> struct vertex_data_type_from_element_type<u16> { static const vertex_base_type type = vertex_base_type::s1; };
namespace nv406e
{
@@ -160,7 +160,7 @@ namespace rsx
force_inline void draw_arrays(thread* rsx, u32 arg)
{
rsx->draw_command = thread::Draw_command::draw_command_array;
rsx->draw_command = rsx::draw_command::array;
u32 first = arg & 0xffffff;
u32 count = (arg >> 24) + 1;
@@ -169,7 +169,7 @@ namespace rsx
force_inline void draw_index_array(thread* rsx, u32 arg)
{
rsx->draw_command = thread::Draw_command::draw_command_indexed;
rsx->draw_command = rsx::draw_command::indexed;
u32 first = arg & 0xffffff;
u32 count = (arg >> 24) + 1;
@@ -178,7 +178,7 @@ namespace rsx
force_inline void draw_inline_array(thread* rsx, u32 arg)
{
rsx->draw_command = thread::Draw_command::draw_command_inlined_array;
rsx->draw_command = rsx::draw_command::inlined_array;
rsx->draw_inline_vertex_array = true;
rsx->inline_vertex_array.push_back(arg);
}
@@ -282,6 +282,20 @@ namespace rsx
break;
}
}
force_inline void set_surface_dirty_bit(thread* rsx, u32)
{
rsx->m_rtts_dirty = true;
}
template<u32 index>
struct set_texture_dirty_bit
{
force_inline static void impl(thread* rsx, u32 arg)
{
rsx->m_textures_dirty[index] = true;
}
};
}
namespace nv308a
@@ -656,9 +670,9 @@ namespace rsx
double limit;
switch (rpcs3::state.config.rsx.frame_limit.value())
{
case rsx_frame_limit::_30: limit = 30.; break;
case rsx_frame_limit::_50: limit = 50.; break;
case rsx_frame_limit::_59_94: limit = 59.94; break;
case rsx_frame_limit::_30: limit = 30.; break;
case rsx_frame_limit::_60: limit = 60.; break;
case rsx_frame_limit::Auto: limit = rsx->fps_limit; break; //TODO
@@ -786,6 +800,16 @@ namespace rsx
bind<NV406E_SEMAPHORE_ACQUIRE, nv406e::semaphore_acquire>();
bind<NV406E_SEMAPHORE_RELEASE, nv406e::semaphore_release>();
/*
// Store previous fbo addresses to detect RTT config changes.
std::array<u32, 4> m_previous_color_address = {};
u32 m_previous_address_z = 0;
u32 m_previous_target = 0;
u32 m_previous_clip_horizontal = 0;
u32 m_previous_clip_vertical = 0;
*/
// NV4097
bind<NV4097_TEXTURE_READ_SEMAPHORE_RELEASE, nv4097::texture_read_semaphore_release>();
bind<NV4097_BACK_END_WRITE_SEMAPHORE_RELEASE, nv4097::back_end_write_semaphore_release>();
@@ -806,6 +830,29 @@ namespace rsx
bind_range<NV4097_SET_TRANSFORM_PROGRAM + 3, 4, 128, nv4097::set_transform_program>();
bind_cpu_only<NV4097_GET_REPORT, nv4097::get_report>();
bind_cpu_only<NV4097_CLEAR_REPORT_VALUE, nv4097::clear_report_value>();
bind<NV4097_SET_SURFACE_CLIP_HORIZONTAL, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_SURFACE_CLIP_VERTICAL, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_SURFACE_COLOR_AOFFSET, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_SURFACE_COLOR_BOFFSET, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_SURFACE_COLOR_COFFSET, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_SURFACE_COLOR_DOFFSET, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_SURFACE_ZETA_OFFSET, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_CONTEXT_DMA_COLOR_A, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_CONTEXT_DMA_COLOR_B, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_CONTEXT_DMA_COLOR_C, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_CONTEXT_DMA_COLOR_D, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_CONTEXT_DMA_ZETA, nv4097::set_surface_dirty_bit>();
bind<NV4097_SET_SURFACE_FORMAT, nv4097::set_surface_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_OFFSET, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_FORMAT, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_ADDRESS, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_CONTROL0, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_CONTROL1, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_CONTROL2, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_CONTROL3, 1, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_FILTER, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_IMAGE_RECT, 8, 16, nv4097::set_texture_dirty_bit>();
bind_range<NV4097_SET_TEXTURE_BORDER_COLOR, 8, 16, nv4097::set_texture_dirty_bit>();
//NV308A
bind_range<NV308A_COLOR, 1, 256, nv308a::color>();
+1 -1
View File
@@ -40,7 +40,7 @@ namespace rsx
u32 y_mask = 0xAAAAAAAA;
// We have to limit the masks to the lower of the two dimensions to allow for non-square textures
u16 limit_mask = (log2width < log2height) ? log2width : log2height;
u32 limit_mask = (log2width < log2height) ? log2width : log2height;
// double the limit mask to account for bits in both x and y
limit_mask = 1 << (limit_mask << 1);
+65 -95
View File
@@ -47,7 +47,7 @@ struct content_permission_t final
s32 cellHddGameCheck(PPUThread& ppu, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellHddGameStatCallback> funcStat, u32 container)
{
cellGame.warning("cellHddGameCheck(version=%d, dirName=*0x%x, errDialog=%d, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
cellGame.error("cellHddGameCheck(version=%d, dirName=*0x%x, errDialog=%d, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
std::string dir = dirName.get_ptr();
@@ -78,27 +78,19 @@ s32 cellHddGameCheck(PPUThread& ppu, u32 version, vm::cptr<char> dirName, u32 er
else
{
// TODO: Is cellHddGameCheck really responsible for writing the information in get->getParam ? (If not, delete this else)
vfsFile f("/dev_hdd0/game/" + dir + "/PARAM.SFO");
const PSFLoader psf(f);
if (!psf)
{
return CELL_HDDGAME_ERROR_BROKEN;
}
const auto& psf = psf::load(vfsFile("/dev_hdd0/game/" + dir + "/PARAM.SFO").VRead<char>());
get->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
get->getParam.attribute = psf.GetInteger("ATTRIBUTE");
get->getParam.resolution = psf.GetInteger("RESOLUTION");
get->getParam.soundFormat = psf.GetInteger("SOUND_FORMAT");
std::string title = psf.GetString("TITLE");
strcpy_trunc(get->getParam.title, title);
std::string app_ver = psf.GetString("APP_VER");
strcpy_trunc(get->getParam.dataVersion, app_ver);
strcpy_trunc(get->getParam.titleId, dir);
get->getParam.parentalLevel = psf.at("PARENTAL_LEVEL").as_integer();
get->getParam.attribute = psf.at("ATTRIBUTE").as_integer();
get->getParam.resolution = psf.at("RESOLUTION").as_integer();
get->getParam.soundFormat = psf.at("SOUND_FORMAT").as_integer();
strcpy_trunc(get->getParam.title, psf.at("TITLE").as_string());
strcpy_trunc(get->getParam.dataVersion, psf.at("APP_VER").as_string());
strcpy_trunc(get->getParam.titleId, psf.at("TITLE_ID").as_string());
for (u32 i = 0; i < CELL_HDDGAME_SYSP_LANGUAGE_NUM; i++)
{
title = psf.GetString(fmt::format("TITLE_%02d", i));
strcpy_trunc(get->getParam.titleLang[i], title);
strcpy_trunc(get->getParam.titleLang[i], psf::get_string(psf, fmt::format("TITLE_%02d", i)));
}
}
@@ -167,17 +159,17 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
size->sysSizeKB = 0;
}
vfsFile f("/app_home/../PARAM.SFO");
const PSFLoader psf(f);
const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead<char>());
if (!psf)
if (psf.empty())
{
// According to testing (in debug mode) cellGameBootCheck doesn't return an error code, when PARAM.SFO doesn't exist.
cellGame.error("cellGameBootCheck(): Cannot read PARAM.SFO.");
return CELL_GAME_RET_OK;
}
std::string category = psf.GetString("CATEGORY");
if (category.substr(0, 2) == "DG")
const std::string& category = psf.at("CATEGORY").as_string();
if (category == "DG")
{
*type = CELL_GAME_GAMETYPE_DISC;
*attributes = 0; // TODO
@@ -188,9 +180,9 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
return CELL_GAME_ERROR_BUSY;
}
}
else if (category.substr(0, 2) == "HG")
else if (category == "HG")
{
std::string titleId = psf.GetString("TITLE_ID");
const std::string& titleId = psf.at("TITLE_ID").as_string();
*type = CELL_GAME_GAMETYPE_HDD;
*attributes = 0; // TODO
if (dirName) strcpy_trunc(*dirName, titleId);
@@ -200,9 +192,9 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
return CELL_GAME_ERROR_BUSY;
}
}
else if (category.substr(0, 2) == "GD")
else if (category == "GD")
{
std::string titleId = psf.GetString("TITLE_ID");
const std::string& titleId = psf.at("TITLE_ID").as_string();
*type = CELL_GAME_GAMETYPE_DISC;
*attributes = CELL_GAME_ATTRIBUTE_PATCH; // TODO
if (dirName) strcpy_trunc(*dirName, titleId); // ???
@@ -212,7 +204,7 @@ s32 cellGameBootCheck(vm::ptr<u32> type, vm::ptr<u32> attributes, vm::ptr<CellGa
return CELL_GAME_ERROR_BUSY;
}
}
else if (psf)
else
{
cellGame.error("cellGameBootCheck(): Unknown CATEGORY.");
}
@@ -234,22 +226,15 @@ s32 cellGamePatchCheck(vm::ptr<CellGameContentSize> size, vm::ptr<void> reserved
size->sysSizeKB = 0;
}
vfsFile f("/app_home/../PARAM.SFO");
const PSFLoader psf(f);
if (!psf)
{
cellGame.error("cellGamePatchCheck(): CELL_GAME_ERROR_ACCESS_ERROR (cannot read PARAM.SFO)");
return CELL_GAME_ERROR_ACCESS_ERROR;
}
const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead<char>());
std::string category = psf.GetString("CATEGORY");
if (category.substr(0, 2) != "GD")
if (psf.empty() || psf.at("CATEGORY").as_string() != "GD")
{
cellGame.error("cellGamePatchCheck(): CELL_GAME_ERROR_NOTPATCH");
return CELL_GAME_ERROR_NOTPATCH;
}
if (!fxm::make<content_permission_t>("/dev_hdd0/game/" + psf.GetString("TITLE_ID"), false))
if (!fxm::make<content_permission_t>("/dev_hdd0/game/" + psf.at("TITLE_ID").as_string(), false))
{
return CELL_GAME_ERROR_BUSY;
}
@@ -358,7 +343,7 @@ s32 cellGameContentPermit(vm::ptr<char[CELL_GAME_PATH_MAX]> contentInfoPath, vm:
s32 cellGameDataCheckCreate2(PPUThread& ppu, u32 version, vm::cptr<char> dirName, u32 errDialog, vm::ptr<CellGameDataStatCallback> funcStat, u32 container)
{
cellGame.warning("cellGameDataCheckCreate2(version=0x%x, dirName=*0x%x, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
cellGame.error("cellGameDataCheckCreate2(version=0x%x, dirName=*0x%x, errDialog=0x%x, funcStat=*0x%x, container=%d)", version, dirName, errDialog, funcStat, container);
if (version != CELL_GAMEDATA_VERSION_CURRENT || errDialog > 1)
{
@@ -377,13 +362,7 @@ s32 cellGameDataCheckCreate2(PPUThread& ppu, u32 version, vm::cptr<char> dirName
return CELL_GAMEDATA_RET_OK;
}
vfsFile f("/app_home/../PARAM.SFO");
const PSFLoader psf(f);
if (!psf)
{
cellGame.error("cellGameDataCheckCreate2(): CELL_GAMEDATA_ERROR_BROKEN (cannot read PARAM.SFO)");
return CELL_GAMEDATA_ERROR_BROKEN;
}
const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead<char>());
vm::var<CellGameDataCBResult> cbResult;
vm::var<CellGameDataStatGet> cbGet;
@@ -406,10 +385,10 @@ s32 cellGameDataCheckCreate2(PPUThread& ppu, u32 version, vm::cptr<char> dirName
cbGet->sysSizeKB = 0;
cbGet->getParam.attribute = CELL_GAMEDATA_ATTR_NORMAL;
cbGet->getParam.parentalLevel = psf.GetInteger("PARENTAL_LEVEL");
strcpy_trunc(cbGet->getParam.dataVersion, psf.GetString("APP_VER"));
strcpy_trunc(cbGet->getParam.titleId, psf.GetString("TITLE_ID"));
strcpy_trunc(cbGet->getParam.title, psf.GetString("TITLE"));
cbGet->getParam.parentalLevel = psf.at("PARENTAL_LEVEL").as_integer();
strcpy_trunc(cbGet->getParam.dataVersion, psf.at("APP_VER").as_string());
strcpy_trunc(cbGet->getParam.titleId, psf.at("TITLE_ID").as_string());
strcpy_trunc(cbGet->getParam.title, psf.at("TITLE").as_string());
// TODO: write lang titles
funcStat(ppu, cbResult, cbGet, cbSet);
@@ -505,26 +484,21 @@ s32 cellGameGetParamInt(u32 id, vm::ptr<u32> value)
{
cellGame.warning("cellGameGetParamInt(id=%d, value=*0x%x)", id, value);
// TODO: Access through cellGame***Check functions
vfsFile f("/app_home/../PARAM.SFO");
const PSFLoader psf(f);
const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead<char>());
if (!psf)
{
return CELL_GAME_ERROR_FAILURE;
}
std::string key;
switch(id)
{
case CELL_GAME_PARAMID_PARENTAL_LEVEL: *value = psf.GetInteger("PARENTAL_LEVEL"); break;
case CELL_GAME_PARAMID_RESOLUTION: *value = psf.GetInteger("RESOLUTION"); break;
case CELL_GAME_PARAMID_SOUND_FORMAT: *value = psf.GetInteger("SOUND_FORMAT"); break;
case CELL_GAME_PARAMID_PARENTAL_LEVEL: key = "PARENTAL_LEVEL"; break;
case CELL_GAME_PARAMID_RESOLUTION: key = "RESOLUTION"; break;
case CELL_GAME_PARAMID_SOUND_FORMAT: key = "SOUND_FORMAT"; break;
default:
cellGame.error("cellGameGetParamInt(): Unimplemented parameter (%d)", id);
return CELL_GAME_ERROR_INVALID_ID;
}
*value = psf.at(key).as_integer();
return CELL_OK;
}
@@ -532,50 +506,46 @@ s32 cellGameGetParamString(u32 id, vm::ptr<char> buf, u32 bufsize)
{
cellGame.warning("cellGameGetParamString(id=%d, buf=*0x%x, bufsize=%d)", id, buf, bufsize);
// TODO: Access through cellGame***Check functions
vfsFile f("/app_home/../PARAM.SFO");
const PSFLoader psf(f);
if (!psf)
{
return CELL_GAME_ERROR_FAILURE;
}
const auto& psf = psf::load(vfsFile("/app_home/../PARAM.SFO").VRead<char>());
std::string data;
std::string key;
switch(id)
{
case CELL_GAME_PARAMID_TITLE: data = psf.GetString("TITLE"); break; // TODO: Is this value correct?
case CELL_GAME_PARAMID_TITLE_DEFAULT: data = psf.GetString("TITLE"); break;
case CELL_GAME_PARAMID_TITLE_JAPANESE: data = psf.GetString("TITLE_00"); break;
case CELL_GAME_PARAMID_TITLE_ENGLISH: data = psf.GetString("TITLE_01"); break;
case CELL_GAME_PARAMID_TITLE_FRENCH: data = psf.GetString("TITLE_02"); break;
case CELL_GAME_PARAMID_TITLE_SPANISH: data = psf.GetString("TITLE_03"); break;
case CELL_GAME_PARAMID_TITLE_GERMAN: data = psf.GetString("TITLE_04"); break;
case CELL_GAME_PARAMID_TITLE_ITALIAN: data = psf.GetString("TITLE_05"); break;
case CELL_GAME_PARAMID_TITLE_DUTCH: data = psf.GetString("TITLE_06"); break;
case CELL_GAME_PARAMID_TITLE_PORTUGUESE: data = psf.GetString("TITLE_07"); break;
case CELL_GAME_PARAMID_TITLE_RUSSIAN: data = psf.GetString("TITLE_08"); break;
case CELL_GAME_PARAMID_TITLE_KOREAN: data = psf.GetString("TITLE_09"); break;
case CELL_GAME_PARAMID_TITLE_CHINESE_T: data = psf.GetString("TITLE_10"); break;
case CELL_GAME_PARAMID_TITLE_CHINESE_S: data = psf.GetString("TITLE_11"); break;
case CELL_GAME_PARAMID_TITLE_FINNISH: data = psf.GetString("TITLE_12"); break;
case CELL_GAME_PARAMID_TITLE_SWEDISH: data = psf.GetString("TITLE_13"); break;
case CELL_GAME_PARAMID_TITLE_DANISH: data = psf.GetString("TITLE_14"); break;
case CELL_GAME_PARAMID_TITLE_NORWEGIAN: data = psf.GetString("TITLE_15"); break;
case CELL_GAME_PARAMID_TITLE_POLISH: data = psf.GetString("TITLE_16"); break;
case CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL: data = psf.GetString("TITLE_17"); break;
case CELL_GAME_PARAMID_TITLE_ENGLISH_UK: data = psf.GetString("TITLE_18"); break;
case CELL_GAME_PARAMID_TITLE: key = "TITLE"; break; // TODO: Is this value correct?
case CELL_GAME_PARAMID_TITLE_DEFAULT: key = "TITLE"; break;
case CELL_GAME_PARAMID_TITLE_JAPANESE: key = "TITLE_00"; break;
case CELL_GAME_PARAMID_TITLE_ENGLISH: key = "TITLE_01"; break;
case CELL_GAME_PARAMID_TITLE_FRENCH: key = "TITLE_02"; break;
case CELL_GAME_PARAMID_TITLE_SPANISH: key = "TITLE_03"; break;
case CELL_GAME_PARAMID_TITLE_GERMAN: key = "TITLE_04"; break;
case CELL_GAME_PARAMID_TITLE_ITALIAN: key = "TITLE_05"; break;
case CELL_GAME_PARAMID_TITLE_DUTCH: key = "TITLE_06"; break;
case CELL_GAME_PARAMID_TITLE_PORTUGUESE: key = "TITLE_07"; break;
case CELL_GAME_PARAMID_TITLE_RUSSIAN: key = "TITLE_08"; break;
case CELL_GAME_PARAMID_TITLE_KOREAN: key = "TITLE_09"; break;
case CELL_GAME_PARAMID_TITLE_CHINESE_T: key = "TITLE_10"; break;
case CELL_GAME_PARAMID_TITLE_CHINESE_S: key = "TITLE_11"; break;
case CELL_GAME_PARAMID_TITLE_FINNISH: key = "TITLE_12"; break;
case CELL_GAME_PARAMID_TITLE_SWEDISH: key = "TITLE_13"; break;
case CELL_GAME_PARAMID_TITLE_DANISH: key = "TITLE_14"; break;
case CELL_GAME_PARAMID_TITLE_NORWEGIAN: key = "TITLE_15"; break;
case CELL_GAME_PARAMID_TITLE_POLISH: key = "TITLE_16"; break;
case CELL_GAME_PARAMID_TITLE_PORTUGUESE_BRAZIL: key = "TITLE_17"; break;
case CELL_GAME_PARAMID_TITLE_ENGLISH_UK: key = "TITLE_18"; break;
case CELL_GAME_PARAMID_TITLE_ID: data = psf.GetString("TITLE_ID"); break;
case CELL_GAME_PARAMID_VERSION: data = psf.GetString("PS3_SYSTEM_VER"); break;
case CELL_GAME_PARAMID_APP_VER: data = psf.GetString("APP_VER"); break;
case CELL_GAME_PARAMID_TITLE_ID: key = "TITLE_ID"; break;
case CELL_GAME_PARAMID_VERSION: key = "PS3_SYSTEM_VER"; break;
case CELL_GAME_PARAMID_APP_VER: key = "APP_VER"; break;
default:
cellGame.error("cellGameGetParamString(): Unimplemented parameter (%d)", id);
return CELL_GAME_ERROR_INVALID_ID;
}
if (data.size() >= bufsize) data.resize(bufsize - 1);
memcpy(buf.get_ptr(), data.c_str(), data.size() + 1);
const std::string& value = psf.at(key).as_string().substr(0, bufsize - 1);
std::copy_n(value.c_str(), value.size() + 1, buf.get_ptr());
return CELL_OK;
}
+7 -7
View File
@@ -9,6 +9,13 @@ enum CellPngTxtType : s32
CELL_PNG_ITXT = 2,
};
enum CellPngUnknownLocation : s32
{
CELL_PNG_BEFORE_PLTE = 1,
CELL_PNG_BEFORE_IDAT = 2,
CELL_PNG_AFTER_IDAT = 8,
};
struct CellPngPLTEentry
{
u8 red;
@@ -33,13 +40,6 @@ struct CellPngSPLTentry
be_t<u32> paletteEntriesNumber;
};
enum CellPngUnknownLocation : s32
{
CELL_PNG_BEFORE_PLTE = 1,
CELL_PNG_BEFORE_IDAT = 2,
CELL_PNG_AFTER_IDAT = 8,
};
struct CellPngTextInfo
{
be_t<s32> txtType; // CellPngTxtType
File diff suppressed because it is too large Load Diff
+58 -23
View File
@@ -83,9 +83,20 @@ enum CellPngDecDecodeStatus : s32
CELL_PNGDEC_DEC_STATUS_STOP = 1,
};
enum CellPngDecBufferMode : s32
{
CELL_PNGDEC_LINE_MODE = 1,
};
enum CellPngDecSpuMode : s32
{
CELL_PNGDEC_RECEIVE_EVENT = 0,
CELL_PNGDEC_TRYRECEIVE_EVENT = 1,
};
// Callbacks for memory management
using CellPngDecCbControlMalloc = vm::ptr<void>(u32 size, vm::ptr<void> cbCtrlMallocArg);
using CellPngDecCbControlFree = s32(vm::ptr<void> ptr, vm::ptr<void> cbCtrlFreeArg);
using CellPngDecCbControlFree = s32(vm::ptr<void> ptr, vm::ptr<void> cbCtrlFreeArg);
// Structs
struct CellPngDecThreadInParam
@@ -179,18 +190,6 @@ struct CellPngDecDataOutInfo
be_t<s32> status; // CellPngDecDecodeStatus
};
// Defines for decoding partial streams
enum CellPngDecBufferMode : s32
{
CELL_PNGDEC_LINE_MODE = 1,
};
enum CellPngDecSpuMode : s32
{
CELL_PNGDEC_RECEIVE_EVENT = 0,
CELL_PNGDEC_TRYRECEIVE_EVENT = 1,
};
// Structs for decoding partial streams
struct CellPngDecStrmInfo
{
@@ -248,7 +247,7 @@ struct CellPngDecExtOutParam
// Callbacks for decoding partial streams
using CellPngDecCbControlStream = s32(vm::ptr<CellPngDecStrmInfo> strmInfo, vm::ptr<CellPngDecStrmParam> strmParam, vm::ptr<void> cbCtrlStrmArg);
using CellPngDecCbControlDisp = s32(vm::ptr<CellPngDecDispInfo> dispInfo, vm::ptr<CellPngDecDispParam> dispParam, vm::ptr<void> cbCtrlDispArg);
using CellPngDecCbControlDisp = s32(vm::ptr<CellPngDecDispInfo> dispInfo, vm::ptr<CellPngDecDispParam> dispParam, vm::ptr<void> cbCtrlDispArg);
struct CellPngDecCbCtrlStrm
{
@@ -263,7 +262,7 @@ struct CellPngDecCbCtrlDisp
};
// Custom structs
struct PngDecoder
struct PngHandle
{
vm::ptr<CellPngDecCbControlMalloc> malloc;
vm::ptr<void> malloc_arg;
@@ -271,17 +270,53 @@ struct PngDecoder
vm::ptr<void> free_arg;
};
// For reading from a buffer using libpng
struct PngBuffer
{
// The cursor location and data pointer for reading from a buffer
size_t cursor;
size_t length;
vm::bptr<void> data;
// The file descriptor, and whether we need to read from a file descriptor
bool file;
u32 fd;
};
struct PngStream
{
vm::ptr<PngDecoder> dec;
// old data:
u32 fd;
u64 fileSize;
// PNG decoding structures
CellPngDecInfo info;
CellPngDecOutParam outParam;
CellPngDecSrc src;
CellPngDecOutParam out_param;
CellPngDecSrc source;
CellPngDecStrmInfo streamInfo;
CellPngDecStrmParam streamParam;
// Fixed alpha value and flag
bool fixed_alpha;
be_t<u32> fixed_alpha_colour;
// Pixel packing value
be_t<s32> packing;
// PNG custom read function structure, for decoding from a buffer
vm::ptr<PngBuffer> buffer;
// libpng structures for reading and decoding the PNG file
png_structp png_ptr;
png_infop info_ptr;
};
// Converts libpng colour type to cellPngDec colour type
static s32 getPngDecColourType(u8 type)
{
switch (type)
{
case PNG_COLOR_TYPE_RGB: return CELL_PNGDEC_RGB;
case PNG_COLOR_TYPE_RGBA: return CELL_PNGDEC_RGBA; // We can't diffrentiate between ARGB and RGBA. Doesn't seem to be exactly important.
case PNG_COLOR_TYPE_PALETTE: return CELL_PNGDEC_PALETTE;
case PNG_COLOR_TYPE_GRAY: return CELL_PNGDEC_GRAYSCALE;
case PNG_COLOR_TYPE_GRAY_ALPHA: return CELL_PNGDEC_GRAYSCALE_ALPHA;
default: throw EXCEPTION("Unknown colour type: %d", type);
}
}
+24 -24
View File
@@ -258,7 +258,7 @@ u8 RescDstFormat2SysutilFormat(u32 dstFormat)
{
case CELL_RESC_SURFACE_F_W16Z16Y16X16:
return CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_R16G16B16X16_FLOAT;
default:
default:
return CELL_VIDEO_OUT_BUFFER_COLOR_FORMAT_X8R8G8B8;
}
}
@@ -267,24 +267,24 @@ u8 GcmSurfaceFormat2GcmTextureFormat(u8 surfaceFormat, u8 surfaceType)
{
u8 result = 0;
switch (surfaceFormat)
switch (rsx::to_surface_color_format(surfaceFormat))
{
case CELL_GCM_SURFACE_A8R8G8B8:
result = CELL_GCM_TEXTURE_A8R8G8B8;
case rsx::surface_color_format::a8r8g8b8:
result = CELL_GCM_TEXTURE_A8R8G8B8;
break;
case CELL_GCM_SURFACE_F_W16Z16Y16X16:
result = CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT;
case rsx::surface_color_format::w16z16y16x16:
result = CELL_GCM_TEXTURE_W16_Z16_Y16_X16_FLOAT;
break;
default:
default:
return 0xFF; //Error
}
switch (surfaceType)
{
case CELL_GCM_SURFACE_PITCH:
case CELL_GCM_SURFACE_PITCH:
result |= CELL_GCM_TEXTURE_LN;
break;
case CELL_GCM_SURFACE_SWIZZLE:
case CELL_GCM_SURFACE_SWIZZLE:
result |= CELL_GCM_TEXTURE_SZ;
break;
default:
@@ -300,13 +300,13 @@ s32 GetRescDestsIndex(u32 dstMode)
{
switch(dstMode)
{
case CELL_RESC_720x480:
case CELL_RESC_720x480:
return 0;
case CELL_RESC_720x576:
case CELL_RESC_720x576:
return 1;
case CELL_RESC_1280x720:
case CELL_RESC_1280x720:
return 2;
case CELL_RESC_1920x1080:
case CELL_RESC_1920x1080:
return 3;
default:
return -1;
@@ -317,14 +317,14 @@ void GetScreenSize(u32 mode, s32 *width, s32 *height)
{
switch (mode)
{
case CELL_RESC_720x480:
*width = 720; *height = 480;
case CELL_RESC_720x480:
*width = 720; *height = 480;
break;
case CELL_RESC_720x576:
*width = 720; *height = 576;
case CELL_RESC_720x576:
*width = 720; *height = 576;
break;
case CELL_RESC_1280x720:
*width = 1280; *height = 720;
case CELL_RESC_1280x720:
*width = 1280; *height = 720;
break;
case CELL_RESC_1920x1080:
*width = 1920; *height = 1080;
@@ -933,18 +933,18 @@ s32 cellRescGcmSurface2RescSrc(vm::ptr<CellGcmSurface> gcmSurface, vm::ptr<CellR
u8 textureFormat = GcmSurfaceFormat2GcmTextureFormat(gcmSurface->colorFormat, gcmSurface->type);
s32 xW = 1, xH = 1;
switch(gcmSurface->antialias)
switch(rsx::to_surface_antialiasing(gcmSurface->antialias))
{
case CELL_GCM_SURFACE_SQUARE_ROTATED_4:
case rsx::surface_antialiasing::square_rotated_4_samples:
xW=xH=2;
break;
case CELL_GCM_SURFACE_SQUARE_CENTERED_4:
case rsx::surface_antialiasing::square_centered_4_samples:
xW=xH=2;
break;
case CELL_GCM_SURFACE_DIAGONAL_CENTERED_2:
case rsx::surface_antialiasing::diagonal_centered_2_samples:
xW=2;
break;
default:
default:
break;
}
+37 -41
View File
@@ -95,20 +95,19 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
listGet->dirNum++;
// PSF parameters
vfsFile f(base_dir + entry->name + "/PARAM.SFO");
const PSFLoader psf(f);
const auto& psf = psf::load(vfsFile(base_dir + entry->name + "/PARAM.SFO").VRead<char>());
if (!psf)
if (psf.empty())
{
break;
}
SaveDataEntry save_entry2;
save_entry2.dirName = psf.GetString("SAVEDATA_DIRECTORY");
save_entry2.listParam = psf.GetString("SAVEDATA_LIST_PARAM");
save_entry2.title = psf.GetString("TITLE");
save_entry2.subtitle = psf.GetString("SUB_TITLE");
save_entry2.details = psf.GetString("DETAIL");
save_entry2.dirName = psf.at("SAVEDATA_DIRECTORY").as_string();
save_entry2.listParam = psf.at("SAVEDATA_LIST_PARAM").as_string();
save_entry2.title = psf.at("TITLE").as_string();
save_entry2.subtitle = psf.at("SUB_TITLE").as_string();
save_entry2.details = psf.at("DETAIL").as_string();
save_entry2.size = 0;
@@ -340,13 +339,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
std::string dir_path = base_dir + save_entry.dirName + "/";
std::string sfo_path = dir_path + "PARAM.SFO";
PSFLoader psf;
// Load PARAM.SFO
{
vfsFile f(sfo_path);
psf.Load(f);
}
auto&& psf = psf::load(vfsFile(sfo_path).VRead<char>());
// Get save stats
{
@@ -361,18 +354,21 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
}
statGet->hddFreeSizeKB = 40 * 1024 * 1024; // 40 GB
statGet->isNewData = save_entry.isNew = !psf;
statGet->isNewData = save_entry.isNew = psf.empty();
statGet->dir.atime = save_entry.atime = dir_info.atime;
statGet->dir.mtime = save_entry.mtime = dir_info.mtime;
statGet->dir.ctime = save_entry.ctime = dir_info.ctime;
strcpy_trunc(statGet->dir.dirName, save_entry.dirName);
statGet->getParam.attribute = psf.GetInteger("ATTRIBUTE"); // ???
strcpy_trunc(statGet->getParam.title, save_entry.title = psf.GetString("TITLE"));
strcpy_trunc(statGet->getParam.subTitle, save_entry.subtitle = psf.GetString("SUB_TITLE"));
strcpy_trunc(statGet->getParam.detail, save_entry.details = psf.GetString("DETAIL"));
strcpy_trunc(statGet->getParam.listParam, save_entry.listParam = psf.GetString("SAVEDATA_LIST_PARAM"));
if (!psf.empty())
{
statGet->getParam.attribute = psf.at("ATTRIBUTE").as_integer(); // ???
strcpy_trunc(statGet->getParam.title, save_entry.title = psf.at("TITLE").as_string());
strcpy_trunc(statGet->getParam.subTitle, save_entry.subtitle = psf.at("SUB_TITLE").as_string());
strcpy_trunc(statGet->getParam.detail, save_entry.details = psf.at("DETAIL").as_string());
strcpy_trunc(statGet->getParam.listParam, save_entry.listParam = psf.at("SAVEDATA_LIST_PARAM").as_string());
}
statGet->bind = 0;
statGet->sizeKB = save_entry.size / 1024;
@@ -410,7 +406,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
{
file.fileType = CELL_SAVEDATA_FILETYPE_CONTENT_SND0;
}
else if (psf.GetInteger("*" + entry->name)) // let's put the list of protected files in PARAM.SFO (int param = 1 if protected)
else if (psf::get_integer(psf, "*" + entry->name)) // let's put the list of protected files in PARAM.SFO (int param = 1 if protected)
{
file.fileType = CELL_SAVEDATA_FILETYPE_SECUREFILE;
}
@@ -438,22 +434,23 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
if (statSet->setParam)
{
psf.Clear();
// Update PARAM.SFO
psf.SetString("ACCOUNT_ID", ""); // ???
psf.SetInteger("ATTRIBUTE", statSet->setParam->attribute);
psf.SetString("CATEGORY", "SD"); // ???
psf.SetString("PARAMS", ""); // ???
psf.SetString("PARAMS2", ""); // ???
psf.SetInteger("PARENTAL_LEVEL", 0); // ???
psf.SetString("DETAIL", statSet->setParam->detail);
psf.SetString("SAVEDATA_DIRECTORY", save_entry.dirName);
psf.SetString("SAVEDATA_LIST_PARAM", statSet->setParam->listParam);
psf.SetString("SUB_TITLE", statSet->setParam->subTitle);
psf.SetString("TITLE", statSet->setParam->title);
psf.insert(
{
{ "ACCOUNT_ID", psf::array(16, "0000000000000000") }, // ???
{ "ATTRIBUTE", statSet->setParam->attribute.value() },
{ "CATEGORY", psf::string(4, "SD") }, // ???
{ "PARAMS", psf::string(16, {}) }, // ???
{ "PARAMS2", psf::string(16, {}) }, // ???
{ "PARENTAL_LEVEL", 0 }, // ???
{ "DETAIL", psf::string(1024, statSet->setParam->detail) },
{ "SAVEDATA_DIRECTORY", psf::string(256, save_entry.dirName) },
{ "SAVEDATA_LIST_PARAM", psf::string(8, statSet->setParam->listParam) },
{ "SUB_TITLE", psf::string(128, statSet->setParam->subTitle) },
{ "TITLE", psf::string(128, statSet->setParam->title) },
});
}
else if (!psf)
else if (psf.empty())
{
// setParam is NULL for new savedata: abort operation
@@ -505,7 +502,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
}
// Create save directory if necessary
if (psf && save_entry.isNew && !Emu.GetVFS().CreateDir(dir_path))
if (psf.size() && save_entry.isNew && !Emu.GetVFS().CreateDir(dir_path))
{
// Let's ignore this error for now
}
@@ -572,7 +569,7 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
}
}
psf.SetInteger("*" + file_path, fileSet->fileType == CELL_SAVEDATA_FILETYPE_SECUREFILE);
psf.emplace("*" + file_path, fileSet->fileType == CELL_SAVEDATA_FILETYPE_SECUREFILE);
std::string local_path;
@@ -621,10 +618,9 @@ never_inline s32 savedata_op(PPUThread& ppu, u32 operation, u32 version, vm::cpt
}
// Write PARAM.SFO
if (psf)
if (psf.size())
{
vfsFile f(sfo_path, fom::rewrite);
psf.Save(f);
vfsFile(sfo_path, fom::rewrite).VWrite(psf::save(psf));
}
return CELL_OK;
+3 -3
View File
@@ -231,9 +231,9 @@ void Emulator::Load()
LOG_NOTICE(LOADER, "");
f.Open("/app_home/../PARAM.SFO");
const PSFLoader psf(f);
std::string title = psf.GetString("TITLE");
std::string title_id = psf.GetString("TITLE_ID");
const auto& psf = psf::load(f.VRead<char>());
std::string title = psf::get_string(psf, "TITLE");
std::string title_id = psf::get_string(psf, "TITLE_ID");
LOG_NOTICE(LOADER, "Title: %s", title.c_str());
LOG_NOTICE(LOADER, "Serial: %s", title_id.c_str());
+2 -2
View File
@@ -25,7 +25,7 @@ public:
t_name->SetForegroundColour(wxColor(255, 255, 255));
t_name->SetPosition(wxPoint(10, 6));
wxStaticText* t_descr = new wxStaticText(this, wxID_ANY, "An early but promising PS3 emulator and debugger.");
wxStaticText* t_descr = new wxStaticText(this, wxID_ANY, "A PlayStation 3 emulator and debugger.");
t_descr->SetBackgroundColour(wxColor(100, 100, 100));
t_descr->SetForegroundColour(wxColor(255, 255, 255));
t_descr->SetPosition(wxPoint(12, 50));
@@ -62,7 +62,7 @@ public:
s_panel_buttons->AddStretchSpacer();
s_panel_buttons->Add(b_forum, 16, 0, 5);
s_panel_buttons->AddStretchSpacer(20);
s_panel_buttons->Add(new wxButton(this, wxID_OK), 16, 0, 5);
s_panel_buttons->Add(new wxButton(this, wxID_OK, "Close") , 16, 0, 5);
s_panel_buttons->AddSpacer(12);
//Panels
+8 -8
View File
@@ -5,13 +5,13 @@
//TODO::Get the enable configuration from ini.
AutoPauseManagerDialog::AutoPauseManagerDialog(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "Auto Pause Manager")
: wxDialog(parent, wxID_ANY, "Automatic pause settings")
{
SetMinSize(wxSize(400, 360));
wxBoxSizer* s_main = new wxBoxSizer(wxVERTICAL);
wxStaticText* s_description = new wxStaticText(this, wxID_ANY, "To use auto pause: enter the ID(s) of a function or a system call. Restart of the game is required to apply. You can enable/disable this in the settings.", wxDefaultPosition, wxDefaultSize, 0);
wxStaticText* s_description = new wxStaticText(this, wxID_ANY, "To use auto pause: enter the ID(s) of a function or a system call. You must restart your emulated game or application for changed settings to take effect. You can enable/disable this in the settings.", wxDefaultPosition, wxDefaultSize, 0);
s_description->Wrap(400);
s_main->Add(s_description, 0, wxALL, 5);
@@ -114,11 +114,11 @@ void AutoPauseManagerDialog::UpdateList(void)
if (m_entries[i] < 1024)
{
m_list->SetItem(i, 1, "System Call");
m_list->SetItem(i, 1, "System call");
}
else
{
m_list->SetItem(i, 1, "Function Call");
m_list->SetItem(i, 1, "Function call");
}
}
m_list->SetColumnWidth(0, wxLIST_AUTOSIZE_USEHEADER);
@@ -176,7 +176,7 @@ void AutoPauseManagerDialog::OnRemove(wxCommandEvent& event)
void AutoPauseManagerDialog::OnSave(wxCommandEvent& event)
{
SaveEntries();
LOG_SUCCESS(HLE,"Auto Pause: File pause.bin was updated.");
LOG_SUCCESS(HLE,"Automatic pause: file pause.bin was updated.");
//event.Skip();
}
@@ -193,7 +193,7 @@ void AutoPauseManagerDialog::OnReload(wxCommandEvent& event)
}
AutoPauseSettingsDialog::AutoPauseSettingsDialog(wxWindow* parent, u32 *entry)
: wxDialog(parent, wxID_ANY, "Auto Pause Setting")
: wxDialog(parent, wxID_ANY, "Automatic pause Setting")
, m_presult(entry)
{
m_entry = *m_presult;
@@ -202,7 +202,7 @@ AutoPauseSettingsDialog::AutoPauseSettingsDialog(wxWindow* parent, u32 *entry)
wxBoxSizer* s_main = new wxBoxSizer(wxVERTICAL);
wxStaticText* s_description = new wxStaticText(this, wxID_ANY, "Specify ID of System Call or Function Call below. You need to use a Hexadecimal ID.", wxDefaultPosition, wxDefaultSize, 0);
wxStaticText* s_description = new wxStaticText(this, wxID_ANY, "Specify ID of system call or function call below. You need to use a hexadecimal ID.", wxDefaultPosition, wxDefaultSize, 0);
s_description->Wrap(400);
s_main->Add(s_description, 0, wxALL, 5);
@@ -220,7 +220,7 @@ AutoPauseSettingsDialog::AutoPauseSettingsDialog(wxWindow* parent, u32 *entry)
m_id->SetValue(fmt::format("%08x", m_entry));
SetTitle("Auto Pause Setting: " + m_id->GetValue());
SetTitle("Automatic pause setting: " + m_id->GetValue());
Bind(wxEVT_BUTTON, &AutoPauseSettingsDialog::OnOk, this, wxID_OK);
Bind(wxEVT_TEXT, &AutoPauseSettingsDialog::OnUpdateValue, this, wxID_STATIC);
+3 -3
View File
@@ -10,13 +10,13 @@ BEGIN_EVENT_TABLE(CgDisasm, wxFrame)
END_EVENT_TABLE()
CgDisasm::CgDisasm(wxWindow* parent)
: wxFrame(parent, wxID_ANY, "Cg Disasm", wxDefaultPosition, wxSize(640, 480))
: wxFrame(parent, wxID_ANY, "Cg disassembler", wxDefaultPosition, wxSize(640, 480))
{
wxMenuBar* menubar = new wxMenuBar();
wxMenu* menu_general = new wxMenu();
menubar->Append(menu_general, "&Open");
menu_general->Append(id_open_file, "Open &Cg binary program");
menubar->Append(menu_general, "&File");
menu_general->Append(id_open_file, "Open &Cg binary");
wxNotebook* nb_cg = new wxNotebook(this, wxID_ANY);
wxPanel* p_cg_disasm = new wxPanel(nb_cg, wxID_ANY);
+3 -3
View File
@@ -19,7 +19,7 @@ wxFont GetFont(int size)
}
CompilerELF::CompilerELF(wxWindow* parent)
: FrameBase(parent, wxID_ANY, "CompilerELF", "", wxSize(640, 680))
: FrameBase(parent, wxID_ANY, "ELF compiler", "", wxSize(640, 680))
, m_status_bar(*CreateStatusBar())
{
m_disable_scroll = false;
@@ -28,11 +28,11 @@ CompilerELF::CompilerELF(wxWindow* parent)
wxMenuBar* menubar = new wxMenuBar();
wxMenu* menu_code = new wxMenu();
menubar->Append(menu_code, "Code");
menubar->Append(menu_code, "File");
//menu_code.Append(id_analyze_code, "Analyze");
menu_code->Append(id_compile_code, "Compile");
menu_code->Append(id_load_elf, "Load ELF");
menu_code->Append(id_compile_code, "Compile");
SetMenuBar(menubar);
asm_list = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(400, -1), wxTE_MULTILINE | wxTE_DONTWRAP | wxTE_RICH2);
+2 -2
View File
@@ -125,7 +125,7 @@ class DumperThread : public ThreadBase
wxArrayString** arr;
public:
DumperThread() : ThreadBase("DumperThread")
DumperThread() : ThreadBase("Dumper thread")
{
}
@@ -204,7 +204,7 @@ struct WaitDumperThread : public ThreadBase
wxArrayString** arr;
WaitDumperThread(bool* _done, u8 _cores, wxString _patch, MTProgressDialog& _prog_dial, wxArrayString** _arr)
: ThreadBase("WaitDumperThread")
: ThreadBase("Wait dumper thread")
, done(_done)
, cores(_cores)
, patch(_patch)
+1 -1
View File
@@ -10,7 +10,7 @@ protected:
FrameBase(
wxWindow* parent,
wxWindowID id = wxID_ANY,
const wxString& framename = "UnknownFrame",
const wxString& framename = "Unknown frame",
const std::string& ininame = "",
wxSize defsize = wxDefaultSize,
wxPoint defposition = wxDefaultPosition,
+11 -17
View File
@@ -10,7 +10,7 @@
#include "Loader/PSF.h"
#include "SettingsDialog.h"
static const std::string m_class_name = "GameViewer";
static const std::string m_class_name = "Game viewer";
// Auxiliary classes
class sortGameData
@@ -105,18 +105,12 @@ void GameViewer::LoadPSF()
}
vfsFile f;
if (!f.Open(sfo))
{
continue;
}
const PSFLoader psf(f);
if (!psf)
{
continue;
}
const auto& psf = psf::load(f.VRead<char>());
// get local path from VFS...
std::string local_path;
@@ -124,14 +118,14 @@ void GameViewer::LoadPSF()
GameInfo game;
game.root = m_games[i];
game.serial = psf.GetString("TITLE_ID");
game.name = psf.GetString("TITLE");
game.app_ver = psf.GetString("APP_VER");
game.category = psf.GetString("CATEGORY");
game.fw = psf.GetString("PS3_SYSTEM_VER");
game.parental_lvl = psf.GetInteger("PARENTAL_LEVEL");
game.resolution = psf.GetInteger("RESOLUTION");
game.sound_format = psf.GetInteger("SOUND_FORMAT");
game.serial = psf::get_string(psf, "TITLE_ID", "unknown");
game.name = psf::get_string(psf, "TITLE", "unknown");
game.app_ver = psf::get_string(psf, "APP_VER", "unknown");
game.category = psf::get_string(psf, "CATEGORY", "unknown");
game.fw = psf::get_string(psf, "PS3_SYSTEM_VER", "unknown");
game.parental_lvl = psf::get_integer(psf, "PARENTAL_LEVEL");
game.resolution = psf::get_integer(psf, "RESOLUTION");
game.sound_format = psf::get_integer(psf, "SOUND_FORMAT");
if (game.serial.length() == 9)
{
@@ -236,7 +230,7 @@ void GameViewer::RightClick(wxListEvent& event)
#endif
m_popup->Append(boot_item);
m_popup->Append(1, _T("Configure"));
m_popup->Append(2, _T("Remove Game"));
m_popup->Append(2, _T("Remove game"));
Bind(wxEVT_MENU, &GameViewer::BootGame, this, 0);
Bind(wxEVT_MENU, &GameViewer::ConfigureGame, this, 1);
+4 -4
View File
@@ -85,12 +85,12 @@ public:
m_img_list = new wxImageList(80, 44);
m_columns.clear();
m_columns.emplace_back(m_columns.size(), 90, "Icon");
m_columns.emplace_back(m_columns.size(), 90, "");
m_columns.emplace_back(m_columns.size(), 160, "Name");
m_columns.emplace_back(m_columns.size(), 85, "Serial");
m_columns.emplace_back(m_columns.size(), 55, "FW");
m_columns.emplace_back(m_columns.size(), 55, "App version");
m_columns.emplace_back(m_columns.size(), 75, "Category");
m_columns.emplace_back(m_columns.size(), 60, "Min. FW");
m_columns.emplace_back(m_columns.size(), 80, "Soft. version");
m_columns.emplace_back(m_columns.size(), 75, "Soft. type");
m_columns.emplace_back(m_columns.size(), 160, "Path");
m_col_icon = &m_columns[0];
m_col_name = &m_columns[1];
+2 -2
View File
@@ -34,8 +34,8 @@ InterpreterDisAsmFrame::InterpreterDisAsmFrame(wxWindow* parent)
m_list = new wxListView(this);
m_choice_units = new wxChoice(this, wxID_ANY);
wxButton* b_go_to_addr = new wxButton(this, wxID_ANY, "Go To Address");
wxButton* b_go_to_pc = new wxButton(this, wxID_ANY, "Go To PC");
wxButton* b_go_to_addr = new wxButton(this, wxID_ANY, "Go to address");
wxButton* b_go_to_pc = new wxButton(this, wxID_ANY, "Go to PC");
m_btn_step = new wxButton(this, wxID_ANY, "Step");
m_btn_run = new wxButton(this, wxID_ANY, "Run");
+20 -20
View File
@@ -23,7 +23,7 @@
#include "KernelExplorer.h"
KernelExplorer::KernelExplorer(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "Kernel Explorer", wxDefaultPosition, wxSize(700, 450))
: wxDialog(parent, wxID_ANY, "Kernel explorer", wxDefaultPosition, wxSize(700, 450))
{
this->SetBackgroundColour(wxColour(240,240,240)); //This fix the ugly background color under Windows
wxBoxSizer* s_panel = new wxBoxSizer(wxVERTICAL);
@@ -59,7 +59,7 @@ void KernelExplorer::Update()
m_tree->DeleteAllItems();
const u32 total_memory_usage = vm::get(vm::user_space)->used.load();
const auto& root = m_tree->AddRoot(fmt::format("Process, ID = 0x00000001, Total Memory Usage = 0x%x (%0.2f MB)", total_memory_usage, (float)total_memory_usage / (1024 * 1024)));
const auto& root = m_tree->AddRoot(fmt::format("Process, ID = 0x00000001, Total memory usage = 0x%x (%0.2f MB)", total_memory_usage, (float)total_memory_usage / (1024 * 1024)));
union name64
{
@@ -116,7 +116,7 @@ void KernelExplorer::Update()
if (lwm_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Mutexes (%zu)", lwm_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight mutexes (%zu)", lwm_map.size()));
for (const auto& data : lwm_map)
{
@@ -132,7 +132,7 @@ void KernelExplorer::Update()
if (cond_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Condition Variables (%zu)", cond_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Condition variables (%zu)", cond_map.size()));
for (const auto& data : cond_map)
{
@@ -148,7 +148,7 @@ void KernelExplorer::Update()
if (lwc_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight Condition Variables (%zu)", lwc_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Lightweight condition variables (%zu)", lwc_map.size()));
for (const auto& data : lwc_map)
{
@@ -164,7 +164,7 @@ void KernelExplorer::Update()
if (eq_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Event Queues (%zu)", eq_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Event queues (%zu)", eq_map.size()));
for (const auto& data : eq_map)
{
@@ -180,13 +180,13 @@ void KernelExplorer::Update()
if (ep_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Event Ports (%zu)", ep_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Event ports (%zu)", ep_map.size()));
for (const auto& data : ep_map)
{
const auto& ep = *data.second;
m_tree->AppendItem(node, fmt::format("Event Port: ID = 0x%08x, Name = %#llx", data.first,
m_tree->AppendItem(node, fmt::format("Event port: ID = 0x%08x, Name = %#llx", data.first,
ep.name));
}
}
@@ -196,13 +196,13 @@ void KernelExplorer::Update()
if (ef_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Event Flags (%zu)", ef_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Event flags (%zu)", ef_map.size()));
for (const auto& data : ef_map)
{
const auto& ef = *data.second;
m_tree->AppendItem(node, fmt::format("Event Flag: ID = 0x%08x", data.first));
m_tree->AppendItem(node, fmt::format("Event flag: ID = 0x%08x", data.first));
}
}
@@ -211,7 +211,7 @@ void KernelExplorer::Update()
if (rwlock_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Reader/writer Locks (%zu)", rwlock_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Reader/writer locks (%zu)", rwlock_map.size()));
for (const auto& data : rwlock_map)
{
@@ -226,7 +226,7 @@ void KernelExplorer::Update()
if (prx_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("PRX Libraries (%zu)", prx_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("PRX libraries (%zu)", prx_map.size()));
for (const auto& data : prx_map)
{
@@ -241,13 +241,13 @@ void KernelExplorer::Update()
if (ct_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Containers (%zu)", ct_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Memory containers (%zu)", ct_map.size()));
for (const auto& data : ct_map)
{
const auto& ct = *data.second;
m_tree->AppendItem(node, fmt::format("Memory Container: ID = 0x%08x", data.first));
m_tree->AppendItem(node, fmt::format("Memory container: ID = 0x%08x", data.first));
}
}
@@ -256,13 +256,13 @@ void KernelExplorer::Update()
if (mem_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("Memory Objects (%zu)", mem_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("Memory objects (%zu)", mem_map.size()));
for (const auto& data : mem_map)
{
const auto& mem = *data.second;
m_tree->AppendItem(node, fmt::format("Memory Object: ID = 0x%08x", data.first));
m_tree->AppendItem(node, fmt::format("Memory object: ID = 0x%08x", data.first));
}
}
@@ -271,13 +271,13 @@ void KernelExplorer::Update()
if (ppu_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("PPU Threads (%zu)", ppu_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("PPU threads (%zu)", ppu_map.size()));
for (const auto& data : ppu_map)
{
const auto& ppu = *data.second;
m_tree->AppendItem(node, fmt::format("PPU Thread: ID = 0x%08x '%s', - %s", data.first,
m_tree->AppendItem(node, fmt::format("PPU thread: ID = 0x%08x '%s', - %s", data.first,
ppu.get_name().c_str(), ppu.ThreadStatusToString()));
}
}
@@ -287,13 +287,13 @@ void KernelExplorer::Update()
if (spu_map.size())
{
const auto& node = m_tree->AppendItem(root, fmt::format("SPU Thread Groups (%d)", spu_map.size()));
const auto& node = m_tree->AppendItem(root, fmt::format("SPU thread groups (%d)", spu_map.size()));
for (const auto& data : spu_map)
{
const auto& tg = *data.second;
m_tree->AppendItem(node, fmt::format("SPU Thread Group: ID = 0x%08x '%s'", data.first,
m_tree->AppendItem(node, fmt::format("SPU thread group: ID = 0x%08x '%s'", data.first,
tg.name.c_str()));
}
}
+3 -3
View File
@@ -9,7 +9,7 @@
#include "Emu/FS/VFS.h"
LLEModulesManagerFrame::LLEModulesManagerFrame(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "LLEModulesManagerFrame", wxDefaultPosition, wxSize(480, 640))
: wxDialog(parent, wxID_ANY, "Modules LLE manager", wxDefaultPosition, wxSize(480, 640))
{
wxBoxSizer *s_panel = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *s_p_panel = new wxBoxSizer(wxVERTICAL);
@@ -18,8 +18,8 @@ LLEModulesManagerFrame::LLEModulesManagerFrame(wxWindow* parent)
// select / unselect
wxStaticBoxSizer* s_selection = new wxStaticBoxSizer(wxHORIZONTAL, p_main);
wxButton* b_select = new wxButton(p_main, wxID_ANY, "Select All", wxDefaultPosition, wxSize(80, -1));
wxButton* b_unselect = new wxButton(p_main, wxID_ANY, "Unselect All", wxDefaultPosition, wxSize(80, -1));
wxButton* b_select = new wxButton(p_main, wxID_ANY, "Select all", wxDefaultPosition, wxSize(80, -1));
wxButton* b_unselect = new wxButton(p_main, wxID_ANY, "Unselect all", wxDefaultPosition, wxSize(80, -1));
s_selection->Add(b_select);
s_selection->Add(b_unselect);
+18 -18
View File
@@ -77,7 +77,7 @@ MainFrame::MainFrame()
wxMenuBar* menubar = new wxMenuBar();
wxMenu* menu_boot = new wxMenu();
menubar->Append(menu_boot, "&Boot");
menubar->Append(menu_boot, "&File");
menu_boot->Append(id_boot_elf, "Boot &ELF / SELF file");
menu_boot->Append(id_boot_game, "Boot &game");
menu_boot->AppendSeparator();
@@ -90,30 +90,30 @@ MainFrame::MainFrame()
menu_sys->Append(id_sys_pause, "&Pause")->Enable(false);
menu_sys->Append(id_sys_stop, "&Stop\tCtrl + S")->Enable(false);
menu_sys->AppendSeparator();
menu_sys->Append(id_sys_send_open_menu, "Send &open system menu cmd")->Enable(false);
menu_sys->Append(id_sys_send_open_menu, "Press &PS button")->Enable(false);
menu_sys->Append(id_sys_send_exit, "Send &exit cmd")->Enable(false);
wxMenu* menu_conf = new wxMenu();
menubar->Append(menu_conf, "&Config");
menu_conf->Append(id_config_emu, "&Settings");
menu_conf->Append(id_config_pad, "&PAD Settings");
menu_conf->Append(id_config_pad, "&Controller settings");
menu_conf->AppendSeparator();
menu_conf->Append(id_config_autopause_manager, "&Auto Pause Settings");
menu_conf->Append(id_config_autopause_manager, "&Auto pause settings");
menu_conf->AppendSeparator();
menu_conf->Append(id_config_vfs_manager, "Virtual &File System Manager");
menu_conf->Append(id_config_vhdd_manager, "Virtual &HDD Manager");
menu_conf->Append(id_config_savedata_manager, "Save &Data Utility");
menu_conf->Append(id_config_lle_modules_manager, "&LLE Modules Manager");
menu_conf->Append(id_config_vfs_manager, "Virtual &file system manager");
menu_conf->Append(id_config_vhdd_manager, "Virtual &hard drive manager");
menu_conf->Append(id_config_savedata_manager, "Save &data manager");
menu_conf->Append(id_config_lle_modules_manager, "Modules &LLE manager");
wxMenu* menu_tools = new wxMenu();
menubar->Append(menu_tools, "&Tools");
menu_tools->Append(id_tools_compiler, "&ELF Compiler");
menu_tools->Append(id_tools_kernel_explorer, "&Kernel Explorer")->Enable(false);
menu_tools->Append(id_tools_memory_viewer, "&Memory Viewer")->Enable(false);
menu_tools->Append(id_tools_rsx_debugger, "&RSX Debugger")->Enable(false);
menu_tools->Append(id_tools_string_search, "&String Search")->Enable(false);
menu_tools->Append(id_tools_cg_disasm, "&Cg Disasm")->Enable();
menu_tools->Append(id_tools_compiler, "&ELF compiler");
menu_tools->Append(id_tools_kernel_explorer, "&Kernel explorer")->Enable(false);
menu_tools->Append(id_tools_memory_viewer, "&Memory viewer")->Enable(false);
menu_tools->Append(id_tools_rsx_debugger, "&RSX debugger")->Enable(false);
menu_tools->Append(id_tools_string_search, "&String search")->Enable(false);
menu_tools->Append(id_tools_cg_disasm, "&Cg disassembler")->Enable();
wxMenu* menu_help = new wxMenu();
menubar->Append(menu_help, "&Help");
@@ -127,7 +127,7 @@ MainFrame::MainFrame()
m_game_viewer = new GameViewer(this);
m_debugger_frame = new DebuggerPanel(this);
AddPane(m_game_viewer, "Game List", wxAUI_DOCK_CENTRE);
AddPane(m_game_viewer, "PS3 software", wxAUI_DOCK_CENTRE);
AddPane(m_log_frame, "Log", wxAUI_DOCK_BOTTOM);
AddPane(m_debugger_frame, "Debugger", wxAUI_DOCK_RIGHT);
@@ -530,7 +530,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
// Emulation
wxMenuItem& pause = *menubar.FindItem(id_sys_pause);
wxMenuItem& stop = *menubar.FindItem(id_sys_stop);
pause.SetItemLabel(is_running ? "&Pause\tCtrl + P" : is_ready ? "&Start\tCtrl + E" : "&Resume\tCtrl + E");
pause.SetItemLabel(is_running ? "&Pause\tCtrl + P" : is_ready ? "&Start\tCtrl + F" : "&Resume\tCtrl + F");
pause.Enable(!is_stopped);
stop.Enable(!is_stopped);
@@ -538,7 +538,7 @@ void MainFrame::UpdateUI(wxCommandEvent& event)
wxMenuItem& send_exit = *menubar.FindItem(id_sys_send_exit);
wxMenuItem& send_open_menu = *menubar.FindItem(id_sys_send_open_menu);
bool enable_commands = !is_stopped;
send_open_menu.SetItemLabel(wxString::Format("Send &%s system menu cmd", (m_sys_menu_opened ? "close" : "open")));
send_open_menu.SetItemLabel(wxString::Format("Press &PS buton %s", (m_sys_menu_opened ? "close" : "open")));
send_open_menu.Enable(enable_commands);
send_exit.Enable(enable_commands);
@@ -565,7 +565,7 @@ void MainFrame::OnKeyDown(wxKeyEvent& event)
{
switch(event.GetKeyCode())
{
case 'E': case 'e': if(Emu.IsPaused()) Emu.Resume(); else if(Emu.IsReady()) Emu.Run(); return;
case 'F': case 'f': if(Emu.IsPaused()) Emu.Resume(); else if(Emu.IsReady()) Emu.Run(); return;
case 'P': case 'p': if(Emu.IsRunning()) Emu.Pause(); return;
case 'S': case 's': if(!Emu.IsStopped()) Emu.Stop(); return;
case 'R': case 'r': if(!Emu.GetPath().empty()) {Emu.Stop(); Emu.Run();} return;
+1 -1
View File
@@ -7,7 +7,7 @@
#include "MemoryStringSearcher.h"
MemoryStringSearcher::MemoryStringSearcher(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "String Searcher", wxDefaultPosition, wxSize(545, 64))
: wxDialog(parent, wxID_ANY, "String searcher", wxDefaultPosition, wxSize(545, 64))
, exit(false)
{
this->SetBackgroundColour(wxColour(240,240,240));
+3 -3
View File
@@ -19,7 +19,7 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent)
wxBoxSizer* s_tools = new wxBoxSizer(wxHORIZONTAL);
//Tools: Memory Viewer Options
wxStaticBoxSizer* s_tools_mem = new wxStaticBoxSizer(wxHORIZONTAL, this, "Memory Viewer Options");
wxStaticBoxSizer* s_tools_mem = new wxStaticBoxSizer(wxHORIZONTAL, this, "Memory viewer options");
wxStaticBoxSizer* s_tools_mem_addr = new wxStaticBoxSizer(wxHORIZONTAL, this, "Address");
t_addr = new wxTextCtrl(this, wxID_ANY, "00000000", wxDefaultPosition, wxSize(60, -1), wxTE_PROCESS_ENTER);
@@ -46,7 +46,7 @@ MemoryViewerPanel::MemoryViewerPanel(wxWindow* parent)
s_tools_mem->Add(s_tools_mem_buttons);
//Tools: Raw Image Preview Options
wxStaticBoxSizer* s_tools_img = new wxStaticBoxSizer(wxHORIZONTAL, this, "Raw Image Preview");
wxStaticBoxSizer* s_tools_img = new wxStaticBoxSizer(wxHORIZONTAL, this, "Raw image preview");
wxStaticBoxSizer* s_tools_img_size = new wxStaticBoxSizer(wxHORIZONTAL, this, "Size");
sc_img_size_x = new wxSpinCtrl(this, wxID_ANY, "256", wxDefaultPosition, wxSize(60, -1));
@@ -223,7 +223,7 @@ void MemoryViewerPanel::ShowMemory()
void MemoryViewerPanel::ShowImage(wxWindow* parent, u32 addr, int mode, u32 width, u32 height, bool flipv)
{
wxString title = wxString::Format("Raw Image @ 0x%x", addr);
wxString title = wxString::Format("Raw image @ 0x%x", addr);
wxDialog* f_image_viewer = new wxDialog(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxMINIMIZE_BOX | wxCLOSE_BOX | wxCAPTION | wxCLIP_CHILDREN);
f_image_viewer->SetBackgroundColour(wxColour(240,240,240)); //This fix the ugly background color under Windows
+14 -14
View File
@@ -7,7 +7,7 @@
#include "PADManager.h"
PADManager::PADManager(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "PAD Settings")
: wxDialog(parent, wxID_ANY, "Controller settings")
, m_button_id(0)
, m_key_pressed(false)
, m_emu_paused(false)
@@ -22,20 +22,20 @@ PADManager::PADManager(wxWindow* parent)
wxBoxSizer* s_subpanel = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* s_subpanel2 = new wxBoxSizer(wxVERTICAL);
// Left Analog Stick
wxStaticBoxSizer* s_round_stick_l = new wxStaticBoxSizer(wxVERTICAL, this, _("Left Analog Stick"));
// Left analog stick
wxStaticBoxSizer* s_round_stick_l = new wxStaticBoxSizer(wxVERTICAL, this, _("Left analog stick"));
wxBoxSizer* s_subpanel_lstick_1 = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* s_subpanel_lstick_2 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* s_subpanel_lstick_3 = new wxBoxSizer(wxVERTICAL);
// D-Pad
wxStaticBoxSizer* s_round_pad_controls = new wxStaticBoxSizer(wxVERTICAL, this, _("D-Pad"));
// Directional pad
wxStaticBoxSizer* s_round_pad_controls = new wxStaticBoxSizer(wxVERTICAL, this, _("Directional pad"));
wxBoxSizer* s_subpanel_pad_1 = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* s_subpanel_pad_2 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* s_subpanel_pad_3 = new wxBoxSizer(wxVERTICAL);
// Left shifts
wxStaticBoxSizer* s_round_pad_shifts_l = new wxStaticBoxSizer(wxVERTICAL, this, _("Left Shifts"));
// L buttons
wxStaticBoxSizer* s_round_pad_shifts_l = new wxStaticBoxSizer(wxVERTICAL, this, _("L buttons"));
wxStaticBoxSizer* s_round_pad_l1 = new wxStaticBoxSizer(wxVERTICAL, this, _("L1"));
wxStaticBoxSizer* s_round_pad_l2 = new wxStaticBoxSizer(wxVERTICAL, this, _("L2"));
wxStaticBoxSizer* s_round_pad_l3 = new wxStaticBoxSizer(wxVERTICAL, this, _("L3"));
@@ -45,8 +45,8 @@ PADManager::PADManager(wxWindow* parent)
wxStaticBoxSizer* s_round_pad_select = new wxStaticBoxSizer(wxVERTICAL, this, _("Select"));
wxStaticBoxSizer* s_round_pad_start = new wxStaticBoxSizer(wxVERTICAL, this, _("Start"));
// Right shifts
wxStaticBoxSizer* s_round_pad_shifts_r = new wxStaticBoxSizer(wxVERTICAL, this, _("Right Shifts"));
// R buttons
wxStaticBoxSizer* s_round_pad_shifts_r = new wxStaticBoxSizer(wxVERTICAL, this, _("R buttons"));
wxStaticBoxSizer* s_round_pad_r1 = new wxStaticBoxSizer(wxVERTICAL, this, _("R1"));
wxStaticBoxSizer* s_round_pad_r2 = new wxStaticBoxSizer(wxVERTICAL, this, _("R2"));
wxStaticBoxSizer* s_round_pad_r3 = new wxStaticBoxSizer(wxVERTICAL, this, _("R3"));
@@ -61,8 +61,8 @@ PADManager::PADManager(wxWindow* parent)
wxBoxSizer* s_subpanel_buttons_2 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* s_subpanel_buttons_3 = new wxBoxSizer(wxVERTICAL);
// Right Analog Stick
wxStaticBoxSizer* s_round_stick_r = new wxStaticBoxSizer(wxVERTICAL, this, _("Right Analog Stick"));
// Right analog stick
wxStaticBoxSizer* s_round_stick_r = new wxStaticBoxSizer(wxVERTICAL, this, _("Right analog stick"));
wxBoxSizer* s_subpanel_rstick_1 = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* s_subpanel_rstick_2 = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer* s_subpanel_rstick_3 = new wxBoxSizer(wxVERTICAL);
@@ -123,13 +123,13 @@ PADManager::PADManager(wxWindow* parent)
s_subpanel_lstick_2->Add(b_right_lstick);
s_subpanel_lstick_3->Add(b_down_lstick);
// D-Pad
// Directional pad
s_subpanel_pad_1->Add(b_up);
s_subpanel_pad_2->Add(b_left);
s_subpanel_pad_2->Add(b_right);
s_subpanel_pad_3->Add(b_down);
// Left shifts
// L button
s_round_pad_l1->Add(b_shift_l1);
s_round_pad_l2->Add(b_shift_l2);
s_round_pad_l3->Add(b_shift_l3);
@@ -138,7 +138,7 @@ PADManager::PADManager(wxWindow* parent)
s_round_pad_select->Add(b_select);
s_round_pad_start->Add(b_start);
// Right shifts
// R button
s_round_pad_r1->Add(b_shift_r1);
s_round_pad_r2->Add(b_shift_r2);
s_round_pad_r3->Add(b_shift_r3);
+144 -68
View File
@@ -25,7 +25,7 @@ enum GCMEnumTypes
};
RSXDebugger::RSXDebugger(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "RSX Debugger", wxDefaultPosition, wxSize(700, 450))
: wxDialog(parent, wxID_ANY, "RSX debugger", wxDefaultPosition, wxSize(700, 450))
, m_item_count(37)
, m_addr(0x0)
, m_cur_texture(0)
@@ -38,7 +38,7 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
wxBoxSizer* s_tools = new wxBoxSizer(wxVERTICAL);
// Controls
wxStaticBoxSizer* s_controls = new wxStaticBoxSizer(wxHORIZONTAL, this, "RSX Debugger Controls");
wxStaticBoxSizer* s_controls = new wxStaticBoxSizer(wxHORIZONTAL, this, "RSX debugger controls");
// Controls: Address
wxStaticBoxSizer* s_controls_addr = new wxStaticBoxSizer(wxHORIZONTAL, this, "Address:");
@@ -89,9 +89,9 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
wxPanel* p_texture = new wxPanel(nb_rsx, wxID_ANY);
wxPanel* p_settings = new wxPanel(nb_rsx, wxID_ANY);
nb_rsx->AddPage(p_commands, wxT("RSX Commands"));
nb_rsx->AddPage(p_captured_frame, wxT("Captured Frame"));
nb_rsx->AddPage(p_captured_draw_calls, wxT("Captured Draw Calls"));
nb_rsx->AddPage(p_commands, wxT("RSX commands"));
nb_rsx->AddPage(p_captured_frame, wxT("Captured frame"));
nb_rsx->AddPage(p_captured_draw_calls, wxT("Captured draw calls"));
nb_rsx->AddPage(p_flags, wxT("Flags"));
nb_rsx->AddPage(p_lightning, wxT("Lightning"));
@@ -177,12 +177,12 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
//Buffers
wxBoxSizer* s_buffers1 = new wxBoxSizer(wxVERTICAL);
wxBoxSizer* s_buffers2 = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer* s_buffers_colorA = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color Buffer A");
wxStaticBoxSizer* s_buffers_colorB = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color Buffer B");
wxStaticBoxSizer* s_buffers_colorC = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color Buffer C");
wxStaticBoxSizer* s_buffers_colorD = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color Buffer D");
wxStaticBoxSizer* s_buffers_depth = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Depth Buffer");
wxStaticBoxSizer* s_buffers_stencil = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Stencil Buffer");
wxStaticBoxSizer* s_buffers_colorA = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color buffer A");
wxStaticBoxSizer* s_buffers_colorB = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color buffer B");
wxStaticBoxSizer* s_buffers_colorC = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color buffer C");
wxStaticBoxSizer* s_buffers_colorD = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Color buffer D");
wxStaticBoxSizer* s_buffers_depth = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Depth buffer");
wxStaticBoxSizer* s_buffers_stencil = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Stencil buffer");
wxStaticBoxSizer* s_buffers_text = new wxStaticBoxSizer(wxHORIZONTAL, p_buffers, "Texture");
//Buffers and textures
@@ -251,8 +251,8 @@ RSXDebugger::RSXDebugger(wxWindow* parent)
p_buffer_colorB->Bind(wxEVT_LEFT_DOWN, &RSXDebugger::OnClickBuffer, this);
p_buffer_colorC->Bind(wxEVT_LEFT_DOWN, &RSXDebugger::OnClickBuffer, this);
p_buffer_colorD->Bind(wxEVT_LEFT_DOWN, &RSXDebugger::OnClickBuffer, this);
//p_buffer_depth->Bind(wxEVT_BUTTON, &RSXDebugger::OnClickBuffer, this);
//p_buffer_stencil->Bind(wxEVT_BUTTON, &RSXDebugger::OnClickBuffer, this);
p_buffer_depth->Bind(wxEVT_LEFT_DOWN, &RSXDebugger::OnClickBuffer, this);
p_buffer_stencil->Bind(wxEVT_LEFT_DOWN, &RSXDebugger::OnClickBuffer, this);
p_buffer_tex->Bind(wxEVT_LEFT_DOWN, &RSXDebugger::OnClickBuffer, this);
m_list_captured_draw_calls->Bind(wxEVT_LEFT_DOWN, &RSXDebugger::OnClickDrawCalls, this);
@@ -364,6 +364,8 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event)
if (event.GetId() == p_buffer_colorB->GetId()) display_buffer(this, buffer_img[1]);
if (event.GetId() == p_buffer_colorC->GetId()) display_buffer(this, buffer_img[2]);
if (event.GetId() == p_buffer_colorD->GetId()) display_buffer(this, buffer_img[3]);
if (event.GetId() == p_buffer_depth->GetId()) display_buffer(this, depth_img);
if (event.GetId() == p_buffer_stencil->GetId()) display_buffer(this, stencil_img);
if (event.GetId() == p_buffer_tex->GetId())
{
u8 location = render.textures[m_cur_texture].location();
@@ -380,18 +382,74 @@ void RSXDebugger::OnClickBuffer(wxMouseEvent& event)
namespace
{
std::array<u8, 3> get_value(gsl::span<const gsl::byte> orig_buffer, rsx::surface_color_format format, size_t idx)
{
switch (format)
{
case rsx::surface_color_format::b8:
{
u8 value = gsl::as_span<const u8>(orig_buffer)[idx];
return{ value, value, value };
}
case rsx::surface_color_format::x32:
{
be_t<u32> stored_val = gsl::as_span<const be_t<u32>>(orig_buffer)[idx];
u32 swapped_val = stored_val;
f32 float_val = (f32&)swapped_val;
u8 val = float_val * 255.f;
return{ val, val, val };
}
case rsx::surface_color_format::a8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_o8b8g8r8:
case rsx::surface_color_format::x8b8g8r8_z8b8g8r8:
{
auto ptr = gsl::as_span<const u8>(orig_buffer);
return{ ptr[1 + idx * 4], ptr[2 + idx * 4], ptr[3 + idx * 4] };
}
case rsx::surface_color_format::a8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_o8r8g8b8:
case rsx::surface_color_format::x8r8g8b8_z8r8g8b8:
{
auto ptr = gsl::as_span<const u8>(orig_buffer);
return{ ptr[3 + idx * 4], ptr[2 + idx * 4], ptr[1 + idx * 4] };
}
case rsx::surface_color_format::w16z16y16x16:
{
auto ptr = gsl::as_span<const u16>(orig_buffer);
f16 h0 = f16(ptr[4 * idx]);
f16 h1 = f16(ptr[4 * idx + 1]);
f16 h2 = f16(ptr[4 * idx + 2]);
f32 f0 = float(h0);
f32 f1 = float(h1);
f32 f2 = float(h2);
u8 val0 = f0 * 255.;
u8 val1 = f1 * 255.;
u8 val2 = f2 * 255.;
return{ val0, val1, val2 };
}
case rsx::surface_color_format::g8b8:
case rsx::surface_color_format::r5g6b5:
case rsx::surface_color_format::x1r5g5b5_o1r5g5b5:
case rsx::surface_color_format::x1r5g5b5_z1r5g5b5:
case rsx::surface_color_format::w32z32y32x32:
throw EXCEPTION("Unsupported format for display");
}
}
/**
* Return a new buffer that can be passed to wxImage ctor.
* The pointer seems to be freed by wxImage.
*/
u8* convert_to_wximage_buffer(u8 *orig_buffer, size_t width, size_t height) noexcept
u8* convert_to_wximage_buffer(rsx::surface_color_format format, gsl::span<const gsl::byte> orig_buffer, size_t width, size_t height) noexcept
{
unsigned char* buffer = (unsigned char*)malloc(width * height * 3);
for (u32 i = 0; i < width * height; i++)
{
buffer[0 + i * 3] = orig_buffer[3 + i * 4];
buffer[1 + i * 3] = orig_buffer[2 + i * 4];
buffer[2 + i * 3] = orig_buffer[1 + i * 4];
const auto &colors = get_value(orig_buffer, format, i);
buffer[0 + i * 3] = colors[0];
buffer[1 + i * 3] = colors[1];
buffer[2 + i * 3] = colors[2];
}
return buffer;
}
@@ -401,6 +459,8 @@ void RSXDebugger::OnClickDrawCalls(wxMouseEvent& event)
{
size_t draw_id = m_list_captured_draw_calls->GetFirstSelected();
const auto& draw_call = frame_debug.draw_calls[draw_id];
wxPanel* p_buffers[] =
{
p_buffer_colorA,
@@ -409,13 +469,14 @@ void RSXDebugger::OnClickDrawCalls(wxMouseEvent& event)
p_buffer_colorD,
};
size_t width = draw_call.width;
size_t height = draw_call.height;
for (size_t i = 0; i < 4; i++)
{
size_t width = frame_debug.draw_calls[draw_id].color_buffer[i].width, height = frame_debug.draw_calls[draw_id].color_buffer[i].height;
if (width && height)
if (width && height && !draw_call.color_buffer[i].empty())
{
unsigned char *orig_buffer = frame_debug.draw_calls[draw_id].color_buffer[i].data.data();
buffer_img[i] = wxImage(width, height, convert_to_wximage_buffer(orig_buffer, width, height));
buffer_img[i] = wxImage(width, height, convert_to_wximage_buffer(draw_call.color_format, draw_call.color_buffer[i], width, height));
wxClientDC dc_canvas(p_buffers[i]);
if (buffer_img[i].IsOk())
@@ -425,56 +486,71 @@ void RSXDebugger::OnClickDrawCalls(wxMouseEvent& event)
// Buffer Z
{
size_t width = frame_debug.draw_calls[draw_id].depth.width, height = frame_debug.draw_calls[draw_id].depth.height;
if (width && height)
if (width && height && !draw_call.depth_stencil[0].empty())
{
u32 *orig_buffer = (u32*)frame_debug.draw_calls[draw_id].depth.data.data();
gsl::span<const gsl::byte> orig_buffer = draw_call.depth_stencil[0];
unsigned char *buffer = (unsigned char *)malloc(width * height * 3);
for (u32 row = 0; row < height; row++)
if (draw_call.depth_format == rsx::surface_depth_format::z24s8)
{
for (u32 col = 0; col < width; col++)
for (u32 row = 0; row < height; row++)
{
u32 depth_val = orig_buffer[row * width + col];
u8 displayed_depth_val = 255 * depth_val / 0xFFFFFF;
buffer[3 * col + 0 + width * row * 3] = displayed_depth_val;
buffer[3 * col + 1 + width * row * 3] = displayed_depth_val;
buffer[3 * col + 2 + width * row * 3] = displayed_depth_val;
for (u32 col = 0; col < width; col++)
{
u32 depth_val = gsl::as_span<const u32>(orig_buffer)[row * width + col];
u8 displayed_depth_val = 255 * depth_val / 0xFFFFFF;
buffer[3 * col + 0 + width * row * 3] = displayed_depth_val;
buffer[3 * col + 1 + width * row * 3] = displayed_depth_val;
buffer[3 * col + 2 + width * row * 3] = displayed_depth_val;
}
}
}
else
{
for (u32 row = 0; row < height; row++)
{
for (u32 col = 0; col < width; col++)
{
u16 depth_val = gsl::as_span<const u16>(orig_buffer)[row * width + col];
u8 displayed_depth_val = 255 * depth_val / 0xFFFF;
buffer[3 * col + 0 + width * row * 3] = displayed_depth_val;
buffer[3 * col + 1 + width * row * 3] = displayed_depth_val;
buffer[3 * col + 2 + width * row * 3] = displayed_depth_val;
}
}
}
wxImage img(width, height, buffer);
depth_img = wxImage(width, height, buffer);
wxClientDC dc_canvas(p_buffer_depth);
if (img.IsOk())
dc_canvas.DrawBitmap(img.Scale(m_panel_width, m_panel_height), 0, 0, false);
if (depth_img.IsOk())
dc_canvas.DrawBitmap(depth_img.Scale(m_panel_width, m_panel_height), 0, 0, false);
}
}
// Buffer S
{
size_t width = frame_debug.draw_calls[draw_id].stencil.width, height = frame_debug.draw_calls[draw_id].stencil.height;
if (width && height)
if (width && height && !draw_call.depth_stencil[1].empty())
{
u8 *orig_buffer = frame_debug.draw_calls[draw_id].stencil.data.data();
gsl::span<const gsl::byte> orig_buffer = draw_call.depth_stencil[1];
unsigned char *buffer = (unsigned char *)malloc(width * height * 3);
for (u32 row = 0; row < height; row++)
{
for (u32 col = 0; col < width; col++)
{
u32 stencil_val = orig_buffer[row * width + col];
u8 stencil_val = gsl::as_span<const u8>(orig_buffer)[row * width + col];
buffer[3 * col + 0 + width * row * 3] = stencil_val;
buffer[3 * col + 1 + width * row * 3] = stencil_val;
buffer[3 * col + 2 + width * row * 3] = stencil_val;
}
}
wxImage img(width, height, buffer);
stencil_img = wxImage(width, height, buffer);
wxClientDC dc_canvas(p_buffer_stencil);
if (img.IsOk())
dc_canvas.DrawBitmap(img.Scale(m_panel_width, m_panel_height), 0, 0, false);
if (stencil_img.IsOk())
dc_canvas.DrawBitmap(stencil_img.Scale(m_panel_width, m_panel_height), 0, 0, false);
}
}
@@ -764,11 +840,11 @@ void RSXDebugger::GetSettings()
render.m_color_mask_g,
render.m_color_mask_b,
render.m_color_mask_a));
LIST_SETTINGS_ADD("Context DMA Color A", wxString::Format("0x%x", render.m_context_dma_color_a));
LIST_SETTINGS_ADD("Context DMA Color B", wxString::Format("0x%x", render.m_context_dma_color_b));
LIST_SETTINGS_ADD("Context DMA Color C", wxString::Format("0x%x", render.m_context_dma_color_c));
LIST_SETTINGS_ADD("Context DMA Color D", wxString::Format("0x%x", render.m_context_dma_color_d));
LIST_SETTINGS_ADD("Context DMA Zeta", wxString::Format("0x%x", render.m_context_dma_z));
LIST_SETTINGS_ADD("Context DMA color A", wxString::Format("0x%x", render.m_context_dma_color_a));
LIST_SETTINGS_ADD("Context DMA color B", wxString::Format("0x%x", render.m_context_dma_color_b));
LIST_SETTINGS_ADD("Context DMA color C", wxString::Format("0x%x", render.m_context_dma_color_c));
LIST_SETTINGS_ADD("Context DMA color D", wxString::Format("0x%x", render.m_context_dma_color_d));
LIST_SETTINGS_ADD("Context DMA zeta", wxString::Format("0x%x", render.m_context_dma_z));
LIST_SETTINGS_ADD("Depth bounds", wxString::Format("Min:%f, Max:%f", render.m_depth_bounds_min, render.m_depth_bounds_max));
LIST_SETTINGS_ADD("Depth func", !(render.m_set_depth_func) ? "(none)" : wxString::Format("0x%x (%s)",
render.m_depth_func,
@@ -784,16 +860,16 @@ void RSXDebugger::GetSettings()
LIST_SETTINGS_ADD("Stencil func", !(render.m_set_stencil_func) ? "(none)" : wxString::Format("0x%x (%s)",
render.m_stencil_func,
ParseGCMEnum(render.m_stencil_func, CELL_GCM_ENUM)));
LIST_SETTINGS_ADD("Surface Pitch A", wxString::Format("0x%x", render.m_surface_pitch_a));
LIST_SETTINGS_ADD("Surface Pitch B", wxString::Format("0x%x", render.m_surface_pitch_b));
LIST_SETTINGS_ADD("Surface Pitch C", wxString::Format("0x%x", render.m_surface_pitch_c));
LIST_SETTINGS_ADD("Surface Pitch D", wxString::Format("0x%x", render.m_surface_pitch_d));
LIST_SETTINGS_ADD("Surface Pitch Z", wxString::Format("0x%x", render.m_surface_pitch_z));
LIST_SETTINGS_ADD("Surface Offset A", wxString::Format("0x%x", render.m_surface_offset_a));
LIST_SETTINGS_ADD("Surface Offset B", wxString::Format("0x%x", render.m_surface_offset_b));
LIST_SETTINGS_ADD("Surface Offset C", wxString::Format("0x%x", render.m_surface_offset_c));
LIST_SETTINGS_ADD("Surface Offset D", wxString::Format("0x%x", render.m_surface_offset_d));
LIST_SETTINGS_ADD("Surface Offset Z", wxString::Format("0x%x", render.m_surface_offset_z));
LIST_SETTINGS_ADD("Surface pitch A", wxString::Format("0x%x", render.m_surface_pitch_a));
LIST_SETTINGS_ADD("Surface pitch B", wxString::Format("0x%x", render.m_surface_pitch_b));
LIST_SETTINGS_ADD("Surface pitch C", wxString::Format("0x%x", render.m_surface_pitch_c));
LIST_SETTINGS_ADD("Surface pitch D", wxString::Format("0x%x", render.m_surface_pitch_d));
LIST_SETTINGS_ADD("Surface pitch Z", wxString::Format("0x%x", render.m_surface_pitch_z));
LIST_SETTINGS_ADD("Surface offset A", wxString::Format("0x%x", render.m_surface_offset_a));
LIST_SETTINGS_ADD("Surface offset B", wxString::Format("0x%x", render.m_surface_offset_b));
LIST_SETTINGS_ADD("Surface offset C", wxString::Format("0x%x", render.m_surface_offset_c));
LIST_SETTINGS_ADD("Surface offset D", wxString::Format("0x%x", render.m_surface_offset_d));
LIST_SETTINGS_ADD("Surface offset Z", wxString::Format("0x%x", render.m_surface_offset_z));
LIST_SETTINGS_ADD("Viewport", wxString::Format("X:%d, Y:%d, W:%d, H:%d",
render.m_viewport_x,
render.m_viewport_y,
@@ -846,8 +922,8 @@ void RSXDebugger::SetPrograms(wxListEvent& event)
wxDEFAULT_DIALOG_STYLE | wxMINIMIZE_BOX | wxMAXIMIZE_BOX | wxRESIZE_BORDER);
wxBoxSizer& s_panel = *new wxBoxSizer(wxHORIZONTAL);
wxStaticBoxSizer& s_vp_box = *new wxStaticBoxSizer(wxHORIZONTAL, &d_editor, "Vertex Program");
wxStaticBoxSizer& s_fp_box = *new wxStaticBoxSizer(wxHORIZONTAL, &d_editor, "Fragment Program");
wxStaticBoxSizer& s_vp_box = *new wxStaticBoxSizer(wxHORIZONTAL, &d_editor, "Vertex program");
wxStaticBoxSizer& s_fp_box = *new wxStaticBoxSizer(wxHORIZONTAL, &d_editor, "Fragment program");
wxTextCtrl* t_vp_edit = new wxTextCtrl(&d_editor, wxID_ANY, program.vp_shader, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
wxTextCtrl* t_fp_edit = new wxTextCtrl(&d_editor, wxID_ANY, program.fp_shader, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
t_vp_edit->SetFont(wxFont(8, wxFONTFAMILY_MODERN, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
@@ -891,10 +967,10 @@ const char* RSXDebugger::ParseGCMEnum(u32 value, u32 type)
case 0x0200: return "Never";
case 0x0201: return "Less";
case 0x0202: return "Equal";
case 0x0203: return "Less or Equal";
case 0x0203: return "Less or equal";
case 0x0204: return "Greater";
case 0x0205: return "Not Equal";
case 0x0206: return "Greater or Equal";
case 0x0205: return "Not equal";
case 0x0206: return "Greater or equal";
case 0x0207: return "Always";
case 0x0: return "Zero";
@@ -917,12 +993,12 @@ const char* RSXDebugger::ParseGCMEnum(u32 value, u32 type)
case 0x8007: return "Min";
case 0x8008: return "Max";
case 0x800A: return "Substract";
case 0x800B: return "Reverse Substract";
case 0xF005: return "Reverse Substract Signed";
case 0xF006: return "Add Signed";
case 0xF007: return "Reverse Add Signed";
case 0x800B: return "Reverse substract";
case 0xF005: return "Reverse substract signed";
case 0xF006: return "Add signed";
case 0xF007: return "Reverse add signed";
default: return "Wrong Value!";
default: return "Wrong value!";
}
}
case CELL_GCM_PRIMITIVE_ENUM:
@@ -940,7 +1016,7 @@ const char* RSXDebugger::ParseGCMEnum(u32 value, u32 type)
case 9: return "QUAD_STRIP";
case 10: return "POLYGON";
default: return "Wrong Value!";
default: return "Wrong value!";
}
}
default: return "Unknown!";
@@ -1002,7 +1078,7 @@ wxString RSXDebugger::DisAsmCommand(u32 cmd, u32 count, u32 currentAddr, u32 ioA
break;
case_16(NV4097_SET_TEXTURE_OFFSET, 0x20):
DISASM("Texture Offset[%d]: %08x", index, (u32)args[0]);
DISASM("Texture offset[%d]: %08x", index, (u32)args[0]);
switch ((args[1] & 0x3) - 1)
{
case CELL_GCM_LOCATION_LOCAL: DISASM("(Local memory);"); break;
+2
View File
@@ -29,6 +29,8 @@ class RSXDebugger : public wxDialog
wxPanel* p_buffer_tex;
wxImage buffer_img[4];
wxImage depth_img;
wxImage stencil_img;
wxTextCtrl* m_text_transform_program;
wxTextCtrl *m_text_shader_program;
+20 -20
View File
@@ -134,24 +134,24 @@ SettingsDialog::SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg)
wxStaticBoxSizer* s_round_llvm_threshold = new wxStaticBoxSizer(wxHORIZONTAL, p_core, _("Compilation threshold"));
// Graphics
wxStaticBoxSizer* s_round_gs_render = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Render"));
wxStaticBoxSizer* s_round_gs_d3d_adaptater = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("D3D Adaptater"));
wxStaticBoxSizer* s_round_gs_render = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Rendering API"));
wxStaticBoxSizer* s_round_gs_d3d_adaptater = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("D3D Adapter"));
wxStaticBoxSizer* s_round_gs_res = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Resolution"));
wxStaticBoxSizer* s_round_gs_aspect = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Aspect ratio"));
wxStaticBoxSizer* s_round_gs_frame_limit = new wxStaticBoxSizer(wxVERTICAL, p_graphics, _("Frame limit"));
// Input / Output
wxStaticBoxSizer* s_round_io_pad_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Pad Handler"));
wxStaticBoxSizer* s_round_io_keyboard_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Keyboard Handler"));
wxStaticBoxSizer* s_round_io_mouse_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Mouse Handler"));
wxStaticBoxSizer* s_round_io_pad_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Controller handler"));
wxStaticBoxSizer* s_round_io_keyboard_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Keyboard handler"));
wxStaticBoxSizer* s_round_io_mouse_handler = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Mouse handler"));
wxStaticBoxSizer* s_round_io_camera = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Camera"));
wxStaticBoxSizer* s_round_io_camera_type = new wxStaticBoxSizer(wxVERTICAL, p_io, _("Camera type"));
// Audio
wxStaticBoxSizer* s_round_audio_out = new wxStaticBoxSizer(wxVERTICAL, p_audio, _("Audio Out"));
wxStaticBoxSizer* s_round_audio_out = new wxStaticBoxSizer(wxVERTICAL, p_audio, _("Audio out"));
// Miscellaneous
wxStaticBoxSizer* s_round_hle_log_lvl = new wxStaticBoxSizer(wxVERTICAL, p_misc, _("Log Level"));
wxStaticBoxSizer* s_round_hle_log_lvl = new wxStaticBoxSizer(wxVERTICAL, p_misc, _("Log level"));
// Networking
wxStaticBoxSizer* s_round_net_status = new wxStaticBoxSizer(wxVERTICAL, p_networking, _("Connection status"));
@@ -183,17 +183,17 @@ SettingsDialog::SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg)
wxCheckBox* chbox_core_hook_stfunc = new wxCheckBox(p_core, wxID_ANY, "Hook static functions");
wxCheckBox* chbox_core_load_liblv2 = new wxCheckBox(p_core, wxID_ANY, "Load liblv2.sprx");
wxCheckBox* chbox_gs_log_prog = new wxCheckBox(p_graphics, wxID_ANY, "Log shader programs");
wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write Depth Buffer");
wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write Color Buffers");
wxCheckBox* chbox_gs_read_color = new wxCheckBox(p_graphics, wxID_ANY, "Read Color Buffers");
wxCheckBox* chbox_gs_read_depth = new wxCheckBox(p_graphics, wxID_ANY, "Read Depth Buffer");
wxCheckBox* chbox_gs_dump_depth = new wxCheckBox(p_graphics, wxID_ANY, "Write depth buffer");
wxCheckBox* chbox_gs_dump_color = new wxCheckBox(p_graphics, wxID_ANY, "Write color buffers");
wxCheckBox* chbox_gs_read_color = new wxCheckBox(p_graphics, wxID_ANY, "Read color buffers");
wxCheckBox* chbox_gs_read_depth = new wxCheckBox(p_graphics, wxID_ANY, "Read depth buffer");
wxCheckBox* chbox_gs_vsync = new wxCheckBox(p_graphics, wxID_ANY, "VSync");
wxCheckBox* chbox_gs_debug_output = new wxCheckBox(p_graphics, wxID_ANY, "Debug Output");
wxCheckBox* chbox_gs_3dmonitor = new wxCheckBox(p_graphics, wxID_ANY, "3D Monitor");
wxCheckBox* chbox_gs_debug_output = new wxCheckBox(p_graphics, wxID_ANY, "Debug output");
wxCheckBox* chbox_gs_3dmonitor = new wxCheckBox(p_graphics, wxID_ANY, "3D monitor");
wxCheckBox* chbox_gs_overlay = new wxCheckBox(p_graphics, wxID_ANY, "Debug overlay");
wxCheckBox* chbox_audio_dump = new wxCheckBox(p_audio, wxID_ANY, "Dump to file");
wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16 bit");
wxCheckBox* chbox_rsx_logging = new wxCheckBox(p_misc, wxID_ANY, "RSX Logging");
wxCheckBox* chbox_audio_conv = new wxCheckBox(p_audio, wxID_ANY, "Convert to 16-bit");
wxCheckBox* chbox_rsx_logging = new wxCheckBox(p_misc, wxID_ANY, "RSX logging");
wxCheckBox* chbox_hle_exitonstop = new wxCheckBox(p_misc, wxID_ANY, "Exit RPCS3 when process finishes");
wxCheckBox* chbox_hle_always_start = new wxCheckBox(p_misc, wxID_ANY, "Always start after boot");
wxCheckBox* chbox_hle_use_default_ini = new wxCheckBox(p_misc, wxID_ANY, "Use default configuration");
@@ -203,8 +203,8 @@ SettingsDialog::SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg)
wxTextCtrl* txt_llvm_threshold = new wxTextCtrl(p_core, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(55, 20));
//Auto Pause
wxCheckBox* chbox_dbg_ap_systemcall = new wxCheckBox(p_misc, wxID_ANY, "Auto Pause at System Call");
wxCheckBox* chbox_dbg_ap_functioncall = new wxCheckBox(p_misc, wxID_ANY, "Auto Pause at Function Call");
wxCheckBox* chbox_dbg_ap_systemcall = new wxCheckBox(p_misc, wxID_ANY, "Automatically pause at system call");
wxCheckBox* chbox_dbg_ap_functioncall = new wxCheckBox(p_misc, wxID_ANY, "Automatically pause at function call");
//Custom EmulationDir
wxCheckBox* chbox_emulationdir_enable = new wxCheckBox(p_system, wxID_ANY, "Use path below as EmulationDir. (Restart required)");
@@ -215,7 +215,7 @@ SettingsDialog::SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg)
ppu_decoder_modes.Add("Interpreter");
ppu_decoder_modes.Add("Interpreter 2");
ppu_decoder_modes.Add("Recompiler (LLVM)");
rbox_ppu_decoder = new wxRadioBox(p_core, wxID_ANY, "PPU Decoder", wxDefaultPosition, wxSize(215, -1), ppu_decoder_modes, 1);
rbox_ppu_decoder = new wxRadioBox(p_core, wxID_ANY, "PPU decoder", wxDefaultPosition, wxSize(215, -1), ppu_decoder_modes, 1);
#if !defined(LLVM_AVAILABLE)
rbox_ppu_decoder->Enable(2, false);
@@ -225,7 +225,7 @@ SettingsDialog::SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg)
spu_decoder_modes.Add("Interpreter (precise)");
spu_decoder_modes.Add("Interpreter (fast)");
spu_decoder_modes.Add("Recompiler (ASMJIT)");
rbox_spu_decoder = new wxRadioBox(p_core, wxID_ANY, "SPU Decoder", wxDefaultPosition, wxSize(215, -1), spu_decoder_modes, 1);
rbox_spu_decoder = new wxRadioBox(p_core, wxID_ANY, "SPU decoder", wxDefaultPosition, wxSize(215, -1), spu_decoder_modes, 1);
cbox_gs_render->Append("Null");
cbox_gs_render->Append("OpenGL");
@@ -260,7 +260,7 @@ SettingsDialog::SettingsDialog(wxWindow *parent, rpcs3::config_t* cfg)
cbox_gs_aspect->Append("4:3");
cbox_gs_aspect->Append("16:9");
for (auto item : { "Off", "50", "59.94", "30", "60", "Auto" })
for (auto item : { "Off", "30", "50", "59.94", "60", "Auto" })
cbox_gs_frame_limit->Append(item);
cbox_pad_handler->Append("Null");
+2 -2
View File
@@ -116,7 +116,7 @@ enum
};
VFSManagerDialog::VFSManagerDialog(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "Virtual File System Manager")
: wxDialog(parent, wxID_ANY, "Virtual file system manager")
{
m_list = new wxListView(this);
@@ -134,7 +134,7 @@ VFSManagerDialog::VFSManagerDialog(wxWindow* parent)
m_list->InsertColumn(0, "Path");
m_list->InsertColumn(1, "Device path");
m_list->InsertColumn(2, "Path to Device");
m_list->InsertColumn(2, "Path to device");
m_list->InsertColumn(3, "Device");
m_list->Bind(wxEVT_LIST_ITEM_ACTIVATED, &VFSManagerDialog::OnEntryConfig, this);
+8 -8
View File
@@ -50,7 +50,7 @@ enum
id_add_hdd
};
VHDDExplorer::VHDDExplorer(wxWindow* parent, const std::string& hdd_path) : wxDialog(parent, wxID_ANY, "Virtual HDD Explorer", wxDefaultPosition)
VHDDExplorer::VHDDExplorer(wxWindow* parent, const std::string& hdd_path) : wxDialog(parent, wxID_ANY, "Virtual hard drive explorer", wxDefaultPosition)
{
m_list = new wxListView(this);
m_drop_target = new VHDDListDropTarget(m_list);
@@ -249,18 +249,18 @@ void VHDDExplorer::OnRemove(wxCommandEvent& event)
void VHDDExplorer::OnCreateDir(wxCommandEvent& event)
{
int i = 1;
while(m_hdd->HasEntry(fmt::format("New Dir (%d)", i))) i++;
while(m_hdd->HasEntry(fmt::format("New dir (%d)", i))) i++;
m_hdd->Create(vfsHDD_Entry_Dir, fmt::format("New Dir (%d)", i));
m_hdd->Create(vfsHDD_Entry_Dir, fmt::format("New dir (%d)", i));
UpdateList();
}
void VHDDExplorer::OnCreateFile(wxCommandEvent& event)
{
int i = 1;
while (m_hdd->HasEntry(fmt::format("New File (%d)", i))) i++;
while (m_hdd->HasEntry(fmt::format("New file (%d)", i))) i++;
m_hdd->Create(vfsHDD_Entry_File, fmt::format("New File (%d)", i));
m_hdd->Create(vfsHDD_Entry_File, fmt::format("New file (%d)", i));
UpdateList();
}
@@ -376,7 +376,7 @@ void VHDDSetInfoDialog::GetResult(u64& size, u64& block_size)
}
VHDDManagerDialog::VHDDManagerDialog(wxWindow* parent)
: wxDialog(parent, wxID_ANY, "Virtual HDD Manager")
: wxDialog(parent, wxID_ANY, "Virtual hard drive Manager")
{
m_list = new wxListView(this);
@@ -438,7 +438,7 @@ void VHDDManagerDialog::DClick(wxListEvent& event)
void VHDDManagerDialog::AddHDD(wxCommandEvent& event)
{
wxFileDialog ctrl(this, "Select HDDs", wxEmptyString, wxEmptyString, "Virtual HDD (*.hdd) | *.hdd",
wxFileDialog ctrl(this, "Select hard drives", wxEmptyString, wxEmptyString, "Virtual hard drive (*.hdd) | *.hdd",
wxFD_OPEN | wxFD_FILE_MUST_EXIST | wxFD_MULTIPLE);
if(ctrl.ShowModal() == wxID_CANCEL)
@@ -498,7 +498,7 @@ void VHDDManagerDialog::OnRemove(wxCommandEvent& event)
void VHDDManagerDialog::OnCreateHDD(wxCommandEvent& event)
{
wxFileDialog ctrl(this, "Select HDD path", wxEmptyString, "new_hdd.hdd", "Virtual HDD (*.hdd) | *.hdd",
wxFileDialog ctrl(this, "Select hard drive path", wxEmptyString, "new_hdd.hdd", "Virtual hard drive (*.hdd) | *.hdd",
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
if(ctrl.ShowModal() == wxID_CANCEL)
+224 -267
View File
@@ -1,300 +1,257 @@
#include "stdafx.h"
#include "Emu/FS/vfsStream.h"
#include "PSF.h"
bool PSFLoader::Load(vfsStream& stream)
namespace psf
{
PSFHeader header;
_log::channel log("PSF");
// load header
if (!stream.SRead(header))
struct header_t
{
return false;
le_t<u32> magic;
le_t<u32> version;
le_t<u32> off_key_table;
le_t<u32> off_data_table;
le_t<u32> entries_num;
};
struct def_table_t
{
le_t<u16> key_off;
le_t<format> param_fmt;
le_t<u32> param_len;
le_t<u32> param_max;
le_t<u32> data_off;
};
const std::string& entry::as_string() const
{
CHECK_ASSERTION(m_type == format::string || m_type == format::array);
return m_value_string;
}
// check magic
if (header.magic != *(u32*)"\0PSF")
u32 entry::as_integer() const
{
LOG_ERROR(LOADER, "PSFLoader::Load() failed: unknown magic (0x%x)", header.magic);
return false;
CHECK_ASSERTION(m_type == format::integer);
return m_value_integer;
}
// check version
if (header.version != 0x101)
entry& entry::operator =(const std::string& value)
{
LOG_ERROR(LOADER, "PSFLoader::Load() failed: unknown version (0x%x)", header.version);
return false;
CHECK_ASSERTION(m_type == format::string || m_type == format::array);
m_value_string = value;
return *this;
}
// load indices
std::vector<PSFDefTable> indices;
indices.resize(header.entries_num);
if (!stream.SRead(indices[0], sizeof(PSFDefTable) * header.entries_num))
entry& entry::operator =(u32 value)
{
return false;
CHECK_ASSERTION(m_type == format::integer);
m_value_integer = value;
return *this;
}
// load key table
if (header.off_key_table > header.off_data_table)
u32 entry::size() const
{
LOG_ERROR(LOADER, "PSFLoader::Load() failed: off_key_table=0x%x, off_data_table=0x%x", header.off_key_table, header.off_data_table);
return false;
}
const u32 key_table_size = header.off_data_table - header.off_key_table;
std::unique_ptr<char[]> keys(new char[key_table_size + 1]);
stream.Seek(header.off_key_table);
if (stream.Read(keys.get(), key_table_size) != key_table_size)
{
return false;
}
keys.get()[key_table_size] = 0;
// load entries
std::vector<PSFEntry> entries;
entries.resize(header.entries_num);
for (u32 i = 0; i < header.entries_num; ++i)
{
entries[i].fmt = indices[i].param_fmt;
if (indices[i].key_off >= key_table_size)
switch (m_type)
{
return false;
case format::string:
case format::array:
return std::min(m_max_size, gsl::narrow<u32>(m_value_string.size() + (m_type == format::string)));
case format::integer:
return SIZE_32(u32);
}
entries[i].name = keys.get() + indices[i].key_off;
throw EXCEPTION("Invalid format (0x%x)", m_type);
}
// load data
stream.Seek(header.off_data_table + indices[i].data_off);
registry load(const std::vector<char>& data)
{
registry result;
if (indices[i].param_fmt == psf_entry_format::integer && indices[i].param_len == 4 && indices[i].param_max >= indices[i].param_len)
// Hack for empty input (TODO)
if (data.empty())
{
// load int data
return result;
}
if (!stream.SRead(entries[i].vint))
// Check size
CHECK_ASSERTION(data.size() >= sizeof(header_t));
CHECK_ASSERTION((std::uintptr_t)data.data() % 8 == 0);
// Get header
const header_t& header = reinterpret_cast<const header_t&>(data[0]);
// Check magic and version
CHECK_ASSERTION(header.magic == *(u32*)"\0PSF");
CHECK_ASSERTION(header.version == 0x101);
CHECK_ASSERTION(sizeof(header_t) + header.entries_num * sizeof(def_table_t) <= header.off_key_table);
CHECK_ASSERTION(header.off_key_table <= header.off_data_table);
CHECK_ASSERTION(header.off_data_table <= data.size());
// Get indices (alignment should be fine)
const def_table_t* indices = reinterpret_cast<const def_table_t*>(data.data() + sizeof(header_t));
// Load entries
for (u32 i = 0; i < header.entries_num; ++i)
{
CHECK_ASSERTION(indices[i].key_off < header.off_data_table - header.off_key_table);
// Get key name range
const auto name_ptr = data.begin() + header.off_key_table + indices[i].key_off;
const auto name_end = std::find(name_ptr , data.begin() + header.off_data_table, '\0');
// Get name (must be unique)
std::string key(name_ptr, name_end);
CHECK_ASSERTION(result.count(key) == 0);
CHECK_ASSERTION(indices[i].param_len <= indices[i].param_max);
CHECK_ASSERTION(indices[i].data_off < data.size() - header.off_data_table);
CHECK_ASSERTION(indices[i].param_max < data.size() - indices[i].data_off);
// Get data pointer
const auto value_ptr = data.begin() + header.off_data_table + indices[i].data_off;
if (indices[i].param_fmt == format::integer && indices[i].param_max == sizeof(u32) && indices[i].param_len == sizeof(u32))
{
return false;
// Integer data
result.emplace(std::piecewise_construct,
std::forward_as_tuple(std::move(key)),
std::forward_as_tuple(reinterpret_cast<const le_t<u32>&>(*value_ptr)));
}
else if (indices[i].param_fmt == format::string || indices[i].param_fmt == format::array)
{
// String/array data
std::string value;
if (indices[i].param_fmt == format::string)
{
// Find null terminator
value.assign(value_ptr, std::find(value_ptr, value_ptr + indices[i].param_len, '\0'));
}
else
{
value.assign(value_ptr, value_ptr + indices[i].param_len);
}
result.emplace(std::piecewise_construct,
std::forward_as_tuple(std::move(key)),
std::forward_as_tuple(indices[i].param_fmt, indices[i].param_max, std::move(value)));
}
else
{
// Possibly unsupported format, entry ignored
log.error("Unknown entry format (key='%s', fmt=0x%x, len=0x%x, max=0x%x)", key, indices[i].param_fmt, indices[i].param_len, indices[i].param_max);
}
}
else if ((indices[i].param_fmt == psf_entry_format::string || indices[i].param_fmt == psf_entry_format::string_not_null_term)
&& indices[i].param_max >= indices[i].param_len)
{
// load str data
const u32 size = indices[i].param_len;
std::unique_ptr<char[]> str(new char[size + 1]);
if (stream.Read(str.get(), size) != size)
{
return false;
}
str.get()[size] = 0;
entries[i].vstr = str.get();
}
else
{
LOG_ERROR(LOADER, "PSFLoader::Load() failed: (i=%d) fmt=0x%x, len=0x%x, max=0x%x", i, indices[i].param_fmt, indices[i].param_len, indices[i].param_max);
return false;
}
return result;
}
// reset data
m_entries = std::move(entries);
std::vector<char> save(const registry& psf)
{
std::vector<def_table_t> indices; indices.reserve(psf.size());
return true;
}
bool PSFLoader::Save(vfsStream& stream) const
{
std::vector<PSFDefTable> indices;
indices.resize(m_entries.size());
// generate header
PSFHeader header;
header.magic = *(u32*)"\0PSF";
header.version = 0x101;
header.entries_num = static_cast<u32>(m_entries.size());
header.off_key_table = sizeof(PSFHeader) + sizeof(PSFDefTable) * header.entries_num;
{
// calculate key table length and generate indices
u32& key_offset = header.off_data_table = 0;
u32 data_offset = 0;
for (u32 i = 0; i < m_entries.size(); i++)
{
indices[i].key_off = key_offset;
indices[i].data_off = data_offset;
indices[i].param_fmt = m_entries[i].fmt;
key_offset += static_cast<u32>(m_entries[i].name.size()) + 1; // key size
switch (m_entries[i].fmt) // calculate data size
{
case psf_entry_format::string_not_null_term:
{
data_offset += (indices[i].param_len = indices[i].param_max = static_cast<u32>(m_entries[i].vstr.size()));
break;
}
case psf_entry_format::string:
{
data_offset += (indices[i].param_len = indices[i].param_max = static_cast<u32>(m_entries[i].vstr.size()) + 1);
break;
}
case psf_entry_format::integer:
{
data_offset += (indices[i].param_len = indices[i].param_max = 4);
break;
}
default:
{
data_offset += (indices[i].param_len = indices[i].param_max = 0);
LOG_ERROR(LOADER, "PSFLoader::Save(): (i=%d) unknown entry format (0x%x, key='%s')", i, m_entries[i].fmt, m_entries[i].name);
}
}
}
}
header.off_data_table += header.off_key_table;
// save header
if (!stream.SWrite(header))
{
return false;
}
// save indices
if (!stream.SWrite(indices[0], sizeof(PSFDefTable) * m_entries.size()))
{
return false;
}
// save key table
for (const auto& entry : m_entries)
{
if (!stream.SWrite(entry.name[0], entry.name.size() + 1))
{
return false;
}
}
// save data
for (const auto& entry : m_entries)
{
switch (entry.fmt)
{
case psf_entry_format::string:
{
if (!stream.SWrite(entry.vstr[0], entry.vstr.size() + 1))
{
return false;
}
break;
}
case psf_entry_format::string_not_null_term:
{
if (!stream.SWrite(entry.vstr[0], entry.vstr.size()))
{
return false;
}
break;
}
case psf_entry_format::integer:
{
if (!stream.SWrite(entry.vint))
{
return false;
}
break;
}
}
}
return true;
}
void PSFLoader::Clear()
{
m_entries.clear();
}
const PSFEntry* PSFLoader::SearchEntry(const std::string& key) const
{
for (auto& entry : m_entries)
{
if (key == entry.name)
{
return &entry;
}
}
return nullptr;
}
PSFEntry& PSFLoader::AddEntry(const std::string& key, psf_entry_format fmt)
{
for (auto& entry : m_entries)
{
if (key == entry.name)
{
entry.fmt = fmt;
return entry;
}
}
PSFEntry new_entry = {};
new_entry.fmt = fmt;
new_entry.name = key;
m_entries.push_back(new_entry);
return m_entries.back();
}
std::string PSFLoader::GetString(const std::string& key, std::string def) const
{
if (const auto entry = SearchEntry(key))
{
if (entry->fmt == psf_entry_format::string || entry->fmt == psf_entry_format::string_not_null_term)
{
return entry->vstr;
}
}
return def;
}
s32 PSFLoader::GetInteger(const std::string& key, s32 def) const
{
if (const auto entry = SearchEntry(key))
{
if (entry->fmt == psf_entry_format::integer)
{
return entry->vint;
}
}
return def;
}
void PSFLoader::SetString(const std::string& key, std::string value)
{
AddEntry(key, psf_entry_format::string).vstr = value;
}
void PSFLoader::SetInteger(const std::string& key, s32 value)
{
AddEntry(key, psf_entry_format::integer).vint = value;
// Generate indices and calculate key table length
std::size_t key_offset = 0, data_offset = 0;
for (const auto& entry : psf)
{
def_table_t index;
index.key_off = gsl::narrow<u32>(key_offset);
index.param_fmt = entry.second.type();
index.param_len = entry.second.size();
index.param_max = entry.second.max();
index.data_off = gsl::narrow<u32>(data_offset);
// Update offsets:
key_offset += gsl::narrow<u32>(entry.first.size() + 1); // key size
data_offset += index.param_max;
indices.push_back(index);
}
// Align next section (data) offset
key_offset = ::align(key_offset, 4);
// Generate header
header_t header;
header.magic = *(u32*)"\0PSF";
header.version = 0x101;
header.off_key_table = gsl::narrow<u32>(sizeof(header_t) + sizeof(def_table_t) * psf.size());
header.off_data_table = gsl::narrow<u32>(header.off_key_table + key_offset);
header.entries_num = gsl::narrow<u32>(psf.size());
// Save header and indices
std::vector<char> result; result.reserve(header.off_data_table + data_offset);
result.insert(result.end(), (char*)&header, (char*)&header + sizeof(header_t));
result.insert(result.end(), (char*)indices.data(), (char*)indices.data() + sizeof(def_table_t) * psf.size());
// Save key table
for (const auto& entry : psf)
{
result.insert(result.end(), entry.first.begin(), entry.first.end());
result.push_back('\0');
}
// Insert zero padding
result.insert(result.end(), header.off_data_table - result.size(), '\0');
// Save data
for (const auto& entry : psf)
{
const auto fmt = entry.second.type();
const u32 max = entry.second.max();
if (fmt == format::integer && max == sizeof(u32))
{
const le_t<u32> value = entry.second.as_integer();
result.insert(result.end(), (char*)&value, (char*)&value + sizeof(u32));
}
else if (fmt == format::string || fmt == format::array)
{
const std::string& value = entry.second.as_string();
const std::size_t size = std::min<std::size_t>(max, value.size());
if (value.size() + (fmt == format::string) > max)
{
// TODO: check real limitations of PSF format
log.error("Entry value shrinkage (key='%s', value='%s', size=0x%zx, max=0x%x)", entry.first, value, size, max);
}
result.insert(result.end(), value.begin(), value.begin() + size);
result.insert(result.end(), max - size, '\0'); // Write zeros up to max_size
}
else
{
throw EXCEPTION("Invalid entry format (key='%s', fmt=0x%x)", entry.first, fmt);
}
}
return result;
}
std::string get_string(const registry& psf, const std::string& key, const std::string& def)
{
const auto found = psf.find(key);
if (found == psf.end() || (found->second.type() != format::string && found->second.type() != format::array))
{
return def;
}
return found->second.as_string();
}
u32 get_integer(const registry& psf, const std::string& key, u32 def)
{
const auto found = psf.find(key);
if (found == psf.end() || found->second.type() != format::integer)
{
return def;
}
return found->second.as_integer();
}
}
+67 -80
View File
@@ -1,88 +1,75 @@
#pragma once
struct vfsStream;
enum class psf_entry_format : u16
namespace psf
{
string_not_null_term = 0x0004,
string = 0x0204,
integer = 0x0404,
};
struct PSFHeader
{
u32 magic;
u32 version;
u32 off_key_table;
u32 off_data_table;
u32 entries_num;
};
struct PSFDefTable
{
u16 key_off;
psf_entry_format param_fmt;
u32 param_len;
u32 param_max;
u32 data_off;
};
struct PSFEntry
{
psf_entry_format fmt;
std::string name;
s32 vint;
std::string vstr;
};
class PSFLoader
{
std::vector<PSFEntry> m_entries;
public:
PSFLoader() = default;
PSFLoader(vfsStream& stream)
enum class format : u16
{
Load(stream);
array = 0x0004, // claimed to be a non-NTS string (char array)
string = 0x0204,
integer = 0x0404,
};
class entry final
{
std::string m_value_string;
u32 m_value_integer; // TODO: is it really unsigned?
u32 m_max_size; // Entry max size (supplementary info, stored in PSF format)
format m_type;
public:
// Construct string entry, assign the value
entry(format type, u32 max_size, const std::string& value = {})
: m_type(type)
, m_max_size(max_size)
, m_value_string(value)
{
CHECK_ASSERTION(type == format::string || type == format::array);
CHECK_ASSERTION(max_size);
}
// Construct integer entry, assign the value
entry(u32 value)
: m_type(format::integer)
, m_max_size(sizeof(u32))
, m_value_integer(value)
{
}
const std::string& as_string() const;
u32 as_integer() const;
entry& operator =(const std::string& value);
entry& operator =(u32 value);
format type() const { return m_type; }
u32 max() const { return m_max_size; }
u32 size() const;
};
// Define PSF registry as a sorted map of entries:
using registry = std::map<std::string, entry>;
// Load PSF registry from binary data
registry load(const std::vector<char>&);
// Convert PSF registry to binary format
std::vector<char> save(const registry&);
// Get string value or default value
std::string get_string(const registry& psf, const std::string& key, const std::string& def = {});
// Get integer value or default value
u32 get_integer(const registry& psf, const std::string& key, u32 def = 0);
// Make string entry
inline entry string(u32 max_size, const std::string& value)
{
return{ format::string, max_size, value };
}
virtual ~PSFLoader() = default;
bool Load(vfsStream& stream);
bool Save(vfsStream& stream) const;
void Clear();
explicit operator bool() const
// Make array entry
inline entry array(u32 max_size, const std::string& value)
{
return !m_entries.empty();
return{ format::array, max_size, value };
}
const PSFEntry* SearchEntry(const std::string& key) const;
PSFEntry& AddEntry(const std::string& key, psf_entry_format format);
std::string GetString(const std::string& key, std::string def = "") const;
s32 GetInteger(const std::string& key, s32 def = 0) const;
void SetString(const std::string& key, std::string value);
void SetInteger(const std::string& key, s32 value);
std::vector<PSFEntry>& entries()
{
return m_entries;
}
const std::vector<PSFEntry>& entries() const
{
return m_entries;
}
std::vector<PSFEntry>::iterator begin()
{
return m_entries.begin();
}
std::vector<PSFEntry>::iterator end()
{
return m_entries.end();
}
};
}
+34 -34
View File
@@ -62,9 +62,9 @@ enum class rsx_aspect_ratio
enum class rsx_frame_limit
{
Off,
_30,
_50,
_59_94,
_30,
_60,
Auto
};
@@ -155,9 +155,9 @@ namespace convert
switch (value)
{
case rsx_frame_limit::Off: return "Off";
case rsx_frame_limit::_30: return "30";
case rsx_frame_limit::_50: return "50";
case rsx_frame_limit::_59_94: return "59.94";
case rsx_frame_limit::_30: return "30";
case rsx_frame_limit::_60: return "60";
case rsx_frame_limit::Auto: return "Auto";
}
@@ -174,15 +174,15 @@ namespace convert
if (value == "Off")
return rsx_frame_limit::Off;
if (value == "30")
return rsx_frame_limit::_30;
if (value == "50")
return rsx_frame_limit::_50;
if (value == "59.94")
return rsx_frame_limit::_59_94;
if (value == "30")
return rsx_frame_limit::_30;
if (value == "60")
return rsx_frame_limit::_60;
@@ -836,8 +836,8 @@ namespace rpcs3
} llvm{ this };
entry<ppu_decoder_type> ppu_decoder { this, "PPU Decoder", ppu_decoder_type::interpreter };
entry<spu_decoder_type> spu_decoder { this, "SPU Decoder", spu_decoder_type::interpreter_precise };
entry<ppu_decoder_type> ppu_decoder { this, "PPU decoder", ppu_decoder_type::interpreter };
entry<spu_decoder_type> spu_decoder { this, "SPU decoder", spu_decoder_type::interpreter_precise };
entry<bool> hook_st_func { this, "Hook static functions", false };
entry<bool> load_liblv2 { this, "Load liblv2.sprx", false };
@@ -849,30 +849,30 @@ namespace rpcs3
{
opengl_group(group *grp) : group{ grp, "opengl" } {}
entry<bool> write_color_buffers { this, "Write Color Buffers", true };
entry<bool> write_depth_buffer { this, "Write Depth Buffer", true };
entry<bool> read_color_buffers { this, "Read Color Buffers", true };
entry<bool> read_depth_buffer { this, "Read Depth Buffer", true };
entry<bool> write_color_buffers { this, "Write color buffers", true };
entry<bool> write_depth_buffer { this, "Write depth buffer", true };
entry<bool> read_color_buffers { this, "Read color buffers", true };
entry<bool> read_depth_buffer { this, "Read depth buffer", true };
} opengl{ this };
struct d3d12_group : protected group
{
d3d12_group(group *grp) : group{ grp, "d3d12" } {}
entry<u32> adaptater { this, "D3D Adaptater", 1 };
entry<bool> debug_output { this, "Debug Output", false };
entry<u32> adaptater { this, "D3D adapter", 0 };
entry<bool> debug_output { this, "Debug output", false };
entry<bool> overlay { this, "Debug overlay", false };
} d3d12{ this };
rsx_group(config_context_t *cfg) : group{ cfg, "rsx" } {}
entry<rsx_renderer_type> renderer { this, "Renderer", rsx_renderer_type::OpenGL };
entry<rsx_renderer_type> renderer { this, "Rendering API", rsx_renderer_type::OpenGL };
entry<rsx_resolution> resolution { this, "Resolution", rsx_resolution::_720x480 };
entry<rsx_aspect_ratio> aspect_ratio{ this, "Aspect ratio", rsx_aspect_ratio::_16x9 };
entry<rsx_frame_limit> frame_limit { this, "Frame limit", rsx_frame_limit::Off };
entry<bool> log_programs { this, "Log shader programs", false };
entry<bool> vsync { this, "VSync", false };
entry<bool> _3dtv { this, "3D Monitor", false };
entry<bool> _3dtv { this, "3D monitor", false };
} rsx{ this };
@@ -880,33 +880,33 @@ namespace rpcs3
{
audio_group(config_context_t *cfg) : group{ cfg, "audio" } {}
entry<audio_output_type> out{ this, "Audio Out", audio_output_type::OpenAL };
entry<audio_output_type> out{ this, "Audio out", audio_output_type::OpenAL };
entry<bool> dump_to_file { this, "Dump to file", false };
entry<bool> convert_to_u16 { this, "Convert to 16 bit", false };
entry<bool> convert_to_u16 { this, "Convert to 16-bit", false };
} audio{ this };
struct io_group : protected group
{
io_group(config_context_t *cfg) : group{ cfg, "io" } {}
entry<io_camera_state> camera { this, "Camera", io_camera_state::connected };
entry<io_camera_type> camera_type { this, "Camera type", io_camera_type::play_station_eye };
entry<io_handler_mode> pad_handler_mode { this, "Pad Handler", io_handler_mode::windows };
entry<io_handler_mode> keyboard_handler_mode{ this, "Keyboard Handler", io_handler_mode::null };
entry<io_handler_mode> mouse_handler_mode { this, "Mouse Handler", io_handler_mode::null };
entry<io_camera_state> camera { this, "Camera", io_camera_state::connected };
entry<io_camera_type> camera_type { this, "Camera type", io_camera_type::play_station_eye };
entry<io_handler_mode> pad_handler_mode { this, "Controller handler", io_handler_mode::windows };
entry<io_handler_mode> keyboard_handler_mode{ this, "Keyboard handler", io_handler_mode::null };
entry<io_handler_mode> mouse_handler_mode { this, "Mouse handler", io_handler_mode::null };
struct pad_group : protected group
{
pad_group(group *grp) : group{ grp, "pad" } {}
entry<int> left_stick_left { this, "Left Analog Stick Left", 314 };
entry<int> left_stick_down { this, "Left Analog Stick Down", 317 };
entry<int> left_stick_right { this, "Left Analog Stick Right", 316 };
entry<int> left_stick_up { this, "Left Analog Stick Up", 315 };
entry<int> right_stick_left { this, "Right Analog Stick Left", 313 };
entry<int> right_stick_down { this, "Right Analog Stick Down", 367 };
entry<int> right_stick_right{ this, "Right Analog Stick Right", 312 };
entry<int> right_stick_up { this, "Right Analog Stick Up", 366 };
entry<int> left_stick_left { this, "Left analog stick Left", 314 };
entry<int> left_stick_down { this, "Left analog stick Down", 317 };
entry<int> left_stick_right { this, "Left analog stick Right", 316 };
entry<int> left_stick_up { this, "Left analog stick Up", 315 };
entry<int> right_stick_left { this, "Right analog stick Left", 313 };
entry<int> right_stick_down { this, "Right analog stick Down", 367 };
entry<int> right_stick_right{ this, "Right analog stick Right", 312 };
entry<int> right_stick_up { this, "Right analog stick Up", 366 };
entry<int> start { this, "Start", 13 };
entry<int> select { this, "Select", 32 };
entry<int> square { this, "Square", static_cast<int>('J') };
@@ -935,8 +935,8 @@ namespace rpcs3
{
log_group(group *grp) : group{ grp, "log" } {}
entry<_log::level> level { this, "Log Level", _log::level::success };
entry<bool> rsx_logging { this, "RSX Logging", false };
entry<_log::level> level { this, "Log level", _log::level::success };
entry<bool> rsx_logging { this, "RSX logging", false };
} log{ this };
struct net_group : protected group
@@ -951,8 +951,8 @@ namespace rpcs3
{
debug_group(group *grp) : group{ grp, "debug" } {}
entry<bool> auto_pause_syscall { this, "Auto Pause at System Call", false };
entry<bool> auto_pause_func_call { this, "Auto Pause at Function Call", false };
entry<bool> auto_pause_syscall { this, "Automatically pause at system call", false };
entry<bool> auto_pause_func_call { this, "Automatically pause at function call", false };
} debug{ this };
entry<bool> exit_on_stop { this, "Exit RPCS3 when process finishes", false };
+2
View File
@@ -87,6 +87,7 @@
<ClCompile Include="Emu\RSX\Common\FragmentProgramDecompiler.cpp" />
<ClCompile Include="Emu\RSX\Common\ProgramStateCache.cpp" />
<ClCompile Include="Emu\RSX\Common\ShaderParam.cpp" />
<ClCompile Include="Emu\RSX\Common\surface_store.cpp" />
<ClCompile Include="Emu\RSX\Common\TextureUtils.cpp" />
<ClCompile Include="Emu\RSX\Common\VertexProgramDecompiler.cpp" />
<ClCompile Include="Emu\RSX\GCM.cpp" />
@@ -516,6 +517,7 @@
<ClInclude Include="Emu\RSX\Common\FragmentProgramDecompiler.h" />
<ClInclude Include="Emu\RSX\Common\ProgramStateCache.h" />
<ClInclude Include="Emu\RSX\Common\ShaderParam.h" />
<ClInclude Include="Emu\RSX\Common\surface_store.h" />
<ClInclude Include="Emu\RSX\Common\TextureUtils.h" />
<ClInclude Include="Emu\RSX\Common\VertexProgramDecompiler.h" />
<ClInclude Include="Emu\RSX\GCM.h" />
+6
View File
@@ -936,6 +936,9 @@
<ClCompile Include="Emu\RSX\Common\ProgramStateCache.cpp">
<Filter>Emu\GPU\RSX\Common</Filter>
</ClCompile>
<ClCompile Include="Emu\RSX\Common\surface_store.cpp">
<Filter>Emu\GPU\RSX\Common</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@@ -1788,5 +1791,8 @@
<ClInclude Include="..\stblib\stb_image.c">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="Emu\RSX\Common\surface_store.h">
<Filter>Emu\GPU\RSX\Common</Filter>
</ClInclude>
</ItemGroup>
</Project>
+3 -3
View File
@@ -3,7 +3,7 @@
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<IncludePath>.\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include;$(UniversalCRT_IncludePath);..\minidx12\Include;..\glm;..\GSL\include</IncludePath>
<IncludePath>.\;..\;..\asmjit\src\asmjit;..\wxWidgets\include\msvc;..\wxWidgets\include;..\ffmpeg\WindowsInclude;..\ffmpeg\Windows\x86_64\Include;$(VC_IncludePath);$(WindowsSDK_IncludePath);..\llvm\include;..\llvm_build\include;$(UniversalCRT_IncludePath);..\minidx12\Include;..\glm;..\GSL\include;..\libpng</IncludePath>
<OutDir>$(SolutionDir)lib\$(Configuration)-$(Platform)\</OutDir>
<LibraryPath>$(SolutionDir)lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)</LibraryPath>
<IntDir>$(SolutionDir)tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
@@ -25,9 +25,9 @@
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;rpcrt4.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>odbc32.lib;odbccp32.lib;comctl32.lib;ws2_32.lib;shlwapi.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;rpcrt4.lib;libpng.lib;%(AdditionalDependencies)</AdditionalDependencies>
<DataExecutionPrevention>true</DataExecutionPrevention>
<AdditionalLibraryDirectories>..\wxWidgets\lib\vc_x64_lib;..\ffmpeg\Windows\x86_64\lib</AdditionalLibraryDirectories>
<AdditionalLibraryDirectories>..\wxWidgets\lib\vc_x64_lib;..\ffmpeg\Windows\x86_64\lib;..\lib\</AdditionalLibraryDirectories>
<BaseAddress>0x10000</BaseAddress>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
</Link>
+45
View File
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
* zlib.props - location of zlib source
*
* libpng version 1.6.20 - December 3, 2015
*
* Copyright (c) 1998-2011 Glenn Randers-Pehrson
*
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
* You must edit this file to record the location of the zlib
* source code.
-->
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<!-- Place the name of the directory containing the source of zlib used for
debugging in this property.
The directory need only contain the '.c' and '.h' files from the
source.
If you use a relative directory name (as below) then it must be
relative to the project directories; these are one level deeper than
the directories containing this file.
If the version of zlib you use does not match that used when the
distribution was built you will get warnings from pngtest that the zlib
versions do not match. The zlib version used in this build is recorded
below:
-->
<ZLibSrcDir>..\..\..\..\wxWidgets\src\zlib\</ZLibSrcDir>
<!-- The following line allows compilation for an ARM target with Visual
Studio 2012. Notice that this is not supported by the Visual Studio
2012 IDE and that the programs that result cannot be run unless they
signed by Microsoft. This is therefore untested; only Microsoft can
test it:
-->
<WindowsSDKDesktopARMSupport>true</WindowsSDKDesktopARMSupport>
</PropertyGroup>
</Project>