summaryrefslogtreecommitdiffstats
path: root/src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_pipelayout.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_pipelayout.cpp')
-rw-r--r--src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_pipelayout.cpp197
1 files changed, 197 insertions, 0 deletions
diff --git a/src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_pipelayout.cpp b/src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_pipelayout.cpp
new file mode 100644
index 00000000..72b319a1
--- /dev/null
+++ b/src/libs/dxvk-native-1.9.2a/src/dxvk/dxvk_pipelayout.cpp
@@ -0,0 +1,197 @@
+#include <cstring>
+
+#include "dxvk_descriptor.h"
+#include "dxvk_limits.h"
+#include "dxvk_pipelayout.h"
+
+namespace dxvk {
+
+ DxvkDescriptorSlotMapping:: DxvkDescriptorSlotMapping() { }
+ DxvkDescriptorSlotMapping::~DxvkDescriptorSlotMapping() { }
+
+
+ void DxvkDescriptorSlotMapping::defineSlot(
+ VkShaderStageFlagBits stage,
+ const DxvkResourceSlot& desc) {
+ uint32_t bindingId = this->getBindingId(desc.slot);
+
+ if (bindingId != InvalidBinding) {
+ m_descriptorSlots[bindingId].stages |= stage;
+ m_descriptorSlots[bindingId].access |= desc.access;
+ } else {
+ DxvkDescriptorSlot slotInfo;
+ slotInfo.slot = desc.slot;
+ slotInfo.type = desc.type;
+ slotInfo.view = desc.view;
+ slotInfo.stages = stage;
+ slotInfo.access = desc.access;
+ m_descriptorSlots.push_back(slotInfo);
+ }
+ }
+
+
+ void DxvkDescriptorSlotMapping::definePushConstRange(
+ VkShaderStageFlagBits stage,
+ uint32_t offset,
+ uint32_t size) {
+ m_pushConstRange.stageFlags |= stage;
+ m_pushConstRange.size = std::max(
+ m_pushConstRange.size, offset + size);
+ }
+
+
+ uint32_t DxvkDescriptorSlotMapping::getBindingId(uint32_t slot) const {
+ // This won't win a performance competition, but the number
+ // of bindings used by a shader is usually much smaller than
+ // the number of resource slots available to the system.
+ for (uint32_t i = 0; i < m_descriptorSlots.size(); i++) {
+ if (m_descriptorSlots[i].slot == slot)
+ return i;
+ }
+
+ return InvalidBinding;
+ }
+
+
+ void DxvkDescriptorSlotMapping::makeDescriptorsDynamic(
+ uint32_t uniformBuffers,
+ uint32_t storageBuffers) {
+ if (this->countDescriptors(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) <= uniformBuffers)
+ this->replaceDescriptors(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC);
+ }
+
+
+ uint32_t DxvkDescriptorSlotMapping::countDescriptors(
+ VkDescriptorType type) const {
+ uint32_t count = 0;
+
+ for (const auto& slot : m_descriptorSlots)
+ count += slot.type == type ? 1 : 0;
+
+ return count;
+ }
+
+
+ void DxvkDescriptorSlotMapping::replaceDescriptors(
+ VkDescriptorType oldType,
+ VkDescriptorType newType) {
+ for (auto& slot : m_descriptorSlots) {
+ if (slot.type == oldType)
+ slot.type = newType;
+ }
+ }
+
+
+ DxvkPipelineLayout::DxvkPipelineLayout(
+ const Rc<vk::DeviceFn>& vkd,
+ const DxvkDescriptorSlotMapping& slotMapping,
+ VkPipelineBindPoint pipelineBindPoint)
+ : m_vkd (vkd),
+ m_pushConstRange(slotMapping.pushConstRange()),
+ m_bindingSlots (slotMapping.bindingCount()) {
+
+ auto bindingCount = slotMapping.bindingCount();
+ auto bindingInfos = slotMapping.bindingInfos();
+
+ if (bindingCount > MaxNumActiveBindings)
+ throw DxvkError(str::format("Too many active bindings in pipeline layout (", bindingCount, ")"));
+
+ for (uint32_t i = 0; i < bindingCount; i++)
+ m_bindingSlots[i] = bindingInfos[i];
+
+ std::vector<VkDescriptorSetLayoutBinding> bindings(bindingCount);
+ std::vector<VkDescriptorUpdateTemplateEntry> tEntries(bindingCount);
+
+ for (uint32_t i = 0; i < bindingCount; i++) {
+ bindings[i].binding = i;
+ bindings[i].descriptorType = bindingInfos[i].type;
+ bindings[i].descriptorCount = 1;
+ bindings[i].stageFlags = bindingInfos[i].stages;
+ bindings[i].pImmutableSamplers = nullptr;
+
+ 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;
+
+ if (bindingInfos[i].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)
+ m_dynamicSlots.push_back(i);
+
+ m_descriptorTypes.set(bindingInfos[i].type);
+ }
+
+ // Create descriptor set layout. We do not need to
+ // create one if there are no active resource bindings.
+ if (bindingCount > 0) {
+ VkDescriptorSetLayoutCreateInfo dsetInfo;
+ dsetInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
+ dsetInfo.pNext = nullptr;
+ dsetInfo.flags = 0;
+ dsetInfo.bindingCount = bindings.size();
+ dsetInfo.pBindings = bindings.data();
+
+ if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(),
+ &dsetInfo, nullptr, &m_descriptorSetLayout) != VK_SUCCESS)
+ throw DxvkError("DxvkPipelineLayout: Failed to create descriptor set layout");
+ }
+
+ // Create pipeline layout with the given descriptor set layout
+ VkPipelineLayoutCreateInfo pipeInfo;
+ pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipeInfo.pNext = nullptr;
+ pipeInfo.flags = 0;
+ pipeInfo.setLayoutCount = bindingCount > 0 ? 1 : 0;
+ pipeInfo.pSetLayouts = &m_descriptorSetLayout;
+ pipeInfo.pushConstantRangeCount = 0;
+ pipeInfo.pPushConstantRanges = nullptr;
+
+ if (m_pushConstRange.size) {
+ pipeInfo.pushConstantRangeCount = 1;
+ pipeInfo.pPushConstantRanges = &m_pushConstRange;
+ }
+
+ if (m_vkd->vkCreatePipelineLayout(m_vkd->device(),
+ &pipeInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
+ m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr);
+ throw DxvkError("DxvkPipelineLayout: Failed to create pipeline layout");
+ }
+
+ // Create descriptor update template. If there are no active
+ // resource bindings, there won't be any descriptors to update.
+ if (bindingCount > 0) {
+ VkDescriptorUpdateTemplateCreateInfo templateInfo;
+ templateInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_UPDATE_TEMPLATE_CREATE_INFO;
+ templateInfo.pNext = nullptr;
+ templateInfo.flags = 0;
+ templateInfo.descriptorUpdateEntryCount = tEntries.size();
+ templateInfo.pDescriptorUpdateEntries = tEntries.data();
+ templateInfo.templateType = VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET;
+ templateInfo.descriptorSetLayout = m_descriptorSetLayout;
+ templateInfo.pipelineBindPoint = pipelineBindPoint;
+ templateInfo.pipelineLayout = m_pipelineLayout;
+ templateInfo.set = 0;
+
+ if (m_vkd->vkCreateDescriptorUpdateTemplate(
+ 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() {
+ m_vkd->vkDestroyDescriptorUpdateTemplate(
+ m_vkd->device(), m_descriptorTemplate, nullptr);
+
+ m_vkd->vkDestroyPipelineLayout(
+ m_vkd->device(), m_pipelineLayout, nullptr);
+
+ m_vkd->vkDestroyDescriptorSetLayout(
+ m_vkd->device(), m_descriptorSetLayout, nullptr);
+ }
+
+} \ No newline at end of file