This commit is contained in:
Vicente Ferrari Smith 2026-02-18 09:02:41 +01:00
parent 268d417373
commit 544e6da087
4 changed files with 350 additions and 268 deletions

82
.idea/editor.xml generated
View File

@ -246,22 +246,100 @@
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StdIsConstantEvaluatedWillAlwaysEvaluateToConstant/@EntryIndexedValue" value="WARNING" type="string" />
<option name="/Default/CodeInspection/Highlighting/InspectionSeverities/=StringLiteralTypo/@EntryIndexedValue" value="DO_NOT_SHOW" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_ARGUMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_BINARY_EXPRESSIONS_CHAIN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_CALLS_CHAIN/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXPRESSION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_EXTENDS_LIST/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_FOR_STMT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_PARAMETER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_ARGUMENT/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTILINE_TYPE_PARAMETER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_MULTIPLE_DECLARATION/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ALIGN_TERNARY/@EntryValue" value="ALIGN_ALL" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/ANONYMOUS_METHOD_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_CLASS_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_DECLARATIONS/@EntryValue" value="0" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DECLARATION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BLANK_LINES_AROUND_FUNCTION_DEFINITION/@EntryValue" value="1" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/BREAK_TEMPLATE_DECLARATION/@EntryValue" value="LINE_BREAK" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CASE_BLOCK_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/EXPORT_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/CONTINUOUS_LINE_INDENT/@EntryValue" value="Double" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_ACCESS_SPECIFIERS_FROM_CLASS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CASE_FROM_SWITCH/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_CLASS_MEMBERS_FROM_ACCESS_SPECIFIERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_COMMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_SIZE/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INDENT_STYLE/@EntryValue" value="Space" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INITIALIZER_BRACES/@EntryValue" value="END_OF_LINE_NO_SPACE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INT_ALIGN_EQ/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/INVOCABLE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_CODE/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_BLANK_LINES_IN_DECLARATIONS/@EntryValue" value="2" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/KEEP_USER_LINEBREAKS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/LINE_BREAK_AFTER_COLON_IN_MEMBER_INITIALIZER_LISTS/@EntryValue" value="ON_SINGLE_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/MEMBER_INITIALIZER_LIST_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/NAMESPACE_INDENTATION/@EntryValue" value="All" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/OTHER_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/REQUIRES_EXPRESSION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_CATCH_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_ELSE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_NAMESPACE_DEFINITIONS_ON_SAME_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/PLACE_WHILE_ON_NEW_LINE/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SIMPLE_BLOCK_STYLE/@EntryValue" value="DO_NOT_CHANGE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_COMMA_IN_TEMPLATE_PARAMS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_FOR_SEMICOLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_PTR_IN_NESTED_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBER/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_DATA_MEMBERS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_REF_IN_METHOD/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_AFTER_UNARY_OPERATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_COLON_IN_BITFIELD_DECLARATOR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_EXTENDS_COLON/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_COLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_FOR_SEMICOLON/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_PTR_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_ABSTRACT_DECL/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBER/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_DATA_MEMBERS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_REF_IN_METHOD/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BEFORE_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_BETWEEN_CLOSING_ANGLE_BRACKETS_IN_TEMPLATE_ARGS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_ARRAY_ACCESS_BRACKETS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_CAST_EXPRESSION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_DECLARATION_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_BLOCKS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_METHOD_PARENTHESES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_EMPTY_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_INITIALIZER_BRACES/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_ARGS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPACE_WITHIN_TEMPLATE_PARAMS/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/SPECIAL_ELSE_IF_TREATMENT/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TAB_WIDTH/@EntryValue" value="4" type="int" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/TYPE_DECLARATION_BRACES/@EntryValue" value="END_OF_LINE" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_BINARY_OPSIGN/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_AFTER_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_ARGUMENTS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_DECLARATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_LPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_INVOCATION_RPAR/@EntryValue" value="false" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_BEFORE_TERNARY_OPSIGNS/@EntryValue" value="true" type="bool" />
<option name="/Default/CodeStyle/CodeFormatting/CppFormatting/WRAP_PARAMETERS_STYLE/@EntryValue" value="WRAP_IF_LONG" type="string" />
<option name="/Default/CodeStyle/EditorConfig/EnableClangFormatSupport/@EntryValue" value="false" type="bool" />
</component>
</project>

View File

@ -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<vertex_p2_st2_col4_a1_u32> 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<const vertex_p2_st2_col4_a1_u32> 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<vertex_p2_st2_col4_a1_u32> &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<vertex_p2_st2_col4_a1_u32> 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<const vertex_p2_st2_col4_a1_u32> 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<vertex_p2_st2_col4_a1_u32> &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);
}
}

View File

@ -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;
}

Binary file not shown.