Skip to content
Snippets Groups Projects
Commit fce1c932 authored by Sascha Willems's avatar Sascha Willems
Browse files

SSBOs are now device local

Heavily increases performance of this sample
Fixes #905
parent 41a52bda
No related branches found
No related tags found
No related merge requests found
...@@ -15,7 +15,7 @@ layout (set = 0, binding = 1) buffer GeometrySBO ...@@ -15,7 +15,7 @@ layout (set = 0, binding = 1) buffer GeometrySBO
uint maxNodeCount; uint maxNodeCount;
}; };
layout (set = 0, binding = 2, r32ui) uniform uimage2D headIndexImage; layout (set = 0, binding = 2, r32ui) uniform coherent uimage2D headIndexImage;
layout (set = 0, binding = 3) buffer LinkedListSBO layout (set = 0, binding = 3) buffer LinkedListSBO
{ {
......
No preview for this file type
...@@ -192,19 +192,34 @@ private: ...@@ -192,19 +192,34 @@ private:
VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &geometryPass.framebuffer)); VK_CHECK_RESULT(vkCreateFramebuffer(device, &fbufCreateInfo, nullptr, &geometryPass.framebuffer));
// Create a buffer for GeometrySBO // Create a buffer for GeometrySBO
// Using the device memory will be best but I will use the host visible buffer to make this example simple. vks::Buffer stagingBuffer;
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&geometryPass.geometry, &stagingBuffer,
sizeof(geometrySBO))); sizeof(geometrySBO)));
VK_CHECK_RESULT(stagingBuffer.map());
VK_CHECK_RESULT(geometryPass.geometry.map()); VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&geometryPass.geometry,
sizeof(geometrySBO)));
// Set up GeometrySBO data. // Set up GeometrySBO data.
geometrySBO.count = 0; geometrySBO.count = 0;
geometrySBO.maxNodeCount = NODE_COUNT * width * height; geometrySBO.maxNodeCount = NODE_COUNT * width * height;
memcpy(geometryPass.geometry.mapped, &geometrySBO, sizeof(geometrySBO)); memcpy(stagingBuffer.mapped, &geometrySBO, sizeof(geometrySBO));
// Copy data to device
VkCommandBuffer copyCmd = vulkanDevice->createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
VkBufferCopy copyRegion = {};
copyRegion.size = sizeof(geometrySBO);
vkCmdCopyBuffer(copyCmd, stagingBuffer.buffer, geometryPass.geometry.buffer, 1, &copyRegion);
vulkanDevice->flushCommandBuffer(copyCmd, queue, true);
stagingBuffer.destroy();
// Create a texture for HeadIndex. // Create a texture for HeadIndex.
// This image will track the head index of each fragment. // This image will track the head index of each fragment.
...@@ -260,12 +275,10 @@ private: ...@@ -260,12 +275,10 @@ private:
// Create a buffer for LinkedListSBO // Create a buffer for LinkedListSBO
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(
VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
&geometryPass.linkedList, &geometryPass.linkedList,
sizeof(Node) * geometrySBO.maxNodeCount)); sizeof(Node) * geometrySBO.maxNodeCount));
VK_CHECK_RESULT(geometryPass.linkedList.map());
// Change HeadIndex image's layout from UNDEFINED to GENERAL // Change HeadIndex image's layout from UNDEFINED to GENERAL
VkCommandBufferAllocateInfo cmdBufAllocInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1); VkCommandBufferAllocateInfo cmdBufAllocInfo = vks::initializers::commandBufferAllocateInfo(cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1);
...@@ -376,7 +389,7 @@ private: ...@@ -376,7 +389,7 @@ private:
pipelineCI.pViewportState = &viewportState; pipelineCI.pViewportState = &viewportState;
pipelineCI.pDepthStencilState = &depthStencilState; pipelineCI.pDepthStencilState = &depthStencilState;
pipelineCI.pDynamicState = &dynamicState; pipelineCI.pDynamicState = &dynamicState;
pipelineCI.stageCount = shaderStages.size(); pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
pipelineCI.pStages = shaderStages.data(); pipelineCI.pStages = shaderStages.data();
pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position }); pipelineCI.pVertexInputState = vkglTF::Vertex::getPipelineVertexInputState({ vkglTF::VertexComponent::Position });
...@@ -400,7 +413,7 @@ private: ...@@ -400,7 +413,7 @@ private:
pipelineCI.pViewportState = &viewportState; pipelineCI.pViewportState = &viewportState;
pipelineCI.pDepthStencilState = &depthStencilState; pipelineCI.pDepthStencilState = &depthStencilState;
pipelineCI.pDynamicState = &dynamicState; pipelineCI.pDynamicState = &dynamicState;
pipelineCI.stageCount = shaderStages.size(); pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
pipelineCI.pStages = shaderStages.data(); pipelineCI.pStages = shaderStages.data();
pipelineCI.pVertexInputState = &vertexInputInfo; pipelineCI.pVertexInputState = &vertexInputInfo;
...@@ -422,10 +435,7 @@ private: ...@@ -422,10 +435,7 @@ private:
}; };
VkDescriptorPoolCreateInfo descriptorPoolInfo = VkDescriptorPoolCreateInfo descriptorPoolInfo =
vks::initializers::descriptorPoolCreateInfo( vks::initializers::descriptorPoolCreateInfo(poolSizes, 2);
poolSizes.size(),
poolSizes.data(),
2);
VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool)); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
} }
...@@ -468,7 +478,7 @@ private: ...@@ -468,7 +478,7 @@ private:
&geometryPass.linkedList.descriptor) &geometryPass.linkedList.descriptor)
}; };
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
// Update a color descriptor set. // Update a color descriptor set.
allocInfo = allocInfo =
...@@ -494,7 +504,7 @@ private: ...@@ -494,7 +504,7 @@ private:
&geometryPass.linkedList.descriptor) &geometryPass.linkedList.descriptor)
}; };
vkUpdateDescriptorSets(device, writeDescriptorSets.size(), writeDescriptorSets.data(), 0, NULL); vkUpdateDescriptorSets(device, static_cast<uint32_t>(writeDescriptorSets.size()), writeDescriptorSets.data(), 0, NULL);
} }
void buildCommandBuffers() void buildCommandBuffers()
...@@ -538,6 +548,15 @@ private: ...@@ -538,6 +548,15 @@ private:
vkCmdClearColorImage(drawCmdBuffers[i], geometryPass.headIndex.image, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresRange); vkCmdClearColorImage(drawCmdBuffers[i], geometryPass.headIndex.image, VK_IMAGE_LAYOUT_GENERAL, &clearColor, 1, &subresRange);
// Clear previous geometry pass data
vkCmdFillBuffer(drawCmdBuffers[i], geometryPass.geometry.buffer, 0, sizeof(uint32_t), 0);
// We need a barrier to make sure all writes are finished before starting to write again
VkMemoryBarrier memoryBarrier = vks::initializers::memoryBarrier();
memoryBarrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
memoryBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
vkCmdPipelineBarrier(drawCmdBuffers[i], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0, 1, &memoryBarrier, 0, nullptr, 0, nullptr);
// Begin the geometry render pass // Begin the geometry render pass
renderPassBeginInfo.renderPass = geometryPass.renderPass; renderPassBeginInfo.renderPass = geometryPass.renderPass;
renderPassBeginInfo.framebuffer = geometryPass.framebuffer; renderPassBeginInfo.framebuffer = geometryPass.framebuffer;
...@@ -569,6 +588,7 @@ private: ...@@ -569,6 +588,7 @@ private:
} }
} }
models.cube.bindBuffers(drawCmdBuffers[i]);
objectData.color = glm::vec4(0.0f, 0.0f, 1.0f, 0.5f); objectData.color = glm::vec4(0.0f, 0.0f, 1.0f, 0.5f);
for (uint32_t x = 0; x < 2; x++) for (uint32_t x = 0; x < 2; x++)
{ {
...@@ -611,17 +631,9 @@ private: ...@@ -611,17 +631,9 @@ private:
void draw() void draw()
{ {
VulkanExampleBase::prepareFrame(); VulkanExampleBase::prepareFrame();
// Clear previous geometry pass data
memset(geometryPass.geometry.mapped, 0, sizeof(uint32_t));
// Command buffer to be submitted to the queue
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer]; submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
// Submit to queue
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE)); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame(); VulkanExampleBase::submitFrame();
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment