From be84413dbd7a31830d0fb4253d02f2de34ef7515 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Thu, 24 Jul 2025 18:26:58 +0300 Subject: [PATCH] D3D9 shader generation. --- XenosRecomp/CMakeLists.txt | 30 +- XenosRecomp/dxc_compiler.cpp | 100 ------ XenosRecomp/dxc_compiler.h | 11 - XenosRecomp/fxc_compiler.cpp | 28 ++ XenosRecomp/fxc_compiler.h | 6 + XenosRecomp/main.cpp | 199 ++--------- XenosRecomp/pch.h | 5 +- XenosRecomp/shader_common.h | 187 +--------- XenosRecomp/shader_recompiler.cpp | 544 +++++------------------------- XenosRecomp/shader_recompiler.h | 1 - 10 files changed, 140 insertions(+), 971 deletions(-) delete mode 100644 XenosRecomp/dxc_compiler.cpp delete mode 100644 XenosRecomp/dxc_compiler.h create mode 100644 XenosRecomp/fxc_compiler.cpp create mode 100644 XenosRecomp/fxc_compiler.h diff --git a/XenosRecomp/CMakeLists.txt b/XenosRecomp/CMakeLists.txt index e505a5e..6b76744 100644 --- a/XenosRecomp/CMakeLists.txt +++ b/XenosRecomp/CMakeLists.txt @@ -1,31 +1,20 @@ project(XenosRecomp) -if (WIN32) - option(XENOS_RECOMP_DXIL "Generate DXIL shader cache" ON) -endif() - -set(SMOLV_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../thirdparty/smol-v/source") - add_executable(XenosRecomp constant_table.h - dxc_compiler.cpp - dxc_compiler.h + fxc_compiler.cpp + fxc_compiler.h main.cpp pch.h shader.h shader_code.h shader_recompiler.cpp - shader_recompiler.h - "${SMOLV_SOURCE_DIR}/smolv.cpp") + shader_recompiler.h) target_link_libraries(XenosRecomp PRIVATE - Microsoft::DirectXShaderCompiler - xxHash::xxhash - libzstd_static + d3dcompiler.lib fmt::fmt) -target_include_directories(XenosRecomp PRIVATE ${SMOLV_SOURCE_DIR}) - target_precompile_headers(XenosRecomp PRIVATE pch.h) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") @@ -41,13 +30,4 @@ endif() if (WIN32) target_compile_definitions(XenosRecomp PRIVATE _CRT_SECURE_NO_WARNINGS) - add_custom_command(TARGET XenosRecomp POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy $ $ - COMMAND_EXPAND_LISTS - ) -endif() - -if (XENOS_RECOMP_DXIL) - target_compile_definitions(XenosRecomp PRIVATE XENOS_RECOMP_DXIL) - target_link_libraries(XenosRecomp PRIVATE Microsoft::DXIL) -endif() +endif() \ No newline at end of file diff --git a/XenosRecomp/dxc_compiler.cpp b/XenosRecomp/dxc_compiler.cpp deleted file mode 100644 index fcbc43a..0000000 --- a/XenosRecomp/dxc_compiler.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "dxc_compiler.h" - -DxcCompiler::DxcCompiler() -{ - HRESULT hr = DxcCreateInstance(CLSID_DxcCompiler, IID_PPV_ARGS(&dxcCompiler)); - assert(SUCCEEDED(hr)); -} - -DxcCompiler::~DxcCompiler() -{ - dxcCompiler->Release(); -} - -IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool compilePixelShader, bool compileLibrary, bool compileSpirv) -{ - DxcBuffer source{}; - source.Ptr = shaderSource.c_str(); - source.Size = shaderSource.size(); - - const wchar_t* args[32]{}; - uint32_t argCount = 0; - - const wchar_t* target = nullptr; - if (compileLibrary) - { - assert(!compileSpirv); - target = L"-T lib_6_3"; - } - else - { - if (compilePixelShader) - target = L"-T ps_6_0"; - else - target = L"-T vs_6_0"; - } - - args[argCount++] = target; - args[argCount++] = L"-HV 2021"; - args[argCount++] = L"-all-resources-bound"; - - if (compileSpirv) - { - args[argCount++] = L"-spirv"; - args[argCount++] = L"-fvk-use-dx-layout"; - - if (!compilePixelShader) - args[argCount++] = L"-fvk-invert-y"; - } - else - { - args[argCount++] = L"-Wno-ignored-attributes"; - args[argCount++] = L"-Qstrip_reflect"; - } - - args[argCount++] = L"-Qstrip_debug"; - -#ifdef UNLEASHED_RECOMP - args[argCount++] = L"-DUNLEASHED_RECOMP"; -#endif - - IDxcResult* result = nullptr; - HRESULT hr = dxcCompiler->Compile(&source, args, argCount, nullptr, IID_PPV_ARGS(&result)); - - IDxcBlob* object = nullptr; - if (SUCCEEDED(hr)) - { - assert(result != nullptr); - - HRESULT status; - hr = result->GetStatus(&status); - assert(SUCCEEDED(hr)); - - if (FAILED(status)) - { - if (result->HasOutput(DXC_OUT_ERRORS)) - { - IDxcBlobUtf8* errors = nullptr; - hr = result->GetOutput(DXC_OUT_ERRORS, IID_PPV_ARGS(&errors), nullptr); - assert(SUCCEEDED(hr) && errors != nullptr); - - fputs(errors->GetStringPointer(), stderr); - - errors->Release(); - } - } - else - { - hr = result->GetOutput(DXC_OUT_OBJECT, IID_PPV_ARGS(&object), nullptr); - assert(SUCCEEDED(hr) && object != nullptr); - } - - result->Release(); - } - else - { - assert(result == nullptr); - } - - return object; -} diff --git a/XenosRecomp/dxc_compiler.h b/XenosRecomp/dxc_compiler.h deleted file mode 100644 index d49bd32..0000000 --- a/XenosRecomp/dxc_compiler.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -struct DxcCompiler -{ - IDxcCompiler3* dxcCompiler = nullptr; - - DxcCompiler(); - ~DxcCompiler(); - - IDxcBlob* compile(const std::string& shaderSource, bool compilePixelShader, bool compileLibrary, bool compileSpirv); -}; diff --git a/XenosRecomp/fxc_compiler.cpp b/XenosRecomp/fxc_compiler.cpp new file mode 100644 index 0000000..7177ab8 --- /dev/null +++ b/XenosRecomp/fxc_compiler.cpp @@ -0,0 +1,28 @@ +#include "fxc_compiler.h" + +ID3DBlob* FxcCompiler::compile(const std::string& shaderSource, bool compilePixelShader) +{ + ID3DBlob* code = nullptr; + ID3DBlob* errorMsgs = nullptr; + + HRESULT result = D3DCompile( + shaderSource.data(), + shaderSource.size(), + nullptr, + nullptr, + nullptr, + "main", + compilePixelShader ? "ps_3_0" : "vs_3_0", + 0, + 0, + &code, + &errorMsgs); + + if (FAILED(result) && errorMsgs != nullptr) + fputs(reinterpret_cast(errorMsgs->GetBufferPointer()), stderr); + + if (errorMsgs != nullptr) + errorMsgs->Release(); + + return code; +} diff --git a/XenosRecomp/fxc_compiler.h b/XenosRecomp/fxc_compiler.h new file mode 100644 index 0000000..5b3bc70 --- /dev/null +++ b/XenosRecomp/fxc_compiler.h @@ -0,0 +1,6 @@ +#pragma once + +struct FxcCompiler +{ + static ID3DBlob* compile(const std::string& shaderSource, bool compilePixelShader); +}; diff --git a/XenosRecomp/main.cpp b/XenosRecomp/main.cpp index d015145..478f75d 100644 --- a/XenosRecomp/main.cpp +++ b/XenosRecomp/main.cpp @@ -1,6 +1,6 @@ #include "shader.h" #include "shader_recompiler.h" -#include "dxc_compiler.h" +#include "fxc_compiler.h" static std::unique_ptr readAllBytes(const char* filePath, size_t& fileSize) { @@ -21,198 +21,37 @@ static void writeAllBytes(const char* filePath, const void* data, size_t dataSiz fclose(file); } -struct RecompiledShader -{ - uint8_t* data = nullptr; - IDxcBlob* dxil = nullptr; - std::vector spirv; - uint32_t specConstantsMask = 0; -}; - int main(int argc, char** argv) { -#ifndef XENOS_RECOMP_INPUT - if (argc < 4) - { - printf("Usage: XenosRecomp [input path] [output path] [shader common header file path]"); - return 0; - } -#endif - - const char* input = -#ifdef XENOS_RECOMP_INPUT - XENOS_RECOMP_INPUT -#else - argv[1] -#endif - ; - - const char* output = -#ifdef XENOS_RECOMP_OUTPUT - XENOS_RECOMP_OUTPUT -#else - argv[2] -#endif - ; - - const char* includeInput = -#ifdef XENOS_RECOMP_INCLUDE_INPUT - XENOS_RECOMP_INCLUDE_INPUT -#else - argv[3] -#endif - ; + std::filesystem::path input(argv[1]); + std::filesystem::path output(argv[2]); + const char* includeInput = argv[3]; size_t includeSize = 0; auto includeData = readAllBytes(includeInput, includeSize); std::string_view include(reinterpret_cast(includeData.get()), includeSize); - if (std::filesystem::is_directory(input)) + for (auto& inputFile : std::filesystem::directory_iterator(input)) { - std::vector> files; - std::map shaders; - - for (auto& file : std::filesystem::recursive_directory_iterator(input)) + if ((inputFile.path().extension() == ".xvu") || (inputFile.path().extension() == ".xpu")) { - if (std::filesystem::is_directory(file)) + fmt::println("{}", inputFile.path().string()); + + auto outputFile = (output / inputFile.path().filename()).string(); + outputFile[outputFile.size() - 3] = 'w'; + + ShaderRecompiler recompiler; + size_t fileSize; + recompiler.recompile(readAllBytes(inputFile.path().string().c_str(), fileSize).get(), include); + ID3DBlob* blob = FxcCompiler::compile(recompiler.out, recompiler.isPixelShader); + if (blob != nullptr) { - continue; - } - - size_t fileSize = 0; - auto fileData = readAllBytes(file.path().string().c_str(), fileSize); - bool foundAny = false; - - for (size_t i = 0; fileSize > sizeof(ShaderContainer) && i < fileSize - sizeof(ShaderContainer) - 1;) - { - auto shaderContainer = reinterpret_cast(fileData.get() + i); - size_t dataSize = shaderContainer->virtualSize + shaderContainer->physicalSize; - - if ((shaderContainer->flags & 0xFFFFFF00) == 0x102A1100 && - dataSize <= (fileSize - i) && - shaderContainer->field1C == 0 && - shaderContainer->field20 == 0) - { - XXH64_hash_t hash = XXH3_64bits(shaderContainer, dataSize); - auto shader = shaders.try_emplace(hash); - if (shader.second) - { - shader.first->second.data = fileData.get() + i; - foundAny = true; - } - - i += dataSize; - } - else - { - i += sizeof(uint32_t); - } + writeAllBytes(outputFile.c_str(), blob->GetBufferPointer(), blob->GetBufferSize()); + blob->Release(); } - if (foundAny) - files.emplace_back(std::move(fileData)); + //writeAllBytes((outputFile + ".hlsl").c_str(), recompiler.out.data(), recompiler.out.size()); } - - std::atomic progress = 0; - - std::for_each(std::execution::par_unseq, shaders.begin(), shaders.end(), [&](auto& hashShaderPair) - { - auto& shader = hashShaderPair.second; - - thread_local ShaderRecompiler recompiler; - recompiler = {}; - recompiler.recompile(shader.data, include); - - shader.specConstantsMask = recompiler.specConstantsMask; - - thread_local DxcCompiler dxcCompiler; - -#ifdef XENOS_RECOMP_DXIL - shader.dxil = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, recompiler.specConstantsMask != 0, false); - assert(shader.dxil != nullptr); - assert(*(reinterpret_cast(shader.dxil->GetBufferPointer()) + 1) != 0 && "DXIL was not signed properly!"); -#endif - - IDxcBlob* spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false, true); - assert(spirv != nullptr); - - bool result = smolv::Encode(spirv->GetBufferPointer(), spirv->GetBufferSize(), shader.spirv, smolv::kEncodeFlagStripDebugInfo); - assert(result); - - spirv->Release(); - - size_t currentProgress = ++progress; - if ((currentProgress % 10) == 0 || (currentProgress == shaders.size() - 1)) - fmt::println("Recompiling shaders... {}%", currentProgress / float(shaders.size()) * 100.0f); - }); - - fmt::println("Creating shader cache..."); - - StringBuffer f; - f.println("#include \"shader_cache.h\""); - f.println("ShaderCacheEntry g_shaderCacheEntries[] = {{"); - - std::vector dxil; - std::vector spirv; - - for (auto& [hash, shader] : shaders) - { - f.println("\t{{ 0x{:X}, {}, {}, {}, {}, {} }},", - hash, dxil.size(), (shader.dxil != nullptr) ? shader.dxil->GetBufferSize() : 0, spirv.size(), shader.spirv.size(), shader.specConstantsMask); - - if (shader.dxil != nullptr) - { - dxil.insert(dxil.end(), reinterpret_cast(shader.dxil->GetBufferPointer()), - reinterpret_cast(shader.dxil->GetBufferPointer()) + shader.dxil->GetBufferSize()); - } - - spirv.insert(spirv.end(), shader.spirv.begin(), shader.spirv.end()); - } - - f.println("}};"); - - fmt::println("Compressing DXIL cache..."); - - int level = ZSTD_maxCLevel(); - -#ifdef XENOS_RECOMP_DXIL - std::vector dxilCompressed(ZSTD_compressBound(dxil.size())); - dxilCompressed.resize(ZSTD_compress(dxilCompressed.data(), dxilCompressed.size(), dxil.data(), dxil.size(), level)); - - f.print("const uint8_t g_compressedDxilCache[] = {{"); - - for (auto data : dxilCompressed) - f.print("{},", data); - - f.println("}};"); - f.println("const size_t g_dxilCacheCompressedSize = {};", dxilCompressed.size()); - f.println("const size_t g_dxilCacheDecompressedSize = {};", dxil.size()); -#endif - - fmt::println("Compressing SPIRV cache..."); - - std::vector spirvCompressed(ZSTD_compressBound(spirv.size())); - spirvCompressed.resize(ZSTD_compress(spirvCompressed.data(), spirvCompressed.size(), spirv.data(), spirv.size(), level)); - - f.print("const uint8_t g_compressedSpirvCache[] = {{"); - - for (auto data : spirvCompressed) - f.print("{},", data); - - f.println("}};"); - - f.println("const size_t g_spirvCacheCompressedSize = {};", spirvCompressed.size()); - f.println("const size_t g_spirvCacheDecompressedSize = {};", spirv.size()); - f.println("const size_t g_shaderCacheEntryCount = {};", shaders.size()); - - writeAllBytes(output, f.out.data(), f.out.size()); - } - else - { - ShaderRecompiler recompiler; - size_t fileSize; - recompiler.recompile(readAllBytes(input, fileSize).get(), include); - writeAllBytes(output, recompiler.out.data(), recompiler.out.size()); } return 0; diff --git a/XenosRecomp/pch.h b/XenosRecomp/pch.h index e59682c..bd244df 100644 --- a/XenosRecomp/pch.h +++ b/XenosRecomp/pch.h @@ -4,7 +4,7 @@ #include #endif -#include +#include #include #include @@ -12,12 +12,9 @@ #include #include #include -#include #include #include #include -#include -#include template static T byteSwap(T value) diff --git a/XenosRecomp/shader_common.h b/XenosRecomp/shader_common.h index 1c74034..198b036 100644 --- a/XenosRecomp/shader_common.h +++ b/XenosRecomp/shader_common.h @@ -1,183 +1,15 @@ #ifndef SHADER_COMMON_H_INCLUDED #define SHADER_COMMON_H_INCLUDED -#define SPEC_CONSTANT_R11G11B10_NORMAL (1 << 0) -#define SPEC_CONSTANT_ALPHA_TEST (1 << 1) - -#ifdef UNLEASHED_RECOMP - #define SPEC_CONSTANT_BICUBIC_GI_FILTER (1 << 2) - #define SPEC_CONSTANT_ALPHA_TO_COVERAGE (1 << 3) - #define SPEC_CONSTANT_REVERSE_Z (1 << 4) -#endif - -#if !defined(__cplusplus) || defined(__INTELLISENSE__) - -#define FLT_MIN asfloat(0xff7fffff) -#define FLT_MAX asfloat(0x7f7fffff) - -#ifdef __spirv__ - -struct PushConstants -{ - uint64_t VertexShaderConstants; - uint64_t PixelShaderConstants; - uint64_t SharedConstants; -}; - -[[vk::push_constant]] ConstantBuffer g_PushConstants; - -#define g_Booleans vk::RawBufferLoad(g_PushConstants.SharedConstants + 256) -#define g_SwappedTexcoords vk::RawBufferLoad(g_PushConstants.SharedConstants + 260) -#define g_HalfPixelOffset vk::RawBufferLoad(g_PushConstants.SharedConstants + 264) -#define g_AlphaThreshold vk::RawBufferLoad(g_PushConstants.SharedConstants + 272) - -[[vk::constant_id(0)]] const uint g_SpecConstants = 0; - -#define g_SpecConstants() g_SpecConstants - -#else - -#define DEFINE_SHARED_CONSTANTS() \ - uint g_Booleans : packoffset(c16.x); \ - uint g_SwappedTexcoords : packoffset(c16.y); \ - float2 g_HalfPixelOffset : packoffset(c16.z); \ - float g_AlphaThreshold : packoffset(c17.x); - -uint g_SpecConstants(); - -#endif - -Texture2D g_Texture2DDescriptorHeap[] : register(t0, space0); -Texture3D g_Texture3DDescriptorHeap[] : register(t0, space1); -TextureCube g_TextureCubeDescriptorHeap[] : register(t0, space2); -SamplerState g_SamplerDescriptorHeap[] : register(s0, space3); - -uint2 getTexture2DDimensions(Texture2D texture) -{ - uint2 dimensions; - texture.GetDimensions(dimensions.x, dimensions.y); - return dimensions; -} - -float4 tfetch2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) -{ - Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; - return texture.Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord + offset / getTexture2DDimensions(texture)); -} - -float2 getWeights2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) -{ - Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; - return select(isnan(texCoord), 0.0, frac(texCoord * getTexture2DDimensions(texture) + offset - 0.5)); -} - -float w0(float a) -{ - return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); -} - -float w1(float a) -{ - return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f); -} - -float w2(float a) -{ - return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f); -} - -float w3(float a) -{ - return (1.0f / 6.0f) * (a * a * a); -} - -float g0(float a) -{ - return w0(a) + w1(a); -} - -float g1(float a) -{ - return w2(a) + w3(a); -} - -float h0(float a) -{ - return -1.0f + w1(a) / (w0(a) + w1(a)) + 0.5f; -} - -float h1(float a) -{ - return 1.0f + w3(a) / (w2(a) + w3(a)) + 0.5f; -} - -float4 tfetch2DBicubic(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) -{ - Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; - SamplerState samplerState = g_SamplerDescriptorHeap[samplerDescriptorIndex]; - uint2 dimensions = getTexture2DDimensions(texture); - - float x = texCoord.x * dimensions.x + offset.x; - float y = texCoord.y * dimensions.y + offset.y; - - x -= 0.5f; - y -= 0.5f; - float px = floor(x); - float py = floor(y); - float fx = x - px; - float fy = y - py; - - float g0x = g0(fx); - float g1x = g1(fx); - float h0x = h0(fx); - float h1x = h1(fx); - float h0y = h0(fy); - float h1y = h1(fy); - - float4 r = - g0(fy) * (g0x * texture.Sample(samplerState, float2(px + h0x, py + h0y) / float2(dimensions)) + - g1x * texture.Sample(samplerState, float2(px + h1x, py + h0y) / float2(dimensions))) + - g1(fy) * (g0x * texture.Sample(samplerState, float2(px + h0x, py + h1y) / float2(dimensions)) + - g1x * texture.Sample(samplerState, float2(px + h1x, py + h1y) / float2(dimensions))); - - return r; -} - -float4 tfetch3D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord) -{ - return g_Texture3DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord); -} - struct CubeMapData { float3 cubeMapDirections[2]; uint cubeMapIndex; }; -float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord, inout CubeMapData cubeMapData) +float4 texCUBE(samplerCUBE s, float3 texCoord, inout CubeMapData cubeMapData) { - return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]); -} - -float4 tfetchR11G11B10(uint4 value) -{ - if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL) - { - return float4( - (value.x & 0x00000400 ? -1.0 : 0.0) + ((value.x & 0x3FF) / 1024.0), - (value.x & 0x00200000 ? -1.0 : 0.0) + (((value.x >> 11) & 0x3FF) / 1024.0), - (value.x & 0x80000000 ? -1.0 : 0.0) + (((value.x >> 22) & 0x1FF) / 512.0), - 0.0); - } - else - { - return asfloat(value); - } -} - -float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex) -{ - return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value; + return texCUBE(s, cubeMapData.cubeMapDirections[texCoord.z]); } float4 cube(float4 value, inout CubeMapData cubeMapData) @@ -204,19 +36,4 @@ float4 max4(float4 src0) return max(max(src0.x, src0.y), max(src0.z, src0.w)); } -float2 getPixelCoord(uint resourceDescriptorIndex, float2 texCoord) -{ - return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord; -} - -float computeMipLevel(float2 pixelCoord) -{ - float2 dx = ddx(pixelCoord); - float2 dy = ddy(pixelCoord); - float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy)); - return max(0.0, 0.5 * log2(deltaMaxSqr)); -} - -#endif - #endif diff --git a/XenosRecomp/shader_recompiler.cpp b/XenosRecomp/shader_recompiler.cpp index d4cbd50..658f7c7 100644 --- a/XenosRecomp/shader_recompiler.cpp +++ b/XenosRecomp/shader_recompiler.cpp @@ -1,5 +1,4 @@ #include "shader_recompiler.h" -#include "shader_common.h" static constexpr char SWIZZLES[] = { @@ -13,24 +12,6 @@ static constexpr char SWIZZLES[] = '_' }; -static constexpr const char* USAGE_TYPES[] = -{ - "float4", // POSITION - "float4", // BLENDWEIGHT - "uint4", // BLENDINDICES - "uint4", // NORMAL - "float4", // PSIZE - "float4", // TEXCOORD - "uint4", // TANGENT - "uint4", // BINORMAL - "float4", // TESSFACTOR - "float4", // POSITIONT - "float4", // COLOR - "float4", // FOG - "float4", // DEPTH - "float4", // SAMPLE -}; - static constexpr const char* USAGE_VARIABLES[] = { "Position", @@ -67,57 +48,6 @@ static constexpr const char* USAGE_SEMANTICS[] = "SAMPLE" }; -struct DeclUsageLocation -{ - DeclUsage usage; - uint32_t usageIndex; - uint32_t location; -}; - -// NOTE: These are specialized Vulkan locations for Unleashed Recompiled. Change as necessary. Likely not going to work with other games. -static constexpr DeclUsageLocation USAGE_LOCATIONS[] = -{ - { DeclUsage::Position, 0, 0 }, - { DeclUsage::Normal, 0, 1 }, - { DeclUsage::Tangent, 0, 2 }, - { DeclUsage::Binormal, 0, 3 }, - { DeclUsage::TexCoord, 0, 4 }, - { DeclUsage::TexCoord, 1, 5 }, - { DeclUsage::TexCoord, 2, 6 }, - { DeclUsage::TexCoord, 3, 7 }, - { DeclUsage::Color, 0, 8 }, - { DeclUsage::BlendIndices, 0, 9 }, - { DeclUsage::BlendWeight, 0, 10 }, - { DeclUsage::Color, 1, 11 }, - { DeclUsage::TexCoord, 4, 12 }, - { DeclUsage::TexCoord, 5, 13 }, - { DeclUsage::TexCoord, 6, 14 }, - { DeclUsage::TexCoord, 7, 15 }, - { DeclUsage::Position, 1, 15 }, -}; - -static constexpr std::pair INTERPOLATORS[] = -{ - { DeclUsage::TexCoord, 0 }, - { DeclUsage::TexCoord, 1 }, - { DeclUsage::TexCoord, 2 }, - { DeclUsage::TexCoord, 3 }, - { DeclUsage::TexCoord, 4 }, - { DeclUsage::TexCoord, 5 }, - { DeclUsage::TexCoord, 6 }, - { DeclUsage::TexCoord, 7 }, - { DeclUsage::TexCoord, 8 }, - { DeclUsage::TexCoord, 9 }, - { DeclUsage::TexCoord, 10 }, - { DeclUsage::TexCoord, 11 }, - { DeclUsage::TexCoord, 12 }, - { DeclUsage::TexCoord, 13 }, - { DeclUsage::TexCoord, 14 }, - { DeclUsage::TexCoord, 15 }, - { DeclUsage::Color, 0 }, - { DeclUsage::Color, 1 } -}; - static constexpr std::string_view TEXTURE_DIMENSIONS[] = { "2D", @@ -179,35 +109,8 @@ void ShaderRecompiler::recompile(const VertexFetchInstruction& instr, uint32_t a auto findResult = vertexElements.find(address); assert(findResult != vertexElements.end()); - switch (findResult->second.usage) - { - case DeclUsage::Normal: - case DeclUsage::Tangent: - case DeclUsage::Binormal: - specConstantsMask |= SPEC_CONSTANT_R11G11B10_NORMAL; - print("tfetchR11G11B10("); - break; - - case DeclUsage::TexCoord: - print("tfetchTexcoord(g_SwappedTexcoords, "); - break; - } - print("i{}{}", USAGE_VARIABLES[uint32_t(findResult->second.usage)], uint32_t(findResult->second.usageIndex)); - switch (findResult->second.usage) - { - case DeclUsage::Normal: - case DeclUsage::Tangent: - case DeclUsage::Binormal: - out += ')'; - break; - - case DeclUsage::TexCoord: - print(", {})", uint32_t(findResult->second.usageIndex)); - break; - } - out += '.'; printDstSwizzle(instr.dstSwizzle, true); @@ -225,7 +128,7 @@ void ShaderRecompiler::recompile(const VertexFetchInstruction& instr, uint32_t a void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicubic) { - if (instr.opcode != FetchOpcode::TextureFetch && instr.opcode != FetchOpcode::GetTextureWeights) + if (instr.opcode != FetchOpcode::TextureFetch) return; if (instr.isPredicated) @@ -248,18 +151,11 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu std::string constName; const char* constNamePtr = nullptr; -#ifdef UNLEASHED_RECOMP - bool subtractFromOne = false; -#endif auto findResult = samplers.find(instr.constIndex); if (findResult != samplers.end()) { constNamePtr = findResult->second; - - #ifdef UNLEASHED_RECOMP - subtractFromOne = hasMtxPrevInvViewProjection && strcmp(constNamePtr, "sampZBuffer") == 0; - #endif } else { @@ -267,36 +163,20 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu constNamePtr = constName.c_str(); } -#ifdef UNLEASHED_RECOMP - if (instr.constIndex == 0 && instr.dimension == TextureDimension::Texture2D) - { - indent(); - print("pixelCoord = getPixelCoord({}_Texture2DDescriptorIndex, ", constNamePtr); - printSrcRegister(2); - out += ");\n"; - } -#endif - indent(); print("r{}.", instr.dstRegister); printDstSwizzle(instr.dstSwizzle, false); out += " = "; + + if (strcmp(constNamePtr, "g_DepthSampler") == 0 || strcmp(constNamePtr, "sampZBuffer") == 0) + out += "1.0 - "; + switch (instr.opcode) { case FetchOpcode::TextureFetch: { - #ifdef UNLEASHED_RECOMP - if (subtractFromOne) - out += "1.0 - "; - #endif - - out += "tfetch"; - break; - } - case FetchOpcode::GetTextureWeights: - { - out += "getWeights"; + out += "tex"; break; } } @@ -317,28 +197,35 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu case TextureDimension::Texture3D: dimension = "3D"; componentCount = 3; + { + auto search = fmt::format("sampler2D {} : register", constNamePtr); + size_t index = out.find(search); + if (index != std::string::npos) + out[index + 7] = '3'; + } break; case TextureDimension::TextureCube: - dimension = "Cube"; + dimension = "CUBE"; componentCount = 3; + { + auto search = fmt::format("sampler2D {} : register", constNamePtr); + size_t index = out.find(search); + if (index != std::string::npos) + { + out.erase(index + 7, 2); + out.insert(index + 7, "CUBE"); + } + } break; } out += dimension; -#ifdef UNLEASHED_RECOMP - if (bicubic) - out += "Bicubic"; -#endif - - print("({0}_Texture{1}DescriptorIndex, {0}_SamplerDescriptorIndex, ", constNamePtr, dimension); + print("({}, ", constNamePtr); printSrcRegister(componentCount); switch (instr.dimension) { - case TextureDimension::Texture2D: - print(", float2({}, {})", instr.offsetX * 0.5f, instr.offsetY * 0.5f); - break; case TextureDimension::TextureCube: out += ", cubeMapData"; break; @@ -461,18 +348,8 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) const char* constantName = reinterpret_cast(constantTableData + findResult->second->name); if (findResult->second->registerCount > 1) { - #ifdef UNLEASHED_RECOMP - if (hasMtxProjection && strcmp(constantName, "g_MtxProjection") == 0) - { - regFormatted = fmt::format("(iterationIndex == 0 ? mtxProjectionReverseZ[{0}] : mtxProjection[{0}])", - reg - findResult->second->registerIndex); - } - else - #endif - { - regFormatted = fmt::format("{}({}{})", constantName, - reg - findResult->second->registerIndex, instr.const0Relative ? (instr.constAddressRegisterRelative ? " + a0" : " + aL") : ""); - } + regFormatted = fmt::format("{}[{}{}]", constantName, + reg - findResult->second->registerIndex, instr.const0Relative ? (instr.constAddressRegisterRelative ? " + a0" : " + aL") : ""); } else { @@ -607,20 +484,6 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) { case ExportRegister::VSPosition: exportRegister = "oPos"; - - #ifdef UNLEASHED_RECOMP - if (hasMtxProjection) - { - indent(); - out += "if ((g_SpecConstants() & SPEC_CONSTANT_REVERSE_Z) == 0 || iterationIndex == 0)\n"; - indent(); - out += "{\n"; - ++indentation; - - closeIfBracket = true; - } - #endif - break; default: @@ -743,15 +606,15 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) break; case AluVectorOpcode::CndEq: - print("select({} == 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); + print("{} == 0.0 ? {} : {}", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); break; case AluVectorOpcode::CndGe: - print("select({} >= 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); + print("{} >= 0.0 ? {} : {}", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); break; case AluVectorOpcode::CndGt: - print("select({} > 0.0, {}, {})", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); + print("{} > 0.0 ? {} : {}", op(VECTOR_0), op(VECTOR_1), op(VECTOR_2)); break; case AluVectorOpcode::Dp4: @@ -918,19 +781,19 @@ void ShaderRecompiler::recompile(const AluInstruction& instr) case AluScalarOpcode::Logc: case AluScalarOpcode::Log: - print("clamp(log2({}), FLT_MIN, FLT_MAX)", op(SCALAR_0)); + print("log2({})", op(SCALAR_0)); break; case AluScalarOpcode::Rcpc: case AluScalarOpcode::Rcpf: case AluScalarOpcode::Rcp: - print("clamp(rcp({}), FLT_MIN, FLT_MAX)", op(SCALAR_0)); + print("rcp({})", op(SCALAR_0)); break; case AluScalarOpcode::Rsqc: case AluScalarOpcode::Rsqf: case AluScalarOpcode::Rsq: - print("clamp(rsqrt({}), FLT_MIN, FLT_MAX)", op(SCALAR_0)); + print("rsqrt({})", op(SCALAR_0)); break; case AluScalarOpcode::Subs: @@ -1113,13 +976,6 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi const auto constantTableContainer = reinterpret_cast(shaderData + shaderContainer->constantTableOffset); constantTableData = reinterpret_cast(&constantTableContainer->constantTable); - out += "#ifdef __spirv__\n\n"; - -#ifdef UNLEASHED_RECOMP - bool isMetaInstancer = false; - bool hasIndexCount = false; -#endif - for (uint32_t i = 0; i < constantTableContainer->constantTable.constants; i++) { const auto constantInfo = reinterpret_cast( @@ -1127,42 +983,17 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi const char* constantName = reinterpret_cast(constantTableData + constantInfo->name); - #ifdef UNLEASHED_RECOMP - if (!isPixelShader) - { - if (strcmp(constantName, "g_MtxProjection") == 0) - hasMtxProjection = true; - else if (strcmp(constantName, "g_InstanceTypes") == 0) - isMetaInstancer = true; - else if (strcmp(constantName, "g_IndexCount") == 0) - hasIndexCount = true; - } - else - { - if (strcmp(constantName, "g_MtxPrevInvViewProjection") == 0) - hasMtxPrevInvViewProjection = true; - } - #endif - switch (constantInfo->registerSet) { case RegisterSet::Float4: { - const char* shaderName = isPixelShader ? "Pixel" : "Vertex"; + print("float4 {}", constantName); if (constantInfo->registerCount > 1) - { - uint32_t tailCount = (isPixelShader ? 224 : 256) - constantInfo->registerIndex; + print("[{}]", constantInfo->registerCount.get()); + + println(" : register(c{});", constantInfo->registerIndex.get()); - println("#define {}(INDEX) select((INDEX) < {}, vk::RawBufferLoad(g_PushConstants.{}ShaderConstants + ({} + min(INDEX, {})) * 16, 0x10), 0.0)", - constantName, tailCount, shaderName, constantInfo->registerIndex.get(), tailCount - 1); - } - else - { - println("#define {} vk::RawBufferLoad(g_PushConstants.{}ShaderConstants + {}, 0x10)", - constantName, shaderName, constantInfo->registerIndex * 16); - } - for (uint16_t j = 0; j < constantInfo->registerCount; j++) float4Constants.emplace(constantInfo->registerIndex + j, constantInfo); @@ -1171,91 +1002,20 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi case RegisterSet::Sampler: { - for (size_t j = 0; j < std::size(TEXTURE_DIMENSIONS); j++) - { - println("#define {}_Texture{}DescriptorIndex vk::RawBufferLoad(g_PushConstants.SharedConstants + {})", - constantName, TEXTURE_DIMENSIONS[j], j * 64 + constantInfo->registerIndex * 4); - } - - println("#define {}_SamplerDescriptorIndex vk::RawBufferLoad(g_PushConstants.SharedConstants + {})", - constantName, std::size(TEXTURE_DIMENSIONS) * 64 + constantInfo->registerIndex * 4); + println("sampler2D {} : register(s{});", constantName, constantInfo->registerIndex.get()); samplers.emplace(constantInfo->registerIndex, constantName); break; } - } - } - - out += "\n#else\n\n"; - - println("cbuffer {}ShaderConstants : register(b{}, space4)", isPixelShader ? "Pixel" : "Vertex", isPixelShader ? 1 : 0); - out += "{\n"; - - for (uint32_t i = 0; i < constantTableContainer->constantTable.constants; i++) - { - const auto constantInfo = reinterpret_cast( - constantTableData + constantTableContainer->constantTable.constantInfo + i * sizeof(ConstantInfo)); - - if (constantInfo->registerSet == RegisterSet::Float4) + case RegisterSet::Bool: { - const char* constantName = reinterpret_cast(constantTableData + constantInfo->name); + println("bool {} : register(b{});", constantName, constantInfo->registerIndex.get()); - print("\tfloat4 {}", constantName); - - if (constantInfo->registerCount > 1) - print("[{}]", constantInfo->registerCount.get()); - - println(" : packoffset(c{});", constantInfo->registerIndex.get()); - - if (constantInfo->registerCount > 1) - { - uint32_t tailCount = (isPixelShader ? 224 : 256) - constantInfo->registerIndex; - println("#define {0}(INDEX) select((INDEX) < {1}, {0}[min(INDEX, {2})], 0.0)", constantName, tailCount, tailCount - 1); - } - } - } - - out += "};\n\n"; - - out += "cbuffer SharedConstants : register(b2, space4)\n"; - out += "{\n"; - - for (uint32_t i = 0; i < constantTableContainer->constantTable.constants; i++) - { - const auto constantInfo = reinterpret_cast( - constantTableData + constantTableContainer->constantTable.constantInfo + i * sizeof(ConstantInfo)); - - if (constantInfo->registerSet == RegisterSet::Sampler) - { - const char* constantName = reinterpret_cast(constantTableData + constantInfo->name); - - for (size_t j = 0; j < std::size(TEXTURE_DIMENSIONS); j++) - { - println("\tuint {}_Texture{}DescriptorIndex : packoffset(c{}.{});", - constantName, TEXTURE_DIMENSIONS[j], j * 4 + constantInfo->registerIndex / 4, SWIZZLES[constantInfo->registerIndex % 4]); - } - - println("\tuint {}_SamplerDescriptorIndex : packoffset(c{}.{});", - constantName, 4 * std::size(TEXTURE_DIMENSIONS) + constantInfo->registerIndex / 4, SWIZZLES[constantInfo->registerIndex % 4]); - } - } - - out += "\tDEFINE_SHARED_CONSTANTS();\n"; - out += "};\n\n"; - - out += "#endif\n"; - - for (uint32_t i = 0; i < constantTableContainer->constantTable.constants; i++) - { - const auto constantInfo = reinterpret_cast( - constantTableData + constantTableContainer->constantTable.constantInfo + i * sizeof(ConstantInfo)); - - if (constantInfo->registerSet == RegisterSet::Bool) - { - const char* constantName = reinterpret_cast(constantTableData + constantInfo->name); - println("\t#define {} (1 << {})", constantName, constantInfo->registerIndex + (isPixelShader ? 16 : 0)); boolConstants.emplace(constantInfo->registerIndex, constantName); + break; + } + } } @@ -1263,41 +1023,37 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi const auto shader = reinterpret_cast(shaderData + shaderContainer->shaderOffset); - out += "#ifndef __spirv__\n"; - - if (isPixelShader) - out += "[shader(\"pixel\")]\n"; - else - out += "[shader(\"vertex\")]\n"; - - out += "#endif\n"; - out += "void main(\n"; if (isPixelShader) { - out += "\tin float4 iPos : SV_Position,\n"; + out += "\tin float4 iPos : VPOS"; - for (auto& [usage, usageIndex] : INTERPOLATORS) - println("\tin float4 i{0}{1} : {2}{1},", USAGE_VARIABLES[uint32_t(usage)], usageIndex, USAGE_SEMANTICS[uint32_t(usage)]); + uint32_t interpolatorCount = (shader->interpolatorInfo >> 5) & 0x1F; - out += "#ifdef __spirv__\n"; - out += "\tin bool iFace : SV_IsFrontFace\n"; - out += "#else\n"; - out += "\tin uint iFace : SV_IsFrontFace\n"; - out += "#endif\n"; + for (uint32_t i = 0; i < interpolatorCount; i++) + { + union + { + Interpolator interpolator; + uint32_t value; + }; + + value = reinterpret_cast(shader)->interpolators[i]; + print(",\n\tin float4 i{0}{1} : {2}{1}", USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex), USAGE_SEMANTICS[uint32_t(interpolator.usage)]); + } auto pixelShader = reinterpret_cast(shader); if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR0) - out += ",\n\tout float4 oC0 : SV_Target0"; + out += ",\n\tout float4 oC0 : COLOR0"; if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR1) - out += ",\n\tout float4 oC1 : SV_Target1"; + out += ",\n\tout float4 oC1 : COLOR1"; if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR2) - out += ",\n\tout float4 oC2 : SV_Target2"; + out += ",\n\tout float4 oC2 : COLOR2"; if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR3) - out += ",\n\tout float4 oC3 : SV_Target3"; + out += ",\n\tout float4 oC3 : COLOR3"; if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_DEPTH) - out += ",\n\tout float oDepth : SV_Depth"; + out += ",\n\tout float oDepth : DEPTH"; } else { @@ -1312,65 +1068,33 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi value = vertexShader->vertexElementsAndInterpolators[vertexShader->field18 + i]; - const char* usageType = USAGE_TYPES[uint32_t(vertexElement.usage)]; - - #ifdef UNLEASHED_RECOMP - if ((vertexElement.usage == DeclUsage::TexCoord && vertexElement.usageIndex == 2 && isMetaInstancer) || - (vertexElement.usage == DeclUsage::Position && vertexElement.usageIndex == 1)) - { - usageType = "uint4"; - } - #endif - - out += '\t'; - - for (auto& usageLocation : USAGE_LOCATIONS) - { - if (usageLocation.usage == vertexElement.usage && usageLocation.usageIndex == vertexElement.usageIndex) - { - print("[[vk::location({})]] ", usageLocation.location); - break; - } - } - - println("in {0} i{1}{2} : {3}{2},", usageType, USAGE_VARIABLES[uint32_t(vertexElement.usage)], + println("\tin float4 i{0}{1} : {2}{1},", USAGE_VARIABLES[uint32_t(vertexElement.usage)], uint32_t(vertexElement.usageIndex), USAGE_SEMANTICS[uint32_t(vertexElement.usage)]); vertexElements.emplace(uint32_t(vertexElement.address), vertexElement); } - #ifdef UNLEASHED_RECOMP - if (hasIndexCount) + uint32_t interpolatorCount = (shader->interpolatorInfo >> 5) & 0x1F; + + for (uint32_t i = 0; i < interpolatorCount; i++) { - out += "\tin uint iVertexId : SV_VertexID,\n"; - out += "\tin uint iInstanceId : SV_InstanceID,\n"; + union + { + Interpolator interpolator; + uint32_t value; + }; + + auto vertexShader = reinterpret_cast(shader); + value = vertexShader->vertexElementsAndInterpolators[vertexShader->field18 + vertexShader->vertexElementCount + i]; + println("\tout float4 o{0}{1} : {2}{1},", USAGE_VARIABLES[uint32_t(interpolator.usage)], uint32_t(interpolator.usageIndex), USAGE_SEMANTICS[uint32_t(interpolator.usage)]); } - #endif - out += "\tout float4 oPos : SV_Position"; - - for (auto& [usage, usageIndex] : INTERPOLATORS) - print(",\n\tout float4 o{0}{1} : {2}{1}", USAGE_VARIABLES[uint32_t(usage)], usageIndex, USAGE_SEMANTICS[uint32_t(usage)]); + out += "\tout float4 oPos : POSITION"; } out += ")\n"; out += "{\n"; -#ifdef UNLEASHED_RECOMP - if (hasMtxProjection) - { - specConstantsMask |= SPEC_CONSTANT_REVERSE_Z; - - out += "\toPos = 0.0;\n"; - - out += "\tfloat4x4 mtxProjection = float4x4(g_MtxProjection(0), g_MtxProjection(1), g_MtxProjection(2), g_MtxProjection(3));\n"; - out += "\tfloat4x4 mtxProjectionReverseZ = mul(mtxProjection, float4x4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 1, 1));\n"; - - out += "\t[unroll] for (int iterationIndex = 0; iterationIndex < 2; iterationIndex++)\n"; - out += "\t{\n"; - } -#endif - if (shaderContainer->definitionTableOffset != NULL) { auto definitionTable = reinterpret_cast(shaderData + shaderContainer->definitionTableOffset); @@ -1381,8 +1105,8 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi auto value = reinterpret_cast*>(shaderData + shaderContainer->virtualSize + definition->physicalOffset); for (uint16_t i = 0; i < (definition->count + 3) / 4; i++) { - println("\tfloat4 c{} = asfloat(uint4(0x{:X}, 0x{:X}, 0x{:X}, 0x{:X}));", - definition->registerIndex + i - (isPixelShader ? 256 : 0), value[0].get(), value[1].get(), value[2].get(), value[3].get()); + println("\tfloat4 c{} = float4({}, {}, {}, {});", + definition->registerIndex + i - (isPixelShader ? 256 : 0), std::_Bit_cast(value[0].get()), std::_Bit_cast(value[1].get()), std::_Bit_cast(value[2].get()), std::_Bit_cast(value[3].get())); value += 4; } @@ -1444,19 +1168,6 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi } } - if (!isPixelShader) - { - #ifdef UNLEASHED_RECOMP - if (!hasMtxProjection) - out += "\toPos = 0.0;\n"; - #endif - - for (auto& [usage, usageIndex] : INTERPOLATORS) - println("\to{}{} = 0.0;", USAGE_VARIABLES[uint32_t(usage)], usageIndex); - - out += "\n"; - } - for (size_t i = 0; i < 32; i++) { if (!printedRegisters[i]) @@ -1464,14 +1175,8 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi print("\tfloat4 r{} = ", i); if (isPixelShader && i == ((shader->fieldC >> 8) & 0xFF)) { - out += "float4((iPos.xy - 0.5) * float2(iFace ? 1.0 : -1.0, 1.0), 0.0, 0.0);\n"; + out += "float4(iPos.xy, 0.0, 0.0);\n"; } - #ifdef UNLEASHED_RECOMP - else if (!isPixelShader && hasIndexCount && i == 0) - { - out += "float4(iVertexId + g_IndexCount.x * iInstanceId, 0.0, 0.0, 0.0);\n"; - } - #endif else { out += "0.0;\n"; @@ -1484,12 +1189,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi out += "\tbool p0 = false;\n"; out += "\tfloat ps = 0.0;\n"; if (isPixelShader) - { -#ifdef UNLEASHED_RECOMP - out += "\tfloat2 pixelCoord = 0.0;\n"; -#endif out += "\tCubeMapData cubeMapData = (CubeMapData)0;\n"; - } const be* code = reinterpret_cast*>(shaderData + shaderContainer->virtualSize + shader->physicalOffset); @@ -1645,9 +1345,6 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi if (simpleControlFlow) { indent(); - #ifdef UNLEASHED_RECOMP - print("[unroll] "); - #endif println("for (aL = 0; aL < i{}.x; aL++)", uint32_t(cfInstr.loopStart.loopId)); indent(); out += "{\n"; @@ -1696,7 +1393,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi { auto findResult = boolConstants.find(cfInstr.condJmp.boolAddress); if (findResult != boolConstants.end()) - println("if ((g_Booleans & {}) {}= 0)", findResult->second, cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); + println("if ({} {}= 0)", findResult->second, cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); else println("if (b{} {}= 0)", uint32_t(cfInstr.condJmp.boolAddress), cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); } @@ -1748,39 +1445,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi } else { - #ifdef UNLEASHED_RECOMP - if (textureFetch.constIndex == 10) // g_GISampler - { - specConstantsMask |= SPEC_CONSTANT_BICUBIC_GI_FILTER; - - indent(); - out += "if (g_SpecConstants() & SPEC_CONSTANT_BICUBIC_GI_FILTER)"; - indent(); - out += '{'; - - ++indentation; - recompile(textureFetch, true); - --indentation; - - indent(); - out += "}"; - indent(); - out += "else"; - indent(); - out += '{'; - - ++indentation; - recompile(textureFetch, false); - --indentation; - - indent(); - out += '}'; - } - else - #endif - { - recompile(textureFetch, false); - } + recompile(textureFetch, false); } } else @@ -1794,56 +1459,10 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi if (shouldReturn) { - if (isPixelShader) - { - specConstantsMask |= SPEC_CONSTANT_ALPHA_TEST; - - indent(); - out += "[branch] if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TEST)"; - indent(); - out += '{'; - - indent(); - out += "\tclip(oC0.w - g_AlphaThreshold);\n"; - - indent(); - out += "}"; - - #ifdef UNLEASHED_RECOMP - specConstantsMask |= SPEC_CONSTANT_ALPHA_TO_COVERAGE; - - indent(); - out += "else if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TO_COVERAGE)"; - indent(); - out += '{'; - - indent(); - out += "\toC0.w *= 1.0 + computeMipLevel(pixelCoord) * 0.25;\n"; - indent(); - out += "\toC0.w = 0.5 + (oC0.w - g_AlphaThreshold) / max(fwidth(oC0.w), 1e-6);\n"; - - indent(); - out += '}'; - #endif - } - else - { - out += "\toPos.xy += g_HalfPixelOffset * oPos.w;\n"; - } - if (simpleControlFlow) { indent(); - #ifdef UNLEASHED_RECOMP - if (hasMtxProjection) - { - out += "continue;\n"; - } - else - #endif - { - out += "return;\n"; - } + out += "return;\n"; } else { @@ -1871,10 +1490,5 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi out += "\t}\n"; } -#ifdef UNLEASHED_RECOMP - if (hasMtxProjection) - out += "\t}\n"; -#endif - out += "}"; } diff --git a/XenosRecomp/shader_recompiler.h b/XenosRecomp/shader_recompiler.h index b2e317d..abd2382 100644 --- a/XenosRecomp/shader_recompiler.h +++ b/XenosRecomp/shader_recompiler.h @@ -32,7 +32,6 @@ struct ShaderRecompiler : StringBuffer std::unordered_map boolConstants; std::unordered_map samplers; std::unordered_map ifEndLabels; - uint32_t specConstantsMask = 0; #ifdef UNLEASHED_RECOMP bool hasMtxProjection = false;