Triangle example code cleanup, use VK_CHECK_RESULT macro instead of asserts, added more comments

This commit is contained in:
saschawillems 2016-05-11 20:39:22 +02:00
parent a9f280016f
commit 4a124d75a3
4 changed files with 92 additions and 94 deletions

Binary file not shown.

View file

@ -15,6 +15,12 @@ layout (binding = 0) uniform UBO
layout (location = 0) out vec3 outColor; layout (location = 0) out vec3 outColor;
out gl_PerVertex
{
vec4 gl_Position;
};
void main() void main()
{ {
outColor = inColor; outColor = inColor;

Binary file not shown.

View file

@ -133,16 +133,16 @@ public:
renderPassBeginInfo.clearValueCount = 2; renderPassBeginInfo.clearValueCount = 2;
renderPassBeginInfo.pClearValues = clearValues; renderPassBeginInfo.pClearValues = clearValues;
VkResult err;
for (int32_t i = 0; i < drawCmdBuffers.size(); ++i) for (int32_t i = 0; i < drawCmdBuffers.size(); ++i)
{ {
// Set target frame buffer // Set target frame buffer
renderPassBeginInfo.framebuffer = frameBuffers[i]; renderPassBeginInfo.framebuffer = frameBuffers[i];
err = vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo); VK_CHECK_RESULT(vkBeginCommandBuffer(drawCmdBuffers[i], &cmdBufInfo));
assert(!err);
// Start the first sub pass specified in our default render pass setup by the base class
// This will clear the color and depth attachment
vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE); vkCmdBeginRenderPass(drawCmdBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
// Update dynamic viewport state // Update dynamic viewport state
@ -204,17 +204,14 @@ public:
0, nullptr, 0, nullptr,
1, &prePresentBarrier); 1, &prePresentBarrier);
err = vkEndCommandBuffer(drawCmdBuffers[i]); VK_CHECK_RESULT(vkEndCommandBuffer(drawCmdBuffers[i]));
assert(!err);
} }
} }
void draw() void draw()
{ {
VkResult err;
// Get next image in the swap chain (back/front buffer) // Get next image in the swap chain (back/front buffer)
err = swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer); VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, &currentBuffer));
assert(!err);
// Add a post present image memory barrier // Add a post present image memory barrier
// This will transform the frame buffer color attachment back // This will transform the frame buffer color attachment back
@ -236,8 +233,7 @@ public:
VkCommandBufferBeginInfo cmdBufInfo = {}; VkCommandBufferBeginInfo cmdBufInfo = {};
cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; cmdBufInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
err = vkBeginCommandBuffer(postPresentCmdBuffer, &cmdBufInfo); VK_CHECK_RESULT(vkBeginCommandBuffer(postPresentCmdBuffer, &cmdBufInfo));
assert(!err);
// Put post present barrier into command buffer // Put post present barrier into command buffer
vkCmdPipelineBarrier( vkCmdPipelineBarrier(
@ -249,19 +245,19 @@ public:
0, nullptr, 0, nullptr,
1, &postPresentBarrier); 1, &postPresentBarrier);
err = vkEndCommandBuffer(postPresentCmdBuffer); VK_CHECK_RESULT(vkEndCommandBuffer(postPresentCmdBuffer));
assert(!err);
// Submit to the queue // Submit the image barrier to the current queue
submitInfo = {}; submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1; submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &postPresentCmdBuffer; submitInfo.pCommandBuffers = &postPresentCmdBuffer;
err = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
assert(!err);
err = vkQueueWaitIdle(queue); // Make sure that the image barrier command submitted to the queue
assert(!err); // has finished executing
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
// The submit infor strcuture contains a list of // The submit infor strcuture contains a list of
// command buffers and semaphores to be submitted to a queue // command buffers and semaphores to be submitted to a queue
@ -284,15 +280,13 @@ public:
submitInfo.pSignalSemaphores = &semaphores.renderComplete; submitInfo.pSignalSemaphores = &semaphores.renderComplete;
// Submit to the graphics queue // Submit to the graphics queue
err = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
assert(!err);
// Present the current buffer to the swap chain // Present the current buffer to the swap chain
// We pass the signal semaphore from the submit info // We pass the signal semaphore from the submit info
// to ensure that the image is not rendered until // to ensure that the image is not rendered until
// all commands have been submitted // all commands have been submitted
err = swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete); VK_CHECK_RESULT(swapChain.queuePresent(queue, currentBuffer, semaphores.renderComplete));
assert(!err);
} }
// Create synchronzation semaphores // Create synchronzation semaphores
@ -304,13 +298,11 @@ public:
// This semaphore ensures that the image is complete // This semaphore ensures that the image is complete
// before starting to submit again // before starting to submit again
VkResult err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.presentComplete); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.presentComplete));
assert(!err);
// This semaphore ensures that all commands submitted // This semaphore ensures that all commands submitted
// have been finished before submitting the image to the queue // have been finished before submitting the image to the queue
err = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.renderComplete); VK_CHECK_RESULT(vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphores.renderComplete));
assert(!err);
} }
// Setups vertex and index buffers for an indexed triangle, // Setups vertex and index buffers for an indexed triangle,
@ -352,6 +344,8 @@ public:
// - Copy the data to this buffer // - Copy the data to this buffer
// - Create another buffer that's local on the device (VRAM) with the same size // - Create another buffer that's local on the device (VRAM) with the same size
// - Copy the data from the host to the device using a command buffer // - Copy the data from the host to the device using a command buffer
// - Delete the host visible (staging) buffer
// - Use the device local buffers for rendering
struct StagingBuffer { struct StagingBuffer {
VkDeviceMemory memory; VkDeviceMemory memory;
@ -371,7 +365,7 @@ public:
cmdBufInfo.commandBufferCount = 1; cmdBufInfo.commandBufferCount = 1;
VkCommandBuffer copyCommandBuffer; VkCommandBuffer copyCommandBuffer;
vkTools::checkResult(vkAllocateCommandBuffers(device, &cmdBufInfo, &copyCommandBuffer)); VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufInfo, &copyCommandBuffer));
// Vertex buffer // Vertex buffer
VkBufferCreateInfo vertexBufferInfo = {}; VkBufferCreateInfo vertexBufferInfo = {};
@ -380,52 +374,51 @@ public:
// Buffer is used as the copy source // Buffer is used as the copy source
vertexBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; vertexBufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
// Create a host-visible buffer to copy the vertex data to (staging buffer) // Create a host-visible buffer to copy the vertex data to (staging buffer)
vkTools::checkResult(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &stagingBuffers.vertices.buffer)); VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &stagingBuffers.vertices.buffer));
vkGetBufferMemoryRequirements(device, stagingBuffers.vertices.buffer, &memReqs); vkGetBufferMemoryRequirements(device, stagingBuffers.vertices.buffer, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.vertices.memory)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.vertices.memory));
// Map and copy // Map and copy
vkTools::checkResult(vkMapMemory(device, stagingBuffers.vertices.memory, 0, memAlloc.allocationSize, 0, &data)); VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.vertices.memory, 0, memAlloc.allocationSize, 0, &data));
memcpy(data, vertexBuffer.data(), vertexBufferSize); memcpy(data, vertexBuffer.data(), vertexBufferSize);
vkUnmapMemory(device, stagingBuffers.vertices.memory); vkUnmapMemory(device, stagingBuffers.vertices.memory);
vkTools::checkResult(vkBindBufferMemory(device, stagingBuffers.vertices.buffer, stagingBuffers.vertices.memory, 0)); VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffers.vertices.buffer, stagingBuffers.vertices.memory, 0));
// Create the destination buffer with device only visibility // Create the destination buffer with device only visibility
// Buffer will be used as a vertex buffer and is the copy destination // Buffer will be used as a vertex buffer and is the copy destination
vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkTools::checkResult(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buf)); VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buf));
vkGetBufferMemoryRequirements(device, vertices.buf, &memReqs); vkGetBufferMemoryRequirements(device, vertices.buf, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAlloc.memoryTypeIndex); memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.mem)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.mem));
vkTools::checkResult(vkBindBufferMemory(device, vertices.buf, vertices.mem, 0)); VK_CHECK_RESULT(vkBindBufferMemory(device, vertices.buf, vertices.mem, 0));
// Index buffer // Index buffer
// todo : comment
VkBufferCreateInfo indexbufferInfo = {}; VkBufferCreateInfo indexbufferInfo = {};
indexbufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; indexbufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
indexbufferInfo.size = indexBufferSize; indexbufferInfo.size = indexBufferSize;
indexbufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT; indexbufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
// Copy index data to a buffer visible to the host (staging buffer) // Copy index data to a buffer visible to the host (staging buffer)
vkTools::checkResult(vkCreateBuffer(device, &indexbufferInfo, nullptr, &stagingBuffers.indices.buffer)); VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &stagingBuffers.indices.buffer));
vkGetBufferMemoryRequirements(device, stagingBuffers.indices.buffer, &memReqs); vkGetBufferMemoryRequirements(device, stagingBuffers.indices.buffer, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.indices.memory)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &stagingBuffers.indices.memory));
vkTools::checkResult(vkMapMemory(device, stagingBuffers.indices.memory, 0, indexBufferSize, 0, &data)); VK_CHECK_RESULT(vkMapMemory(device, stagingBuffers.indices.memory, 0, indexBufferSize, 0, &data));
memcpy(data, indexBuffer.data(), indexBufferSize); memcpy(data, indexBuffer.data(), indexBufferSize);
vkUnmapMemory(device, stagingBuffers.indices.memory); vkUnmapMemory(device, stagingBuffers.indices.memory);
vkTools::checkResult(vkBindBufferMemory(device, stagingBuffers.indices.buffer, stagingBuffers.indices.memory, 0)); VK_CHECK_RESULT(vkBindBufferMemory(device, stagingBuffers.indices.buffer, stagingBuffers.indices.memory, 0));
// Create destination buffer with device only visibility // Create destination buffer with device only visibility
indexbufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; indexbufferInfo.usage = VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
vkTools::checkResult(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buf)); VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buf));
vkGetBufferMemoryRequirements(device, indices.buf, &memReqs); vkGetBufferMemoryRequirements(device, indices.buf, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memAlloc.memoryTypeIndex); memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &indices.mem)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indices.mem));
vkTools::checkResult(vkBindBufferMemory(device, indices.buf, indices.mem, 0)); VK_CHECK_RESULT(vkBindBufferMemory(device, indices.buf, indices.mem, 0));
indices.count = indexBuffer.size(); indices.count = indexBuffer.size();
VkCommandBufferBeginInfo cmdBufferBeginInfo = {}; VkCommandBufferBeginInfo cmdBufferBeginInfo = {};
@ -437,7 +430,7 @@ public:
// Put buffer region copies into command buffer // Put buffer region copies into command buffer
// Note that the staging buffer must not be deleted before the copies // Note that the staging buffer must not be deleted before the copies
// have been submitted and executed // have been submitted and executed
vkTools::checkResult(vkBeginCommandBuffer(copyCommandBuffer, &cmdBufferBeginInfo)); VK_CHECK_RESULT(vkBeginCommandBuffer(copyCommandBuffer, &cmdBufferBeginInfo));
// Vertex buffer // Vertex buffer
copyRegion.size = vertexBufferSize; copyRegion.size = vertexBufferSize;
@ -456,7 +449,7 @@ public:
1, 1,
&copyRegion); &copyRegion);
vkTools::checkResult(vkEndCommandBuffer(copyCommandBuffer)); VK_CHECK_RESULT(vkEndCommandBuffer(copyCommandBuffer));
// Submit copies to the queue // Submit copies to the queue
VkSubmitInfo copySubmitInfo = {}; VkSubmitInfo copySubmitInfo = {};
@ -464,8 +457,8 @@ public:
copySubmitInfo.commandBufferCount = 1; copySubmitInfo.commandBufferCount = 1;
copySubmitInfo.pCommandBuffers = &copyCommandBuffer; copySubmitInfo.pCommandBuffers = &copyCommandBuffer;
vkTools::checkResult(vkQueueSubmit(queue, 1, &copySubmitInfo, VK_NULL_HANDLE)); VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &copySubmitInfo, VK_NULL_HANDLE));
vkTools::checkResult(vkQueueWaitIdle(queue)); VK_CHECK_RESULT(vkQueueWaitIdle(queue));
vkFreeCommandBuffers(device, cmdPool, 1, &copyCommandBuffer); vkFreeCommandBuffers(device, cmdPool, 1, &copyCommandBuffer);
@ -480,7 +473,8 @@ public:
// Don't use staging // Don't use staging
// Create host-visible buffers only and use these for rendering // Create host-visible buffers only and use these for rendering
// This is not advised for real world applications and will // This is not advised for real world applications and will
// result in lower performances // result in lower performances at least on devices that
// separate between host visible and device local memory
// Vertex buffer // Vertex buffer
VkBufferCreateInfo vertexBufferInfo = {}; VkBufferCreateInfo vertexBufferInfo = {};
@ -489,15 +483,15 @@ public:
vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; vertexBufferInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
// Copy vertex data to a buffer visible to the host // Copy vertex data to a buffer visible to the host
vkTools::checkResult(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buf)); VK_CHECK_RESULT(vkCreateBuffer(device, &vertexBufferInfo, nullptr, &vertices.buf));
vkGetBufferMemoryRequirements(device, vertices.buf, &memReqs); vkGetBufferMemoryRequirements(device, vertices.buf, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.mem)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &vertices.mem));
vkTools::checkResult(vkMapMemory(device, vertices.mem, 0, memAlloc.allocationSize, 0, &data)); VK_CHECK_RESULT(vkMapMemory(device, vertices.mem, 0, memAlloc.allocationSize, 0, &data));
memcpy(data, vertexBuffer.data(), vertexBufferSize); memcpy(data, vertexBuffer.data(), vertexBufferSize);
vkUnmapMemory(device, vertices.mem); vkUnmapMemory(device, vertices.mem);
vkTools::checkResult(vkBindBufferMemory(device, vertices.buf, vertices.mem, 0)); VK_CHECK_RESULT(vkBindBufferMemory(device, vertices.buf, vertices.mem, 0));
// Index buffer // Index buffer
VkBufferCreateInfo indexbufferInfo = {}; VkBufferCreateInfo indexbufferInfo = {};
@ -507,15 +501,15 @@ public:
// Copy index data to a buffer visible to the host // Copy index data to a buffer visible to the host
memset(&indices, 0, sizeof(indices)); memset(&indices, 0, sizeof(indices));
vkTools::checkResult(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buf)); VK_CHECK_RESULT(vkCreateBuffer(device, &indexbufferInfo, nullptr, &indices.buf));
vkGetBufferMemoryRequirements(device, indices.buf, &memReqs); vkGetBufferMemoryRequirements(device, indices.buf, &memReqs);
memAlloc.allocationSize = memReqs.size; memAlloc.allocationSize = memReqs.size;
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &memAlloc.memoryTypeIndex); memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
vkTools::checkResult(vkAllocateMemory(device, &memAlloc, nullptr, &indices.mem)); VK_CHECK_RESULT(vkAllocateMemory(device, &memAlloc, nullptr, &indices.mem));
vkTools::checkResult(vkMapMemory(device, indices.mem, 0, indexBufferSize, 0, &data)); VK_CHECK_RESULT(vkMapMemory(device, indices.mem, 0, indexBufferSize, 0, &data));
memcpy(data, indexBuffer.data(), indexBufferSize); memcpy(data, indexBuffer.data(), indexBufferSize);
vkUnmapMemory(device, indices.mem); vkUnmapMemory(device, indices.mem);
vkTools::checkResult(vkBindBufferMemory(device, indices.buf, indices.mem, 0)); VK_CHECK_RESULT(vkBindBufferMemory(device, indices.buf, indices.mem, 0));
indices.count = indexBuffer.size(); indices.count = indexBuffer.size();
} }
@ -539,7 +533,7 @@ public:
vertices.attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; vertices.attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
vertices.attributeDescriptions[1].offset = sizeof(float) * 3; vertices.attributeDescriptions[1].offset = sizeof(float) * 3;
// Assign to vertex buffer // Assign to vertex input state
vertices.inputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; vertices.inputState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertices.inputState.pNext = NULL; vertices.inputState.pNext = NULL;
vertices.inputState.flags = VK_FLAGS_NONE; vertices.inputState.flags = VK_FLAGS_NONE;
@ -573,8 +567,7 @@ public:
// Requesting descriptors beyond maxSets will result in an error // Requesting descriptors beyond maxSets will result in an error
descriptorPoolInfo.maxSets = 1; descriptorPoolInfo.maxSets = 1;
VkResult vkRes = vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool); VK_CHECK_RESULT(vkCreateDescriptorPool(device, &descriptorPoolInfo, nullptr, &descriptorPool));
assert(!vkRes);
} }
void setupDescriptorSetLayout() void setupDescriptorSetLayout()
@ -598,8 +591,7 @@ public:
descriptorLayout.bindingCount = 1; descriptorLayout.bindingCount = 1;
descriptorLayout.pBindings = &layoutBinding; descriptorLayout.pBindings = &layoutBinding;
VkResult err = vkCreateDescriptorSetLayout(device, &descriptorLayout, NULL, &descriptorSetLayout); VK_CHECK_RESULT(vkCreateDescriptorSetLayout(device, &descriptorLayout, NULL, &descriptorSetLayout));
assert(!err);
// Create the pipeline layout that is used to generate the rendering pipelines that // Create the pipeline layout that is used to generate the rendering pipelines that
// are based on this descriptor set layout // are based on this descriptor set layout
@ -611,25 +603,25 @@ public:
pPipelineLayoutCreateInfo.setLayoutCount = 1; pPipelineLayoutCreateInfo.setLayoutCount = 1;
pPipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout; pPipelineLayoutCreateInfo.pSetLayouts = &descriptorSetLayout;
err = vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout); VK_CHECK_RESULT(vkCreatePipelineLayout(device, &pPipelineLayoutCreateInfo, nullptr, &pipelineLayout));
assert(!err);
} }
void setupDescriptorSet() void setupDescriptorSet()
{ {
// Update descriptor sets determining the shader binding points // Allocate a new descriptor set from the global descriptor pool
// For every binding point used in a shader there needs to be one
// descriptor set matching that binding point
VkWriteDescriptorSet writeDescriptorSet = {};
VkDescriptorSetAllocateInfo allocInfo = {}; VkDescriptorSetAllocateInfo allocInfo = {};
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = descriptorPool; allocInfo.descriptorPool = descriptorPool;
allocInfo.descriptorSetCount = 1; allocInfo.descriptorSetCount = 1;
allocInfo.pSetLayouts = &descriptorSetLayout; allocInfo.pSetLayouts = &descriptorSetLayout;
VkResult vkRes = vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet); VK_CHECK_RESULT(vkAllocateDescriptorSets(device, &allocInfo, &descriptorSet));
assert(!vkRes);
// Update the descriptor set determining the shader binding points
// For every binding point used in a shader there needs to be one
// descriptor set matching that binding point
VkWriteDescriptorSet writeDescriptorSet = {};
// Binding 0 : Uniform buffer // Binding 0 : Uniform buffer
writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; writeDescriptorSet.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
@ -661,8 +653,6 @@ public:
VkGraphicsPipelineCreateInfo pipelineCreateInfo = {}; VkGraphicsPipelineCreateInfo pipelineCreateInfo = {};
VkResult err;
pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; pipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
// The layout used for this pipeline // The layout used for this pipeline
pipelineCreateInfo.layout = pipelineLayout; pipelineCreateInfo.layout = pipelineLayout;
@ -767,13 +757,14 @@ public:
pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.pDynamicState = &dynamicState;
// Create rendering pipeline // Create rendering pipeline
err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid); VK_CHECK_RESULT(vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipelineCreateInfo, nullptr, &pipelines.solid));
assert(!err);
} }
void prepareUniformBuffers() void prepareUniformBuffers()
{ {
// Prepare and initialize uniform buffer containing shader uniforms // Prepare and initialize a uniform buffer block containing shader uniforms
// In Vulkan there are no more single uniforms like in GL
// All shader uniforms are passed as uniform buffer blocks
VkMemoryRequirements memReqs; VkMemoryRequirements memReqs;
// Vertex shader uniform buffer block // Vertex shader uniform buffer block
@ -783,27 +774,24 @@ public:
allocInfo.pNext = NULL; allocInfo.pNext = NULL;
allocInfo.allocationSize = 0; allocInfo.allocationSize = 0;
allocInfo.memoryTypeIndex = 0; allocInfo.memoryTypeIndex = 0;
VkResult err;
bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
bufferInfo.size = sizeof(uboVS); bufferInfo.size = sizeof(uboVS);
bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT; bufferInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
// Create a new buffer // Create a new buffer
err = vkCreateBuffer(device, &bufferInfo, nullptr, &uniformDataVS.buffer); VK_CHECK_RESULT(vkCreateBuffer(device, &bufferInfo, nullptr, &uniformDataVS.buffer));
assert(!err);
// Get memory requirements including size, alignment and memory type // Get memory requirements including size, alignment and memory type
vkGetBufferMemoryRequirements(device, uniformDataVS.buffer, &memReqs); vkGetBufferMemoryRequirements(device, uniformDataVS.buffer, &memReqs);
allocInfo.allocationSize = memReqs.size; allocInfo.allocationSize = memReqs.size;
// Gets the appropriate memory type for this type of buffer allocation // Get the memory type index that supports host visibile memory access
// Only memory types that are visible to the host // Most implementations offer multiple memory tpyes and selecting the
getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, &allocInfo.memoryTypeIndex); // correct one to allocate memory from is important
allocInfo.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT);
// Allocate memory for the uniform buffer // Allocate memory for the uniform buffer
err = vkAllocateMemory(device, &allocInfo, nullptr, &(uniformDataVS.memory)); VK_CHECK_RESULT(vkAllocateMemory(device, &allocInfo, nullptr, &(uniformDataVS.memory)));
assert(!err);
// Bind memory to buffer // Bind memory to buffer
err = vkBindBufferMemory(device, uniformDataVS.buffer, uniformDataVS.memory, 0); VK_CHECK_RESULT(vkBindBufferMemory(device, uniformDataVS.buffer, uniformDataVS.memory, 0));
assert(!err);
// Store information in the uniform's descriptor // Store information in the uniform's descriptor
uniformDataVS.descriptor.buffer = uniformDataVS.buffer; uniformDataVS.descriptor.buffer = uniformDataVS.buffer;
@ -826,12 +814,12 @@ public:
uboVS.modelMatrix = glm::rotate(uboVS.modelMatrix, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f)); uboVS.modelMatrix = glm::rotate(uboVS.modelMatrix, glm::radians(rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
// Map uniform buffer and update it // Map uniform buffer and update it
// If you want to keep a handle to the memory and not unmap it afer updating,
// create the memory with the VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
uint8_t *pData; uint8_t *pData;
VkResult err = vkMapMemory(device, uniformDataVS.memory, 0, sizeof(uboVS), 0, (void **)&pData); VK_CHECK_RESULT(vkMapMemory(device, uniformDataVS.memory, 0, sizeof(uboVS), 0, (void **)&pData));
assert(!err);
memcpy(pData, &uboVS, sizeof(uboVS)); memcpy(pData, &uboVS, sizeof(uboVS));
vkUnmapMemory(device, uniformDataVS.memory); vkUnmapMemory(device, uniformDataVS.memory);
assert(!err);
} }
void prepare() void prepare()
@ -852,13 +840,17 @@ public:
{ {
if (!prepared) if (!prepared)
return; return;
vkDeviceWaitIdle(device);
draw(); draw();
vkDeviceWaitIdle(device); vkDeviceWaitIdle(device);
} }
virtual void viewChanged() virtual void viewChanged()
{ {
// Before updating the uniform buffer we want to make
// sure that the device has finished all operations
// In a real-world application you would use synchronization
// objects for this
vkDeviceWaitIdle(device);
// This function is called by the base example class // This function is called by the base example class
// each time the view is changed by user input // each time the view is changed by user input
updateUniformBuffers(); updateUniformBuffers();