diff --git a/examples/computeraytracing/computeraytracing.cpp b/examples/computeraytracing/computeraytracing.cpp index f6953f09..0fe99e81 100644 --- a/examples/computeraytracing/computeraytracing.cpp +++ b/examples/computeraytracing/computeraytracing.cpp @@ -128,7 +128,7 @@ public: // Get device properties for the requested texture format VkFormatProperties 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); // Prepare blit target texture diff --git a/examples/descriptorindexing/descriptorindexing.cpp b/examples/descriptorindexing/descriptorindexing.cpp index c2d45f7a..83e5879c 100644 --- a/examples/descriptorindexing/descriptorindexing.cpp +++ b/examples/descriptorindexing/descriptorindexing.cpp @@ -3,6 +3,8 @@ * * 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] * * Copyright (C) 2021-2023 Sascha Willems - www.saschawillems.de @@ -24,12 +26,12 @@ public: vks::Buffer indexBuffer; uint32_t indexCount{ 0 }; - vks::Buffer uniformBufferVS; - struct { + struct UniformData { glm::mat4 projection; glm::mat4 view; glm::mat4 model; - } uboVS; + } uniformData; + vks::Buffer uniformBuffer; VkPipeline pipeline{ VK_NULL_HANDLE }; VkPipelineLayout pipelineLayout{ VK_NULL_HANDLE }; @@ -74,15 +76,17 @@ public: ~VulkanExample() { - for (auto &texture : textures) { - texture.destroy(); + if (device) { + for (auto& texture : textures) { + texture.destroy(); + } + vkDestroyPipeline(device, pipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); + vertexBuffer.destroy(); + indexBuffer.destroy(); + uniformBuffer.destroy(); } - vkDestroyPipeline(device, pipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayout, nullptr); - vertexBuffer.destroy(); - indexBuffer.destroy(); - uniformBufferVS.destroy(); } // 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() { std::vector vertices; @@ -177,19 +181,27 @@ public: indexCount = static_cast(indices.size()); - // For the sake of simplicity we won't stage the vertex data to the gpu memory - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &vertexBuffer, - vertices.size() * sizeof(Vertex), - vertices.data())); - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &indexBuffer, - indices.size() * sizeof(uint32_t), - indices.data())); + // Create buffers and upload data to the GPU + struct StagingBuffers { + vks::Buffer vertices; + vks::Buffer indices; + } stagingBuffers; + + // Host visible source buffers (staging) + 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_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())); + + // Device local destination buffers + 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))); + 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 @@ -211,8 +223,7 @@ public: std::vector setLayoutBindings = { // Binding 0 : Vertex shader uniform buffer 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 - // In the fragment shader: + // [POI] Binding 1 contains a texture array that is dynamically non-uniform sampled from in the fragment shader: // outFragColor = texture(textures[nonuniformEXT(inTexIndex)], inUV); vks::initializers::descriptorSetLayoutBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT, 1, static_cast(textures.size())) }; @@ -257,7 +268,7 @@ public: std::vector 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 std::vector textureDescriptors(textures.size()); @@ -284,10 +295,11 @@ public: void preparePipelines() { - + // Layout VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = vks::initializers::pipelineLayoutCreateInfo(&descriptorSetLayout, 1); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + // Pipeline 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); VkPipelineColorBlendAttachmentState blendAttachmentState = vks::initializers::pipelineColorBlendAttachmentState(0xf, VK_FALSE); @@ -335,21 +347,17 @@ public: void prepareUniformBuffers() { - VK_CHECK_RESULT(vulkanDevice->createBuffer( - VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &uniformBufferVS, - sizeof(uboVS))); - VK_CHECK_RESULT(uniformBufferVS.map()); + 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_CHECK_RESULT(uniformBuffer.map()); updateUniformBuffersCamera(); } void updateUniformBuffersCamera() { - uboVS.projection = camera.matrices.perspective; - uboVS.view = camera.matrices.view; - uboVS.model = glm::mat4(1.0f); - memcpy(uniformBufferVS.mapped, &uboVS, sizeof(uboVS)); + uniformData.projection = camera.matrices.perspective; + uniformData.view = camera.matrices.view; + uniformData.model = glm::mat4(1.0f); + memcpy(uniformBuffer.mapped, &uniformData, sizeof(UniformData)); } 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() { VulkanExampleBase::prepare(); @@ -410,18 +409,21 @@ public: 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() { if (!prepared) return; - draw(); - if (camera.updated) - updateUniformBuffersCamera(); - } - - virtual void viewChanged() - { updateUniformBuffersCamera(); + draw(); } }; diff --git a/examples/vertexattributes/vertexattributes.cpp b/examples/vertexattributes/vertexattributes.cpp index 491b1d3e..f41966fa 100644 --- a/examples/vertexattributes/vertexattributes.cpp +++ b/examples/vertexattributes/vertexattributes.cpp @@ -1,7 +1,7 @@ /* * 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) */ @@ -153,23 +153,25 @@ VulkanExample::VulkanExample() : VulkanExampleBase() VulkanExample::~VulkanExample() { - vkDestroyPipeline(device, pipelines.vertexAttributesInterleaved, nullptr); - vkDestroyPipeline(device, pipelines.vertexAttributesSeparate, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); - vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); - indices.destroy(); - shaderData.buffer.destroy(); - separateVertexBuffers.normal.destroy(); - separateVertexBuffers.pos.destroy(); - separateVertexBuffers.tangent.destroy(); - separateVertexBuffers.uv.destroy(); - interleavedVertexBuffer.destroy(); - for (Image image : scene.images) { - vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); - vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); - vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); - vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); + if (device) { + vkDestroyPipeline(device, pipelines.vertexAttributesInterleaved, nullptr); + vkDestroyPipeline(device, pipelines.vertexAttributesSeparate, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.matrices, nullptr); + vkDestroyDescriptorSetLayout(device, descriptorSetLayouts.textures, nullptr); + indices.destroy(); + shaderData.buffer.destroy(); + separateVertexBuffers.normal.destroy(); + separateVertexBuffers.pos.destroy(); + separateVertexBuffers.tangent.destroy(); + separateVertexBuffers.uv.destroy(); + interleavedVertexBuffer.destroy(); + for (Image image : scene.images) { + vkDestroyImageView(vulkanDevice->logicalDevice, image.texture.view, nullptr); + vkDestroyImage(vulkanDevice->logicalDevice, image.texture.image, nullptr); + vkDestroySampler(vulkanDevice->logicalDevice, image.texture.sampler, nullptr); + vkFreeMemory(vulkanDevice->logicalDevice, image.texture.deviceMemory, nullptr); + } } } @@ -178,6 +180,33 @@ void VulkanExample::getEnabledFeatures() 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() { VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo(); @@ -545,44 +574,10 @@ void VulkanExample::prepare() 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() -{ - renderFrame(); - if (camera.updated) { - updateUniformBuffers(); - } -} - -void VulkanExample::viewChanged() { updateUniformBuffers(); + renderFrame(); } void VulkanExample::OnUpdateUIOverlay(vks::UIOverlay* overlay) diff --git a/examples/vertexattributes/vertexattributes.h b/examples/vertexattributes/vertexattributes.h index ebfd508f..344fde55 100644 --- a/examples/vertexattributes/vertexattributes.h +++ b/examples/vertexattributes/vertexattributes.h @@ -1,7 +1,7 @@ /* * 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) */ @@ -137,6 +137,5 @@ public: void loadSceneNode(const tinygltf::Node& inputNode, const tinygltf::Model& input, Node* parent); void drawSceneNode(VkCommandBuffer commandBuffer, Node node); virtual void render(); - virtual void viewChanged(); virtual void OnUpdateUIOverlay(vks::UIOverlay* overlay); };