1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-04-05 16:40:17 +02:00

[dxbc] Gather binding info during shader compilation

This commit is contained in:
Philip Rebohle 2025-02-18 00:51:04 +01:00 committed by Philip Rebohle
parent 5f16faaae0
commit 75599780f2
8 changed files with 110 additions and 12 deletions

View File

@ -108,6 +108,47 @@ namespace dxvk {
m_analysis->uavInfos[registerId].nonInvariantAccess = true; m_analysis->uavInfos[registerId].nonInvariantAccess = true;
} break; } break;
case DxbcInstClass::Declaration: {
switch (ins.op) {
case DxbcOpcode::DclConstantBuffer: {
uint32_t registerId = ins.dst[0].idx[0].offset;
if (registerId < DxbcConstBufBindingCount)
m_analysis->bindings.cbvMask |= 1u << registerId;
} break;
case DxbcOpcode::DclSampler: {
uint32_t registerId = ins.dst[0].idx[0].offset;
if (registerId < DxbcSamplerBindingCount)
m_analysis->bindings.samplerMask |= 1u << registerId;
} break;
case DxbcOpcode::DclResource:
case DxbcOpcode::DclResourceRaw:
case DxbcOpcode::DclResourceStructured: {
uint32_t registerId = ins.dst[0].idx[0].offset;
uint32_t idx = registerId / 64u;
uint32_t bit = registerId % 64u;
if (registerId < DxbcResourceBindingCount)
m_analysis->bindings.srvMask[idx] |= uint64_t(1u) << bit;
} break;
case DxbcOpcode::DclUavTyped:
case DxbcOpcode::DclUavRaw:
case DxbcOpcode::DclUavStructured: {
uint32_t registerId = ins.dst[0].idx[0].offset;
if (registerId < DxbcUavBindingCount)
m_analysis->bindings.uavMask |= uint64_t(1u) << registerId;
} break;
default: ;
}
} break;
default: default:
break; break;
} }

View File

@ -53,6 +53,8 @@ namespace dxvk {
DxbcClipCullInfo clipCullIn; DxbcClipCullInfo clipCullIn;
DxbcClipCullInfo clipCullOut; DxbcClipCullInfo clipCullOut;
DxbcBindingMask bindings = { };
bool usesDerivatives = false; bool usesDerivatives = false;
bool usesKill = false; bool usesKill = false;

View File

@ -10,9 +10,8 @@ namespace dxvk {
case DxbcProgramType::HullShader : return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; case DxbcProgramType::HullShader : return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
case DxbcProgramType::DomainShader : return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; case DxbcProgramType::DomainShader : return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
case DxbcProgramType::ComputeShader : return VK_SHADER_STAGE_COMPUTE_BIT; case DxbcProgramType::ComputeShader : return VK_SHADER_STAGE_COMPUTE_BIT;
default: throw DxvkError("DxbcProgramInfo::shaderStage: Unsupported program type");
} }
throw DxvkError("DxbcProgramInfo::shaderStage: Unsupported program type");
} }
@ -24,9 +23,8 @@ namespace dxvk {
case DxbcProgramType::HullShader : return spv::ExecutionModelTessellationControl; case DxbcProgramType::HullShader : return spv::ExecutionModelTessellationControl;
case DxbcProgramType::DomainShader : return spv::ExecutionModelTessellationEvaluation; case DxbcProgramType::DomainShader : return spv::ExecutionModelTessellationEvaluation;
case DxbcProgramType::ComputeShader : return spv::ExecutionModelGLCompute; case DxbcProgramType::ComputeShader : return spv::ExecutionModelGLCompute;
default: throw DxvkError("DxbcProgramInfo::executionModel: Unsupported program type");
} }
throw DxvkError("DxbcProgramInfo::executionModel: Unsupported program type");
} }
} }

View File

@ -17,7 +17,11 @@ namespace dxvk {
HullShader = 3, HullShader = 3,
DomainShader = 4, DomainShader = 4,
ComputeShader = 5, ComputeShader = 5,
Count
}; };
using DxbcProgramTypeFlags = Flags<DxbcProgramType>;
/** /**

View File

@ -237,6 +237,7 @@ namespace dxvk {
case DxbcProgramType::GeometryShader: this->emitGsFinalize(); break; case DxbcProgramType::GeometryShader: this->emitGsFinalize(); break;
case DxbcProgramType::PixelShader: this->emitPsFinalize(); break; case DxbcProgramType::PixelShader: this->emitPsFinalize(); break;
case DxbcProgramType::ComputeShader: this->emitCsFinalize(); break; case DxbcProgramType::ComputeShader: this->emitCsFinalize(); break;
default: throw DxvkError("Invalid shader stage");
} }
// Emit float control mode if the extension is supported // Emit float control mode if the extension is supported
@ -6138,7 +6139,7 @@ namespace dxvk {
case DxbcProgramType::HullShader: emitHsSystemValueStore(sv, mask, value); break; case DxbcProgramType::HullShader: emitHsSystemValueStore(sv, mask, value); break;
case DxbcProgramType::DomainShader: emitDsSystemValueStore(sv, mask, value); break; case DxbcProgramType::DomainShader: emitDsSystemValueStore(sv, mask, value); break;
case DxbcProgramType::PixelShader: emitPsSystemValueStore(sv, mask, value); break; case DxbcProgramType::PixelShader: emitPsSystemValueStore(sv, mask, value); break;
case DxbcProgramType::ComputeShader: break; default: break;
} }
} }
} }
@ -6822,6 +6823,7 @@ namespace dxvk {
case DxbcProgramType::GeometryShader: emitGsInit(); break; case DxbcProgramType::GeometryShader: emitGsInit(); break;
case DxbcProgramType::PixelShader: emitPsInit(); break; case DxbcProgramType::PixelShader: emitPsInit(); break;
case DxbcProgramType::ComputeShader: emitCsInit(); break; case DxbcProgramType::ComputeShader: emitCsInit(); break;
default: throw DxvkError("Invalid shader stage");
} }
} }

View File

@ -42,7 +42,7 @@ namespace dxvk {
Rc<DxvkShader> DxbcModule::compile( Rc<DxvkShader> DxbcModule::compile(
const DxbcModuleInfo& moduleInfo, const DxbcModuleInfo& moduleInfo,
const std::string& fileName) const { const std::string& fileName) {
if (m_shexChunk == nullptr) if (m_shexChunk == nullptr)
throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk"); throw DxvkError("DxbcModule::compile: No SHDR/SHEX chunk");
@ -54,6 +54,8 @@ namespace dxvk {
m_psgnChunk, analysisInfo); m_psgnChunk, analysisInfo);
this->runAnalyzer(analyzer, m_shexChunk->slice()); this->runAnalyzer(analyzer, m_shexChunk->slice());
m_bindings = std::make_optional(analysisInfo.bindings);
DxbcCompiler compiler( DxbcCompiler compiler(
fileName, moduleInfo, fileName, moduleInfo,
@ -62,7 +64,7 @@ namespace dxvk {
m_psgnChunk, analysisInfo); m_psgnChunk, analysisInfo);
this->runCompiler(compiler, m_shexChunk->slice()); this->runCompiler(compiler, m_shexChunk->slice());
return compiler.finalize(); return compiler.finalize();
} }

View File

@ -7,6 +7,7 @@
#include "dxbc_header.h" #include "dxbc_header.h"
#include "dxbc_modinfo.h" #include "dxbc_modinfo.h"
#include "dxbc_reader.h" #include "dxbc_reader.h"
#include "dxbc_util.h"
// References used for figuring out DXBC: // References used for figuring out DXBC:
// - https://github.com/tgjones/slimshader-cpp // - https://github.com/tgjones/slimshader-cpp
@ -41,7 +42,16 @@ namespace dxvk {
return m_shexChunk->programInfo(); return m_shexChunk->programInfo();
} }
/**
* \brief Queries shader binding mask
*
* Only valid after successfully compiling the shader.
*/
std::optional<DxbcBindingMask> bindings() const {
return m_bindings;
}
/** /**
* \brief Input and output signature chunks * \brief Input and output signature chunks
* *
@ -50,7 +60,7 @@ namespace dxvk {
*/ */
Rc<DxbcIsgn> isgn() const { return m_isgnChunk; } Rc<DxbcIsgn> isgn() const { return m_isgnChunk; }
Rc<DxbcIsgn> osgn() const { return m_osgnChunk; } Rc<DxbcIsgn> osgn() const { return m_osgnChunk; }
/** /**
* \brief Compiles DXBC shader to SPIR-V module * \brief Compiles DXBC shader to SPIR-V module
* *
@ -61,7 +71,7 @@ namespace dxvk {
*/ */
Rc<DxvkShader> compile( Rc<DxvkShader> compile(
const DxbcModuleInfo& moduleInfo, const DxbcModuleInfo& moduleInfo,
const std::string& fileName) const; const std::string& fileName);
/** /**
* \brief Compiles a pass-through geometry shader * \brief Compiles a pass-through geometry shader
@ -85,6 +95,8 @@ namespace dxvk {
Rc<DxbcIsgn> m_osgnChunk; Rc<DxbcIsgn> m_osgnChunk;
Rc<DxbcIsgn> m_psgnChunk; Rc<DxbcIsgn> m_psgnChunk;
Rc<DxbcShex> m_shexChunk; Rc<DxbcShex> m_shexChunk;
std::optional<DxbcBindingMask> m_bindings;
void runAnalyzer( void runAnalyzer(
DxbcAnalyzer& analyzer, DxbcAnalyzer& analyzer,

View File

@ -33,6 +33,43 @@ namespace dxvk {
}; };
/**
* \brief Shader binding mask
*
* Stores a bit masks of resource bindings
* that are accessed by any given shader.
*/
struct DxbcBindingMask {
uint32_t cbvMask = 0u;
uint32_t samplerMask = 0u;
uint64_t uavMask = 0u;
std::array<uint64_t, 2> srvMask = { };
void reset() {
cbvMask = 0u;
samplerMask = 0u;
uavMask = 0u;
srvMask = { };
}
bool empty() const {
uint64_t mask = (uint64_t(cbvMask) | uint64_t(samplerMask) << 32u)
| (uavMask | srvMask[0] | srvMask[1]);
return !mask;
}
DxbcBindingMask operator & (const DxbcBindingMask& other) const {
DxbcBindingMask result = *this;
result.cbvMask &= other.cbvMask;
result.samplerMask &= other.samplerMask;
result.uavMask &= other.uavMask;
result.srvMask[0] &= other.srvMask[0];
result.srvMask[1] &= other.srvMask[1];
return result;
}
};
/** /**
* \brief Computes first binding index for a given stage * \brief Computes first binding index for a given stage
* *
@ -124,4 +161,4 @@ namespace dxvk {
uint32_t primitiveVertexCount( uint32_t primitiveVertexCount(
DxbcPrimitive primitive); DxbcPrimitive primitive);
} }