Skip to content

Commit

Permalink
Wrap pipeline layout creation, use in thin3d
Browse files Browse the repository at this point in the history
Two more types
  • Loading branch information
hrydgard committed Oct 8, 2023
1 parent dbe395d commit 88a5057
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 50 deletions.
66 changes: 66 additions & 0 deletions Common/GPU/Vulkan/VulkanRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,72 @@ void VulkanRenderManager::FlushSync() {
}
}

VKRPipelineLayout *VulkanRenderManager::CreatePipelineLayout(BindingType *bindingTypes, size_t bindingCount, bool geoShadersEnabled, const char *tag) {
VKRPipelineLayout *layout = new VKRPipelineLayout();
layout->tag = tag;
layout->bindingCount = (uint32_t)bindingCount;

_dbg_assert_(bindingCount <= ARRAY_SIZE(layout->bindingTypes));
memcpy(layout->bindingTypes, bindingTypes, sizeof(BindingType) * bindingCount);

VkDescriptorSetLayoutBinding bindings[VKRPipelineLayout::MAX_DESC_SET_BINDINGS];
for (int i = 0; i < bindingCount; i++) {
bindings[i].binding = i;
bindings[i].descriptorCount = 1;
bindings[i].pImmutableSamplers = nullptr;

switch (bindingTypes[i]) {
case BindingType::COMBINED_IMAGE_SAMPLER:
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
break;
case BindingType::UNIFORM_BUFFER_DYNAMIC_VERTEX:
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
bindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
break;
case BindingType::UNIFORM_BUFFER_DYNAMIC_ALL:
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
bindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
if (geoShadersEnabled) {
bindings[i].stageFlags |= VK_SHADER_STAGE_GEOMETRY_BIT;
}
break;
case BindingType::STORAGE_BUFFER_VERTEX:
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT;
break;
case BindingType::STORAGE_BUFFER_COMPUTE:
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
break;
case BindingType::STORAGE_IMAGE_COMPUTE:
bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bindings[i].stageFlags = VK_SHADER_STAGE_COMPUTE_BIT;
break;
default:
_dbg_assert_(false);
break;
}
}

VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
dsl.bindingCount = (uint32_t)bindingCount;
dsl.pBindings = bindings;
VkResult res = vkCreateDescriptorSetLayout(vulkan_->GetDevice(), &dsl, nullptr, &layout->descriptorSetLayout);
_assert_(VK_SUCCESS == res && layout->descriptorSetLayout);

VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
VkDescriptorSetLayout setLayouts[1] = { layout->descriptorSetLayout };
pl.setLayoutCount = ARRAY_SIZE(setLayouts);
pl.pSetLayouts = setLayouts;
res = vkCreatePipelineLayout(vulkan_->GetDevice(), &pl, nullptr, &layout->pipelineLayout);
_assert_(VK_SUCCESS == res && layout->pipelineLayout);

vulkan_->SetDebugName(layout->descriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, tag);
vulkan_->SetDebugName(layout->pipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, tag);
return layout;
}

void VulkanRenderManager::ResetStats() {
initTimeMs_.Reset();
totalGPUTimeMs_.Reset();
Expand Down
44 changes: 29 additions & 15 deletions Common/GPU/Vulkan/VulkanRenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,21 +168,6 @@ struct VKRComputePipeline {
}
};

struct VKRPipelineLayout {
~VKRPipelineLayout() {
_assert_(!pipelineLayout && !descriptorSetLayout);
}

void Destroy(VulkanContext *vulkan) {
vulkan->Delete().QueueDeletePipelineLayout(pipelineLayout);
vulkan->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout);
}

VkPipelineLayout pipelineLayout;
VkDescriptorSetLayout descriptorSetLayout; // only support 1 for now.
int pushConstSize;
};

struct CompileQueueEntry {
CompileQueueEntry(VKRGraphicsPipeline *p, VkRenderPass _compatibleRenderPass, RenderPassType _renderPassType, VkSampleCountFlagBits _sampleCount)
: type(Type::GRAPHICS), graphics(p), compatibleRenderPass(_compatibleRenderPass), renderPassType(_renderPassType), sampleCount(_sampleCount) {}
Expand All @@ -199,6 +184,34 @@ struct CompileQueueEntry {
VkSampleCountFlagBits sampleCount;
};

enum class BindingType {
COMBINED_IMAGE_SAMPLER,
UNIFORM_BUFFER_DYNAMIC_VERTEX,
UNIFORM_BUFFER_DYNAMIC_ALL,
STORAGE_BUFFER_VERTEX,
STORAGE_BUFFER_COMPUTE,
STORAGE_IMAGE_COMPUTE,
};

// Note that we only support a single descriptor set due to compatibility with some ancient devices.
// We should probably eventually give that up.
struct VKRPipelineLayout {
~VKRPipelineLayout() {
_assert_(!pipelineLayout && !descriptorSetLayout);
}
void Destroy(VulkanContext *vulkan) {
vulkan->Delete().QueueDeletePipelineLayout(pipelineLayout);
vulkan->Delete().QueueDeleteDescriptorSetLayout(descriptorSetLayout);
}
enum { MAX_DESC_SET_BINDINGS = 10 };
BindingType bindingTypes[MAX_DESC_SET_BINDINGS];
uint32_t bindingCount;
VkPipelineLayout pipelineLayout;
VkDescriptorSetLayout descriptorSetLayout; // only support 1 for now.
int pushConstSize = 0;
const char *tag;
};

class VulkanRenderManager {
public:
VulkanRenderManager(VulkanContext *vulkan, bool useThread, HistoryBuffer<FrameTimeData, FRAME_TIME_HISTORY_LENGTH> &frameTimeHistory);
Expand Down Expand Up @@ -259,6 +272,7 @@ class VulkanRenderManager {
layout->descriptorSetLayout = descSetLayout;
return layout;
}
VKRPipelineLayout *CreatePipelineLayout(BindingType *bindingTypes, size_t bindingCount, bool geoShadersEnabled, const char *tag);

void ReportBadStateForDraw();

Expand Down
42 changes: 7 additions & 35 deletions Common/GPU/Vulkan/thin3d_vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1062,45 +1062,17 @@ VKContext::VKContext(VulkanContext *vulkan, bool useRenderThread)
// binding 0 - uniform data
// binding 1 - combined sampler/image 0
// binding 2 - combined sampler/image 1
VkDescriptorSetLayoutBinding bindings[MAX_BOUND_TEXTURES + 1];
bindings[0].descriptorCount = 1;
bindings[0].pImmutableSamplers = nullptr;
bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
bindings[0].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
bindings[0].binding = 0;
// ...etc
BindingType bindings[MAX_BOUND_TEXTURES + 1];
bindings[0] = BindingType::UNIFORM_BUFFER_DYNAMIC_ALL;
for (int i = 0; i < MAX_BOUND_TEXTURES; ++i) {
bindings[i + 1].descriptorCount = 1;
bindings[i + 1].pImmutableSamplers = nullptr;
bindings[i + 1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bindings[i + 1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
bindings[i + 1].binding = i + 1;
}

VkDescriptorSetLayout descSetLayout;
VkDescriptorSetLayoutCreateInfo dsl = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO };
dsl.bindingCount = ARRAY_SIZE(bindings);
dsl.pBindings = bindings;
VkResult res = vkCreateDescriptorSetLayout(device_, &dsl, nullptr, &descSetLayout);
_assert_(VK_SUCCESS == res);

vulkan_->SetDebugName(descSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT, "thin3d_d_layout");

VkPipelineLayout pipelineLayout;
VkPipelineLayoutCreateInfo pl = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO };
pl.pPushConstantRanges = nullptr;
pl.pushConstantRangeCount = 0;
VkDescriptorSetLayout setLayouts[1] = { descSetLayout };
pl.setLayoutCount = ARRAY_SIZE(setLayouts);
pl.pSetLayouts = setLayouts;
res = vkCreatePipelineLayout(device_, &pl, nullptr, &pipelineLayout);
_assert_(VK_SUCCESS == res);

vulkan_->SetDebugName(pipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT, "thin3d_p_layout");
bindings[1 + i] = BindingType::COMBINED_IMAGE_SAMPLER;
}

pipelineLayout_ = renderManager_.CreatePipelineLayout(pipelineLayout, descSetLayout);
pipelineLayout_ = renderManager_.CreatePipelineLayout(bindings, ARRAY_SIZE(bindings), caps_.geometryShaderSupported, "thin3d_layout");

VkPipelineCacheCreateInfo pc{ VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO };
res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_);
VkResult res = vkCreatePipelineCache(vulkan_->GetDevice(), &pc, nullptr, &pipelineCache_);
_assert_(VK_SUCCESS == res);
}

Expand Down

0 comments on commit 88a5057

Please sign in to comment.