mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 22:29:15 +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:
parent
bf06654a83
commit
2166769096
@ -1,13 +1,14 @@
|
|||||||
#include "dxbc_compiler.h"
|
#include "dxbc_compiler.h"
|
||||||
|
|
||||||
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;
|
||||||
@ -738,8 +746,8 @@ namespace dxvk {
|
|||||||
resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||||
m_resourceSlots.push_back(resource);
|
m_resourceSlots.push_back(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxbcCompiler::emitDclSampler(const DxbcShaderInstruction& ins) {
|
void DxbcCompiler::emitDclSampler(const DxbcShaderInstruction& ins) {
|
||||||
// dclSampler takes one operand:
|
// dclSampler takes one operand:
|
||||||
// (dst0) The sampler register to declare
|
// (dst0) The sampler register to declare
|
||||||
@ -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)
|
DxbcRegisterInfo ptrInfo;
|
||||||
throw DxvkError("DxbcCompiler: Immediate constant buffer not defined");
|
ptrInfo.type.ctype = DxbcScalarType::Float32;
|
||||||
|
ptrInfo.type.ccount = 4;
|
||||||
|
ptrInfo.type.alength = 0;
|
||||||
|
|
||||||
|
DxbcRegisterPointer result;
|
||||||
|
result.type.ctype = ptrInfo.type.ctype;
|
||||||
|
result.type.ccount = ptrInfo.type.ccount;
|
||||||
|
|
||||||
const DxbcRegisterValue constId
|
const DxbcRegisterValue constId
|
||||||
= emitIndexLoad(operand.idx[0]);
|
= emitIndexLoad(operand.idx[0]);
|
||||||
|
|
||||||
DxbcRegisterInfo ptrInfo;
|
if (m_immConstBuf != 0) {
|
||||||
ptrInfo.type.ctype = DxbcScalarType::Uint32;
|
ptrInfo.sclass = spv::StorageClassPrivate;
|
||||||
ptrInfo.type.ccount = 4;
|
|
||||||
ptrInfo.type.alength = 0;
|
result.id = m_module.opAccessChain(
|
||||||
ptrInfo.sclass = spv::StorageClassPrivate;
|
getPointerTypeId(ptrInfo),
|
||||||
|
m_immConstBuf, 1, &constId.id);
|
||||||
DxbcRegisterPointer result;
|
return result;
|
||||||
result.type.ctype = ptrInfo.type.ctype;
|
} else if (m_constantBuffers.at(Icb_BindingSlotId).varId != 0) {
|
||||||
result.type.ccount = ptrInfo.type.ccount;
|
const std::array<uint32_t, 2> indices =
|
||||||
result.id = m_module.opAccessChain(
|
{{ m_module.consti32(0), constId.id }};
|
||||||
getPointerTypeId(ptrInfo),
|
|
||||||
m_immConstBuf, 1, &constId.id);
|
ptrInfo.sclass = spv::StorageClassUniform;
|
||||||
return result;
|
|
||||||
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -458,7 +458,8 @@ 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);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user