1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-06 13:54:14 +01:00

[dxvk] Enable the use of VK_KHR_descriptor_update_template

Reduces the CPU overhead of descriptor set updates, which usually
happen once per draw call. Gains seem to be minor in most games,
some outliers show significantly better performance (i.e. Tomb Raider).
This commit is contained in:
Philip Rebohle 2018-03-17 23:50:03 +01:00
parent 0f800c6c51
commit 94aa650f3e
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
8 changed files with 83 additions and 60 deletions

View File

@ -134,11 +134,12 @@ namespace dxvk {
} }
void updateDescriptorSet( void updateDescriptorSetWithTemplate(
uint32_t descriptorCount, VkDescriptorSet descriptorSet,
const VkWriteDescriptorSet* descriptorWrites) { VkDescriptorUpdateTemplateKHR descriptorTemplate,
m_vkd->vkUpdateDescriptorSets(m_vkd->device(), const void* data) {
descriptorCount, descriptorWrites, 0, nullptr); m_vkd->vkUpdateDescriptorSetWithTemplateKHR(m_vkd->device(),
descriptorSet, descriptorTemplate, data);
} }

View File

@ -26,7 +26,8 @@ namespace dxvk {
m_layout = new DxvkPipelineLayout(m_vkd, m_layout = new DxvkPipelineLayout(m_vkd,
slotMapping.bindingCount(), slotMapping.bindingCount(),
slotMapping.bindingInfos()); slotMapping.bindingInfos(),
VK_PIPELINE_BIND_POINT_COMPUTE);
m_cs = cs->createShaderModule(m_vkd, slotMapping); m_cs = cs->createShaderModule(m_vkd, slotMapping);
} }

View File

@ -7,20 +7,7 @@
namespace dxvk { namespace dxvk {
DxvkContext::DxvkContext(const Rc<DxvkDevice>& device) DxvkContext::DxvkContext(const Rc<DxvkDevice>& device)
: m_device(device) { : m_device(device) { }
for (uint32_t i = 0; i < m_descWrites.size(); i++) {
m_descWrites[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
m_descWrites[i].pNext = nullptr;
m_descWrites[i].dstSet = VK_NULL_HANDLE;
m_descWrites[i].dstBinding = i;
m_descWrites[i].dstArrayElement = 0;
m_descWrites[i].descriptorCount = 1;
m_descWrites[i].descriptorType = VkDescriptorType(0);
m_descWrites[i].pImageInfo = &m_descInfos[i].image;
m_descWrites[i].pBufferInfo = &m_descInfos[i].buffer;
m_descWrites[i].pTexelBufferView = &m_descInfos[i].texelBuffer;
}
}
DxvkContext::~DxvkContext() { DxvkContext::~DxvkContext() {
@ -1620,13 +1607,10 @@ namespace dxvk {
m_cmd->allocateDescriptorSet( m_cmd->allocateDescriptorSet(
layout->descriptorSetLayout()); layout->descriptorSetLayout());
for (uint32_t i = 0; i < layout->bindingCount(); i++) { m_cmd->updateDescriptorSetWithTemplate(
m_descWrites[i].dstSet = dset; dset, layout->descriptorTemplate(),
m_descWrites[i].descriptorType = layout->binding(i).type; m_descInfos.data());
}
m_cmd->updateDescriptorSet(
layout->bindingCount(), m_descWrites.data());
m_cmd->cmdBindDescriptorSet(bindPoint, m_cmd->cmdBindDescriptorSet(bindPoint,
layout->pipelineLayout(), dset); layout->pipelineLayout(), dset);
} }

View File

@ -578,7 +578,6 @@ namespace dxvk {
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<VkWriteDescriptorSet, MaxNumActiveBindings> m_descWrites;
void renderPassBegin(); void renderPassBegin();
void renderPassEnd(); void renderPassEnd();

View File

@ -129,11 +129,12 @@ namespace dxvk {
* used by DXVK if supported by the implementation. * used by DXVK if supported by the implementation.
*/ */
struct DxvkDeviceExtensions : public DxvkExtensionList { struct DxvkDeviceExtensions : public DxvkExtensionList {
DxvkExtension amdRasterizationOrder = { this, VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, DxvkExtensionType::Optional }; DxvkExtension amdRasterizationOrder = { this, VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME, DxvkExtensionType::Optional };
DxvkExtension khrMaintenance1 = { this, VK_KHR_MAINTENANCE1_EXTENSION_NAME, DxvkExtensionType::Required }; DxvkExtension khrDescriptorUpdateTemplate = { this, VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME, DxvkExtensionType::Required };
DxvkExtension khrMaintenance2 = { this, VK_KHR_MAINTENANCE2_EXTENSION_NAME, DxvkExtensionType::Desired }; DxvkExtension khrMaintenance1 = { this, VK_KHR_MAINTENANCE1_EXTENSION_NAME, DxvkExtensionType::Required };
DxvkExtension khrShaderDrawParameters = { this, VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, DxvkExtensionType::Required }; DxvkExtension khrMaintenance2 = { this, VK_KHR_MAINTENANCE2_EXTENSION_NAME, DxvkExtensionType::Desired };
DxvkExtension khrSwapchain = { this, VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtensionType::Required }; DxvkExtension khrShaderDrawParameters = { this, VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME, DxvkExtensionType::Required };
DxvkExtension khrSwapchain = { this, VK_KHR_SWAPCHAIN_EXTENSION_NAME, DxvkExtensionType::Required };
}; };
} }

View File

@ -52,7 +52,8 @@ namespace dxvk {
m_layout = new DxvkPipelineLayout(m_vkd, m_layout = new DxvkPipelineLayout(m_vkd,
slotMapping.bindingCount(), slotMapping.bindingCount(),
slotMapping.bindingInfos()); slotMapping.bindingInfos(),
VK_PIPELINE_BIND_POINT_GRAPHICS);
if (vs != nullptr) m_vs = vs ->createShaderModule(m_vkd, slotMapping); if (vs != nullptr) m_vs = vs ->createShaderModule(m_vkd, slotMapping);
if (tcs != nullptr) m_tcs = tcs->createShaderModule(m_vkd, slotMapping); if (tcs != nullptr) m_tcs = tcs->createShaderModule(m_vkd, slotMapping);

View File

@ -1,5 +1,6 @@
#include <cstring> #include <cstring>
#include "dxvk_descriptor.h"
#include "dxvk_pipelayout.h" #include "dxvk_pipelayout.h"
namespace dxvk { namespace dxvk {
@ -44,26 +45,32 @@ namespace dxvk {
DxvkPipelineLayout::DxvkPipelineLayout( DxvkPipelineLayout::DxvkPipelineLayout(
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
uint32_t bindingCount, uint32_t bindingCount,
const DxvkDescriptorSlot* bindingInfos) const DxvkDescriptorSlot* bindingInfos,
: m_vkd(vkd) { VkPipelineBindPoint pipelineBindPoint)
: m_vkd(vkd), m_bindingSlots(bindingCount) {
m_bindingSlots.resize(bindingCount);
for (uint32_t i = 0; i < bindingCount; i++) for (uint32_t i = 0; i < bindingCount; i++)
m_bindingSlots[i] = bindingInfos[i]; m_bindingSlots[i] = bindingInfos[i];
std::vector<VkDescriptorSetLayoutBinding> bindings; std::vector<VkDescriptorSetLayoutBinding> bindings(bindingCount);
std::vector<VkDescriptorUpdateTemplateEntryKHR> tEntries(bindingCount);
for (uint32_t i = 0; i < bindingCount; i++) { for (uint32_t i = 0; i < bindingCount; i++) {
VkDescriptorSetLayoutBinding binding; bindings[i].binding = i;
binding.binding = i; bindings[i].descriptorType = bindingInfos[i].type;
binding.descriptorType = bindingInfos[i].type; bindings[i].descriptorCount = 1;
binding.descriptorCount = 1; bindings[i].stageFlags = bindingInfos[i].stages;
binding.stageFlags = bindingInfos[i].stages; bindings[i].pImmutableSamplers = nullptr;
binding.pImmutableSamplers = nullptr;
bindings.push_back(binding); tEntries[i].dstBinding = i;
tEntries[i].dstArrayElement = 0;
tEntries[i].descriptorCount = 1;
tEntries[i].descriptorType = bindingInfos[i].type;
tEntries[i].offset = sizeof(DxvkDescriptorInfo) * i;
tEntries[i].stride = 0;
} }
// Create descriptor set layout
VkDescriptorSetLayoutCreateInfo dsetInfo; VkDescriptorSetLayoutCreateInfo dsetInfo;
dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
dsetInfo.pNext = nullptr; dsetInfo.pNext = nullptr;
@ -75,6 +82,7 @@ namespace dxvk {
&dsetInfo, nullptr, &m_descriptorSetLayout) != VK_SUCCESS) &dsetInfo, nullptr, &m_descriptorSetLayout) != VK_SUCCESS)
throw DxvkError("DxvkPipelineLayout: Failed to create descriptor set layout"); throw DxvkError("DxvkPipelineLayout: Failed to create descriptor set layout");
// Create pipeline layout
VkPipelineLayoutCreateInfo pipeInfo; VkPipelineLayoutCreateInfo pipeInfo;
pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeInfo.pNext = nullptr; pipeInfo.pNext = nullptr;
@ -85,24 +93,42 @@ namespace dxvk {
pipeInfo.pPushConstantRanges = nullptr; pipeInfo.pPushConstantRanges = nullptr;
if (m_vkd->vkCreatePipelineLayout(m_vkd->device(), if (m_vkd->vkCreatePipelineLayout(m_vkd->device(),
&pipeInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) { &pipeInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
m_vkd->vkDestroyDescriptorSetLayout( m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr);
m_vkd->device(), m_descriptorSetLayout, nullptr);
throw DxvkError("DxvkPipelineLayout: Failed to create pipeline layout"); throw DxvkError("DxvkPipelineLayout: Failed to create pipeline layout");
} }
// Create descriptor update template
VkDescriptorUpdateTemplateCreateInfoKHR templateInfo;
templateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO_KHR;
templateInfo.pNext = nullptr;
templateInfo.flags = 0;
templateInfo.descriptorUpdateEntryCount = tEntries.size();
templateInfo.pDescriptorUpdateEntries = tEntries.data();
templateInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET_KHR;
templateInfo.descriptorSetLayout = m_descriptorSetLayout;
templateInfo.pipelineBindPoint = pipelineBindPoint;
templateInfo.pipelineLayout = m_pipelineLayout;
templateInfo.set = 0;
if (m_vkd->vkCreateDescriptorUpdateTemplateKHR(m_vkd->device(),
&templateInfo, nullptr, &m_descriptorTemplate) != VK_SUCCESS) {
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr);
m_vkd->vkDestroyPipelineLayout(m_vkd->device(), m_pipelineLayout, nullptr);
throw DxvkError("DxvkPipelineLayout: Failed to create descriptor update template");
}
} }
DxvkPipelineLayout::~DxvkPipelineLayout() { DxvkPipelineLayout::~DxvkPipelineLayout() {
if (m_pipelineLayout != VK_NULL_HANDLE) { m_vkd->vkDestroyDescriptorUpdateTemplateKHR(
m_vkd->vkDestroyPipelineLayout( m_vkd->device(), m_descriptorTemplate, nullptr);
m_vkd->device(), m_pipelineLayout, nullptr);
}
if (m_descriptorSetLayout != VK_NULL_HANDLE) { m_vkd->vkDestroyPipelineLayout(
m_vkd->vkDestroyDescriptorSetLayout( m_vkd->device(), m_pipelineLayout, nullptr);
m_vkd->device(), m_descriptorSetLayout, nullptr);
} m_vkd->vkDestroyDescriptorSetLayout(
m_vkd->device(), m_descriptorSetLayout, nullptr);
} }
} }

View File

@ -111,7 +111,8 @@ namespace dxvk {
DxvkPipelineLayout( DxvkPipelineLayout(
const Rc<vk::DeviceFn>& vkd, const Rc<vk::DeviceFn>& vkd,
uint32_t bindingCount, uint32_t bindingCount,
const DxvkDescriptorSlot* bindingInfos); const DxvkDescriptorSlot* bindingInfos,
VkPipelineBindPoint pipelineBindPoint);
~DxvkPipelineLayout(); ~DxvkPipelineLayout();
@ -157,12 +158,21 @@ namespace dxvk {
return m_pipelineLayout; return m_pipelineLayout;
} }
/**
* \brief Descriptor update template
* \returns Descriptor update template
*/
VkDescriptorUpdateTemplateKHR descriptorTemplate() const {
return m_descriptorTemplate;
}
private: private:
Rc<vk::DeviceFn> m_vkd; Rc<vk::DeviceFn> m_vkd;
VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE; VkDescriptorSetLayout m_descriptorSetLayout = VK_NULL_HANDLE;
VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
VkDescriptorUpdateTemplateKHR m_descriptorTemplate = VK_NULL_HANDLE;
std::vector<DxvkDescriptorSlot> m_bindingSlots; std::vector<DxvkDescriptorSlot> m_bindingSlots;