1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-03-15 07:29:17 +01:00

[dxbc] Map large ICBs to a constant buffer

Should fix an issue with compiling a specific compute shader in
the game Dragon Ball Xenoverse 2 (#523).
This commit is contained in:
Philip Rebohle 2018-07-30 20:52:42 +02:00
parent bf06654a83
commit 2166769096
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 89 additions and 33 deletions

View File

@ -2,12 +2,13 @@
namespace dxvk { namespace dxvk {
constexpr uint32_t Icb_BindingSlotId = 14;
constexpr uint32_t Icb_MaxBakedDwords = 16;
constexpr uint32_t PerVertex_Position = 0; constexpr uint32_t PerVertex_Position = 0;
constexpr uint32_t PerVertex_CullDist = 1; constexpr uint32_t PerVertex_CullDist = 1;
constexpr uint32_t PerVertex_ClipDist = 2; constexpr uint32_t PerVertex_ClipDist = 2;
constexpr uint32_t PushConstant_InstanceId = 0;
DxbcCompiler::DxbcCompiler( DxbcCompiler::DxbcCompiler(
const std::string& fileName, const std::string& fileName,
const DxbcModuleInfo& moduleInfo, const DxbcModuleInfo& moduleInfo,
@ -206,7 +207,7 @@ namespace dxvk {
m_resourceSlots.data(), m_resourceSlots.data(),
m_interfaceSlots, m_interfaceSlots,
m_module.compile(), m_module.compile(),
DxvkShaderConstData()); std::move(m_immConstData));
} }
@ -684,11 +685,18 @@ namespace dxvk {
const uint32_t bufferId = ins.dst[0].idx[0].offset; const uint32_t bufferId = ins.dst[0].idx[0].offset;
const uint32_t elementCount = ins.dst[0].idx[1].offset; const uint32_t elementCount = ins.dst[0].idx[1].offset;
this->emitDclConstantBufferVar(bufferId, elementCount);
}
void DxbcCompiler::emitDclConstantBufferVar(
uint32_t regIdx,
uint32_t numConstants) {
// Uniform buffer data is stored as a fixed-size array // Uniform buffer data is stored as a fixed-size array
// of 4x32-bit vectors. SPIR-V requires explicit strides. // of 4x32-bit vectors. SPIR-V requires explicit strides.
const uint32_t arrayType = m_module.defArrayTypeUnique( const uint32_t arrayType = m_module.defArrayTypeUnique(
getVectorTypeId({ DxbcScalarType::Float32, 4 }), getVectorTypeId({ DxbcScalarType::Float32, 4 }),
m_module.constu32(elementCount)); m_module.constu32(numConstants));
m_module.decorateArrayStride(arrayType, 16); m_module.decorateArrayStride(arrayType, 16);
// SPIR-V requires us to put that array into a // SPIR-V requires us to put that array into a
@ -698,7 +706,7 @@ namespace dxvk {
m_module.decorateBlock (structType); m_module.decorateBlock (structType);
m_module.memberDecorateOffset(structType, 0, 0); m_module.memberDecorateOffset(structType, 0, 0);
m_module.setDebugName (structType, str::format("struct_cb", bufferId).c_str()); m_module.setDebugName (structType, str::format("struct_cb", regIdx).c_str());
m_module.setDebugMemberName (structType, 0, "m"); m_module.setDebugMemberName (structType, 0, "m");
// Variable that we'll use to access the buffer // Variable that we'll use to access the buffer
@ -707,13 +715,13 @@ namespace dxvk {
spv::StorageClassUniform); spv::StorageClassUniform);
m_module.setDebugName(varId, m_module.setDebugName(varId,
str::format("cb", bufferId).c_str()); str::format("cb", regIdx).c_str());
// Compute the DXVK binding slot index for the buffer. // Compute the DXVK binding slot index for the buffer.
// D3D11 needs to bind the actual buffers to this slot. // D3D11 needs to bind the actual buffers to this slot.
const uint32_t bindingId = computeResourceSlotId( const uint32_t bindingId = computeResourceSlotId(
m_version.type(), DxbcBindingType::ConstantBuffer, m_version.type(), DxbcBindingType::ConstantBuffer,
bufferId); regIdx);
m_module.decorateDescriptorSet(varId, 0); m_module.decorateDescriptorSet(varId, 0);
m_module.decorateBinding(varId, bindingId); m_module.decorateBinding(varId, bindingId);
@ -723,13 +731,13 @@ namespace dxvk {
const uint32_t specConstId = m_module.specConstBool(true); const uint32_t specConstId = m_module.specConstBool(true);
m_module.decorateSpecId(specConstId, bindingId); m_module.decorateSpecId(specConstId, bindingId);
m_module.setDebugName(specConstId, m_module.setDebugName(specConstId,
str::format("cb", bufferId, "_bound").c_str()); str::format("cb", regIdx, "_bound").c_str());
DxbcConstantBuffer buf; DxbcConstantBuffer buf;
buf.varId = varId; buf.varId = varId;
buf.specId = specConstId; buf.specId = specConstId;
buf.size = elementCount; buf.size = numConstants;
m_constantBuffers.at(bufferId) = buf; m_constantBuffers.at(regIdx) = buf;
// Store descriptor info for the shader interface // Store descriptor info for the shader interface
DxvkResourceSlot resource; DxvkResourceSlot resource;
@ -1302,6 +1310,19 @@ namespace dxvk {
if ((ins.customDataSize & 0x3) != 0) if ((ins.customDataSize & 0x3) != 0)
throw DxvkError("DxbcCompiler: Immediate constant buffer size not a multiple of four DWORDs"); throw DxvkError("DxbcCompiler: Immediate constant buffer size not a multiple of four DWORDs");
if (ins.customDataSize <= Icb_MaxBakedDwords) {
this->emitDclImmediateConstantBufferBaked(
ins.customDataSize, ins.customData);
} else {
this->emitDclImmediateConstantBufferUbo(
ins.customDataSize, ins.customData);
}
}
void DxbcCompiler::emitDclImmediateConstantBufferBaked(
uint32_t dwordCount,
const uint32_t* dwordArray) {
// Declare individual vector constants as 4x32-bit vectors // Declare individual vector constants as 4x32-bit vectors
std::array<uint32_t, 4096> vectorIds; std::array<uint32_t, 4096> vectorIds;
@ -1310,14 +1331,14 @@ namespace dxvk {
vecType.ccount = 4; vecType.ccount = 4;
const uint32_t vectorTypeId = getVectorTypeId(vecType); const uint32_t vectorTypeId = getVectorTypeId(vecType);
const uint32_t vectorCount = ins.customDataSize / 4; const uint32_t vectorCount = dwordCount / 4;
for (uint32_t i = 0; i < vectorCount; i++) { for (uint32_t i = 0; i < vectorCount; i++) {
std::array<uint32_t, 4> scalarIds = { std::array<uint32_t, 4> scalarIds = {
m_module.constu32(ins.customData[4 * i + 0]), m_module.constu32(dwordArray[4 * i + 0]),
m_module.constu32(ins.customData[4 * i + 1]), m_module.constu32(dwordArray[4 * i + 1]),
m_module.constu32(ins.customData[4 * i + 2]), m_module.constu32(dwordArray[4 * i + 2]),
m_module.constu32(ins.customData[4 * i + 3]), m_module.constu32(dwordArray[4 * i + 3]),
}; };
vectorIds.at(i) = m_module.constComposite( vectorIds.at(i) = m_module.constComposite(
@ -1346,6 +1367,14 @@ namespace dxvk {
} }
void DxbcCompiler::emitDclImmediateConstantBufferUbo(
uint32_t dwordCount,
const uint32_t* dwordArray) {
this->emitDclConstantBufferVar(Icb_BindingSlotId, dwordCount / 4);
m_immConstData = DxvkShaderConstData(dwordCount, dwordArray);
}
void DxbcCompiler::emitCustomData(const DxbcShaderInstruction& ins) { void DxbcCompiler::emitCustomData(const DxbcShaderInstruction& ins) {
switch (ins.customDataType) { switch (ins.customDataType) {
case DxbcCustomDataClass::ImmConstBuf: case DxbcCustomDataClass::ImmConstBuf:
@ -4280,25 +4309,39 @@ namespace dxvk {
DxbcRegisterPointer DxbcCompiler::emitGetImmConstBufPtr( DxbcRegisterPointer DxbcCompiler::emitGetImmConstBufPtr(
const DxbcRegister& operand) { const DxbcRegister& operand) {
if (m_immConstBuf == 0)
throw DxvkError("DxbcCompiler: Immediate constant buffer not defined");
const DxbcRegisterValue constId
= emitIndexLoad(operand.idx[0]);
DxbcRegisterInfo ptrInfo; DxbcRegisterInfo ptrInfo;
ptrInfo.type.ctype = DxbcScalarType::Uint32; ptrInfo.type.ctype = DxbcScalarType::Float32;
ptrInfo.type.ccount = 4; ptrInfo.type.ccount = 4;
ptrInfo.type.alength = 0; ptrInfo.type.alength = 0;
ptrInfo.sclass = spv::StorageClassPrivate;
DxbcRegisterPointer result; DxbcRegisterPointer result;
result.type.ctype = ptrInfo.type.ctype; result.type.ctype = ptrInfo.type.ctype;
result.type.ccount = ptrInfo.type.ccount; result.type.ccount = ptrInfo.type.ccount;
const DxbcRegisterValue constId
= emitIndexLoad(operand.idx[0]);
if (m_immConstBuf != 0) {
ptrInfo.sclass = spv::StorageClassPrivate;
result.id = m_module.opAccessChain( result.id = m_module.opAccessChain(
getPointerTypeId(ptrInfo), getPointerTypeId(ptrInfo),
m_immConstBuf, 1, &constId.id); m_immConstBuf, 1, &constId.id);
return result; return result;
} else if (m_constantBuffers.at(Icb_BindingSlotId).varId != 0) {
const std::array<uint32_t, 2> indices =
{{ m_module.consti32(0), constId.id }};
ptrInfo.sclass = spv::StorageClassUniform;
result.id = m_module.opAccessChain(
getPointerTypeId(ptrInfo),
m_constantBuffers.at(Icb_BindingSlotId).varId,
indices.size(), indices.data());
return result;
} else {
throw DxvkError("DxbcCompiler: Immediate constant buffer not defined");
}
} }

View File

@ -459,6 +459,7 @@ namespace dxvk {
// Immediate constant buffer. If defined, this is // Immediate constant buffer. If defined, this is
// an array of four-component uint32 vectors. // an array of four-component uint32 vectors.
uint32_t m_immConstBuf = 0; uint32_t m_immConstBuf = 0;
DxvkShaderConstData m_immConstData;
/////////////////////////////////////////////////// ///////////////////////////////////////////////////
// Sample pos array. If defined, this iis an array // Sample pos array. If defined, this iis an array
@ -528,6 +529,10 @@ namespace dxvk {
void emitDclConstantBuffer( void emitDclConstantBuffer(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitDclConstantBufferVar(
uint32_t regIdx,
uint32_t numConstants);
void emitDclSampler( void emitDclSampler(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
@ -584,6 +589,14 @@ namespace dxvk {
void emitDclImmediateConstantBuffer( void emitDclImmediateConstantBuffer(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);
void emitDclImmediateConstantBufferBaked(
uint32_t dwordCount,
const uint32_t* dwordArray);
void emitDclImmediateConstantBufferUbo(
uint32_t dwordCount,
const uint32_t* dwordArray);
void emitCustomData( void emitCustomData(
const DxbcShaderInstruction& ins); const DxbcShaderInstruction& ins);