Skip to content

Commit 4663e0d

Browse files
committed
Update additional samples to use new sync
1 parent ddc254c commit 4663e0d

2 files changed

Lines changed: 253 additions & 257 deletions

File tree

examples/inlineuniformblocks/inlineuniformblocks.cpp

Lines changed: 143 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
*
66
* Relevant code parts are marked with [POI]
77
*
8-
* Copyright (C) 2018-2023 by Sascha Willems - www.saschawillems.de
8+
* Copyright (C) 2018-2025 by Sascha Willems - www.saschawillems.de
99
*
1010
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
1111
*/
@@ -27,7 +27,7 @@ class VulkanExample : public VulkanExampleBase
2727
float r, g, b;
2828
float ambient;
2929
} material;
30-
VkDescriptorSet descriptorSet;
30+
std::vector<VkDescriptorSet> descriptorSets;
3131
void setRandomMaterial(bool applyRandomSeed) {
3232
std::random_device rndDevice;
3333
std::default_random_engine rndEngine(applyRandomSeed ? rndDevice() : 0);
@@ -48,26 +48,31 @@ class VulkanExample : public VulkanExampleBase
4848
glm::mat4 view;
4949
glm::vec3 camPos;
5050
} uniformData;
51-
vks::Buffer uniformBuffer;
51+
std::vector<vks::Buffer> uniformBuffers;
5252

5353
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
5454
VkPipeline pipeline{ VK_NULL_HANDLE };
55-
VkDescriptorSet descriptorSet{ VK_NULL_HANDLE };
5655

5756
struct DescriptorSetLaysts {
5857
VkDescriptorSetLayout scene{ VK_NULL_HANDLE };
5958
VkDescriptorSetLayout object{ VK_NULL_HANDLE };
6059
} descriptorSetLayouts;
60+
std::vector<VkDescriptorSet> descriptorSets;
61+
62+
bool doUpdateMaterials{ false };
6163

6264
VulkanExample() : VulkanExampleBase()
6365
{
66+
useNewSync = true;
6467
title = "Inline uniform blocks";
6568
camera.type = Camera::CameraType::firstperson;
6669
camera.setPosition(glm::vec3(0.0f, 0.0f, -10.0f));
6770
camera.setRotation(glm::vec3(0.0, 0.0f, 0.0f));
6871
camera.setPerspective(60.0f, (float)width / (float)height, 0.1f, 256.0f);
6972
camera.movementSpeed = 4.0f;
7073
camera.rotationSpeed = 0.25f;
74+
uniformBuffers.resize(maxConcurrentFrames);
75+
descriptorSets.resize(maxConcurrentFrames);
7176

7277
/*
7378
[POI] Enable extensions required for inline uniform blocks
@@ -91,67 +96,9 @@ class VulkanExample : public VulkanExampleBase
9196
vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
9297
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.scene, nullptr);
9398
vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.object, nullptr);
94-
uniformBuffer.destroy();
95-
}
96-
}
97-
98-
void buildCommandBuffers()
99-
{
100-
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
101-
102-
VkClearValue clearValues[2];
103-
clearValues[0].color = { { 0.15f, 0.15f, 0.15f, 1.0f } };
104-
clearValues[1].depthStencil = { 1.0f, 0 };
105-
106-
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
107-
renderPassBeginInfo.renderPass = renderPass;
108-
renderPassBeginInfo.renderArea.offset.x = 0;
109-
renderPassBeginInfo.renderArea.offset.y = 0;
110-
renderPassBeginInfo.renderArea.extent.width = width;
111-
renderPassBeginInfo.renderArea.extent.height = height;
112-
renderPassBeginInfo.clearValueCount = 2;
113-
renderPassBeginInfo.pClearValues = clearValues;
114-
115-
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
116-
{
117-
renderPassBeginInfo.framebuffer = frameBuffers[i];
118-
119-
VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
120-
121-
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
122-
123-
VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
124-
vkCmdSetViewport(drawCmdBuffers[i], 0, 1, &viewport);
125-
126-
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
127-
vkCmdSetScissor(drawCmdBuffers[i], 0, 1, &scissor);
128-
129-
// Render objects
130-
vkCmdBindPipeline(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
131-
132-
uint32_t objcount = static_cast<uint32_t>(objects.size());
133-
for (uint32_t x = 0; x < objcount; x++) {
134-
/*
135-
[POI] Bind descriptor sets
136-
Set 0 = Scene matrices:
137-
Set 1 = Object inline uniform block (In shader pbr.frag: layout (set = 1, binding = 0) uniform UniformInline ... )
138-
*/
139-
std::vector<VkDescriptorSet> descriptorSets = {
140-
descriptorSet,
141-
objects[x].descriptorSet
142-
};
143-
vkCmdBindDescriptorSets(drawCmdBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, descriptorSets.data(), 0, nullptr);
144-
145-
glm::vec3 pos = glm::vec3(sin(glm::radians(x * (360.0f / objcount))), cos(glm::radians(x * (360.0f / objcount))), 0.0f) * 3.5f;
146-
147-
vkCmdPushConstants(drawCmdBuffers[i], pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos);
148-
model.draw(drawCmdBuffers[i]);
99+
for (auto& buffer : uniformBuffers) {
100+
buffer.destroy();
149101
}
150-
drawUI(drawCmdBuffers[i]);
151-
152-
vkCmdEndRenderPass(drawCmdBuffers[i]);
153-
154-
VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
155102
}
156103
}
157104

@@ -169,11 +116,11 @@ class VulkanExample : public VulkanExampleBase
169116
{
170117
// Pool
171118
std::vector<VkDescriptorPoolSize> poolSizes = {
172-
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1),
119+
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, maxConcurrentFrames),
173120
/* [POI] Allocate inline uniform blocks */
174121
vks::initializers::descriptorPoolSize(VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT, static_cast<uint32_t>(objects.size()) * sizeof(Object::Material)),
175122
};
176-
VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, static_cast<uint32_t>(objects.size()) + 1);
123+
VkDescriptorPoolCreateInfo descriptorPoolCI = vks::initializers::descriptorPoolCreateInfo(poolSizes, (static_cast<uint32_t>(objects.size()) + 1) * maxConcurrentFrames);
177124
/*
178125
[POI] New structure that has to be chained into the descriptor pool's createinfo if you want to allocate inline uniform blocks
179126
*/
@@ -203,43 +150,45 @@ class VulkanExample : public VulkanExampleBase
203150
descriptorLayoutCI = vks::initializers::descriptorSetLayoutCreateInfo(setLayoutBindings);
204151
VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayoutCI, nullptr, &descriptorSetLayouts.object));
205152

206-
// Sets
207-
// Scene
208-
VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1);
209-
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &descriptorSet));
210-
std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
211-
vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor),
212-
};
213-
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
214-
// Objects
215-
for (auto& object : objects) {
216-
VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.object, 1);
217-
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &object.descriptorSet));
153+
// Sets per frame, just like the buffers themselves
154+
for (auto i = 0; i < uniformBuffers.size(); i++) {
155+
VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.scene, 1);
156+
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &descriptorSets[i]));
157+
std::vector<VkWriteDescriptorSet> writeDescriptorSets = {
158+
vks::initializers::writeDescriptorSet(descriptorSets[i], VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffers[i].descriptor),
159+
};
160+
vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, nullptr);
161+
// Objects with inline uniform blocks
162+
for (auto& object : objects) {
163+
object.descriptorSets.resize(maxConcurrentFrames);
164+
VkDescriptorSetAllocateInfo descriptorAllocateInfo = vks::initializers::descriptorSetAllocateInfo(descriptorPool, &descriptorSetLayouts.object, 1);
165+
VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &descriptorAllocateInfo, &object.descriptorSets[i]));
218166

219-
/*
220-
[POI] New structure that defines size and data of the inline uniform block needs to be chained into the write descriptor set
221-
We will be using this inline uniform block to pass per-object material information to the fragment shader
222-
*/
223-
VkWriteDescriptorSetInlineUniformBlockEXT writeDescriptorSetInlineUniformBlock{};
224-
writeDescriptorSetInlineUniformBlock.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
225-
writeDescriptorSetInlineUniformBlock.dataSize = sizeof(Object::Material);
226-
// Uniform data for the inline block
227-
writeDescriptorSetInlineUniformBlock.pData = &object.material;
228-
229-
/*
230-
[POI] Setup the inline uniform block
231-
*/
232-
VkWriteDescriptorSet writeDescriptorSet{};
233-
writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
234-
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
235-
writeDescriptorSet.dstSet = object.descriptorSet;
236-
writeDescriptorSet.dstBinding = 0;
237-
// Descriptor count for an inline uniform block contains data sizes of the block(last parameter)
238-
writeDescriptorSet.descriptorCount = sizeof(Object::Material);
239-
// Chain inline uniform block structure
240-
writeDescriptorSet.pNext = &writeDescriptorSetInlineUniformBlock;
167+
/*
168+
[POI] New structure that defines size and data of the inline uniform block needs to be chained into the write descriptor set
169+
We will be using this inline uniform block to pass per-object material information to the fragment shader
170+
*/
171+
VkWriteDescriptorSetInlineUniformBlockEXT writeDescriptorSetInlineUniformBlock{};
172+
writeDescriptorSetInlineUniformBlock.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK_EXT;
173+
writeDescriptorSetInlineUniformBlock.dataSize = sizeof(Object::Material);
174+
// Uniform data for the inline block
175+
writeDescriptorSetInlineUniformBlock.pData = &object.material;
241176

242-
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
177+
/*
178+
[POI] Setup the inline uniform block
179+
*/
180+
VkWriteDescriptorSet writeDescriptorSet{};
181+
writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
182+
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
183+
writeDescriptorSet.dstSet = object.descriptorSets[i];
184+
writeDescriptorSet.dstBinding = 0;
185+
// Descriptor count for an inline uniform block contains data sizes of the block(last parameter)
186+
writeDescriptorSet.descriptorCount = sizeof(Object::Material);
187+
// Chain inline uniform block structure
188+
writeDescriptorSet.pNext = &writeDescriptorSetInlineUniformBlock;
189+
190+
vkUpdateDescriptorSets(device, 1, &writeDescriptorSet, 0, nullptr);
191+
}
243192
}
244193
}
245194

@@ -273,7 +222,7 @@ class VulkanExample : public VulkanExampleBase
273222
VkPipelineMultisampleStateCreateInfo multisampleStateCI = vks::initializers::pipelineMultisampleStateCreateInfo(VK_SAMPLE_COUNT_1_BIT);
274223
std::vector<VkDynamicState> dynamicStateEnables = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
275224
VkPipelineDynamicStateCreateInfo dynamicStateCI = vks::initializers::pipelineDynamicStateCreateInfo(dynamicStateEnables);
276-
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages;
225+
std::array<VkPipelineShaderStageCreateInfo, 2> shaderStages{};
277226

278227
VkGraphicsPipelineCreateInfo pipelineCI = vks::initializers::pipelineCreateInfo(pipelineLayout, renderPass);
279228
pipelineCI.pInputAssemblyState = &inputAssemblyStateCI;
@@ -294,9 +243,10 @@ class VulkanExample : public VulkanExampleBase
294243

295244
void prepareUniformBuffers()
296245
{
297-
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &uniformBuffer, sizeof(UniformData)));
298-
VK_CHECK_RESULT(uniformBuffer.map());
299-
updateUniformBuffers();
246+
for (auto& buffer : uniformBuffers) {
247+
VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &buffer, sizeof(UniformData), &uniformData));
248+
VK_CHECK_RESULT(buffer.map());
249+
}
300250
}
301251

302252
void updateUniformBuffers()
@@ -305,47 +255,14 @@ class VulkanExample : public VulkanExampleBase
305255
uniformData.view = camera.matrices.view;
306256
uniformData.model = glm::scale(glm::mat4(1.0f), glm::vec3(0.5f));
307257
uniformData.camPos = camera.position * glm::vec3(-1.0f, 1.0f, -1.0f);
308-
memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData));
309-
}
310-
311-
void prepare()
312-
{
313-
VulkanExampleBase::prepare();
314-
loadAssets();
315-
prepareUniformBuffers();
316-
setupDescriptors();
317-
preparePipelines();
318-
buildCommandBuffers();
319-
prepared = true;
320-
}
321-
322-
void draw()
323-
{
324-
VulkanExampleBase::prepareFrame();
325-
submitInfo.commandBufferCount = 1;
326-
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
327-
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
328-
VulkanExampleBase::submitFrame();
329-
}
330-
331-
virtual void render()
332-
{
333-
if (!prepared)
334-
return;
335-
updateUniformBuffers();
336-
draw();
258+
memcpy(uniformBuffers[currentBuffer].mapped, &uniformData, sizeof(UniformData));
337259
}
338260

339261
/*
340-
[POI] Update descriptor sets at runtime, called from the UI to randomize materials
262+
[POI] Update descriptor set data at runtime using inline uniform blocks
341263
*/
342264
void updateMaterials() {
343-
// Setup random materials for every object in the scene
344-
for (uint32_t i = 0; i < objects.size(); i++) {
345-
objects[i].setRandomMaterial(!benchmark.active);
346-
}
347-
348-
for (auto &object : objects) {
265+
for (auto& object : objects) {
349266
/*
350267
[POI] New structure that defines size and data of the inline uniform block needs to be chained into the write descriptor set
351268
We will be using this inline uniform block to pass per-object material information to the fragment shader
@@ -362,7 +279,7 @@ class VulkanExample : public VulkanExampleBase
362279
VkWriteDescriptorSet writeDescriptorSet{};
363280
writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
364281
writeDescriptorSet.descriptorType = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;
365-
writeDescriptorSet.dstSet = object.descriptorSet;
282+
writeDescriptorSet.dstSet = object.descriptorSets[currentBuffer];
366283
writeDescriptorSet.dstBinding = 0;
367284
writeDescriptorSet.descriptorCount = sizeof(Object::Material);
368285
writeDescriptorSet.pNext = &writeDescriptorSetInlineUniformBlock;
@@ -371,10 +288,93 @@ class VulkanExample : public VulkanExampleBase
371288
}
372289
}
373290

291+
void prepare()
292+
{
293+
VulkanExampleBase::prepare();
294+
loadAssets();
295+
prepareUniformBuffers();
296+
setupDescriptors();
297+
preparePipelines();
298+
prepared = true;
299+
}
300+
301+
void buildCommandBuffer()
302+
{
303+
VkCommandBuffer cmdBuffer = drawCmdBuffers[currentBuffer];
304+
vkResetCommandBuffer(cmdBuffer, 0);
305+
306+
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
307+
308+
VkClearValue clearValues[2]{};
309+
clearValues[0].color = { { 0.15f, 0.15f, 0.15f, 1.0f } };
310+
clearValues[1].depthStencil = { 1.0f, 0 };
311+
312+
VkRenderPassBeginInfo renderPassBeginInfo = vks::initializers::renderPassBeginInfo();
313+
renderPassBeginInfo.renderPass = renderPass;
314+
renderPassBeginInfo.renderArea.offset.x = 0;
315+
renderPassBeginInfo.renderArea.offset.y = 0;
316+
renderPassBeginInfo.renderArea.extent.width = width;
317+
renderPassBeginInfo.renderArea.extent.height = height;
318+
renderPassBeginInfo.clearValueCount = 2;
319+
renderPassBeginInfo.pClearValues = clearValues;
320+
renderPassBeginInfo.framebuffer = frameBuffers[currentImageIndex];
321+
322+
VK_CHECK_RESULT(vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo));
323+
324+
vkCmdBeginRenderPass(cmdBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
325+
326+
VkViewport viewport = vks::initializers::viewport((float)width, (float)height, 0.0f, 1.0f);
327+
vkCmdSetViewport(cmdBuffer, 0, 1, &viewport);
328+
329+
VkRect2D scissor = vks::initializers::rect2D(width, height, 0, 0);
330+
vkCmdSetScissor(cmdBuffer, 0, 1, &scissor);
331+
332+
// Render objects
333+
vkCmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
334+
335+
uint32_t objcount = static_cast<uint32_t>(objects.size());
336+
for (uint32_t i = 0; i < objcount; i++) {
337+
/*
338+
[POI] Bind descriptor sets
339+
Set 0 = Scene matrices:
340+
Set 1 = Object inline uniform block (In shader pbr.frag: layout (set = 1, binding = 0) uniform UniformInline ... )
341+
*/
342+
std::vector<VkDescriptorSet> sets = {
343+
descriptorSets[currentBuffer],
344+
objects[i].descriptorSets[currentBuffer]
345+
};
346+
vkCmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 2, sets.data(), 0, nullptr);
347+
348+
glm::vec3 pos = glm::vec3(sin(glm::radians(i * (360.0f / objcount))), cos(glm::radians(i * (360.0f / objcount))), 0.0f) * 3.5f;
349+
350+
vkCmdPushConstants(cmdBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(glm::vec3), &pos);
351+
model.draw(cmdBuffer);
352+
}
353+
drawUI(cmdBuffer);
354+
355+
vkCmdEndRenderPass(cmdBuffer);
356+
357+
VK_CHECK_RESULT(vkEndCommandBuffer(cmdBuffer));
358+
}
359+
360+
virtual void render()
361+
{
362+
if (!prepared)
363+
return;
364+
VulkanExampleBase::prepareFrame();
365+
updateUniformBuffers();
366+
updateMaterials();
367+
buildCommandBuffer();
368+
VulkanExampleBase::submitFrame();
369+
}
370+
374371
virtual void OnUpdateUIOverlay(vks::UIOverlay *overlay)
375372
{
376373
if (overlay->button("Randomize")) {
377-
updateMaterials();
374+
// Randomize material properties
375+
for (uint32_t i = 0; i < objects.size(); i++) {
376+
objects[i].setRandomMaterial(!benchmark.active);
377+
}
378378
}
379379
}
380380

0 commit comments

Comments
 (0)