diff --git a/Blaze.cpp b/Blaze.cpp index e917224..db44cca 100644 --- a/Blaze.cpp +++ b/Blaze.cpp @@ -5,10 +5,12 @@ #include #include +#include #include #include #include +#include #include #define ASSERT(COND) assert((COND)) @@ -194,6 +196,7 @@ int main() vkGetDeviceQueue(device, directQueueFamilyIndex, 0, &directQueue); } + VkFormat swapchainFormat; VkExtent2D swapchainExtent = { WIDTH, HEIGHT }; VkSwapchainKHR swapchain; std::vector swapchainImages; @@ -244,6 +247,7 @@ int main() } } ASSERT(format.format != VK_FORMAT_UNDEFINED); + swapchainFormat = format.format; uint32_t presentModeCount; vkGetPhysicalDeviceSurfacePresentModesKHR(physicalDeviceInUse, surface, &presentModeCount, nullptr); @@ -324,6 +328,215 @@ int main() } } + VkPipelineLayout pipelineLayout; + VkPipeline trianglePipeline; + { + size_t dataSize; + void* rawData = SDL_LoadFile("Triangle.spv", &dataSize); + ASSERT(dataSize % 4 == 0); + + if (not rawData) + { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "%s", SDL_GetError()); + abort(); + } + + auto data = static_cast(rawData); + + VkShaderModuleCreateInfo const shaderModuleCreateInfo = { + .sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .codeSize = dataSize, + .pCode = data, + }; + + VkShaderModule shaderModule; + VK_CHECK(vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, &shaderModule)); + + VkPipelineLayoutCreateInfo constexpr pipelineLayoutCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .setLayoutCount = 0, + .pSetLayouts = nullptr, + .pushConstantRangeCount = 0, + .pPushConstantRanges = nullptr, + }; + VK_CHECK(vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout)); + + std::array stages = { + VkPipelineShaderStageCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_VERTEX_BIT, + .module = shaderModule, + .pName = "VertexMain", + .pSpecializationInfo = nullptr, + }, + VkPipelineShaderStageCreateInfo{ + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .stage = VK_SHADER_STAGE_FRAGMENT_BIT, + .module = shaderModule, + .pName = "FragmentMain", + .pSpecializationInfo = nullptr, + } + }; + + VkPipelineVertexInputStateCreateInfo constexpr vertexInputState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .vertexBindingDescriptionCount = 0, + .pVertexBindingDescriptions = nullptr, + .vertexAttributeDescriptionCount = 0, + .pVertexAttributeDescriptions = nullptr, + }; + + VkPipelineInputAssemblyStateCreateInfo constexpr inputAssembly = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, + .primitiveRestartEnable = VK_FALSE, + }; + + VkPipelineTessellationStateCreateInfo constexpr tessellationState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .patchControlPoints = 0, + }; + + VkPipelineViewportStateCreateInfo constexpr viewportState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .viewportCount = 1, + .pViewports = nullptr, + .scissorCount = 1, + .pScissors = nullptr, + }; + + VkPipelineRasterizationStateCreateInfo constexpr rasterizationState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .depthClampEnable = VK_TRUE, + .rasterizerDiscardEnable = VK_FALSE, + .polygonMode = VK_POLYGON_MODE_FILL, + .cullMode = VK_CULL_MODE_NONE, + .frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE, + .depthBiasEnable = VK_FALSE, + .depthBiasConstantFactor = 0.0f, + .depthBiasClamp = 0.0f, + .depthBiasSlopeFactor = 0.0f, + .lineWidth = 1.0f, + }; + + VkPipelineMultisampleStateCreateInfo constexpr multisampleState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .rasterizationSamples = VK_SAMPLE_COUNT_1_BIT, + .sampleShadingEnable = VK_FALSE, + .minSampleShading = 0.0f, + .pSampleMask = nullptr, + .alphaToCoverageEnable = VK_FALSE, + .alphaToOneEnable = VK_FALSE, + }; + + VkPipelineDepthStencilStateCreateInfo constexpr depthStencilState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .depthTestEnable = VK_FALSE, + .depthWriteEnable = VK_FALSE, + .depthCompareOp = VK_COMPARE_OP_ALWAYS, + .depthBoundsTestEnable = VK_FALSE, + .stencilTestEnable = VK_FALSE, + .front = {}, + .back = {}, + .minDepthBounds = 0.0f, + .maxDepthBounds = 1.0f, + }; + + VkPipelineColorBlendAttachmentState constexpr colorBlendAttachmentState = { + .blendEnable = VK_FALSE, + .srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA, + .dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + .colorBlendOp = VK_BLEND_OP_ADD, + .srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE, + .dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO, + .alphaBlendOp = VK_BLEND_OP_ADD, + .colorWriteMask = VK_COLOR_COMPONENT_R_BIT + | VK_COLOR_COMPONENT_G_BIT + | VK_COLOR_COMPONENT_B_BIT + | VK_COLOR_COMPONENT_A_BIT, + }; + + VkPipelineColorBlendStateCreateInfo const colorBlendState = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .logicOpEnable = VK_FALSE, + .logicOp = VK_LOGIC_OP_COPY, + .attachmentCount = 1, + .pAttachments = &colorBlendAttachmentState, + .blendConstants = {0.0f, 0.0f, 0.0f, 0.0f}, + }; + + std::array constexpr dynamicStates = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo const dynamicStateCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO, + .pNext = nullptr, + .flags = 0, + .dynamicStateCount = static_cast(dynamicStates.size()), + .pDynamicStates = dynamicStates.data() + }; + + VkPipelineRenderingCreateInfoKHR const renderingCreateInfo = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR, + .colorAttachmentCount = 1, + .pColorAttachmentFormats = &swapchainFormat, + }; + + VkGraphicsPipelineCreateInfo const graphicsPipelineCreateInfo = { + .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, + .pNext = &renderingCreateInfo, + .flags = 0, + .stageCount = static_cast(stages.size()), + .pStages = stages.data(), + .pVertexInputState = &vertexInputState, + .pInputAssemblyState = &inputAssembly, + .pTessellationState = &tessellationState, + .pViewportState = &viewportState, + .pRasterizationState = &rasterizationState, + .pMultisampleState = &multisampleState, + .pDepthStencilState = &depthStencilState, + .pColorBlendState = &colorBlendState, + .pDynamicState = &dynamicStateCreateInfo, + .layout = pipelineLayout, + .renderPass = nullptr, + .subpass = 0, + .basePipelineHandle = nullptr, + .basePipelineIndex = 0, + }; + + VK_CHECK(vkCreateGraphicsPipelines(device, nullptr, 1, &graphicsPipelineCreateInfo, nullptr, &trianglePipeline)); + + vkDestroyShaderModule(device, shaderModule, nullptr); + + SDL_free(rawData); + } + // Create 1 command pool per frame. std::array commandPools; { @@ -443,7 +656,6 @@ int main() .pImageMemoryBarriers = &renderToPresentBarrier, }; - uint32_t frameIndex = 0; bool isRunning = true; while (isRunning) @@ -473,7 +685,8 @@ int main() uint32_t currentImageIndex; VK_CHECK(vkAcquireNextImageKHR(device, swapchain, std::numeric_limits::max(), imageAcquiredSemaphore, nullptr, ¤tImageIndex)); - vkResetFences(device, 1, &fence); + VK_CHECK(vkResetFences(device, 1, &fence)); + VK_CHECK(vkResetCommandPool(device, commandPools[frameIndex], 0)); acquireToRenderBarrier.image = swapchainImages[currentImageIndex]; renderToPresentBarrier.image = swapchainImages[currentImageIndex]; @@ -487,6 +700,10 @@ int main() .pInheritanceInfo = nullptr, }; + VkClearColorValue constexpr static BLACK_CLEAR = { + .float32 = { 0.0f, 0.0f, 0.0f, 1.0f }, + }; + VK_CHECK(vkBeginCommandBuffer(cmd, &beginInfo)); { VkRenderingAttachmentInfo const attachmentInfo = { @@ -499,7 +716,7 @@ int main() .resolveImageLayout = VK_IMAGE_LAYOUT_UNDEFINED, .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR, .storeOp = VK_ATTACHMENT_STORE_OP_STORE, - .clearValue = {.color = {{100.0f / 255.0f, 149.0f / 255.0f, 237.0f / 255.0f}}}, + .clearValue = {.color = BLACK_CLEAR}, }; VkRenderingInfo renderingInfo = { @@ -517,9 +734,27 @@ int main() vkCmdPipelineBarrier2(cmd, &acquireToRenderDependency); vkCmdBeginRendering(cmd, &renderingInfo); + { + VkViewport viewport = { + .x = 0, + .y = static_cast(swapchainExtent.height), + .width = static_cast(swapchainExtent.width), + .height = -static_cast(swapchainExtent.height), + .minDepth = 0.0f, + .maxDepth = 1.0f, + }; + vkCmdSetViewport(cmd, 0, 1, &viewport); + VkRect2D scissor = { + .offset = {0, 0}, + .extent = swapchainExtent, + }; + vkCmdSetScissor(cmd, 0, 1, &scissor); - // Render Something? + // Render Something? + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, trianglePipeline); + vkCmdDraw(cmd, 3, 1, 0, 0); + } vkCmdEndRendering(cmd); vkCmdPipelineBarrier2(cmd, &renderToPresentDependency); } @@ -557,9 +792,36 @@ int main() frameIndex = (frameIndex + 1) % NUM_FRAMES; } - for (VkImageView view : swapchainViews) { + VK_CHECK(vkDeviceWaitIdle(device)); + + for (VkFence fence : frameInUseFences) + { + vkDestroyFence(device, fence, nullptr); + } + + for (VkSemaphore semaphore : imageAcquiredSemaphores) + { + vkDestroySemaphore(device, semaphore, nullptr); + } + + for (VkSemaphore semaphore : renderFinishedSemaphores) + { + vkDestroySemaphore(device, semaphore, nullptr); + } + + for (VkCommandPool commandPool : commandPools) + { + vkDestroyCommandPool(device, commandPool, nullptr); + } + + for (VkImageView view : swapchainViews) + { vkDestroyImageView(device, view, nullptr); } + + vkDestroyPipeline(device, trianglePipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroySwapchainKHR(device, swapchain, nullptr); vkDestroyDevice(device, nullptr); diff --git a/Blaze.vcxproj b/Blaze.vcxproj index ccd2400..017513e 100644 --- a/Blaze.vcxproj +++ b/Blaze.vcxproj @@ -157,6 +157,19 @@ + + Document + slangc %(FullPath) -profile sm_6_6 -target spirv -o %(Filename).spv + %(Filename).spv + slangc %(FullPath) -profile sm_6_6 -target spirv -o %(Filename).spv + %(Filename).spv + false + false + false + false + Compiling slang shader + Compiling slang shader + diff --git a/Blaze.vcxproj.filters b/Blaze.vcxproj.filters index 5572f79..d3a09f9 100644 --- a/Blaze.vcxproj.filters +++ b/Blaze.vcxproj.filters @@ -13,6 +13,9 @@ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + {672b8ec5-258c-4a21-bbf7-66d3b1185fe9} + @@ -36,4 +39,9 @@ Resource Files + + + Shader Files + + \ No newline at end of file diff --git a/PLAN.md b/PLAN.md index 77ae754..b7aa37b 100644 --- a/PLAN.md +++ b/PLAN.md @@ -14,9 +14,9 @@ - [X] Create logical device - [X] Create swapchain - [X] Clear Render Attachments -- [ ] Create a Triangle - - [ ] Create pipeline - - [ ] Draw +- [X] Create a Triangle + - [X] Create pipeline + - [X] Draw - [ ] Create a Box - [ ] Create Vertex buffer - [ ] Load texture diff --git a/Triangle.slang b/Triangle.slang new file mode 100644 index 0000000..d02bf6f --- /dev/null +++ b/Triangle.slang @@ -0,0 +1,34 @@ + +const static float4 vertexPos[] = { + float4(0.0f, 0.5f, 0.5f, 1.0f), + float4(-0.5f, -0.5f, 0.5f, 1.0f), + float4(0.5f, -0.5f, 0.5f, 1.0f), +}; +const static float4 vertexColors[] = { + float4(1.0f, 0.0f, 0.0f, 1.0f), + float4(0.0f, 1.0f, 0.0f, 1.0f), + float4(0.0f, 0.0f, 1.0f, 1.0f), +}; + +struct VertexOut { + float4 outPosition : SV_Position; + float4 vertexColor : CoarseColor; +}; + +[shader("vertex")] +VertexOut VertexMain( + uint vertexId: SV_VertexID +) { + VertexOut output; + output.outPosition = vertexPos[vertexId]; + output.vertexColor = vertexColors[vertexId]; + return output; +} + +[shader("fragment")] +float4 FragmentMain( + float4 interpolatedColors: CoarseColor, +) : SV_Target0 { + return float4(interpolatedColors.rgb, 1.0f); +} + diff --git a/Triangle.spv b/Triangle.spv new file mode 100644 index 0000000..9ab68bc Binary files /dev/null and b/Triangle.spv differ diff --git a/vcpkg.json b/vcpkg.json index 4e93083..b5dc1c5 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -2,6 +2,7 @@ "dependencies": [ "fmt", "volk", + "shader-slang", { "name": "sdl3", "features": [ "vulkan" ]