Skip to content

Commit 4b4527a

Browse files
[Renderer] descriptor set update safety
1 parent ea5e065 commit 4b4527a

8 files changed

Lines changed: 206 additions & 112 deletions

File tree

Engine/Renderer/Private/Assets/ModelLoader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ namespace MauRen
2424
ModelLoader(ModelLoader&&) = delete;
2525
ModelLoader& operator=(ModelLoader const&) = delete;
2626
ModelLoader& operator=(ModelLoader const&&) = delete;
27-
/*
27+
/**
2828
* load assimp by file
2929
* -> this files contains one big static mesh
3030
* -> split up in submeshes

Engine/Renderer/Private/Vulkan/Assets/VulkanLightManager.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -162,35 +162,27 @@ namespace MauRen
162162
}
163163
}
164164

165-
void VulkanLightManager::PreDraw(uint32_t setCount, VkDescriptorSet const* pDescriptorSets, uint32_t frame)
165+
void VulkanLightManager::PreDraw(VulkanDescriptorContext& descriptorContext, uint32_t frame)
166166
{
167+
//TODO only do this when the contents change
167168
{
168169
ME_PROFILE_SCOPE("Light data update - buffer")
169170
memcpy(m_LightBuffers[frame].mapped, m_Lights.data(), m_Lights.size() * sizeof(Light));
170171
}
171172

173+
//TODO only do this when the contents change
172174
{
173175
ME_PROFILE_SCOPE("Light instance data update - descriptor sets")
174176

175177
// Will likely never be empty but if it is, skip to prevent errors
176178
if (not m_Lights.empty())
177179
{
178-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
179-
VkDescriptorBufferInfo bufferInfo = {};
180+
VkDescriptorBufferInfo bufferInfo{};
180181
bufferInfo.buffer = m_LightBuffers[frame].buffer.buffer;
181182
bufferInfo.offset = 0;
182183
bufferInfo.range = m_Lights.size() * sizeof(Light);
183184

184-
VkWriteDescriptorSet descriptorWrite = {};
185-
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
186-
descriptorWrite.dstSet = *pDescriptorSets;
187-
descriptorWrite.dstBinding = 12; // Binding index -TODO use a get Binding on the context
188-
descriptorWrite.dstArrayElement = 0; // Array element offset (if applicable)
189-
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
190-
descriptorWrite.descriptorCount = 1;
191-
descriptorWrite.pBufferInfo = &bufferInfo;
192-
193-
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
185+
descriptorContext.BindLightBuffer(bufferInfo, frame);
194186
}
195187
}
196188
}

Engine/Renderer/Private/Vulkan/Assets/VulkanLightManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ namespace MauRen
3232

3333
void SetSceneAABBOverride(glm::vec3 const& min, glm::vec3 const& max);
3434
void PreQueue(glm::mat4 const& viewProj);
35-
void PreDraw(uint32_t setCount, VkDescriptorSet const* pDescriptorSets, uint32_t frame);
35+
void PreDraw(VulkanDescriptorContext& descriptorContext, uint32_t frame);
3636
void QueueLight(VulkanCommandPoolManager& cmdPoolManager, VulkanDescriptorContext& descriptorContext, MauEng::CLight const& light);
3737
void PostDraw();
3838

Engine/Renderer/Private/Vulkan/Assets/VulkanMeshManager.cpp

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "VulkanMaterialManager.h"
77

88
#include "Assets/ModelLoader.h"
9+
#include "Vulkan/VulkanDescriptorContext.h"
910
#include "Vulkan/VulkanMemoryAllocator.h"
1011

1112
namespace MauRen
@@ -124,8 +125,9 @@ namespace MauRen
124125
throw std::runtime_error("Mesh not found! ");
125126
}
126127

127-
void VulkanMeshManager::PreDraw(uint32_t setCount, VkDescriptorSet const* pDescriptorSets, uint32_t frame)
128+
void VulkanMeshManager::PreDraw(VulkanDescriptorContext& descriptorContext, uint32_t frame)
128129
{
130+
//TODO only does this when contents change
129131
{
130132
ME_PROFILE_SCOPE("Mesh instance data update - buffer")
131133

@@ -138,28 +140,16 @@ namespace MauRen
138140
memcpy(m_DrawCommandBuffers[frame].mapped, m_DrawCommands.data(), m_DrawCommands.size() * sizeof(DrawCommand));
139141
}
140142

143+
//TODO only does this when contents change
141144
{
142145
if (not m_MeshInstanceData.empty())
143146
{
144-
145-
ME_PROFILE_SCOPE("Mesh instance data update - descriptor sets")
146-
147-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
148147
VkDescriptorBufferInfo bufferInfo = {};
149148
bufferInfo.buffer = m_MeshInstanceDataBuffers[frame].buffer.buffer;
150149
bufferInfo.offset = 0;
151150
bufferInfo.range = m_MeshInstanceData.size() * sizeof(MeshInstanceData);
152151

153-
VkWriteDescriptorSet descriptorWrite = {};
154-
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
155-
descriptorWrite.dstSet = *pDescriptorSets;
156-
descriptorWrite.dstBinding = 5; // Binding index -TODO use a get Binding on the context
157-
descriptorWrite.dstArrayElement = 0; // Array element offset (if applicable)
158-
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
159-
descriptorWrite.descriptorCount = 1;
160-
descriptorWrite.pBufferInfo = &bufferInfo;
161-
162-
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
152+
descriptorContext.BindMeshInstanceDataBuffer(bufferInfo, frame);
163153
}
164154
}
165155
}
@@ -216,8 +206,6 @@ namespace MauRen
216206

217207
void VulkanMeshManager::InitializeDrawCommandBuffers() noexcept
218208
{
219-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
220-
221209
VkDeviceSize constexpr BUFFER_SIZE{ sizeof(DrawCommand) * MAX_DRAW_COMMANDS };
222210

223211
for (size_t i{ 0 }; i < MAX_FRAMES_IN_FLIGHT; ++i)
@@ -235,8 +223,6 @@ namespace MauRen
235223

236224
void VulkanMeshManager::CreateVertexAndIndexBuffers() noexcept
237225
{
238-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
239-
240226
{
241227
VkDeviceSize constexpr BUFFER_SIZE{ sizeof(Vertex) * MAX_VERTICES };
242228

Engine/Renderer/Private/Vulkan/Assets/VulkanMeshManager.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ namespace MauRen
5050
}
5151
}
5252

53-
void PreDraw(uint32_t setCount, VkDescriptorSet const* pDescriptorSets, uint32_t frame);
53+
void PreDraw(VulkanDescriptorContext& descriptorContext, uint32_t frame);
5454
void Draw(VkCommandBuffer commandBuffer, VkPipelineLayout layout, uint32_t setCount, VkDescriptorSet const* pDescriptorSets, uint32_t frame);
5555
void PostDraw(VkCommandBuffer commandBuffer, VkPipelineLayout layout, uint32_t setCount, VkDescriptorSet const* pDescriptorSets, uint32_t frame);
5656

Engine/Renderer/Private/Vulkan/VulkanDescriptorContext.cpp

Lines changed: 96 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -2,124 +2,108 @@
22

33
namespace MauRen
44
{
5-
// ! THIS IS NOT SAFE TO CALL DURING A FRAME, HAS TO BE HANDLED IF WE WANT THAT
65
void VulkanDescriptorContext::BindTexture(uint32_t destLocation, VkImageView imageView, VkImageLayout imageLayout)
76
{
87
VkDescriptorImageInfo imageInfo{};
98
imageInfo.imageLayout = imageLayout;
109
imageInfo.imageView = imageView;
1110
imageInfo.sampler = VK_NULL_HANDLE;
1211

13-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
14-
1512
for (size_t i{ 0 }; i < MAX_FRAMES_IN_FLIGHT; ++i)
1613
{
17-
VkWriteDescriptorSet descriptorWrite{};
18-
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
19-
descriptorWrite.dstSet = m_DescriptorSets[i];
20-
descriptorWrite.dstBinding = TEXTURE_BINDING_SLOT;
21-
descriptorWrite.dstArrayElement = destLocation;
22-
23-
ME_ASSERT(destLocation < MAX_TEXTURES);
24-
25-
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
26-
descriptorWrite.descriptorCount = 1;
27-
28-
descriptorWrite.pImageInfo = &imageInfo;
29-
30-
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
14+
m_DescriptorSetUpdates[i].emplace_back(
15+
DescriptorSetUpdate::CreateImageUpdate(
16+
m_DescriptorSets[i],
17+
TEXTURE_BINDING_SLOT,
18+
destLocation,
19+
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
20+
{ imageInfo }
21+
)
22+
);
3123
}
3224
}
3325

34-
// ! THIS IS NOT SAFE TO CALL DURING A FRAME, HAS TO BE HANDLED IF WE WANT THAT
3526
void VulkanDescriptorContext::BindMaterialBuffer(VkDescriptorBufferInfo bufferInfo, uint32_t frame)
3627
{
37-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
38-
39-
// Update descriptor set
40-
VkWriteDescriptorSet descriptorWrite{};
41-
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
42-
descriptorWrite.dstSet = m_DescriptorSets[frame];
43-
44-
descriptorWrite.dstBinding = MATERIAL_DATA_BINDING_SLOT;
45-
descriptorWrite.dstArrayElement = 0;
46-
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
47-
descriptorWrite.descriptorCount = 1;
48-
descriptorWrite.pBufferInfo = &bufferInfo;
49-
50-
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
28+
m_DescriptorSetUpdates[frame].emplace_back(
29+
DescriptorSetUpdate::CreateBufferUpdate(
30+
m_DescriptorSets[frame],
31+
MATERIAL_DATA_BINDING_SLOT,
32+
0,
33+
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
34+
{ bufferInfo }
35+
)
36+
);
5137
}
5238

53-
// ! THIS IS NOT SAFE TO CALL DURING A FRAME, HAS TO BE HANDLED IF WE WANT THAT
5439
void VulkanDescriptorContext::BindLightBuffer(VkDescriptorBufferInfo bufferInfo, uint32_t frame)
5540
{
56-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
57-
58-
// Update descriptor set
59-
VkWriteDescriptorSet descriptorWrite{};
60-
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
61-
descriptorWrite.dstSet = m_DescriptorSets[frame];
62-
63-
descriptorWrite.dstBinding = LIGHT_BUFFER_SLOT;
64-
descriptorWrite.dstArrayElement = 0;
65-
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
66-
descriptorWrite.descriptorCount = 1;
67-
descriptorWrite.pBufferInfo = &bufferInfo;
68-
69-
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
41+
m_DescriptorSetUpdates[frame].emplace_back(
42+
DescriptorSetUpdate::CreateBufferUpdate(
43+
m_DescriptorSets[frame],
44+
LIGHT_BUFFER_SLOT,
45+
0,
46+
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
47+
{ bufferInfo }
48+
)
49+
);
7050
}
7151

72-
// ! THIS IS NOT SAFE TO CALL DURING A FRAME, HAS TO BE HANDLED IF WE WANT THAT
7352
void VulkanDescriptorContext::BindShadowMap(uint32_t destLocation, VkImageView imageView, VkImageLayout imageLayout)
7453
{
7554
VkDescriptorImageInfo imageInfo{};
7655
imageInfo.imageLayout = imageLayout;
7756
imageInfo.imageView = imageView;
7857
imageInfo.sampler = VK_NULL_HANDLE;
7958

80-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
59+
ME_ASSERT(destLocation < MAX_SHADOW_MAPS);
8160

8261
for (size_t i{ 0 }; i < MAX_FRAMES_IN_FLIGHT; ++i)
8362
{
84-
VkWriteDescriptorSet descriptorWrite{};
85-
descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
86-
descriptorWrite.dstSet = m_DescriptorSets[i];
87-
descriptorWrite.dstBinding = SHADOW_MAPS_SLOT;
88-
descriptorWrite.dstArrayElement = destLocation;
89-
90-
ME_ASSERT(destLocation < MAX_SHADOW_MAPS);
91-
92-
descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
93-
descriptorWrite.descriptorCount = 1;
94-
95-
descriptorWrite.pImageInfo = &imageInfo;
96-
97-
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &descriptorWrite, 0, nullptr);
63+
m_DescriptorSetUpdates[i].emplace_back(
64+
DescriptorSetUpdate::CreateImageUpdate(
65+
m_DescriptorSets[i],
66+
SHADOW_MAPS_SLOT,
67+
destLocation,
68+
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
69+
{ imageInfo }
70+
)
71+
);
9872
}
9973
}
10074

10175
void VulkanDescriptorContext::BindShadowMapSampler(VkSampler sampler)
10276
{
103-
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
104-
10577
VkDescriptorImageInfo imageInfo{};
10678
imageInfo.sampler = sampler;
10779

10880
for (size_t i{ 0 }; i < MAX_FRAMES_IN_FLIGHT; ++i)
10981
{
110-
VkWriteDescriptorSet samplerWrite{};
111-
samplerWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
112-
samplerWrite.dstSet = m_DescriptorSets[i];
113-
samplerWrite.dstBinding = SHADOW_MAP_SAMPLER;
114-
samplerWrite.dstArrayElement = 0;
115-
samplerWrite.descriptorType = VK_DESCRIPTOR_TYPE_SAMPLER;
116-
samplerWrite.descriptorCount = 1;
117-
samplerWrite.pImageInfo = &imageInfo;
118-
119-
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &samplerWrite, 0, nullptr);
82+
m_DescriptorSetUpdates[i].emplace_back(
83+
DescriptorSetUpdate::CreateImageUpdate(
84+
m_DescriptorSets[i],
85+
SHADOW_MAP_SAMPLER,
86+
0,
87+
VK_DESCRIPTOR_TYPE_SAMPLER,
88+
{ imageInfo }
89+
)
90+
);
12091
}
12192
}
12293

94+
void VulkanDescriptorContext::BindMeshInstanceDataBuffer(VkDescriptorBufferInfo bufferInfo, uint32_t frame)
95+
{
96+
m_DescriptorSetUpdates[frame].emplace_back(
97+
DescriptorSetUpdate::CreateBufferUpdate(
98+
m_DescriptorSets[frame],
99+
MESH_INSTANCE_DATA_BINDING_SLOT,
100+
0,
101+
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
102+
{ bufferInfo }
103+
)
104+
);
105+
}
106+
123107
void VulkanDescriptorContext::CreateDescriptorSetLayout()
124108
{
125109
VkDescriptorSetLayoutBinding uboLayoutBinding{};
@@ -502,4 +486,41 @@ namespace MauRen
502486
VulkanUtils::SafeDestroy(deviceContext->GetLogicalDevice(), m_DescriptorPool, nullptr);
503487
VulkanUtils::SafeDestroy(deviceContext->GetLogicalDevice(), m_DescriptorSetLayout, nullptr);
504488
}
489+
490+
void VulkanDescriptorContext::ProcessDescriptorUpdateQueue(uint32_t frame) noexcept
491+
{
492+
auto const deviceContext{ VulkanDeviceContextManager::GetInstance().GetDeviceContext() };
493+
494+
auto& updates{ m_DescriptorSetUpdates[frame] };
495+
496+
for (auto const& update : updates)
497+
{
498+
VkWriteDescriptorSet write{};
499+
write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
500+
write.dstSet = update.targetSet;
501+
write.dstBinding = update.dstBinding;
502+
write.dstArrayElement = update.dstArrayElement;
503+
write.descriptorType = update.descriptorType;
504+
505+
switch (update.type)
506+
{
507+
case DescriptorSetUpdate::EType::Buffer:
508+
write.pBufferInfo = std::get<std::vector<VkDescriptorBufferInfo>>(update.descriptorData).data();
509+
write.descriptorCount = static_cast<uint32_t>(std::size(std::get<std::vector<VkDescriptorBufferInfo>>(update.descriptorData)));
510+
break;
511+
case DescriptorSetUpdate::EType::Image:
512+
write.pImageInfo = std::get<std::vector<VkDescriptorImageInfo>>(update.descriptorData).data();
513+
write.descriptorCount = static_cast<uint32_t>(std::size(std::get<std::vector<VkDescriptorImageInfo>>(update.descriptorData)));
514+
break;
515+
case DescriptorSetUpdate::EType::TexelBuffer:
516+
write.pTexelBufferView = std::get<std::vector<VkBufferView>>(update.descriptorData).data();
517+
write.descriptorCount = static_cast<uint32_t>(std::size(std::get<std::vector<VkBufferView>>(update.descriptorData)));
518+
break;
519+
}
520+
521+
vkUpdateDescriptorSets(deviceContext->GetLogicalDevice(), 1, &write, 0, nullptr);
522+
}
523+
524+
updates.clear();
525+
}
505526
}

0 commit comments

Comments
 (0)