diff --git a/Makefile b/Makefile index 73487f8..afadde2 100644 --- a/Makefile +++ b/Makefile @@ -13,6 +13,8 @@ shaders: glslangValidator -V gradient.comp -o gradient.comp.spv glslangValidator -V sky.comp -o sky.comp.spv 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 %.cpp : %.rl ragel -I $(ROOT_DIR) -G1 -o $@ $< diff --git a/colored_triangle.frag b/colored_triangle.frag new file mode 100644 index 0000000..2f05038 --- /dev/null +++ b/colored_triangle.frag @@ -0,0 +1,13 @@ +#version 450 + +//shader input +layout (location = 0) in vec3 inColor; + +//output write +layout (location = 0) out vec4 outFragColor; + +void main() +{ + //return red + outFragColor = vec4(inColor,1.0f); +} diff --git a/colored_triangle.frag.spv b/colored_triangle.frag.spv new file mode 100644 index 0000000..ad41591 Binary files /dev/null and b/colored_triangle.frag.spv differ diff --git a/colored_triangle.vert b/colored_triangle.vert new file mode 100644 index 0000000..8b0db4a --- /dev/null +++ b/colored_triangle.vert @@ -0,0 +1,24 @@ +#version 450 + +layout (location = 0) out vec3 outColor; + +void main() +{ + //const array of positions for the triangle + const vec3 positions[3] = vec3[3]( + vec3(1.f,1.f, 0.0f), + vec3(-1.f,1.f, 0.0f), + vec3(0.f,-1.f, 0.0f) + ); + + //const array of colors for the triangle + const vec3 colors[3] = vec3[3]( + vec3(1.0f, 0.0f, 0.0f), //red + vec3(0.0f, 1.0f, 0.0f), //green + vec3(00.f, 0.0f, 1.0f) //blue + ); + + //output the position of each vertex + gl_Position = vec4(positions[gl_VertexIndex], 1.0f); + outColor = colors[gl_VertexIndex]; +} diff --git a/colored_triangle.vert.spv b/colored_triangle.vert.spv new file mode 100644 index 0000000..ffd8bf3 Binary files /dev/null and b/colored_triangle.vert.spv differ diff --git a/vk_engine.cpp b/vk_engine.cpp index 448cffb..1106b6d 100644 --- a/vk_engine.cpp +++ b/vk_engine.cpp @@ -144,8 +144,12 @@ void VulkanEngine::draw() draw_background(t.cmd); + vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + draw_geometry(t.cmd); + // ZED: ? - vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_GENERAL, + vkutil::transition_image(t.cmd, _drawImage.image, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); // ZED: ? @@ -159,15 +163,47 @@ void VulkanEngine::draw() // ZED: ? vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); - _gui.draw_imgui(_swapchainExtent, t.cmd, _swapchainImageViews[t.swapchainImageIndex]); // ZED: end drawing the things + _gui.draw_imgui(_swapchainExtent, t.cmd, _swapchainImageViews[t.swapchainImageIndex]); // ZED: finalize image and commit command buffer - vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + vkutil::transition_image(t.cmd, _swapchainImages[t.swapchainImageIndex], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); commit_transaction(t); } +void VulkanEngine::draw_geometry(VkCommandBuffer cmd) +{ + VkRenderingAttachmentInfo colorAttachment = vkinit::attachment_info(_drawImage.imageView, nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + VkRenderingInfo renderInfo = vkinit::rendering_info(_drawExtent, &colorAttachment, nullptr); + vkCmdBeginRendering(cmd, &renderInfo); + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, _trianglePipeline); + + VkViewport viewport{ + .x = 0, + .y = 0, + .width = (float)_drawExtent.width, + .height = (float)_drawExtent.height, + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + + vkCmdSetViewport(cmd, 0, 1, &viewport); + + VkRect2D scissor{ + .offset = { .x = 0, .y = 0, }, + .extent = _drawExtent + }; + + vkCmdSetScissor(cmd, 0, 1, &scissor); + + vkCmdDraw(cmd, 3, 1, 0, 0); + + vkCmdEndRendering(cmd); +} + void VulkanEngine::run() { //main loop @@ -428,6 +464,7 @@ void VulkanEngine::init_descriptors() { void VulkanEngine::init_pipelines() { init_background_pipelines(); + init_triangle_pipelines(); init_shaders(); } @@ -530,4 +567,49 @@ void VulkanEngine::immediate_submit(std::function&& f } +void VulkanEngine::init_triangle_pipelines() +{ + VkShaderModule triangleFragShader; + if(!vkutil::load_shader_module("colored_triangle.frag.spv",_device, &triangleFragShader)) { + std::print("Error when building the triangle fragment shaders module"); + } else { + std::print("Triangle fragment shader successfully loaded"); + } + + VkShaderModule triangleVertexShader; + if(!vkutil::load_shader_module("colored_triangle.vert.spv", _device, &triangleVertexShader)) { + std::println("Error when building the triangle, vertex shader module"); + } else { + std::println("Triangle vertex shader successfully loaded"); + } + + VkPipelineLayoutCreateInfo pipeline_layout_info = vkinit::pipeline_layout_create_info(); + + VK_CHECK(vkCreatePipelineLayout(_device, &pipeline_layout_info, nullptr, &_trianglePipelineLayout)); + + PipelineBuilder pipelineBuilder; + + pipelineBuilder._pipelineLayout = _trianglePipelineLayout; + 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(); + + // connect the image format we will drw into, from draw image + pipelineBuilder.set_color_attachment_format(_drawImage.imageFormat); + pipelineBuilder.set_depth_format(VK_FORMAT_UNDEFINED); + + _trianglePipeline = pipelineBuilder.build_pipeline(_device); + + vkDestroyShaderModule(_device, triangleFragShader, nullptr); + vkDestroyShaderModule(_device, triangleVertexShader, nullptr); + + _mainDeletionQueue.push_function([&]() { + vkDestroyPipelineLayout(_device, _trianglePipelineLayout, nullptr); + vkDestroyPipeline(_device, _trianglePipeline, nullptr); + }); +} diff --git a/vk_engine.h b/vk_engine.h index 0f684f4..465088c 100644 --- a/vk_engine.h +++ b/vk_engine.h @@ -66,6 +66,7 @@ public: std::vector _swapchainImageViews; VkExtent2D _swapchainExtent; + // VMA stuff VmaAllocator _allocator; @@ -93,7 +94,9 @@ public: // imgui shader stuff std::vector backgroundEffects; int currentBackgroundEffect{0}; - + VkPipelineLayout _trianglePipelineLayout; + VkPipeline _trianglePipeline; + // ZED's REFACTOR VkGUI _gui; @@ -126,8 +129,10 @@ private: 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 create_swapchain(uint32_t width, uint32_t height); void destroy_swapchain(); void draw_background(VkCommandBuffer cmd); + void draw_geometry(VkCommandBuffer cmd); }; diff --git a/vk_initializers.cpp b/vk_initializers.cpp index f54839b..b54c78c 100644 --- a/vk_initializers.cpp +++ b/vk_initializers.cpp @@ -156,3 +156,28 @@ VkRenderingInfo vkinit::rendering_info(VkExtent2D renderExtent, VkRenderingAttac .pStencilAttachment = nullptr, }; } + + +VkPipelineShaderStageCreateInfo vkinit::pipeline_shader_stage_create_info(VkShaderStageFlagBits stage, VkShaderModule shader, const char* entry) { + return { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .stage = stage, + .module = shader, + .pName = entry, + }; +} + + +VkPipelineLayoutCreateInfo vkinit::pipeline_layout_create_info() +{ + return { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .setLayoutCount = 0, + .pSetLayouts = nullptr, + .pushConstantRangeCount = 0, + .pPushConstantRanges = nullptr, + }; +} + diff --git a/vk_initializers.h b/vk_initializers.h index 000b378..3cec09a 100644 --- a/vk_initializers.h +++ b/vk_initializers.h @@ -35,5 +35,9 @@ namespace vkinit { VkImageView view, VkClearValue* clear ,VkImageLayout layout=VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); VkRenderingInfo rendering_info(VkExtent2D renderExtent, VkRenderingAttachmentInfo* colorAttachment, VkRenderingAttachmentInfo* depthAttachment); + + VkPipelineShaderStageCreateInfo pipeline_shader_stage_create_info(VkShaderStageFlagBits stage, VkShaderModule shader, const char* entry="main"); + + VkPipelineLayoutCreateInfo pipeline_layout_create_info(); } diff --git a/vk_pipelines.cpp b/vk_pipelines.cpp index acecc80..b7b3c8d 100644 --- a/vk_pipelines.cpp +++ b/vk_pipelines.cpp @@ -40,3 +40,165 @@ bool vkutil::load_shader_module(const char* filePath, *outShaderModule = shaderModule; return true; } + + +void PipelineBuilder::clear() { + // clear all of the structs we need back to 0 with their correct stype + + _inputAssembly = { .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; + + _rasterizer = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; + + _colorBlendAttachment = {}; + + _multisampling = { .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; + + _pipelineLayout = {}; + + _depthStencil = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; + + _renderInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO }; + + _shaderStages.clear(); +} + +VkPipeline PipelineBuilder::build_pipeline(VkDevice device) +{ + VkPipelineViewportStateCreateInfo viewportState{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .viewportCount = 1, + .scissorCount = 1, + }; + + VkPipelineColorBlendStateCreateInfo colorBlending{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_COPY, + .attachmentCount = 1, + .pAttachments = &_colorBlendAttachment, + }; + + VkPipelineVertexInputStateCreateInfo _vertexInputInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO + }; + + VkDynamicState state[] = { + VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo dynamicInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .dynamicStateCount = 2, + // ZED: we don't need to do this? state is also &state[0] + .pDynamicStates = &state[0], + }; + + // build the actual pipeline + VkGraphicsPipelineCreateInfo pipelineInfo = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = &_renderInfo, + .stageCount = (uint32_t)_shaderStages.size(), + .pStages = _shaderStages.data(), + .pVertexInputState = &_vertexInputInfo, + .pInputAssemblyState = &_inputAssembly, + .pViewportState = &viewportState, + .pRasterizationState = &_rasterizer, + .pMultisampleState = &_multisampling, + .pDepthStencilState = &_depthStencil, + .pColorBlendState = &colorBlending, + .pDynamicState = &dynamicInfo, + .layout = _pipelineLayout, + }; + + // its easy to error out on create graphics pipeline, so we handle it a bit + // better than the common VK_CHECK case + + VkPipeline newPipeline; + auto works = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &newPipeline); + + if(works != VK_SUCCESS) { + std::println("failed to create pipeline"); + return VK_NULL_HANDLE; + } else { + return newPipeline; + } +} + +void PipelineBuilder::set_shaders(VkShaderModule vertexShader, VkShaderModule fragmentShader) +{ + _shaderStages.clear(); + + _shaderStages.push_back( + vkinit::pipeline_shader_stage_create_info( + VK_SHADER_STAGE_VERTEX_BIT, + vertexShader)); + + _shaderStages.push_back( + vkinit::pipeline_shader_stage_create_info( + VK_SHADER_STAGE_FRAGMENT_BIT, + fragmentShader)); +} + +void PipelineBuilder::set_input_topology(VkPrimitiveTopology topology) +{ + _inputAssembly.topology = topology; + _inputAssembly.primitiveRestartEnable = VK_FALSE; +} + +void PipelineBuilder::set_polygon_mode(VkPolygonMode mode) +{ + _rasterizer.polygonMode = mode; + _rasterizer.lineWidth = 1.0f; +} + +void PipelineBuilder::set_cull_mode(VkCullModeFlags cullMode, VkFrontFace frontFace) +{ + _rasterizer.cullMode = cullMode; + _rasterizer.frontFace = frontFace; +} + +void PipelineBuilder::set_multisampling_none() +{ + _multisampling.sampleShadingEnable = VK_FALSE; + _multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + _multisampling.minSampleShading = 1.0f; + _multisampling.pSampleMask = nullptr; + _multisampling.alphaToCoverageEnable = VK_FALSE; + _multisampling.alphaToOneEnable = VK_FALSE; +} + +void PipelineBuilder::disable_blending() +{ + _colorBlendAttachment.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT + | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT + | VK_COLOR_COMPONENT_A_BIT; + + _colorBlendAttachment.blendEnable = VK_FALSE; +} + +void PipelineBuilder::set_color_attachment_format(VkFormat format) +{ + _colorAttachmentFormat = format; + _renderInfo.colorAttachmentCount = 1; + _renderInfo.pColorAttachmentFormats = &_colorAttachmentFormat; +} + +void PipelineBuilder::set_depth_format(VkFormat format) +{ + _renderInfo.depthAttachmentFormat = format; +} + +void PipelineBuilder::disable_depthtest() +{ + _depthStencil.depthTestEnable = VK_FALSE; + _depthStencil.depthWriteEnable = VK_FALSE; + _depthStencil.depthCompareOp = VK_COMPARE_OP_NEVER; + _depthStencil.depthBoundsTestEnable = VK_FALSE; + _depthStencil.stencilTestEnable = VK_FALSE; + _depthStencil.front = {}; + _depthStencil.back = {}; + _depthStencil.minDepthBounds = 0.0f; + _depthStencil.maxDepthBounds = 1.0f; +} diff --git a/vk_pipelines.h b/vk_pipelines.h index df9c74d..16b4067 100644 --- a/vk_pipelines.h +++ b/vk_pipelines.h @@ -2,6 +2,37 @@ #include "vk_types.h" +class PipelineBuilder { + public: + std::vector _shaderStages; + + VkPipelineInputAssemblyStateCreateInfo _inputAssembly; + VkPipelineRasterizationStateCreateInfo _rasterizer; + VkPipelineColorBlendAttachmentState _colorBlendAttachment; + VkPipelineMultisampleStateCreateInfo _multisampling; + VkPipelineLayout _pipelineLayout; + VkPipelineDepthStencilStateCreateInfo _depthStencil; + VkPipelineRenderingCreateInfo _renderInfo; + VkFormat _colorAttachmentFormat; + + PipelineBuilder() { + clear(); + } + + void clear(); + + VkPipeline build_pipeline(VkDevice device); + void set_shaders(VkShaderModule vertexShader, VkShaderModule fragmentShader); + void set_input_topology(VkPrimitiveTopology topology); + void set_polygon_mode(VkPolygonMode mode); + void set_cull_mode(VkCullModeFlags cullMode, VkFrontFace frontFace); + void set_multisampling_none(); + void disable_blending(); + void set_color_attachment_format(VkFormat format); + void set_depth_format(VkFormat format); + void disable_depthtest(); +}; + namespace vkutil { bool load_shader_module(const char* filePath, VkDevice device,