From c905ef9ca75197593cc7772a7e06e53a60d5f999 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 14 Dec 2025 13:28:49 -0500 Subject: [PATCH] [BREAKING] This crashes on Linux, and looks like it's crashing wayland? Testing on Windows. --- Makefile | 1 + colored_triangle_mesh.vert | 37 +++++++ colored_triangle_mesh.vert.spv | Bin 0 -> 2760 bytes vk_engine.cpp | 189 +++++++++++++++++++++++++++++++++ vk_engine.h | 14 ++- vk_types.h | 28 ++++- 6 files changed, 267 insertions(+), 2 deletions(-) create mode 100644 colored_triangle_mesh.vert create mode 100644 colored_triangle_mesh.vert.spv diff --git a/Makefile b/Makefile index e6a7c36..99a8005 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ shaders: glslangValidator -V gradient_color.comp -o gradient_color.comp.spv glslangValidator -V colored_triangle.frag -o colored_triangle.frag.spv glslangValidator -V colored_triangle.vert -o colored_triangle.vert.spv + glslangValidator -V colored_triangle_mesh.vert -o colored_triangle_mesh.vert.spv %.cpp : %.rl ragel -I $(ROOT_DIR) -G1 -o $@ $< diff --git a/colored_triangle_mesh.vert b/colored_triangle_mesh.vert new file mode 100644 index 0000000..fe9bec5 --- /dev/null +++ b/colored_triangle_mesh.vert @@ -0,0 +1,37 @@ +#version 450 +#extension GL_EXT_buffer_reference : require + +layout (location = 0) out vec3 outColor; +layout (location = 1) out vec2 outUV; + +struct Vertex { + + vec3 position; + float uv_x; + vec3 normal; + float uv_y; + vec4 color; +}; + +layout(buffer_reference, std430) readonly buffer VertexBuffer{ + Vertex vertices[]; +}; + +//push constants block +layout( push_constant ) uniform constants +{ + mat4 render_matrix; + VertexBuffer vertexBuffer; +} PushConstants; + +void main() +{ + //load vertex data from device adress + Vertex v = PushConstants.vertexBuffer.vertices[gl_VertexIndex]; + + //output data + gl_Position = PushConstants.render_matrix *vec4(v.position, 1.0f); + outColor = v.color.xyz; + outUV.x = v.uv_x; + outUV.y = v.uv_y; +} diff --git a/colored_triangle_mesh.vert.spv b/colored_triangle_mesh.vert.spv new file mode 100644 index 0000000000000000000000000000000000000000..7461a400c8a0a0bf9cd7093701b0dd74b9984d28 GIT binary patch literal 2760 zcmZ9M>vB_76vua)CR9*SD;E`FYSpS}y#bMigVy7$`SbYEqijHYC6B4^?(MD(M-SI7U-`srFQ!uZiyY=V zO&-qzbkOSbl;41^K-J6>{0{;a(uq{xZQlOrhoVYzkWnk^wX;;lI-N(|?EBeZ zl>L(ErczW(>99ZSj5__iUWG{g>}Pz`#8cl1X5C(YaM0>L!%7psr_+AcZTGwV0lZAV zr{G7qTxMQvz2T_U8x4^w%pm5W^M~1>dC(dSIu;I_y&UCz-h!CB1@eP*7WWvl#7@tHSts=9$9VVX z8~*?@-hE8s%ejo2+vVnneHr5%ff*xKn!=RD?AcoGq6&G`{ZCLg&k|M5u}lWzl+PkL zTMasgzdKOZuD)34=C5M)+Yg`M`qc0}S=jVBkM7-TGj^4XFTnrizpM)4F13r9*Ih)u z;Kp7g&imJ1MfQHxtrz*k)L(&H+uYX+eW}3Cpi?@Za}Iu~(9a;N8-EsVym`a^8nQ?G z>u`O|V}5ma8}S#BozGtNUxqu2r2cjxd%ux?71=$6?i=y$L;ncb`!jwGZZ7Y|d3=vG z$fLjdr_da90sS+$wZy7OzAIzJv`OZ@47a9s=Ti6k7Snze?!CA#>ll9>O6j+o+BcE( zHMja!q1&tZ)VB-FH?@Oo4(HbYPGJ+*U)^_W&Y0^vWRL#e!?l^?D&LEFyd#hJKOp|M zn9Dcm_hB!apzin_-e~Dzh7~6_v`LZ9o#*?32Czj-{pO3 zSgQtU^H_Ho{uX2}=D0zp>NUt1XIX)anS+e+y}Sb%W3R@j>lbz2MK;FzQRh8mV^$$! z)b)!x?;{)IT}7Qs$j12oj8WImm__)9kTKq~F}}r*A!B@_#;EJ3-8b_EjHxvW9tRxU4`F`0`o2!Y{9;7LdNT_-FN$YG1CUJ{pe#q zoA6tZZ{L2LNqqx~nQtS<%+6$uZy@n|X!c((FmaDP+LQVG4z!!k{oaMl7jLnGyj$S< s_}1@1eh+>F=1|usax{?5;qL6o9QPsd$ngN#9R3%WLtUSL>FyfzAE&d)g8%>k literal 0 HcmV?d00001 diff --git a/vk_engine.cpp b/vk_engine.cpp index 1106b6d..51695b6 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -201,6 +201,19 @@ void VulkanEngine::draw_geometry(VkCommandBuffer cmd) vkCmdDraw(cmd, 3, 1, 0, 0); + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _meshPipeline); + + GPUDrawPushConstants push_constants{ + .worldMatrix = glm::mat4{ 1.0f }, + .vertexBuffer = rectangle.vertexBufferAddress, + }; + + vkCmdPushConstants(cmd, _meshPipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(GPUDrawPushConstants), +&push_constants); + vkCmdBindIndexBuffer(cmd, rectangle.indexBuffer.buffer, 0, VK_INDEX_TYPE_UINT32); + + vkCmdDrawIndexed(cmd, 6, 1, 0, 0, 0); + vkCmdEndRendering(cmd); } @@ -465,6 +478,7 @@ void VulkanEngine::init_pipelines() { init_background_pipelines(); init_triangle_pipelines(); + init_mesh_pipeline(); init_shaders(); } @@ -566,6 +580,60 @@ void VulkanEngine::immediate_submit(std::function&& f VK_CHECK(vkWaitForFences(_device, 1, &_immFence, true,9999999999)); } +void VulkanEngine::init_mesh_pipeline() +{ + VkShaderModule triangleFragShader; + if (!vkutil::load_shader_module("colored_triangle.frag.spv", _device, &triangleFragShader)) { + std::print("Error when building the triangle fragment shader module"); + } + else { + std::print("Triangle fragment shader succesfully loaded"); + } + + VkShaderModule triangleVertexShader; + if (!vkutil::load_shader_module("colored_triangle_mesh.vert.spv", _device, &triangleVertexShader)) { + std::print("Error when building the triangle vertex shader module"); + } + else { + std::print("Triangle vertex shader succesfully loaded"); + } + + VkPushConstantRange bufferRange{ + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = sizeof(GPUDrawPushConstants), + }; + + VkPipelineLayoutCreateInfo pipeline_layout_info = vkinit::pipeline_layout_create_info(); + pipeline_layout_info.pPushConstantRanges = &bufferRange; + pipeline_layout_info.pushConstantRangeCount = 1; + + VK_CHECK(vkCreatePipelineLayout(_device, &pipeline_layout_info, nullptr, &_meshPipelineLayout)); + + + PipelineBuilder pipelineBuilder; + + pipelineBuilder._pipelineLayout = _meshPipelineLayout; + pipelineBuilder.set_shaders(triangleVertexShader, triangleFragShader); + pipelineBuilder.set_input_topology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + pipelineBuilder.set_polygon_mode(VK_POLYGON_MODE_FILL); + pipelineBuilder.set_cull_mode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE); + pipelineBuilder.set_multisampling_none(); + pipelineBuilder.disable_blending(); + pipelineBuilder.disable_depthtest(); + pipelineBuilder.set_color_attachment_format(_drawImage.imageFormat); + pipelineBuilder.set_depth_format(VK_FORMAT_UNDEFINED); + + _meshPipeline = pipelineBuilder.build_pipeline(_device); + vkDestroyShaderModule(_device, triangleFragShader, nullptr); + vkDestroyShaderModule(_device, triangleVertexShader, nullptr); + + _mainDeletionQueue.push_function([&]() { + vkDestroyPipelineLayout(_device, _meshPipelineLayout, nullptr); + vkDestroyPipeline(_device, _meshPipeline, nullptr); + }); +} + void VulkanEngine::init_triangle_pipelines() { @@ -613,3 +681,124 @@ void VulkanEngine::init_triangle_pipelines() vkDestroyPipeline(_device, _trianglePipeline, nullptr); }); } + + +AllocatedBuffer VulkanEngine::create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage) +{ + VkBufferCreateInfo bufferInfo{ + .sType=VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, + .size = allocSize, + .usage = usage, + }; + + VmaAllocationCreateInfo vmaallocInfo{ + .flags = VMA_ALLOCATION_CREATE_MAPPED_BIT, + .usage = memoryUsage, + }; + + AllocatedBuffer newBuffer; + + VK_CHECK(vmaCreateBuffer(_allocator, &bufferInfo, + &vmaallocInfo, &newBuffer.buffer, + &newBuffer.allocation, &newBuffer.info)); + + return newBuffer; +} + +void VulkanEngine::destroy_buffer(const AllocatedBuffer& buffer) +{ + vmaDestroyBuffer(_allocator, buffer.buffer, buffer.allocation); +} + + +GPUMeshBuffers VulkanEngine::uploadMesh(std::span indices, std::span vertices) +{ + const size_t vertexBufferSize = vertices.size() * sizeof(Vertex); + const size_t indexBufferSize = indices.size() * sizeof(uint32_t); + + GPUMeshBuffers newSurface; + + newSurface.vertexBuffer = create_buffer( + vertexBufferSize, + VK_BUFFER_USAGE_STORAGE_BUFFER_BIT + | VK_BUFFER_USAGE_TRANSFER_DST_BIT + | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, + VMA_MEMORY_USAGE_GPU_ONLY); + + VkBufferDeviceAddressInfo deviceAddressInfo{ + .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO, + .buffer = newSurface.vertexBuffer.buffer + }; + + newSurface.vertexBufferAddress = vkGetBufferDeviceAddress(_device, &deviceAddressInfo); + + newSurface.indexBuffer = create_buffer(indexBufferSize, + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT, + VMA_MEMORY_USAGE_GPU_ONLY); + + AllocatedBuffer staging = create_buffer(vertexBufferSize + indexBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_CPU_ONLY); + + void* data = staging.allocation->GetMappedData(); + + memcpy(data, vertices.data(), vertexBufferSize); + memcpy((char *)data + vertexBufferSize, indices.data(), indexBufferSize); + + immediate_submit([&](VkCommandBuffer cmd) { + VkBufferCopy vertexCopy{ + .srcOffset = 0, + .dstOffset = 0, + .size = vertexBufferSize, + }; + + vkCmdCopyBuffer(cmd, staging.buffer, + newSurface.vertexBuffer.buffer, 1, + &vertexCopy); + + VkBufferCopy indexCopy{ + .srcOffset = vertexBufferSize, + .dstOffset = 0, + .size = indexBufferSize, + }; + + vkCmdCopyBuffer(cmd, staging.buffer, + newSurface.indexBuffer.buffer, 1, + &indexCopy); + }); + + destroy_buffer(staging); + + return newSurface; +} + +void VulkanEngine::init_default_data() { + std::array rect_vertices; + + rect_vertices[0].position = {0.5,-0.5, 0}; + rect_vertices[1].position = {0.5,0.5, 0}; + rect_vertices[2].position = {-0.5,-0.5, 0}; + rect_vertices[3].position = {-0.5,0.5, 0}; + + rect_vertices[0].color = {0,0, 0,1}; + rect_vertices[1].color = { 0.5,0.5,0.5 ,1}; + rect_vertices[2].color = { 1,0, 0,1 }; + rect_vertices[3].color = { 0,1, 0,1 }; + + std::array rect_indices; + + rect_indices[0] = 0; + rect_indices[1] = 1; + rect_indices[2] = 2; + + rect_indices[3] = 2; + rect_indices[4] = 1; + rect_indices[5] = 3; + + rectangle = uploadMesh(rect_indices, rect_vertices); + + _mainDeletionQueue.push_function([&](){ + destroy_buffer(rectangle.indexBuffer); + destroy_buffer(rectangle.vertexBuffer); + }); +} + + diff --git a/vk_engine.h b/vk_engine.h index 465088c..dcececa 100644 --- a/vk_engine.h +++ b/vk_engine.h @@ -96,6 +96,10 @@ public: int currentBackgroundEffect{0}; VkPipelineLayout _trianglePipelineLayout; VkPipeline _trianglePipeline; + VkPipelineLayout _meshPipelineLayout; + VkPipeline _meshPipeline; + + GPUMeshBuffers rectangle; // ZED's REFACTOR VkGUI _gui; @@ -128,11 +132,19 @@ private: void init_pipelines(); void init_background_pipelines(); void init_shaders(); - void load_shader(const char *file_name, const char *entry_point, ComputeEffect data); void init_triangle_pipelines(); + void init_mesh_pipeline(); + void init_default_data(); + + void load_shader(const char *file_name, const char *entry_point, ComputeEffect data); void create_swapchain(uint32_t width, uint32_t height); + AllocatedBuffer create_buffer(size_t allocSize, VkBufferUsageFlags usage, VmaMemoryUsage memoryUsage); + void destroy_swapchain(); + void destroy_buffer(const AllocatedBuffer& buffer); void draw_background(VkCommandBuffer cmd); void draw_geometry(VkCommandBuffer cmd); + + GPUMeshBuffers uploadMesh(std::span indices, std::span vertices); }; diff --git a/vk_types.h b/vk_types.h index ed4264a..4f93e18 100644 --- a/vk_types.h +++ b/vk_types.h @@ -30,6 +30,14 @@ } while (0) +constexpr unsigned int FRAME_OVERLAP=2; + +struct AllocatedBuffer { + VkBuffer buffer; + VmaAllocation allocation; + VmaAllocationInfo info; +}; + struct AllocatedImage { VkImage image; VkImageView imageView; @@ -53,4 +61,22 @@ struct ComputeEffect { ComputePushConstants data; }; -constexpr unsigned int FRAME_OVERLAP=2; +struct Vertex { + glm::vec3 position; + float uv_x; + glm::vec3 normal; + float uv_y; + glm::vec4 color; +}; + +struct GPUMeshBuffers { + AllocatedBuffer indexBuffer; + AllocatedBuffer vertexBuffer; + VkDeviceAddress vertexBufferAddress; +}; + +struct GPUDrawPushConstants { + glm::mat4 worldMatrix; + VkDeviceAddress vertexBuffer; +}; +