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:
parent
0f800c6c51
commit
94aa650f3e
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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 };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -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);
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -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;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user