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:
parent
68760f5b20
commit
3d213efe53
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user