diff --git a/.idea/editor.xml b/.idea/editor.xml
index 33921db..8d0e15e 100644
--- a/.idea/editor.xml
+++ b/.idea/editor.xml
@@ -246,22 +246,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/renderer/renderer.cpp b/renderer/renderer.cpp
index c1d2f33..835989f 100644
--- a/renderer/renderer.cpp
+++ b/renderer/renderer.cpp
@@ -49,7 +49,7 @@ void Renderer::submit_quad() {
cmd.colored_quad = {
.position = pos,
.size = {0.25, 0.25},
- .color = {1, 1, 1, 1},
+ .color = {0, 1, 1, 1},
};
commands.push_back(cmd);
@@ -285,270 +285,6 @@ void Renderer::destroy_buffer(const AllocatedBuffer& buffer) {
//
// }
-void Renderer::end_frame() {
-
- Frame &frame = frames[currentFrame];
-
- vkWaitForFences(device, 1, &frame.in_flight_fence, VK_TRUE, UINT64_MAX);
- vkResetFences(device, 1, &frame.in_flight_fence);
-
- uint32_t imageIndex;
- vkAcquireNextImageKHR(
- device,
- swapchain,
- UINT64_MAX,
- frame.imageAvailable,
- VK_NULL_HANDLE,
- &imageIndex
- );
-
- commands = counting_sort_descending(commands, [](const RenderCommand &cmd){
- return cmd.key.depth;
- });
-
- std::vector vertices;
-
- for (auto& cmd : commands) {
-
-
- switch (cmd.pipeline) {
- case PipelineType::ColoredQuad: {
- const auto &q = cmd.colored_quad;
-
- // Calculate spatial corners
- float x0 = q.position.x;
- float y0 = q.position.y;
- float x1 = q.position.x + q.size.x;
- float y1 = q.position.y + q.size.y;
-
- // Calculate UV corners
- // float u0 = q.uvMin.x;
- // float v0 = q.uvMin.y;
- // float u1 = q.uvMax.x;
- // float v1 = q.uvMax.y;
-
- // Define the 4 corners of the quad
- vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {0, 0}, q.color, 1, 0 };
- vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {0, 0}, q.color, 1, 0 };
- vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {0, 0}, q.color, 1, 0 };
- vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {0, 0}, q.color, 1, 0 };
-
- // vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {u0, v0}, q.color, 1, q.textureID };
- // vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {u1, v0}, q.color, 1, q.textureID };
- // vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {u0, v1}, q.color, 1, q.textureID };
- // vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {u1, v1}, q.color, 1, q.textureID };
-
- // --- Triangle 1 (TL, TR, BL) ---
- vertices.push_back(vTL);
- vertices.push_back(vTR);
- vertices.push_back(vBL);
-
- // --- Triangle 2 (TR, BR, BL) ---
- vertices.push_back(vTR);
- vertices.push_back(vBR);
- vertices.push_back(vBL);
-
- break;
- }
- default:
- break;
- }
- }
-
- VkCommandBuffer command_buffer = frame.command_buffer;
- vkResetCommandBuffer(command_buffer, 0);
-
- recordCommandBuffer(
- command_buffer,
- images[imageIndex],
- imageViews[imageIndex],
- swapchain_extent,
- imageLayouts[imageIndex],
- frame,
- vertices
- );
-
- imageLayouts[imageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
-
- VkSemaphoreSubmitInfo waitBinary{
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = frame.imageAvailable,
- .stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
- };
-
- VkSemaphoreSubmitInfo signalBinary{
- .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
- .semaphore = renderFinished[imageIndex],
- .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
- };
-
- VkCommandBufferSubmitInfo cmdInfo{
- .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
- .commandBuffer = command_buffer,
- };
-
- const VkSubmitInfo2 submit{
- .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
- .waitSemaphoreInfoCount = 1,
- .pWaitSemaphoreInfos = &waitBinary,
- .commandBufferInfoCount = 1,
- .pCommandBufferInfos = &cmdInfo,
- .signalSemaphoreInfoCount = 1,
- .pSignalSemaphoreInfos = &signalBinary,
- };
-
- vkQueueSubmit2(graphics_queue, 1, &submit, frame.in_flight_fence);
-
- VkPresentInfoKHR present{
- .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
- .waitSemaphoreCount = 1,
- .pWaitSemaphores = &renderFinished[imageIndex],
- .swapchainCount = 1,
- .pSwapchains = &swapchain,
- .pImageIndices = &imageIndex,
- };
-
- vkQueuePresentKHR(graphics_queue, &present);
-
- currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
-}
-
-void Renderer::upload_vertex_buffer(
- VkCommandBuffer cmd,
- const Frame &frame,
- std::span vertices) const {
- VkMemoryPropertyFlags memPropFlags;
- vmaGetAllocationMemoryProperties(allocator, frame.vertexBuffer.allocation, &memPropFlags);
-
- if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
- // The Allocation ended up in a mappable memory.
- // Calling vmaCopyMemoryToAllocation() does vmaMapMemory(), memcpy(), vmaUnmapMemory(), and vmaFlushAllocation().
- VkResult result = vmaCopyMemoryToAllocation(allocator, vertices.data(), frame.vertexBuffer.allocation, 0, vertices.size() * sizeof(vertex_p2_st2_col4_a1_u32));
- // Check result...
-
- VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
- bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
- bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
- bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
- bufMemBarrier.buffer = frame.vertexBuffer.buffer;
- bufMemBarrier.offset = 0;
- bufMemBarrier.size = VK_WHOLE_SIZE;
-
- // It's important to insert a buffer memory barrier here to ensure writing to the buffer has finished.
- vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
- 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
- }
-}
-
-void Renderer::recordCommandBuffer(
- VkCommandBuffer cmd,
- VkImage image,
- VkImageView imageView,
- VkExtent2D extent,
- VkImageLayout oldLayout,
- const Frame &frame,
- const std::vector &vertices) const
-{
-
- VkCommandBufferBeginInfo begin{ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO };
- vkBeginCommandBuffer(cmd, &begin);
-
- {
- VkImageMemoryBarrier2 toColor{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
- toColor.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
- toColor.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
- toColor.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
- toColor.oldLayout = oldLayout;
- toColor.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- toColor.image = image;
- toColor.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
-
- VkDependencyInfo dep{
- .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
- .imageMemoryBarrierCount = 1,
- .pImageMemoryBarriers = &toColor
- };
- vkCmdPipelineBarrier2(cmd, &dep);
- }
-
- VkClearValue clearColor = {{{0.1f, 0.1f, 0.2f, 1.0f}}};
- VkRenderingAttachmentInfo colorAttach{
- .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
- .imageView = imageView,
- .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .clearValue = clearColor
- };
-
- VkRenderingInfo ri{
- .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
- .renderArea = {{0,0}, extent},
- .layerCount = 1,
- .colorAttachmentCount = 1,
- .pColorAttachments = &colorAttach
- };
-
- upload_vertex_buffer(cmd, frame, vertices);
-
- vkCmdBeginRendering(cmd, &ri);
-
- VkViewport vp{0.0f, 0.0f, (float)extent.width, (float)extent.height, 0.0f, 1.0f};
- VkRect2D sc{{0, 0}, extent};
- vkCmdSetViewport(cmd, 0, 1, &vp);
- vkCmdSetScissor(cmd, 0, 1, &sc);
-
- vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, 0, nullptr);
- VkDeviceSize vOffset{ 0 };
- vkCmdBindVertexBuffers(cmd, 0, 1, &frame.vertexBuffer.buffer, &vOffset);
-
- PipelineType lastPipeline = PipelineType::None; // Track current state
- uint32_t vertexOffset = currentFrame * MAX_VERTICES_PER_BATCH;
- uint32_t currentBatchVertices = 0;
-
- for (const auto & render_command : commands) {
- // Only switch pipelines if we have to
- if (render_command.pipeline != lastPipeline) {
- // If we were mid-batch, draw what we have before switching
- if (currentBatchVertices > 0) {
- vkCmdDraw(cmd, currentBatchVertices, 1, vertexOffset, 0);
- vertexOffset += currentBatchVertices;
- currentBatchVertices = 0;
- }
-
- vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, get_pipeline(render_command.pipeline));
- lastPipeline = render_command.pipeline;
- }
-
- currentBatchVertices += 6;
- }
-
- // Draw the final batch
- if (currentBatchVertices > 0) {
- vkCmdDraw(cmd, currentBatchVertices, 1, vertexOffset, 0);
- }
-
- vkCmdEndRendering(cmd);
-
- // 3. Transition back to Present
- {
- VkImageMemoryBarrier2 toPresent{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
- toPresent.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
- toPresent.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
- toPresent.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
- toPresent.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
- toPresent.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
- toPresent.image = image;
- toPresent.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
-
- VkDependencyInfo dep{ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .imageMemoryBarrierCount = 1, .pImageMemoryBarriers = &toPresent };
- vkCmdPipelineBarrier2(cmd, &dep);
- }
-
- vkEndCommandBuffer(cmd);
-}
-
VkPipeline Renderer::get_pipeline(PipelineType type) const {
switch (type) {
case PipelineType::TexturedQuad: return textured_quad_pipeline;
@@ -794,3 +530,271 @@ void Renderer::create_default_sampler() {
vkCreateSampler(device, &samplerInfo, nullptr, &defaultSampler);
}
+
+void Renderer::end_frame() {
+
+ Frame &frame = frames[currentFrame];
+
+ vkWaitForFences(device, 1, &frame.in_flight_fence, VK_TRUE, UINT64_MAX);
+ vkResetFences(device, 1, &frame.in_flight_fence);
+
+ uint32_t imageIndex;
+ vkAcquireNextImageKHR(
+ device,
+ swapchain,
+ UINT64_MAX,
+ frame.imageAvailable,
+ VK_NULL_HANDLE,
+ &imageIndex
+ );
+
+ commands = counting_sort_descending(commands, [](const RenderCommand &cmd){
+ return cmd.key.depth;
+ });
+
+ std::vector vertices;
+
+ for (auto& cmd : commands) {
+
+
+ switch (cmd.pipeline) {
+ case PipelineType::ColoredQuad: {
+ const auto &q = cmd.colored_quad;
+
+ // Calculate spatial corners
+ float x0 = q.position.x;
+ float y0 = q.position.y;
+ float x1 = q.position.x + q.size.x;
+ float y1 = q.position.y + q.size.y;
+
+ // Calculate UV corners
+ // float u0 = q.uvMin.x;
+ // float v0 = q.uvMin.y;
+ // float u1 = q.uvMax.x;
+ // float v1 = q.uvMax.y;
+
+ // Define the 4 corners of the quad
+ vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {0, 0}, q.color, 1, 0 };
+ vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {0, 0}, q.color, 1, 0 };
+ vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {0, 0}, q.color, 1, 0 };
+ vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {0, 0}, q.color, 1, 0 };
+
+ // vertex_p2_st2_col4_a1_u32 vTL = { {x0, y0}, {u0, v0}, q.color, 1, q.textureID };
+ // vertex_p2_st2_col4_a1_u32 vTR = { {x1, y0}, {u1, v0}, q.color, 1, q.textureID };
+ // vertex_p2_st2_col4_a1_u32 vBL = { {x0, y1}, {u0, v1}, q.color, 1, q.textureID };
+ // vertex_p2_st2_col4_a1_u32 vBR = { {x1, y1}, {u1, v1}, q.color, 1, q.textureID };
+
+ // --- Triangle 1 (TL, TR, BL) ---
+ vertices.push_back(vTL);
+ vertices.push_back(vTR);
+ vertices.push_back(vBL);
+
+ // --- Triangle 2 (TR, BR, BL) ---
+ vertices.push_back(vTR);
+ vertices.push_back(vBR);
+ vertices.push_back(vBL);
+
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ VkCommandBuffer cmd = frame.command_buffer;
+ vkResetCommandBuffer(cmd, 0);
+
+ VkCommandBufferBeginInfo cbBI {
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
+ };
+ vkBeginCommandBuffer(cmd, &cbBI);
+
+ recordCommandBuffer(
+ cmd,
+ images[imageIndex],
+ imageViews[imageIndex],
+ swapchain_extent,
+ imageLayouts[imageIndex],
+ frame,
+ vertices
+ );
+
+ vkEndCommandBuffer(cmd);
+
+ imageLayouts[imageIndex] = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ VkSemaphoreSubmitInfo waitBinary{
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = frame.imageAvailable,
+ .stageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT
+ };
+
+ VkSemaphoreSubmitInfo signalBinary{
+ .sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO,
+ .semaphore = renderFinished[imageIndex],
+ .stageMask = VK_PIPELINE_STAGE_2_ALL_GRAPHICS_BIT
+ };
+
+ VkCommandBufferSubmitInfo cmdInfo{
+ .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_SUBMIT_INFO,
+ .commandBuffer = cmd,
+ };
+
+ const VkSubmitInfo2 submit{
+ .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2,
+ .waitSemaphoreInfoCount = 1,
+ .pWaitSemaphoreInfos = &waitBinary,
+ .commandBufferInfoCount = 1,
+ .pCommandBufferInfos = &cmdInfo,
+ .signalSemaphoreInfoCount = 1,
+ .pSignalSemaphoreInfos = &signalBinary,
+ };
+
+ vkQueueSubmit2(graphics_queue, 1, &submit, frame.in_flight_fence);
+
+ VkPresentInfoKHR present{
+ .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ .waitSemaphoreCount = 1,
+ .pWaitSemaphores = &renderFinished[imageIndex],
+ .swapchainCount = 1,
+ .pSwapchains = &swapchain,
+ .pImageIndices = &imageIndex,
+ };
+
+ vkQueuePresentKHR(graphics_queue, &present);
+
+ currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
+}
+
+void Renderer::upload_vertex_buffer(
+ VkCommandBuffer cmd,
+ const Frame &frame,
+ std::span vertices) const {
+ VkMemoryPropertyFlags memPropFlags;
+ vmaGetAllocationMemoryProperties(allocator, frame.vertexBuffer.allocation, &memPropFlags);
+
+ if(memPropFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
+ // The Allocation ended up in a mappable memory.
+ // Calling vmaCopyMemoryToAllocation() does vmaMapMemory(), memcpy(), vmaUnmapMemory(), and vmaFlushAllocation().
+ VkResult result = vmaCopyMemoryToAllocation(allocator, vertices.data(), frame.vertexBuffer.allocation, 0, vertices.size() * sizeof(vertex_p2_st2_col4_a1_u32));
+ // Check result...
+
+ VkBufferMemoryBarrier bufMemBarrier = { VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER };
+ bufMemBarrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ bufMemBarrier.dstAccessMask = VK_ACCESS_UNIFORM_READ_BIT;
+ bufMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
+ bufMemBarrier.buffer = frame.vertexBuffer.buffer;
+ bufMemBarrier.offset = 0;
+ bufMemBarrier.size = VK_WHOLE_SIZE;
+
+ // It's important to insert a buffer memory barrier here to ensure writing to the buffer has finished.
+ vkCmdPipelineBarrier(cmd, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_VERTEX_SHADER_BIT,
+ 0, 0, nullptr, 1, &bufMemBarrier, 0, nullptr);
+ }
+}
+
+void Renderer::recordCommandBuffer(
+ VkCommandBuffer cmd,
+ VkImage image,
+ VkImageView imageView,
+ VkExtent2D extent,
+ VkImageLayout oldLayout,
+ const Frame &frame,
+ const std::vector &vertices) const
+{
+
+ {
+ VkImageMemoryBarrier2 toColor{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
+ toColor.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
+ toColor.dstStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
+ toColor.dstAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
+ toColor.oldLayout = oldLayout;
+ toColor.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ toColor.image = image;
+ toColor.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
+
+ VkDependencyInfo dep{
+ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
+ .imageMemoryBarrierCount = 1,
+ .pImageMemoryBarriers = &toColor
+ };
+ vkCmdPipelineBarrier2(cmd, &dep);
+ }
+
+ VkClearValue clearColor = {{{0.1f, 0.1f, 0.2f, 1.0f}}};
+ VkRenderingAttachmentInfo colorAttach{
+ .sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
+ .imageView = imageView,
+ .imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
+ .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
+ .clearValue = clearColor
+ };
+
+ VkRenderingInfo ri{
+ .sType = VK_STRUCTURE_TYPE_RENDERING_INFO,
+ .renderArea = {{0,0}, extent},
+ .layerCount = 1,
+ .colorAttachmentCount = 1,
+ .pColorAttachments = &colorAttach
+ };
+
+ upload_vertex_buffer(cmd, frame, vertices);
+
+ vkCmdBeginRendering(cmd, &ri);
+
+ VkViewport vp{0.0f, 0.0f, (float)extent.width, (float)extent.height, 0.0f, 1.0f};
+ VkRect2D sc{{0, 0}, extent};
+ vkCmdSetViewport(cmd, 0, 1, &vp);
+ vkCmdSetScissor(cmd, 0, 1, &sc);
+
+ vkCmdBindDescriptorSets(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout, 0, 1, &set, 0, nullptr);
+ VkDeviceSize vOffset{ 0 };
+ vkCmdBindVertexBuffers(cmd, 0, 1, &frame.vertexBuffer.buffer, &vOffset);
+
+ PipelineType lastPipeline = PipelineType::None; // Track current state
+ // uint32_t vertexOffset = currentFrame * MAX_VERTICES_PER_BATCH;
+ uint32_t currentBatchVertices = 0;
+
+ for (const auto & render_command : commands) {
+ // Only switch pipelines if we have to
+ if (render_command.pipeline != lastPipeline) {
+ // If we were mid-batch, draw what we have before switching
+ if (currentBatchVertices > 0) {
+ vkCmdDraw(cmd, currentBatchVertices, 1, 0, 0);
+ // vertexOffset += currentBatchVertices;
+ currentBatchVertices = 0;
+ }
+
+ vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, get_pipeline(render_command.pipeline));
+ lastPipeline = render_command.pipeline;
+ }
+
+ currentBatchVertices += 6;
+ }
+
+ // Draw the final batch
+ if (currentBatchVertices > 0) {
+ vkCmdDraw(cmd, currentBatchVertices, 1, 0, 0);
+ }
+
+ vkCmdEndRendering(cmd);
+
+ // 3. Transition back to Present
+ {
+ VkImageMemoryBarrier2 toPresent{ .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
+ toPresent.srcStageMask = VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT;
+ toPresent.srcAccessMask = VK_ACCESS_2_COLOR_ATTACHMENT_WRITE_BIT;
+ toPresent.dstStageMask = VK_PIPELINE_STAGE_2_BOTTOM_OF_PIPE_BIT;
+ toPresent.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ toPresent.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ toPresent.image = image;
+ toPresent.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
+
+ VkDependencyInfo dep{ .sType = VK_STRUCTURE_TYPE_DEPENDENCY_INFO, .imageMemoryBarrierCount = 1, .pImageMemoryBarriers = &toPresent };
+ vkCmdPipelineBarrier2(cmd, &dep);
+ }
+
+}
diff --git a/shaders/triangle.frag b/shaders/triangle.frag
index 3d9e39c..f69440e 100644
--- a/shaders/triangle.frag
+++ b/shaders/triangle.frag
@@ -12,5 +12,5 @@ layout(location = 0) out vec4 out_color;
void main() {
// outColor = texture(texSamplers[nonuniformEXT(tex_id)], uv) * color;
- out_color = vec4(1);
+ out_color = color;
}
diff --git a/shaders/triangle.frag.spv b/shaders/triangle.frag.spv
index 5d95baa..76394c3 100644
Binary files a/shaders/triangle.frag.spv and b/shaders/triangle.frag.spv differ