mirror of
https://github.com/hedge-dev/XenosRecomp.git
synced 2025-12-24 17:02:24 +00:00
Specialization constant & DXIL library implementation.
This commit is contained in:
parent
30f5986047
commit
73f17ee29a
6 changed files with 93 additions and 35 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ struct DxcCompiler
|
|||
DxcCompiler();
|
||||
~DxcCompiler();
|
||||
|
||||
IDxcBlob* compile(const std::string& shaderSource, bool isPixelShader, bool compileSpirv);
|
||||
};
|
||||
IDxcBlob* compile(const std::string& shaderSource, bool compilePixelShader, bool compileLibrary, bool compileSpirv);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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<uint32_t*>(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<uint8_t*>(shader.dxil->GetBufferPointer()),
|
||||
reinterpret_cast<uint8_t*>(shader.dxil->GetBufferPointer()) + shader.dxil->GetBufferSize());
|
||||
|
|
|
|||
|
|
@ -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<PushConstants> g_PushConstants;
|
||||
|
||||
#define g_AlphaTestMode vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 256)
|
||||
#define g_AlphaThreshold vk::RawBufferLoad<float>(g_PushConstants.SharedConstants + 260)
|
||||
#define g_Booleans vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 264)
|
||||
#define g_SwappedTexcoords vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 268)
|
||||
#define g_InputLayoutFlags vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 272)
|
||||
#define g_EnableGIBicubicFiltering vk::RawBufferLoad<bool>(g_PushConstants.SharedConstants + 276)
|
||||
#define g_Booleans vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 256)
|
||||
#define g_SwappedTexcoords vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 260)
|
||||
#define g_AlphaThreshold vk::RawBufferLoad<float>(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
|
||||
|
|
@ -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<const Shader*>(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<const PixelShader*>(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 += '{';
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ struct ShaderRecompiler : StringBuffer
|
|||
std::unordered_map<uint32_t, const char*> boolConstants;
|
||||
std::unordered_map<uint32_t, const char*> samplers;
|
||||
std::unordered_map<uint32_t, uint32_t> ifEndLabels;
|
||||
uint32_t specConstantsMask = 0;
|
||||
|
||||
void indent()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue