2017-12-03 20:23:26 +01:00
|
|
|
#include <cstring>
|
|
|
|
|
2018-03-17 23:50:03 +01:00
|
|
|
#include "dxvk_descriptor.h"
|
2017-12-07 09:38:31 +01:00
|
|
|
#include "dxvk_pipelayout.h"
|
2017-12-03 00:40:58 +01:00
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
2017-12-07 09:38:31 +01:00
|
|
|
DxvkDescriptorSlotMapping:: DxvkDescriptorSlotMapping() { }
|
|
|
|
DxvkDescriptorSlotMapping::~DxvkDescriptorSlotMapping() { }
|
|
|
|
|
|
|
|
|
|
|
|
void DxvkDescriptorSlotMapping::defineSlot(
|
2018-12-13 14:40:38 +01:00
|
|
|
VkShaderStageFlagBits stage,
|
2019-06-23 15:49:29 +02:00
|
|
|
const DxvkResourceSlot& desc) {
|
|
|
|
uint32_t bindingId = this->getBindingId(desc.slot);
|
2017-12-07 09:38:31 +01:00
|
|
|
|
|
|
|
if (bindingId != InvalidBinding) {
|
2017-12-20 12:13:08 +01:00
|
|
|
m_descriptorSlots[bindingId].stages |= stage;
|
2019-06-23 15:49:29 +02:00
|
|
|
m_descriptorSlots[bindingId].access |= desc.access;
|
2017-12-07 09:38:31 +01:00
|
|
|
} else {
|
|
|
|
DxvkDescriptorSlot slotInfo;
|
2019-06-23 15:49:29 +02:00
|
|
|
slotInfo.slot = desc.slot;
|
|
|
|
slotInfo.type = desc.type;
|
|
|
|
slotInfo.view = desc.view;
|
2017-12-07 09:38:31 +01:00
|
|
|
slotInfo.stages = stage;
|
2019-06-23 15:49:29 +02:00
|
|
|
slotInfo.access = desc.access;
|
2017-12-07 09:38:31 +01:00
|
|
|
m_descriptorSlots.push_back(slotInfo);
|
|
|
|
}
|
|
|
|
}
|
2019-05-07 20:27:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
2017-12-07 09:38:31 +01:00
|
|
|
|
|
|
|
|
2017-12-08 22:30:41 +01:00
|
|
|
uint32_t DxvkDescriptorSlotMapping::getBindingId(uint32_t slot) const {
|
2017-12-07 09:38:31 +01:00
|
|
|
// 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++) {
|
2017-12-20 12:13:08 +01:00
|
|
|
if (m_descriptorSlots[i].slot == slot)
|
2017-12-07 09:38:31 +01:00
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return InvalidBinding;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-06-22 00:29:04 +02:00
|
|
|
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);
|
|
|
|
|
|
|
|
if (this->countDescriptors(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) <= storageBuffers)
|
|
|
|
this->replaceDescriptors(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-23 17:40:36 +01:00
|
|
|
DxvkPipelineLayout::DxvkPipelineLayout(
|
2017-12-03 20:23:26 +01:00
|
|
|
const Rc<vk::DeviceFn>& vkd,
|
2019-05-07 20:25:50 +02:00
|
|
|
const DxvkDescriptorSlotMapping& slotMapping,
|
2018-03-17 23:50:03 +01:00
|
|
|
VkPipelineBindPoint pipelineBindPoint)
|
2019-05-07 20:27:26 +02:00
|
|
|
: m_vkd (vkd),
|
|
|
|
m_pushConstRange(slotMapping.pushConstRange()),
|
|
|
|
m_bindingSlots (slotMapping.bindingCount()) {
|
2019-05-07 20:25:50 +02:00
|
|
|
|
|
|
|
auto bindingCount = slotMapping.bindingCount();
|
|
|
|
auto bindingInfos = slotMapping.bindingInfos();
|
2018-01-10 13:44:04 +01:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < bindingCount; i++)
|
|
|
|
m_bindingSlots[i] = bindingInfos[i];
|
2017-12-03 20:23:26 +01:00
|
|
|
|
2018-03-17 23:50:03 +01:00
|
|
|
std::vector<VkDescriptorSetLayoutBinding> bindings(bindingCount);
|
|
|
|
std::vector<VkDescriptorUpdateTemplateEntryKHR> tEntries(bindingCount);
|
2017-12-03 20:23:26 +01:00
|
|
|
|
2017-12-03 00:40:58 +01:00
|
|
|
for (uint32_t i = 0; i < bindingCount; i++) {
|
2018-03-17 23:50:03 +01:00
|
|
|
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;
|
2018-06-22 00:29:04 +02:00
|
|
|
|
|
|
|
if (bindingInfos[i].type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC
|
|
|
|
|| bindingInfos[i].type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)
|
|
|
|
m_dynamicSlots.push_back(i);
|
|
|
|
|
|
|
|
m_descriptorTypes.set(bindingInfos[i].type);
|
2017-12-03 00:40:58 +01:00
|
|
|
}
|
|
|
|
|
2018-03-26 23:13:33 +02:00
|
|
|
// 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");
|
|
|
|
}
|
2017-12-03 00:40:58 +01:00
|
|
|
|
2018-03-26 23:13:33 +02:00
|
|
|
// Create pipeline layout with the given descriptor set layout
|
2017-12-03 00:40:58 +01:00
|
|
|
VkPipelineLayoutCreateInfo pipeInfo;
|
|
|
|
pipeInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
|
|
|
pipeInfo.pNext = nullptr;
|
|
|
|
pipeInfo.flags = 0;
|
2018-03-26 23:13:33 +02:00
|
|
|
pipeInfo.setLayoutCount = bindingCount > 0 ? 1 : 0;
|
2017-12-03 00:40:58 +01:00
|
|
|
pipeInfo.pSetLayouts = &m_descriptorSetLayout;
|
|
|
|
pipeInfo.pushConstantRangeCount = 0;
|
|
|
|
pipeInfo.pPushConstantRanges = nullptr;
|
2019-05-07 20:27:26 +02:00
|
|
|
|
|
|
|
if (m_pushConstRange.size) {
|
|
|
|
pipeInfo.pushConstantRangeCount = 1;
|
|
|
|
pipeInfo.pPushConstantRanges = &m_pushConstRange;
|
|
|
|
}
|
2017-12-03 00:40:58 +01:00
|
|
|
|
|
|
|
if (m_vkd->vkCreatePipelineLayout(m_vkd->device(),
|
2018-03-17 23:50:03 +01:00
|
|
|
&pipeInfo, nullptr, &m_pipelineLayout) != VK_SUCCESS) {
|
|
|
|
m_vkd->vkDestroyDescriptorSetLayout(m_vkd->device(), m_descriptorSetLayout, nullptr);
|
2018-01-23 17:40:36 +01:00
|
|
|
throw DxvkError("DxvkPipelineLayout: Failed to create pipeline layout");
|
2017-12-03 00:40:58 +01:00
|
|
|
}
|
2018-03-17 23:50:03 +01:00
|
|
|
|
2018-03-26 23:13:33 +02:00
|
|
|
// Create descriptor update template. If there are no active
|
|
|
|
// resource bindings, there won't be any descriptors to update.
|
|
|
|
if (bindingCount > 0) {
|
|
|
|
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");
|
|
|
|
}
|
2018-03-17 23:50:03 +01:00
|
|
|
}
|
2017-12-03 00:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-01-23 17:40:36 +01:00
|
|
|
DxvkPipelineLayout::~DxvkPipelineLayout() {
|
2018-03-17 23:50:03 +01:00
|
|
|
m_vkd->vkDestroyDescriptorUpdateTemplateKHR(
|
|
|
|
m_vkd->device(), m_descriptorTemplate, nullptr);
|
2017-12-03 00:40:58 +01:00
|
|
|
|
2018-03-17 23:50:03 +01:00
|
|
|
m_vkd->vkDestroyPipelineLayout(
|
|
|
|
m_vkd->device(), m_pipelineLayout, nullptr);
|
|
|
|
|
|
|
|
m_vkd->vkDestroyDescriptorSetLayout(
|
|
|
|
m_vkd->device(), m_descriptorSetLayout, nullptr);
|
2017-12-03 00:40:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|