Code cleanup

This commit is contained in:
Sascha Willems 2024-01-16 19:32:34 +01:00
parent f211a64153
commit 24591c6570
4 changed files with 108 additions and 112 deletions

View file

@ -128,7 +128,7 @@ public:
// Get device properties for the requested texture format // Get device properties for the requested texture format
VkFormatProperties formatProperties; VkFormatProperties formatProperties;
vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties); vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
// Check if requested image format supports image storage operations required for storing pixesl fromn the compute shader // Check if requested image format supports image storage operations required for storing pixel from the compute shader
assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT); assert(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT);
// Prepare blit target texture // Prepare blit target texture

View file

@ -3,6 +3,8 @@
* *
* Demonstrates use of descriptor indexing to dynamically index into a variable sized array of images * Demonstrates use of descriptor indexing to dynamically index into a variable sized array of images
* *
* The sample renders multiple objects with the index of the texture (descriptor) to use passed as a vertex attribute (aka "descriptor indexing")
*
* Relevant code parts are marked with [POI] * Relevant code parts are marked with [POI]
* *
* Copyright (C) 2021-2023 Sascha Willems - www.saschawillems.de * Copyright (C) 2021-2023 Sascha Willems - www.saschawillems.de
@ -24,12 +26,12 @@ public:
vks::Buffer indexBuffer; vks::Buffer indexBuffer;
uint32_t indexCount{ 0 }; uint32_t indexCount{ 0 };
vks::Buffer uniformBufferVS; struct UniformData {
struct {
glm::mat4 projection; glm::mat4 projection;
glm::mat4 view; glm::mat4 view;
glm::mat4 model; glm::mat4 model;
} uboVS; } uniformData;
vks::Buffer uniformBuffer;
VkPipeline pipeline{ VK_NULL_HANDLE }; VkPipeline pipeline{ VK_NULL_HANDLE };
VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE };
@ -74,6 +76,7 @@ public:
~VulkanExample() ~VulkanExample()
{ {
if (device) {
for (auto& texture : textures) { for (auto& texture : textures) {
texture.destroy(); texture.destroy();
} }
@ -82,7 +85,8 @@ public:
vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr);
vertexBuffer.destroy(); vertexBuffer.destroy();
indexBuffer.destroy(); indexBuffer.destroy();
uniformBufferVS.destroy(); uniformBuffer.destroy();
}
} }
// Generate some random textures // Generate some random textures
@ -106,7 +110,7 @@ public:
} }
} }
// Generates a line of cubes with randomized per-face texture indices // Generates a line of cubes with randomized per-face texture indices and uploads them to the GPU
void generateCubes() void generateCubes()
{ {
std::vector<Vertex> vertices; std::vector<Vertex> vertices;
@ -177,19 +181,27 @@ public:
indexCount = static_cast<uint32_t>(indices.size()); indexCount = static_cast<uint32_t>(indices.size());
// For the sake of simplicity we won't stage the vertex data to the gpu memory // Create buffers and upload data to the GPU
VK_CHECK_RESULT(vulkanDevice->createBuffer( struct StagingBuffers {
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, vks::Buffer vertices;
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vks::Buffer indices;
&vertexBuffer, } stagingBuffers;
vertices.size() * sizeof(Vertex),
vertices.data())); // Host visible source buffers (staging)
VK_CHECK_RESULT(vulkanDevice->createBuffer( VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.vertices, vertices.size() * sizeof(Vertex), vertices.data()));
VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, &stagingBuffers.indices, indices.size() * sizeof(uint32_t), indices.data()));
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&indexBuffer, // Device local destination buffers
indices.size() * sizeof(uint32_t), VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &vertexBuffer, vertices.size() * sizeof(Vertex)));
indices.data())); VK_CHECK_RESULT(vulkanDevice->createBuffer(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &indexBuffer, indices.size() * sizeof(uint32_t)));
// Copy from host do device
vulkanDevice->copyBuffer(&stagingBuffers.vertices, &vertexBuffer, queue);
vulkanDevice->copyBuffer(&stagingBuffers.indices, &indexBuffer, queue);
// Clean up
stagingBuffers.vertices.destroy();
stagingBuffers.indices.destroy();
} }
// [POI] Set up descriptor sets and set layout // [POI] Set up descriptor sets and set layout
@ -211,8 +223,7 @@ public:
std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = { std::vector<VkDescriptorSetLayoutBinding> setLayoutBindings = {
// Binding 0 : Vertex shader uniform buffer // Binding 0 : Vertex shader uniform buffer
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0), vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_SHADER_STAGE_VERTEX_BIT, 0),
// [POI] Binding 1 contains a texture array that is dynamically non-uniform sampled from // [POI] Binding 1 contains a texture array that is dynamically non-uniform sampled from in the fragment shader:
// In the fragment shader:
// outFragColor = texture(textures[nonuniformEXT(inTexIndex)], inUV); // outFragColor = texture(textures[nonuniformEXT(inTexIndex)], inUV);
vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1, static_cast<uint32_t>(textures.size())) vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1, static_cast<uint32_t>(textures.size()))
}; };
@ -257,7 +268,7 @@ public:
std::vector<VkWriteDescriptorSet> writeDescriptorSets(2); std::vector<VkWriteDescriptorSet> writeDescriptorSets(2);
writeDescriptorSets[0] = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBufferVS.descriptor); writeDescriptorSets[0] = vks::initializers::writeDescriptorSet(descriptorSet, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, &uniformBuffer.descriptor);
// Image descriptors for the texture array // Image descriptors for the texture array
std::vector<VkDescriptorImageInfo> textureDescriptors(textures.size()); std::vector<VkDescriptorImageInfo> textureDescriptors(textures.size());
@ -284,10 +295,11 @@ public:
void preparePipelines() void preparePipelines()
{ {
// Layout
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1);
VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout));
// Pipeline
VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE); VkPipelineInputAssemblyStateCreateInfo inputAssemblyStateCI = vks::initializers::pipelineInputAssemblyStateCreateInfo(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0, VK_FALSE);
VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0); VkPipelineRasterizationStateCreateInfo rasterizationStateCI = vks::initializers::pipelineRasterizationStateCreateInfo(VK_POLYGON_MODE_FILL, VK_CULL_MODE_NONE, VK_FRONT_FACE_COUNTER_CLOCKWISE, 0);
VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE);
@ -335,21 +347,17 @@ public:
void prepareUniformBuffers() void prepareUniformBuffers()
{ {
VK_CHECK_RESULT(vulkanDevice->createBuffer( 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)));
VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_CHECK_RESULT(uniformBuffer.map());
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&uniformBufferVS,
sizeof(uboVS)));
VK_CHECK_RESULT(uniformBufferVS.map());
updateUniformBuffersCamera(); updateUniformBuffersCamera();
} }
void updateUniformBuffersCamera() void updateUniformBuffersCamera()
{ {
uboVS.projection = camera.matrices.perspective; uniformData.projection = camera.matrices.perspective;
uboVS.view = camera.matrices.view; uniformData.view = camera.matrices.view;
uboVS.model = glm::mat4(1.0f); uniformData.model = glm::mat4(1.0f);
memcpy(uniformBufferVS.mapped, &uboVS, sizeof(uboVS)); memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData));
} }
void buildCommandBuffers() void buildCommandBuffers()
@ -389,15 +397,6 @@ public:
} }
} }
void draw()
{
VulkanExampleBase::prepareFrame();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
}
void prepare() void prepare()
{ {
VulkanExampleBase::prepare(); VulkanExampleBase::prepare();
@ -410,18 +409,21 @@ public:
prepared = true; prepared = true;
} }
void draw()
{
VulkanExampleBase::prepareFrame();
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &drawCmdBuffers[currentBuffer];
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
VulkanExampleBase::submitFrame();
}
virtual void render() virtual void render()
{ {
if (!prepared) if (!prepared)
return; return;
updateUniformBuffersCamera();
draw(); draw();
if (camera.updated)
updateUniformBuffersCamera();
}
virtual void viewChanged()
{
updateUniformBuffersCamera();
} }
}; };

View file

@ -1,7 +1,7 @@
/* /*
* Vulkan Example - Passing vertex attributes using interleaved and separate buffers * Vulkan Example - Passing vertex attributes using interleaved and separate buffers
* *
* Copyright (C) 2022 by Sascha Willems - www.saschawillems.de * Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de
* *
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/ */
@ -153,6 +153,7 @@ VulkanExample::VulkanExample() : VulkanExampleBase()
VulkanExample::~VulkanExample() VulkanExample::~VulkanExample()
{ {
if (device) {
vkDestroyPipeline(device, pipelines.vertexAttributesInterleaved, nullptr); vkDestroyPipeline(device, pipelines.vertexAttributesInterleaved, nullptr);
vkDestroyPipeline(device, pipelines.vertexAttributesSeparate, nullptr); vkDestroyPipeline(device, pipelines.vertexAttributesSeparate, nullptr);
vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
@ -172,12 +173,40 @@ VulkanExample::~VulkanExample()
vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr);
} }
} }
}
void VulkanExample::getEnabledFeatures() void VulkanExample::getEnabledFeatures()
{ {
enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy; enabledFeatures.samplerAnisotropy = deviceFeatures.samplerAnisotropy;
} }
void VulkanExample::drawSceneNode(VkCommandBuffer commandBuffer, Node node)
{
if (node.mesh.primitives.size() > 0) {
PushConstBlock pushConstBlock;
glm::mat4 nodeMatrix = node.matrix;
Node* currentParent = node.parent;
while (currentParent) {
nodeMatrix = currentParent->matrix * nodeMatrix;
currentParent = currentParent->parent;
}
for (Primitive& primitive : node.mesh.primitives) {
if (primitive.indexCount > 0) {
Material& material = scene.materials[primitive.materialIndex];
pushConstBlock.nodeMatrix = nodeMatrix;
pushConstBlock.alphaMask = (material.alphaMode == "MASK");
pushConstBlock.alphaMaskCutoff = material.alphaCutOff;
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &material.descriptorSet, 0, nullptr);
vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0);
}
}
}
for (auto& child : node.children) {
drawSceneNode(commandBuffer, child);
}
}
void VulkanExample::buildCommandBuffers() void VulkanExample::buildCommandBuffers()
{ {
VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
@ -545,44 +574,10 @@ void VulkanExample::prepare()
prepared = true; prepared = true;
} }
void VulkanExample::drawSceneNode(VkCommandBuffer commandBuffer, Node node)
{
if (node.mesh.primitives.size() > 0) {
PushConstBlock pushConstBlock;
glm::mat4 nodeMatrix = node.matrix;
Node* currentParent = node.parent;
while (currentParent) {
nodeMatrix = currentParent->matrix * nodeMatrix;
currentParent = currentParent->parent;
}
for (Primitive& primitive : node.mesh.primitives) {
if (primitive.indexCount > 0) {
Material& material = scene.materials[primitive.materialIndex];
pushConstBlock.nodeMatrix = nodeMatrix;
pushConstBlock.alphaMask = (material.alphaMode == "MASK");
pushConstBlock.alphaMaskCutoff = material.alphaCutOff;
vkCmdPushConstants(commandBuffer, pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(PushConstBlock), &pushConstBlock);
vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 1, 1, &material.descriptorSet, 0, nullptr);
vkCmdDrawIndexed(commandBuffer, primitive.indexCount, 1, primitive.firstIndex, 0, 0);
}
}
}
for (auto& child : node.children) {
drawSceneNode(commandBuffer, child);
}
}
void VulkanExample::render() void VulkanExample::render()
{ {
updateUniformBuffers();
renderFrame(); renderFrame();
if (camera.updated) {
updateUniformBuffers();
}
}
void VulkanExample::viewChanged()
{
updateUniformBuffers();
} }
void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay)

View file

@ -1,7 +1,7 @@
/* /*
* Vulkan Example - Passing vertex attributes using interleaved and separate buffers * Vulkan Example - Passing vertex attributes using interleaved and separate buffers
* *
* Copyright (C) 2022 by Sascha Willems - www.saschawillems.de * Copyright (C) 2022-2023 by Sascha Willems - www.saschawillems.de
* *
* This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT) * This code is licensed under the MIT license (MIT) (http://opensource.org/licenses/MIT)
*/ */
@ -137,6 +137,5 @@ public:
void loadSceneNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, Node* parent); void loadSceneNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, Node* parent);
void drawSceneNode(VkCommandBuffer commandBuffer, Node node); void drawSceneNode(VkCommandBuffer commandBuffer, Node node);
virtual void render(); virtual void render();
virtual void viewChanged();
virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay);
}; };