mirror of
https://github.com/EduApps-CDG/OpenDX
synced 2024-12-30 09:45:37 +01:00
[dxvk] Implement support for dynamic buffer binding offsets
This commit is contained in:
parent
826b1245a1
commit
4b5ec1be3e
@ -231,12 +231,14 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void cmdBindDescriptorSet(
|
void cmdBindDescriptorSet(
|
||||||
VkPipelineBindPoint pipeline,
|
VkPipelineBindPoint pipeline,
|
||||||
VkPipelineLayout pipelineLayout,
|
VkPipelineLayout pipelineLayout,
|
||||||
VkDescriptorSet descriptorSet) {
|
VkDescriptorSet descriptorSet,
|
||||||
|
uint32_t dynamicOffsetCount,
|
||||||
|
const uint32_t* pDynamicOffsets) {
|
||||||
m_vkd->vkCmdBindDescriptorSets(m_execBuffer,
|
m_vkd->vkCmdBindDescriptorSets(m_execBuffer,
|
||||||
pipeline, pipelineLayout, 0, 1,
|
pipeline, pipelineLayout, 0, 1,
|
||||||
&descriptorSet, 0, nullptr);
|
&descriptorSet, dynamicOffsetCount, pDynamicOffsets);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -311,7 +311,8 @@ namespace dxvk {
|
|||||||
pipeInfo.pipeline);
|
pipeInfo.pipeline);
|
||||||
m_cmd->cmdBindDescriptorSet(
|
m_cmd->cmdBindDescriptorSet(
|
||||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
pipeInfo.pipeLayout, descriptorSet);
|
pipeInfo.pipeLayout, descriptorSet,
|
||||||
|
0, nullptr);
|
||||||
m_cmd->cmdPushConstants(
|
m_cmd->cmdPushConstants(
|
||||||
pipeInfo.pipeLayout,
|
pipeInfo.pipeLayout,
|
||||||
VK_SHADER_STAGE_COMPUTE_BIT,
|
VK_SHADER_STAGE_COMPUTE_BIT,
|
||||||
@ -548,7 +549,8 @@ namespace dxvk {
|
|||||||
pipeInfo.pipeline);
|
pipeInfo.pipeline);
|
||||||
m_cmd->cmdBindDescriptorSet(
|
m_cmd->cmdBindDescriptorSet(
|
||||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
pipeInfo.pipeLayout, descriptorSet);
|
pipeInfo.pipeLayout, descriptorSet,
|
||||||
|
0, nullptr);
|
||||||
m_cmd->cmdPushConstants(
|
m_cmd->cmdPushConstants(
|
||||||
pipeInfo.pipeLayout,
|
pipeInfo.pipeLayout,
|
||||||
VK_SHADER_STAGE_COMPUTE_BIT,
|
VK_SHADER_STAGE_COMPUTE_BIT,
|
||||||
@ -1109,7 +1111,7 @@ namespace dxvk {
|
|||||||
m_cmd->cmdBeginRenderPass(&passInfo, VK_SUBPASS_CONTENTS_INLINE);
|
m_cmd->cmdBeginRenderPass(&passInfo, VK_SUBPASS_CONTENTS_INLINE);
|
||||||
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle);
|
m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle);
|
||||||
m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
pipeInfo.pipeLayout, descriptorWrite.dstSet);
|
pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr);
|
||||||
|
|
||||||
m_cmd->cmdSetViewport(0, 1, &viewport);
|
m_cmd->cmdSetViewport(0, 1, &viewport);
|
||||||
m_cmd->cmdSetScissor (0, 1, &scissor);
|
m_cmd->cmdSetScissor (0, 1, &scissor);
|
||||||
@ -1146,12 +1148,22 @@ namespace dxvk {
|
|||||||
if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
if (usage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)
|
||||||
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
|
m_flags.set(DxvkContextFlag::GpDirtyVertexBuffers);
|
||||||
|
|
||||||
if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
|
||||||
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
|
||||||
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
|
|
||||||
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
|
|
||||||
m_flags.set(DxvkContextFlag::GpDirtyResources,
|
m_flags.set(DxvkContextFlag::GpDirtyResources,
|
||||||
DxvkContextFlag::CpDirtyResources);
|
DxvkContextFlag::CpDirtyResources);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usage & (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
|
||||||
|
| VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
|
||||||
|
if (prevSlice.handle() != slice.handle()) {
|
||||||
|
m_flags.set(DxvkContextFlag::GpDirtyResources,
|
||||||
|
DxvkContextFlag::CpDirtyResources);
|
||||||
|
} else {
|
||||||
|
m_flags.set(DxvkContextFlag::GpDirtyDescriptorOffsets,
|
||||||
|
DxvkContextFlag::CpDirtyDescriptorOffsets);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1783,58 +1795,94 @@ namespace dxvk {
|
|||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateComputeShaderResources() {
|
void DxvkContext::updateComputeShaderResources() {
|
||||||
if (m_flags.test(DxvkContextFlag::CpDirtyResources)) {
|
if (m_state.cp.pipeline == nullptr)
|
||||||
if (m_state.cp.pipeline != nullptr) {
|
return;
|
||||||
this->updateShaderResources(
|
|
||||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
if ((m_flags.test(DxvkContextFlag::CpDirtyResources))
|
||||||
m_state.cp.pipeline->layout());
|
|| (m_flags.test(DxvkContextFlag::CpDirtyDescriptorOffsets)
|
||||||
}
|
&& m_state.cp.pipeline->layout()->hasStaticBufferBindings())) {
|
||||||
|
m_flags.clr(DxvkContextFlag::CpDirtyResources);
|
||||||
|
|
||||||
|
this->updateShaderResources(
|
||||||
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
|
m_state.cp.pipeline->layout());
|
||||||
|
|
||||||
|
m_flags.set(
|
||||||
|
DxvkContextFlag::CpDirtyDescriptorSet,
|
||||||
|
DxvkContextFlag::CpDirtyDescriptorOffsets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateComputeShaderDescriptors() {
|
void DxvkContext::updateComputeShaderDescriptors() {
|
||||||
if (m_flags.test(DxvkContextFlag::CpDirtyResources)) {
|
if (m_state.cp.pipeline == nullptr)
|
||||||
m_flags.clr(DxvkContextFlag::CpDirtyResources);
|
return;
|
||||||
|
|
||||||
if (m_state.cp.pipeline != nullptr) {
|
if (m_flags.test(DxvkContextFlag::CpDirtyDescriptorSet)) {
|
||||||
this->updateShaderDescriptors(
|
m_cpSet = this->updateShaderDescriptors(
|
||||||
VK_PIPELINE_BIND_POINT_COMPUTE,
|
VK_PIPELINE_BIND_POINT_COMPUTE,
|
||||||
m_state.cp.state.bsBindingState,
|
m_state.cp.state.bsBindingState,
|
||||||
m_state.cp.pipeline->layout());
|
m_state.cp.pipeline->layout());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_flags.test(DxvkContextFlag::CpDirtyDescriptorOffsets)) {
|
||||||
|
this->updateShaderDescriptorSetBinding(
|
||||||
|
VK_PIPELINE_BIND_POINT_COMPUTE, m_cpSet,
|
||||||
|
m_state.cp.pipeline->layout());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flags.clr(
|
||||||
|
DxvkContextFlag::CpDirtyDescriptorOffsets,
|
||||||
|
DxvkContextFlag::CpDirtyDescriptorSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateGraphicsShaderResources() {
|
void DxvkContext::updateGraphicsShaderResources() {
|
||||||
if (m_flags.test(DxvkContextFlag::GpDirtyResources)) {
|
if (m_state.gp.pipeline == nullptr)
|
||||||
if (m_state.gp.pipeline != nullptr) {
|
return;
|
||||||
this->updateShaderResources(
|
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
if ((m_flags.test(DxvkContextFlag::GpDirtyResources))
|
||||||
m_state.gp.pipeline->layout());
|
|| (m_flags.test(DxvkContextFlag::GpDirtyDescriptorOffsets)
|
||||||
}
|
&& m_state.gp.pipeline->layout()->hasStaticBufferBindings())) {
|
||||||
|
m_flags.clr(DxvkContextFlag::GpDirtyResources);
|
||||||
|
|
||||||
|
this->updateShaderResources(
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
|
m_state.gp.pipeline->layout());
|
||||||
|
|
||||||
|
m_flags.set(
|
||||||
|
DxvkContextFlag::GpDirtyDescriptorSet,
|
||||||
|
DxvkContextFlag::GpDirtyDescriptorOffsets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateGraphicsShaderDescriptors() {
|
void DxvkContext::updateGraphicsShaderDescriptors() {
|
||||||
if (m_flags.test(DxvkContextFlag::GpDirtyResources)) {
|
if (m_state.gp.pipeline == nullptr)
|
||||||
m_flags.clr(DxvkContextFlag::GpDirtyResources);
|
return;
|
||||||
|
|
||||||
if (m_state.gp.pipeline != nullptr) {
|
if (m_flags.test(DxvkContextFlag::GpDirtyDescriptorSet)) {
|
||||||
this->updateShaderDescriptors(
|
m_gpSet = this->updateShaderDescriptors(
|
||||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||||
m_state.gp.state.bsBindingState,
|
m_state.gp.state.bsBindingState,
|
||||||
m_state.gp.pipeline->layout());
|
m_state.gp.pipeline->layout());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_flags.test(DxvkContextFlag::GpDirtyDescriptorOffsets)) {
|
||||||
|
this->updateShaderDescriptorSetBinding(
|
||||||
|
VK_PIPELINE_BIND_POINT_GRAPHICS, m_gpSet,
|
||||||
|
m_state.gp.pipeline->layout());
|
||||||
|
}
|
||||||
|
|
||||||
|
m_flags.clr(
|
||||||
|
DxvkContextFlag::GpDirtyDescriptorOffsets,
|
||||||
|
DxvkContextFlag::GpDirtyDescriptorSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateShaderResources(
|
void DxvkContext::updateShaderResources(
|
||||||
VkPipelineBindPoint bindPoint,
|
VkPipelineBindPoint bindPoint,
|
||||||
const Rc<DxvkPipelineLayout>& layout) {
|
const DxvkPipelineLayout* layout) {
|
||||||
DxvkBindingState& bindingState =
|
DxvkBindingState& bindingState =
|
||||||
bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||||
? m_state.gp.state.bsBindingState
|
? m_state.gp.state.bsBindingState
|
||||||
@ -1917,11 +1965,27 @@ namespace dxvk {
|
|||||||
m_descInfos[i].buffer = m_device->dummyBufferDescriptor();
|
m_descInfos[i].buffer = m_device->dummyBufferDescriptor();
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||||
|
if (res.bufferSlice.defined()) {
|
||||||
|
updatePipelineState |= bindingState.setBound(i);
|
||||||
|
|
||||||
|
auto physicalSlice = res.bufferSlice.physicalSlice();
|
||||||
|
m_descInfos[i].buffer.buffer = physicalSlice.handle();
|
||||||
|
m_descInfos[i].buffer.offset = 0; /* dynamic */
|
||||||
|
m_descInfos[i].buffer.range = physicalSlice.length();
|
||||||
|
|
||||||
|
m_cmd->trackResource(physicalSlice.resource());
|
||||||
|
} else {
|
||||||
|
updatePipelineState |= bindingState.setUnbound(i);
|
||||||
|
m_descInfos[i].buffer = m_device->dummyBufferDescriptor();
|
||||||
|
} break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Logger::err(str::format("DxvkContext: Unhandled descriptor type: ", binding.type));
|
Logger::err(str::format("DxvkContext: Unhandled descriptor type: ", binding.type));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updatePipelineState) {
|
if (updatePipelineState) {
|
||||||
m_flags.set(bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
m_flags.set(bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS
|
||||||
? DxvkContextFlag::GpDirtyPipelineState
|
? DxvkContextFlag::GpDirtyPipelineState
|
||||||
@ -1930,21 +1994,43 @@ namespace dxvk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void DxvkContext::updateShaderDescriptors(
|
VkDescriptorSet DxvkContext::updateShaderDescriptors(
|
||||||
VkPipelineBindPoint bindPoint,
|
VkPipelineBindPoint bindPoint,
|
||||||
const DxvkBindingState& bindingState,
|
const DxvkBindingState& bindingState,
|
||||||
const Rc<DxvkPipelineLayout>& layout) {
|
const DxvkPipelineLayout* layout) {
|
||||||
|
VkDescriptorSet descriptorSet = VK_NULL_HANDLE;
|
||||||
|
|
||||||
if (layout->bindingCount() != 0) {
|
if (layout->bindingCount() != 0) {
|
||||||
const VkDescriptorSet dset =
|
descriptorSet = m_cmd->allocateDescriptorSet(
|
||||||
m_cmd->allocateDescriptorSet(
|
layout->descriptorSetLayout());
|
||||||
layout->descriptorSetLayout());
|
|
||||||
|
|
||||||
m_cmd->updateDescriptorSetWithTemplate(
|
m_cmd->updateDescriptorSetWithTemplate(
|
||||||
dset, layout->descriptorTemplate(),
|
descriptorSet, layout->descriptorTemplate(),
|
||||||
m_descInfos.data());
|
m_descInfos.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
return descriptorSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void DxvkContext::updateShaderDescriptorSetBinding(
|
||||||
|
VkPipelineBindPoint bindPoint,
|
||||||
|
VkDescriptorSet set,
|
||||||
|
const DxvkPipelineLayout* layout) {
|
||||||
|
if (set != VK_NULL_HANDLE) {
|
||||||
|
for (uint32_t i = 0; i < layout->dynamicBindingCount(); i++) {
|
||||||
|
const auto& binding = layout->dynamicBinding(i);
|
||||||
|
const auto& res = m_rc[binding.slot];
|
||||||
|
|
||||||
|
m_descOffsets[i] = res.bufferSlice.defined()
|
||||||
|
? res.bufferSlice.physicalSlice().offset()
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
m_cmd->cmdBindDescriptorSet(bindPoint,
|
m_cmd->cmdBindDescriptorSet(bindPoint,
|
||||||
layout->pipelineLayout(), dset);
|
layout->pipelineLayout(), set,
|
||||||
|
layout->dynamicBindingCount(),
|
||||||
|
m_descOffsets.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2128,10 +2214,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
switch (binding.type) {
|
switch (binding.type) {
|
||||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||||
access.set(DxvkAccess::Write);
|
access.set(DxvkAccess::Write);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||||
requiresBarrier = m_barriers.isBufferDirty(
|
requiresBarrier = m_barriers.isBufferDirty(
|
||||||
slot.bufferSlice.physicalSlice(), access);
|
slot.bufferSlice.physicalSlice(), access);
|
||||||
break;
|
break;
|
||||||
@ -2180,10 +2268,12 @@ namespace dxvk {
|
|||||||
|
|
||||||
switch (binding.type) {
|
switch (binding.type) {
|
||||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||||
|
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||||
access |= VK_ACCESS_SHADER_WRITE_BIT;
|
access |= VK_ACCESS_SHADER_WRITE_BIT;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
|
|
||||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||||
|
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||||
m_barriers.accessBuffer(
|
m_barriers.accessBuffer(
|
||||||
slot.bufferSlice.physicalSlice(),
|
slot.bufferSlice.physicalSlice(),
|
||||||
stages, access,
|
stages, access,
|
||||||
|
@ -636,11 +636,15 @@ namespace dxvk {
|
|||||||
|
|
||||||
VkPipeline m_gpActivePipeline = VK_NULL_HANDLE;
|
VkPipeline m_gpActivePipeline = VK_NULL_HANDLE;
|
||||||
VkPipeline m_cpActivePipeline = VK_NULL_HANDLE;
|
VkPipeline m_cpActivePipeline = VK_NULL_HANDLE;
|
||||||
|
|
||||||
|
VkDescriptorSet m_gpSet = VK_NULL_HANDLE;
|
||||||
|
VkDescriptorSet m_cpSet = VK_NULL_HANDLE;
|
||||||
|
|
||||||
std::vector<DxvkQueryRevision> m_activeQueries;
|
std::vector<DxvkQueryRevision> m_activeQueries;
|
||||||
|
|
||||||
std::array<DxvkShaderResourceSlot, MaxNumResourceSlots> m_rc;
|
std::array<DxvkShaderResourceSlot, MaxNumResourceSlots> m_rc;
|
||||||
std::array<DxvkDescriptorInfo, MaxNumActiveBindings> m_descInfos;
|
std::array<DxvkDescriptorInfo, MaxNumActiveBindings> m_descInfos;
|
||||||
|
std::array<uint32_t, MaxNumActiveBindings> m_descOffsets;
|
||||||
|
|
||||||
void startRenderPass();
|
void startRenderPass();
|
||||||
void spillRenderPass();
|
void spillRenderPass();
|
||||||
@ -673,13 +677,18 @@ namespace dxvk {
|
|||||||
|
|
||||||
void updateShaderResources(
|
void updateShaderResources(
|
||||||
VkPipelineBindPoint bindPoint,
|
VkPipelineBindPoint bindPoint,
|
||||||
const Rc<DxvkPipelineLayout>& layout);
|
const DxvkPipelineLayout* layout);
|
||||||
|
|
||||||
void updateShaderDescriptors(
|
VkDescriptorSet updateShaderDescriptors(
|
||||||
VkPipelineBindPoint bindPoint,
|
VkPipelineBindPoint bindPoint,
|
||||||
const DxvkBindingState& bindingState,
|
const DxvkBindingState& bindingState,
|
||||||
const Rc<DxvkPipelineLayout>& layout);
|
const DxvkPipelineLayout* layout);
|
||||||
|
|
||||||
|
void updateShaderDescriptorSetBinding(
|
||||||
|
VkPipelineBindPoint bindPoint,
|
||||||
|
VkDescriptorSet set,
|
||||||
|
const DxvkPipelineLayout* layout);
|
||||||
|
|
||||||
void updateFramebuffer();
|
void updateFramebuffer();
|
||||||
|
|
||||||
void updateIndexBufferBinding();
|
void updateIndexBufferBinding();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user