mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-03-14 04: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"
|
||||
|
||||
namespace dxvk {
|
||||
|
||||
constexpr uint32_t Icb_BindingSlotId = 14;
|
||||
constexpr uint32_t Icb_MaxBakedDwords = 16;
|
||||
|
||||
constexpr uint32_t PerVertex_Position = 0;
|
||||
constexpr uint32_t PerVertex_CullDist = 1;
|
||||
constexpr uint32_t PerVertex_ClipDist = 2;
|
||||
|
||||
constexpr uint32_t PushConstant_InstanceId = 0;
|
||||
|
||||
DxbcCompiler::DxbcCompiler(
|
||||
const std::string& fileName,
|
||||
const DxbcModuleInfo& moduleInfo,
|
||||
@ -206,7 +207,7 @@ namespace dxvk {
|
||||
m_resourceSlots.data(),
|
||||
m_interfaceSlots,
|
||||
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 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
|
||||
// of 4x32-bit vectors. SPIR-V requires explicit strides.
|
||||
const uint32_t arrayType = m_module.defArrayTypeUnique(
|
||||
getVectorTypeId({ DxbcScalarType::Float32, 4 }),
|
||||
m_module.constu32(elementCount));
|
||||
m_module.constu32(numConstants));
|
||||
m_module.decorateArrayStride(arrayType, 16);
|
||||
|
||||
// SPIR-V requires us to put that array into a
|
||||
@ -698,7 +706,7 @@ namespace dxvk {
|
||||
m_module.decorateBlock (structType);
|
||||
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");
|
||||
|
||||
// Variable that we'll use to access the buffer
|
||||
@ -707,13 +715,13 @@ namespace dxvk {
|
||||
spv::StorageClassUniform);
|
||||
|
||||
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.
|
||||
// D3D11 needs to bind the actual buffers to this slot.
|
||||
const uint32_t bindingId = computeResourceSlotId(
|
||||
m_version.type(), DxbcBindingType::ConstantBuffer,
|
||||
bufferId);
|
||||
regIdx);
|
||||
|
||||
m_module.decorateDescriptorSet(varId, 0);
|
||||
m_module.decorateBinding(varId, bindingId);
|
||||
@ -723,13 +731,13 @@ namespace dxvk {
|
||||
const uint32_t specConstId = m_module.specConstBool(true);
|
||||
m_module.decorateSpecId(specConstId, bindingId);
|
||||
m_module.setDebugName(specConstId,
|
||||
str::format("cb", bufferId, "_bound").c_str());
|
||||
str::format("cb", regIdx, "_bound").c_str());
|
||||
|
||||
DxbcConstantBuffer buf;
|
||||
buf.varId = varId;
|
||||
buf.specId = specConstId;
|
||||
buf.size = elementCount;
|
||||
m_constantBuffers.at(bufferId) = buf;
|
||||
buf.size = numConstants;
|
||||
m_constantBuffers.at(regIdx) = buf;
|
||||
|
||||
// Store descriptor info for the shader interface
|
||||
DxvkResourceSlot resource;
|
||||
@ -738,8 +746,8 @@ namespace dxvk {
|
||||
resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
|
||||
m_resourceSlots.push_back(resource);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void DxbcCompiler::emitDclSampler(const DxbcShaderInstruction& ins) {
|
||||
// dclSampler takes one operand:
|
||||
// (dst0) The sampler register to declare
|
||||
@ -1302,6 +1310,19 @@ namespace dxvk {
|
||||
if ((ins.customDataSize & 0x3) != 0)
|
||||
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
|
||||
std::array<uint32_t, 4096> vectorIds;
|
||||
|
||||
@ -1310,14 +1331,14 @@ namespace dxvk {
|
||||
vecType.ccount = 4;
|
||||
|
||||
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++) {
|
||||
std::array<uint32_t, 4> scalarIds = {
|
||||
m_module.constu32(ins.customData[4 * i + 0]),
|
||||
m_module.constu32(ins.customData[4 * i + 1]),
|
||||
m_module.constu32(ins.customData[4 * i + 2]),
|
||||
m_module.constu32(ins.customData[4 * i + 3]),
|
||||
m_module.constu32(dwordArray[4 * i + 0]),
|
||||
m_module.constu32(dwordArray[4 * i + 1]),
|
||||
m_module.constu32(dwordArray[4 * i + 2]),
|
||||
m_module.constu32(dwordArray[4 * i + 3]),
|
||||
};
|
||||
|
||||
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) {
|
||||
switch (ins.customDataType) {
|
||||
case DxbcCustomDataClass::ImmConstBuf:
|
||||
@ -4280,25 +4309,39 @@ namespace dxvk {
|
||||
|
||||
DxbcRegisterPointer DxbcCompiler::emitGetImmConstBufPtr(
|
||||
const DxbcRegister& operand) {
|
||||
if (m_immConstBuf == 0)
|
||||
throw DxvkError("DxbcCompiler: Immediate constant buffer not defined");
|
||||
DxbcRegisterInfo ptrInfo;
|
||||
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
|
||||
= emitIndexLoad(operand.idx[0]);
|
||||
|
||||
DxbcRegisterInfo ptrInfo;
|
||||
ptrInfo.type.ctype = DxbcScalarType::Uint32;
|
||||
ptrInfo.type.ccount = 4;
|
||||
ptrInfo.type.alength = 0;
|
||||
ptrInfo.sclass = spv::StorageClassPrivate;
|
||||
|
||||
DxbcRegisterPointer result;
|
||||
result.type.ctype = ptrInfo.type.ctype;
|
||||
result.type.ccount = ptrInfo.type.ccount;
|
||||
result.id = m_module.opAccessChain(
|
||||
getPointerTypeId(ptrInfo),
|
||||
m_immConstBuf, 1, &constId.id);
|
||||
return result;
|
||||
if (m_immConstBuf != 0) {
|
||||
ptrInfo.sclass = spv::StorageClassPrivate;
|
||||
|
||||
result.id = m_module.opAccessChain(
|
||||
getPointerTypeId(ptrInfo),
|
||||
m_immConstBuf, 1, &constId.id);
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -458,7 +458,8 @@ namespace dxvk {
|
||||
//////////////////////////////////////////////////
|
||||
// Immediate constant buffer. If defined, this is
|
||||
// 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
|
||||
@ -528,6 +529,10 @@ namespace dxvk {
|
||||
void emitDclConstantBuffer(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclConstantBufferVar(
|
||||
uint32_t regIdx,
|
||||
uint32_t numConstants);
|
||||
|
||||
void emitDclSampler(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
@ -584,6 +589,14 @@ namespace dxvk {
|
||||
void emitDclImmediateConstantBuffer(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
void emitDclImmediateConstantBufferBaked(
|
||||
uint32_t dwordCount,
|
||||
const uint32_t* dwordArray);
|
||||
|
||||
void emitDclImmediateConstantBufferUbo(
|
||||
uint32_t dwordCount,
|
||||
const uint32_t* dwordArray);
|
||||
|
||||
void emitCustomData(
|
||||
const DxbcShaderInstruction& ins);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user