1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-01 16:24:12 +01:00

[dxbc] Use SSBOs for dynamically indexed constant buffers if needed

SSBOs are tightly bound-checked on all Nvidia GPUs, so this allows for
a more accurate workaround for games relying on OOB access behaviour.
This commit is contained in:
Philip Rebohle 2019-10-28 14:17:46 +01:00
parent 68760f5b20
commit 3d213efe53
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
5 changed files with 27 additions and 9 deletions

View File

@ -34,7 +34,8 @@ namespace dxvk {
}
if (pDesc->BindFlags & D3D11_BIND_CONSTANT_BUFFER) {
info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
info.usage |= VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
info.stages |= m_device->GetEnabledShaderStages();
info.access |= VK_ACCESS_UNIFORM_READ_BIT;
}

View File

@ -755,16 +755,20 @@ namespace dxvk {
// (1) Number of constants in the buffer
const uint32_t bufferId = ins.dst[0].idx[0].offset;
const uint32_t elementCount = ins.dst[0].idx[1].offset;
bool asSsbo = m_moduleInfo.options.dynamicIndexedConstantBufferAsSsbo
&& ins.controls.accessType() == DxbcConstantBufferAccessType::DynamicallyIndexed;
this->emitDclConstantBufferVar(bufferId, elementCount,
str::format("cb", bufferId).c_str());
str::format("cb", bufferId).c_str(), asSsbo);
}
void DxbcCompiler::emitDclConstantBufferVar(
uint32_t regIdx,
uint32_t numConstants,
const char* name) {
const char* name,
bool asSsbo) {
// 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(
@ -776,7 +780,9 @@ namespace dxvk {
// struct and decorate that struct as a block.
const uint32_t structType = m_module.defStructTypeUnique(1, &arrayType);
m_module.decorateBlock (structType);
m_module.decorate(structType, asSsbo
? spv::DecorationBufferBlock
: spv::DecorationBlock);
m_module.memberDecorateOffset(structType, 0, 0);
m_module.setDebugName (structType, str::format(name, "_t").c_str());
@ -796,7 +802,10 @@ namespace dxvk {
m_module.decorateDescriptorSet(varId, 0);
m_module.decorateBinding(varId, bindingId);
if (asSsbo)
m_module.decorate(varId, spv::DecorationNonWritable);
// Declare a specialization constant which will
// store whether or not the resource is bound.
const uint32_t specConstId = m_module.specConstBool(true);
@ -813,7 +822,9 @@ namespace dxvk {
// Store descriptor info for the shader interface
DxvkResourceSlot resource;
resource.slot = bindingId;
resource.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
resource.type = asSsbo
? VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
: VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
resource.view = VK_IMAGE_VIEW_TYPE_MAX_ENUM;
resource.access = VK_ACCESS_UNIFORM_READ_BIT;
m_resourceSlots.push_back(resource);
@ -1505,7 +1516,8 @@ namespace dxvk {
void DxbcCompiler::emitDclImmediateConstantBufferUbo(
uint32_t dwordCount,
const uint32_t* dwordArray) {
this->emitDclConstantBufferVar(Icb_BindingSlotId, dwordCount / 4, "icb");
this->emitDclConstantBufferVar(Icb_BindingSlotId, dwordCount / 4, "icb",
m_moduleInfo.options.dynamicIndexedConstantBufferAsSsbo);
m_immConstData = DxvkShaderConstData(dwordCount, dwordArray);
}

View File

@ -575,7 +575,8 @@ namespace dxvk {
void emitDclConstantBufferVar(
uint32_t regIdx,
uint32_t numConstants,
const char* name);
const char* name,
bool asSsbo);
void emitDclSampler(
const DxbcShaderInstruction& ins);

View File

@ -41,7 +41,7 @@ namespace dxvk {
zeroInitWorkgroupMemory = options.zeroInitWorkgroupMemory;
if (DxvkGpuVendor(devInfo.core.properties.vendorID) != DxvkGpuVendor::Amd)
constantBufferRangeCheck = options.constantBufferRangeCheck;
dynamicIndexedConstantBufferAsSsbo = options.constantBufferRangeCheck;
// Disable early discard on RADV (with LLVM) due to GPU hangs
// Disable early discard on Nvidia because it may hurt performance

View File

@ -39,6 +39,10 @@ namespace dxvk {
// Fixes issues in some games, breaks others.
bool constantBufferRangeCheck = false;
/// Implement dynamically indexed uniform buffers
/// with storage buffers for tight bounds checking
bool dynamicIndexedConstantBufferAsSsbo = false;
/// Clear thread-group shared memory to zero
bool zeroInitWorkgroupMemory = false;