diff --git a/ShaderRecomp/dxc_compiler.cpp b/ShaderRecomp/dxc_compiler.cpp index 4259f8e..e33a05e 100644 --- a/ShaderRecomp/dxc_compiler.cpp +++ b/ShaderRecomp/dxc_compiler.cpp @@ -11,7 +11,7 @@ DxcCompiler::~DxcCompiler() dxcCompiler->Release(); } -IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool isPixelShader, bool compileSpirv) +IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool compilePixelShader, bool compileLibrary, bool compileSpirv) { DxcBuffer source{}; source.Ptr = shaderSource.c_str(); @@ -20,7 +20,21 @@ IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool isPixelShad const wchar_t* args[16]{}; uint32_t argCount = 0; - args[argCount++] = isPixelShader ? L"-T ps_6_0" : L"-T vs_6_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"; @@ -29,7 +43,7 @@ IDxcBlob* DxcCompiler::compile(const std::string& shaderSource, bool isPixelShad args[argCount++] = L"-spirv"; args[argCount++] = L"-fvk-use-dx-layout"; - if (!isPixelShader) + if (!compilePixelShader) args[argCount++] = L"-fvk-invert-y"; } else diff --git a/ShaderRecomp/dxc_compiler.h b/ShaderRecomp/dxc_compiler.h index 49a579f..d49bd32 100644 --- a/ShaderRecomp/dxc_compiler.h +++ b/ShaderRecomp/dxc_compiler.h @@ -7,5 +7,5 @@ struct DxcCompiler DxcCompiler(); ~DxcCompiler(); - IDxcBlob* compile(const std::string& shaderSource, bool isPixelShader, bool compileSpirv); -}; \ No newline at end of file + IDxcBlob* compile(const std::string& shaderSource, bool compilePixelShader, bool compileLibrary, bool compileSpirv); +}; diff --git a/ShaderRecomp/main.cpp b/ShaderRecomp/main.cpp index 9df5309..258c466 100644 --- a/ShaderRecomp/main.cpp +++ b/ShaderRecomp/main.cpp @@ -26,6 +26,7 @@ struct RecompiledShader uint8_t* data = nullptr; IDxcBlob* dxil = nullptr; IDxcBlob* spirv = nullptr; + uint32_t specConstantsMask = 0; }; int main(int argc, char** argv) @@ -109,9 +110,11 @@ int main(int argc, char** argv) recompiler = {}; recompiler.recompile(shader.data, include); + shader.specConstantsMask = recompiler.specConstantsMask; + thread_local DxcCompiler dxcCompiler; - shader.dxil = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false); - shader.spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, true); + shader.dxil = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, recompiler.specConstantsMask != 0, false); + shader.spirv = dxcCompiler.compile(recompiler.out, recompiler.isPixelShader, false, true); assert(shader.dxil != nullptr && shader.spirv != nullptr); assert(*(reinterpret_cast(shader.dxil->GetBufferPointer()) + 1) != 0 && "DXIL was not signed properly!"); @@ -132,8 +135,8 @@ int main(int argc, char** argv) for (auto& [hash, shader] : shaders) { - f.println("\t{{ 0x{:X}, {}, {}, {}, {} }},", - hash, dxil.size(), shader.dxil->GetBufferSize(), spirv.size(), shader.spirv->GetBufferSize()); + f.println("\t{{ 0x{:X}, {}, {}, {}, {}, {} }},", + hash, dxil.size(), shader.dxil->GetBufferSize(), spirv.size(), shader.spirv->GetBufferSize(), shader.specConstantsMask); dxil.insert(dxil.end(), reinterpret_cast(shader.dxil->GetBufferPointer()), reinterpret_cast(shader.dxil->GetBufferPointer()) + shader.dxil->GetBufferSize()); diff --git a/ShaderRecomp/shader_common.hlsli b/ShaderRecomp/shader_common.h similarity index 85% rename from ShaderRecomp/shader_common.hlsli rename to ShaderRecomp/shader_common.h index af37837..7a77628 100644 --- a/ShaderRecomp/shader_common.hlsli +++ b/ShaderRecomp/shader_common.h @@ -1,8 +1,17 @@ +#ifndef SHADER_COMMON_H_INCLUDED +#define SHADER_COMMON_H_INCLUDED + +#define SPEC_CONSTANT_R11G11B10_NORMAL (1 << 0) +#define SPEC_CONSTANT_HAS_BONE (1 << 1) +#define SPEC_CONSTANT_BICUBIC_GI_FILTER (1 << 2) +#define SPEC_CONSTANT_ALPHA_TEST (1 << 3) +#define SPEC_CONSTANT_ALPHA_TO_COVERAGE (1 << 4) + +#if !defined(__cplusplus) || defined(__INTELLISENSE__) + #define FLT_MIN asfloat(0xff7fffff) #define FLT_MAX asfloat(0x7f7fffff) -#define INPUT_LAYOUT_FLAG_HAS_R11G11B10_NORMAL (1 << 0) - #ifdef __spirv__ struct PushConstants @@ -14,22 +23,22 @@ struct PushConstants [[vk::push_constant]] ConstantBuffer g_PushConstants; -#define g_AlphaTestMode vk::RawBufferLoad(g_PushConstants.SharedConstants + 256) -#define g_AlphaThreshold vk::RawBufferLoad(g_PushConstants.SharedConstants + 260) -#define g_Booleans vk::RawBufferLoad(g_PushConstants.SharedConstants + 264) -#define g_SwappedTexcoords vk::RawBufferLoad(g_PushConstants.SharedConstants + 268) -#define g_InputLayoutFlags vk::RawBufferLoad(g_PushConstants.SharedConstants + 272) -#define g_EnableGIBicubicFiltering vk::RawBufferLoad(g_PushConstants.SharedConstants + 276) +#define g_Booleans vk::RawBufferLoad(g_PushConstants.SharedConstants + 256) +#define g_SwappedTexcoords vk::RawBufferLoad(g_PushConstants.SharedConstants + 260) +#define g_AlphaThreshold vk::RawBufferLoad(g_PushConstants.SharedConstants + 264) + +[[vk::constant_id(0)]] const uint g_SpecConstants = 0; + +#define g_SpecConstants() g_SpecConstants #else #define DEFINE_SHARED_CONSTANTS() \ - uint g_AlphaTestMode : packoffset(c16.x); \ - float g_AlphaThreshold : packoffset(c16.y); \ - uint g_Booleans : packoffset(c16.z); \ - uint g_SwappedTexcoords : packoffset(c16.w); \ - uint g_InputLayoutFlags : packoffset(c17.x); \ - bool g_EnableGIBicubicFiltering : packoffset(c17.y) + uint g_Booleans : packoffset(c16.x); \ + uint g_SwappedTexcoords : packoffset(c16.y); \ + float g_AlphaThreshold : packoffset(c16.z) \ + +uint g_SpecConstants(); #endif @@ -145,9 +154,9 @@ float4 tfetchCube(uint resourceDescriptorIndex, uint samplerDescriptorIndex, flo return g_TextureCubeDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], cubeMapData.cubeMapDirections[texCoord.z]); } -float4 tfetchR11G11B10(uint inputLayoutFlags, uint4 value) +float4 tfetchR11G11B10(uint4 value) { - if (inputLayoutFlags & INPUT_LAYOUT_FLAG_HAS_R11G11B10_NORMAL) + if (g_SpecConstants() & SPEC_CONSTANT_R11G11B10_NORMAL) { return float4( (value.x & 0x00000400 ? -1.0 : 0.0) + ((value.x & 0x3FF) / 1024.0), @@ -163,7 +172,7 @@ float4 tfetchR11G11B10(uint inputLayoutFlags, uint4 value) float4 tfetchTexcoord(uint swappedTexcoords, float4 value, uint semanticIndex) { - return (swappedTexcoords & (1 << semanticIndex)) != 0 ? value.yxwz : value; + return (swappedTexcoords & (1ull << semanticIndex)) != 0 ? value.yxwz : value; } float4 cube(float4 value, inout CubeMapData cubeMapData) @@ -202,3 +211,7 @@ float computeMipLevel(float2 pixelCoord) float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy)); return max(0.0, 0.5 * log2(deltaMaxSqr)); } + +#endif + +#endif diff --git a/ShaderRecomp/shader_recompiler.cpp b/ShaderRecomp/shader_recompiler.cpp index 79b537b..371d3da 100644 --- a/ShaderRecomp/shader_recompiler.cpp +++ b/ShaderRecomp/shader_recompiler.cpp @@ -1,4 +1,5 @@ #include "shader_recompiler.h" +#include "shader_common.h" static constexpr char SWIZZLES[] = { @@ -182,7 +183,8 @@ void ShaderRecompiler::recompile(const VertexFetchInstruction& instr, uint32_t a case DeclUsage::Normal: case DeclUsage::Tangent: case DeclUsage::Binormal: - print("tfetchR11G11B10(g_InputLayoutFlags, "); + specConstantsMask |= SPEC_CONSTANT_R11G11B10_NORMAL; + print("tfetchR11G11B10("); break; case DeclUsage::TexCoord: @@ -1199,6 +1201,15 @@ 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) @@ -1208,7 +1219,11 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi for (auto& [usage, usageIndex] : INTERPOLATORS) println("\tin float4 i{0}{1} : {2}{1},", USAGE_VARIABLES[uint32_t(usage)], usageIndex, USAGE_SEMANTICS[uint32_t(usage)]); - out += "\tin bool iFace : SV_IsFrontFace"; + out += "#ifdef __spirv__\n"; + out += "\tin bool iFace : SV_IsFrontFace\n"; + out += "#else\n"; + out += "\tin uint iFace : SV_IsFrontFace\n"; + out += "#endif\n"; auto pixelShader = reinterpret_cast(shader); if (pixelShader->outputs & PIXEL_SHADER_OUTPUT_COLOR0) @@ -1582,11 +1597,19 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi } else { - auto findResult = boolConstants.find(cfInstr.condJmp.boolAddress); - if (findResult != boolConstants.end()) - println("if ((g_Booleans & {}) {}= 0)", findResult->second, cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); + if (!isPixelShader && cfInstr.condJmp.boolAddress == 0) // mrgHasBone + { + specConstantsMask |= SPEC_CONSTANT_HAS_BONE; + println("if ((g_SpecConstants() & SPEC_CONSTANT_HAS_BONE) {}= 0)", cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); + } else - println("if (b{} {}= 0)", uint32_t(cfInstr.condJmp.boolAddress), cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); + { + auto findResult = boolConstants.find(cfInstr.condJmp.boolAddress); + if (findResult != boolConstants.end()) + println("if ((g_Booleans & {}) {}= 0)", findResult->second, cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); + else + println("if (b{} {}= 0)", uint32_t(cfInstr.condJmp.boolAddress), cfInstr.condJmp.condition ^ simpleControlFlow ? "!" : "="); + } } if (simpleControlFlow) @@ -1638,8 +1661,10 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi { if (textureFetch.constIndex == 10) // g_GISampler { + specConstantsMask |= SPEC_CONSTANT_BICUBIC_GI_FILTER; + indent(); - out += "[branch] if (g_EnableGIBicubicFiltering)"; + out += "if (g_SpecConstants() & SPEC_CONSTANT_BICUBIC_GI_FILTER)"; indent(); out += '{'; @@ -1680,8 +1705,10 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi { if (isPixelShader) { + specConstantsMask |= (SPEC_CONSTANT_ALPHA_TEST | SPEC_CONSTANT_ALPHA_TO_COVERAGE); + indent(); - out += "[branch] if (g_AlphaTestMode == 1)"; + out += "[branch] if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TEST)"; indent(); out += '{'; @@ -1691,7 +1718,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData, const std::string_vi indent(); out += "}"; indent(); - out += "else if (g_AlphaTestMode == 2)"; + out += "else if (g_SpecConstants() & SPEC_CONSTANT_ALPHA_TEST)"; indent(); out += '{'; diff --git a/ShaderRecomp/shader_recompiler.h b/ShaderRecomp/shader_recompiler.h index a59a8b4..ad399f3 100644 --- a/ShaderRecomp/shader_recompiler.h +++ b/ShaderRecomp/shader_recompiler.h @@ -32,6 +32,7 @@ struct ShaderRecompiler : StringBuffer std::unordered_map boolConstants; std::unordered_map samplers; std::unordered_map ifEndLabels; + uint32_t specConstantsMask = 0; void indent() {