Triangle example code cleanup, use VK_CHECK_RESULT macro instead of asserts, added more comments
This commit is contained in:
parent
a9f280016f
commit
4a124d75a3
4 changed files with 92 additions and 94 deletions
Binary file not shown.
|
|
@ -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.
|
|
@ -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, ¤tBuffer);
|
VK_CHECK_RESULT(swapChain.acquireNextImage(semaphores.presentComplete, ¤tBuffer));
|
||||||
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, ©CommandBuffer));
|
VK_CHECK_RESULT(vkAllocateCommandBuffers(device, &cmdBufInfo, ©CommandBuffer));
|
||||||
|
|
||||||
// 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,
|
||||||
©Region);
|
©Region);
|
||||||
|
|
||||||
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 = ©CommandBuffer;
|
copySubmitInfo.pCommandBuffers = ©CommandBuffer;
|
||||||
|
|
||||||
vkTools::checkResult(vkQueueSubmit(queue, 1, ©SubmitInfo, VK_NULL_HANDLE));
|
VK_CHECK_RESULT(vkQueueSubmit(queue, 1, ©SubmitInfo, VK_NULL_HANDLE));
|
||||||
vkTools::checkResult(vkQueueWaitIdle(queue));
|
VK_CHECK_RESULT(vkQueueWaitIdle(queue));
|
||||||
|
|
||||||
vkFreeCommandBuffers(device, cmdPool, 1, ©CommandBuffer);
|
vkFreeCommandBuffers(device, cmdPool, 1, ©CommandBuffer);
|
||||||
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue