diff --git a/Nuake/src/Rendering/Vulkan/PipelineBuilder.cpp b/Nuake/src/Rendering/Vulkan/PipelineBuilder.cpp new file mode 100644 index 00000000..7ccf7464 --- /dev/null +++ b/Nuake/src/Rendering/Vulkan/PipelineBuilder.cpp @@ -0,0 +1,164 @@ +#include "PipelineBuilder.h" + +#include "src/Core/Logger.h" + +#include "src/Rendering/Vulkan/VulkanInit.h" + +using namespace Nuake; + +void PipelineBuilder::Clear() +{ + 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::BuildPipeline(VkDevice device) +{ + // make viewport state from our stored viewport and scissor. + // at the moment we wont support multiple viewports or scissors + VkPipelineViewportStateCreateInfo viewportState = {}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.pNext = nullptr; + + viewportState.viewportCount = 1; + viewportState.scissorCount = 1; + + // setup dummy color blending. We arent using transparent objects yet + // the blending is just "no blend", but we do write to the color attachment + VkPipelineColorBlendStateCreateInfo colorBlending = {}; + colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlending.pNext = nullptr; + + colorBlending.logicOpEnable = VK_FALSE; + colorBlending.logicOp = VK_LOGIC_OP_COPY; + colorBlending.attachmentCount = 1; + colorBlending.pAttachments = &ColorBlendAttachment; + + // completely clear VertexInputStateCreateInfo, as we have no need for it + VkPipelineVertexInputStateCreateInfo _vertexInputInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; + + // build the actual pipeline + // we now use all of the info structs we have been writing into into this one + // to create the pipeline + VkGraphicsPipelineCreateInfo pipelineInfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO }; + // connect the renderInfo to the pNext extension mechanism + pipelineInfo.pNext = &RenderInfo; + + pipelineInfo.stageCount = (uint32_t)ShaderStages.size(); + pipelineInfo.pStages = ShaderStages.data(); + pipelineInfo.pVertexInputState = &_vertexInputInfo; + pipelineInfo.pInputAssemblyState = &InputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &Rasterizer; + pipelineInfo.pMultisampleState = &Multisampling; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.pDepthStencilState = &DepthStencil; + pipelineInfo.layout = PipelineLayout; + + VkDynamicState state[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR }; + + VkPipelineDynamicStateCreateInfo dynamicInfo = { .sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; + dynamicInfo.pDynamicStates = &state[0]; + dynamicInfo.dynamicStateCount = 2; + + pipelineInfo.pDynamicState = &dynamicInfo; + + // its easy to error out on create graphics pipeline, so we handle it a bit + // better than the common VK_CHECK case + VkPipeline newPipeline; + if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &newPipeline) != VK_SUCCESS) + { + Logger::Log("Failed to create graphics pipeline", "vulkan", CRITICAL); + return VK_NULL_HANDLE; // failed to create graphics pipeline + } + + return newPipeline; +} + +void PipelineBuilder::SetShaders(VkShaderModule vert, VkShaderModule frag) +{ + ShaderStages.clear(); + + ShaderStages.push_back(VulkanInit::PipelineShaderStageCreateInfo(VK_SHADER_STAGE_VERTEX_BIT, vert)); + + ShaderStages.push_back(VulkanInit::PipelineShaderStageCreateInfo(VK_SHADER_STAGE_FRAGMENT_BIT, frag)); +} + +void PipelineBuilder::SetInputTopology(VkPrimitiveTopology topology) +{ + InputAssembly.topology = topology; + // we are not going to use primitive restart on the entire tutorial so leave + // it on false + InputAssembly.primitiveRestartEnable = VK_FALSE; +} + +void PipelineBuilder::SetPolygonMode(VkPolygonMode polygonMode) +{ + Rasterizer.polygonMode = polygonMode; + Rasterizer.lineWidth = 1.f; +} + +void PipelineBuilder::SetCullMode(VkCullModeFlags cullMode, VkFrontFace frontFace) +{ + Rasterizer.cullMode = cullMode; + Rasterizer.frontFace = frontFace; +} + +void PipelineBuilder::SetMultiSamplingNone() +{ + Multisampling.sampleShadingEnable = VK_FALSE; + // multisampling defaulted to no multisampling (1 sample per pixel) + Multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + Multisampling.minSampleShading = 1.0f; + Multisampling.pSampleMask = nullptr; + // no alpha to coverage either + Multisampling.alphaToCoverageEnable = VK_FALSE; + Multisampling.alphaToOneEnable = VK_FALSE; +} + +void PipelineBuilder::DisableBlending() +{ + // default write mask + ColorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + // no blending + ColorBlendAttachment.blendEnable = VK_FALSE; +} + +void PipelineBuilder::SetColorAttachment(VkFormat format) +{ + ColorAttachmentformat = format; + // connect the format to the renderInfo structure + RenderInfo.colorAttachmentCount = 1; + RenderInfo.pColorAttachmentFormats = &ColorAttachmentformat; +} + +void PipelineBuilder::SetDepthFormat(VkFormat depthFormat) +{ + RenderInfo.depthAttachmentFormat = depthFormat; +} + +void PipelineBuilder::DisableDepthTest() +{ + 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.f; + DepthStencil.maxDepthBounds = 1.f; +} diff --git a/Nuake/src/Rendering/Vulkan/PipelineBuilder.h b/Nuake/src/Rendering/Vulkan/PipelineBuilder.h new file mode 100644 index 00000000..6ce0eb74 --- /dev/null +++ b/Nuake/src/Rendering/Vulkan/PipelineBuilder.h @@ -0,0 +1,40 @@ +#pragma once +#include + +#include + +namespace Nuake +{ + class PipelineBuilder + { + public: + std::vector ShaderStages; + + VkPipelineInputAssemblyStateCreateInfo InputAssembly; + VkPipelineRasterizationStateCreateInfo Rasterizer; + VkPipelineColorBlendAttachmentState ColorBlendAttachment; + VkPipelineMultisampleStateCreateInfo Multisampling; + VkPipelineLayout PipelineLayout; + VkPipelineDepthStencilStateCreateInfo DepthStencil; + VkPipelineRenderingCreateInfo RenderInfo; + VkFormat ColorAttachmentformat; + + + PipelineBuilder() { Clear(); } + ~PipelineBuilder() = default; + + void Clear(); + + VkPipeline BuildPipeline(VkDevice device); + void SetShaders(VkShaderModule vert, VkShaderModule frag); + + void SetInputTopology(VkPrimitiveTopology topology); + void SetPolygonMode(VkPolygonMode polygonMode); + void SetCullMode(VkCullModeFlags cullMode, VkFrontFace frontFace); + void SetMultiSamplingNone(); + void DisableBlending(); + void SetColorAttachment(VkFormat format); + void SetDepthFormat(VkFormat depthFormat); + void DisableDepthTest(); + }; +} \ No newline at end of file diff --git a/Nuake/src/Rendering/Vulkan/VulkanAllocatedBuffer.cpp b/Nuake/src/Rendering/Vulkan/VulkanAllocatedBuffer.cpp new file mode 100644 index 00000000..0c557ba8 --- /dev/null +++ b/Nuake/src/Rendering/Vulkan/VulkanAllocatedBuffer.cpp @@ -0,0 +1,33 @@ +#include "VulkanAllocatedBuffer.h" + +#include "VulkanAllocator.h" +#include "VulkanCheck.h" +#include "VulkanRenderer.h" + + +using namespace Nuake; + +#include "vk_mem_alloc.h" + +AllocatedBuffer::AllocatedBuffer(size_t inSize, VkBufferUsageFlags inFlags, VmaMemoryUsage inUsage) +{ + // allocate buffer + VkBufferCreateInfo bufferInfo = { .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO }; + bufferInfo.pNext = nullptr; + bufferInfo.size = inSize; + + bufferInfo.usage = inFlags; + + VmaAllocationCreateInfo vmaallocInfo = {}; + vmaallocInfo.usage = inUsage; + vmaallocInfo.flags = VMA_ALLOCATION_CREATE_MAPPED_BIT; + + // allocate the buffer + VK_CALL(vmaCreateBuffer(VulkanAllocator::Get().GetAllocator(), &bufferInfo, &vmaallocInfo, &Buffer, &Allocation, + &Info)); +} + +AllocatedBuffer::~AllocatedBuffer() +{ + // TODO: deletion of buffer +} diff --git a/Nuake/src/Rendering/Vulkan/VulkanAllocatedBuffer.h b/Nuake/src/Rendering/Vulkan/VulkanAllocatedBuffer.h new file mode 100644 index 00000000..79fbd582 --- /dev/null +++ b/Nuake/src/Rendering/Vulkan/VulkanAllocatedBuffer.h @@ -0,0 +1,36 @@ +#pragma once + +#include "src/Core/Maths.h" + +#include +#include + + +namespace Nuake +{ + class AllocatedBuffer + { + private: + VkBuffer Buffer; + VmaAllocation Allocation; + VmaAllocationInfo Info; + + public: + AllocatedBuffer(size_t size, VkBufferUsageFlags flags, VmaMemoryUsage usage); + ~AllocatedBuffer(); + }; + + struct GPUMeshBuffers + { + AllocatedBuffer indexBuffer; + AllocatedBuffer vertexBuffer; + VkDeviceAddress vertexBufferAddress; + }; + + // push constants for our mesh object draws + struct GPUDrawPushConstants + { + glm::mat4 worldMatrix; + VkDeviceAddress vertexBuffer; + }; +} \ No newline at end of file diff --git a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp index 3bdf14f1..39a47de0 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.cpp @@ -10,6 +10,7 @@ using namespace Nuake; +#include "vk_mem_alloc.h" VulkanImage::VulkanImage(ImageFormat inFormat, Vector2 inSize) : Format(inFormat), @@ -48,6 +49,11 @@ VulkanImage::VulkanImage(void* inData, ImageFormat inFormat, Vector2 inSize) } +VulkanImage::~VulkanImage() +{ + // TODO: deletion of image +} + VkDescriptorSet& VulkanImage::GetImGuiDescriptorSet() { if (!ImGuiDescriptorSetGenerated) diff --git a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h index d807ecfb..2568cd79 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h +++ b/Nuake/src/Rendering/Vulkan/VulkanImage/VulkanImage.h @@ -42,11 +42,12 @@ namespace Nuake public: VulkanImage(ImageFormat format, Vector2 size); VulkanImage(void* data, ImageFormat format, Vector2 size); - ~VulkanImage() = default; + ~VulkanImage(); Vector2 GetSize() const { return Vector2(Extent.x, Extent.y); } VkImageView& GetImageView() { return ImageView; } VkImage& GetImage() { return Image; } VkDescriptorSet& GetImGuiDescriptorSet(); + ImageFormat GetFormat() const { return Format; } }; } \ No newline at end of file diff --git a/Nuake/src/Rendering/Vulkan/VulkanInit.cpp b/Nuake/src/Rendering/Vulkan/VulkanInit.cpp index 9900c4c9..fd17162f 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanInit.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanInit.cpp @@ -90,7 +90,7 @@ VkCommandBufferSubmitInfo VulkanInit::CommandBufferSubmitInfo(VkCommandBuffer cm return info; } -VkSubmitInfo2 VulkanInit::SubmitInfo(VkCommandBufferSubmitInfo * cmd, VkSemaphoreSubmitInfo * signalSemaphoreInfo, VkSemaphoreSubmitInfo * waitSemaphoreInfo) +VkSubmitInfo2 VulkanInit::SubmitInfo(VkCommandBufferSubmitInfo* cmd, VkSemaphoreSubmitInfo * signalSemaphoreInfo, VkSemaphoreSubmitInfo * waitSemaphoreInfo) { VkSubmitInfo2 info = {}; info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO_2; @@ -102,7 +102,7 @@ VkSubmitInfo2 VulkanInit::SubmitInfo(VkCommandBufferSubmitInfo * cmd, VkSemaphor info.signalSemaphoreInfoCount = signalSemaphoreInfo == nullptr ? 0 : 1; info.pSignalSemaphoreInfos = signalSemaphoreInfo; - info.commandBufferInfoCount = 1; + info.commandBufferInfoCount = cmd == nullptr ? 0 : 1; info.pCommandBufferInfos = cmd; return info; @@ -186,6 +186,34 @@ VkRenderingInfo VulkanInit::RenderingInfo(VkExtent2D renderExtent, VkRenderingAt return renderInfo; } +VkPipelineLayoutCreateInfo VulkanInit::PipelineLayoutCreateInfo() +{ + VkPipelineLayoutCreateInfo info{}; + info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + info.pNext = nullptr; + + // empty defaults + info.flags = 0; + info.setLayoutCount = 0; + info.pSetLayouts = nullptr; + info.pushConstantRangeCount = 0; + info.pPushConstantRanges = nullptr; + return info; +} + +VkPipelineShaderStageCreateInfo VulkanInit::PipelineShaderStageCreateInfo(VkShaderStageFlagBits flags, VkShaderModule shader) +{ + VkPipelineShaderStageCreateInfo info{}; + info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + info.pNext = nullptr; + + // shader stage + info.stage = flags; + info.module = shader; + info.pName = "main"; + return info; +} + // This is a helper to transtion images between readable, writable layouts. void VulkanUtil::TransitionImage(VkCommandBuffer cmd, VkImage image, VkImageLayout currentLayout, VkImageLayout newLayout) { diff --git a/Nuake/src/Rendering/Vulkan/VulkanInit.h b/Nuake/src/Rendering/Vulkan/VulkanInit.h index 8bbe886e..97b01a4c 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanInit.h +++ b/Nuake/src/Rendering/Vulkan/VulkanInit.h @@ -26,6 +26,9 @@ namespace Nuake static VkRenderingAttachmentInfo AttachmentInfo(VkImageView view, VkClearValue* clear, VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); static VkRenderingInfo RenderingInfo(VkExtent2D renderExtent, VkRenderingAttachmentInfo * colorAttachment, VkRenderingAttachmentInfo * depthAttachment); + + static VkPipelineLayoutCreateInfo PipelineLayoutCreateInfo(); + static VkPipelineShaderStageCreateInfo PipelineShaderStageCreateInfo(VkShaderStageFlagBits flags, VkShaderModule shader); }; class VulkanUtil diff --git a/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp b/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp index 48441da7..8f764d02 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp +++ b/Nuake/src/Rendering/Vulkan/VulkanRenderer.cpp @@ -17,6 +17,7 @@ #include "VulkanAllocator.h" #include "VulkanCheck.h" +#include "PipelineBuilder.h" using namespace Nuake; @@ -70,9 +71,13 @@ void VkRenderer::Initialize() InitDescriptors(); - BackgroundShader = ShaderCompiler::Get().CompileShader("../Resources/Shaders/Vulkan/background.comp"); + ShaderCompiler& shaderCompiler = ShaderCompiler::Get(); + TriangleVertShader = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.vert"); + BackgroundShader = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/background.comp"); + TriangleFragShader = shaderCompiler.CompileShader("../Resources/Shaders/Vulkan/triangle.frag"); InitPipeline(); + InitTrianglePipeline(); InitImgui(); @@ -306,7 +311,6 @@ void VkRenderer::UpdateDescriptorSets() drawImageWrite.pImageInfo = &imgInfo; vkUpdateDescriptorSets(Device, 1, &drawImageWrite, 0, nullptr); - } void VkRenderer::InitPipeline() @@ -345,6 +349,82 @@ void VkRenderer::InitBackgroundPipeline() }); } +void VkRenderer::InitTrianglePipeline() +{ + VkPipelineLayoutCreateInfo pipeline_layout_info = VulkanInit::PipelineLayoutCreateInfo(); + VK_CALL(vkCreatePipelineLayout(Device, &pipeline_layout_info, nullptr, &TrianglePipelineLayout)); + + PipelineBuilder pipelineBuilder; + + //use the triangle layout we created + pipelineBuilder.PipelineLayout = TrianglePipelineLayout; + //connecting the vertex and pixel shaders to the pipeline + pipelineBuilder.SetShaders(TriangleVertShader->GetModule(), TriangleFragShader->GetModule()); + //it will draw triangles + pipelineBuilder.SetInputTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + //filled triangles + pipelineBuilder.SetPolygonMode(VK_POLYGON_MODE_FILL); + //no backface culling + pipelineBuilder.SetCullMode(VK_CULL_MODE_NONE, VK_FRONT_FACE_CLOCKWISE); + //no multisampling + pipelineBuilder.SetMultiSamplingNone(); + //no blending + pipelineBuilder.DisableBlending(); + //no depth testing + pipelineBuilder.DisableDepthTest(); + + //connect the image format we will draw into, from draw image + pipelineBuilder.SetColorAttachment(static_cast(DrawImage->GetFormat())); + pipelineBuilder.SetDepthFormat(VK_FORMAT_UNDEFINED); + + //finally build the pipeline + TrianglePipeline = pipelineBuilder.BuildPipeline(Device); + + //clean structures + //vkDestroyShaderModule(Device, Triangl, nullptr); + //vkDestroyShaderModule(Device, TriangleVertexShader, nullptr); + + MainDeletionQueue.push_function([&]() { + vkDestroyPipelineLayout(Device, TrianglePipelineLayout, nullptr); + vkDestroyPipeline(Device, TrianglePipeline, nullptr); + }); +} + +void VkRenderer::DrawGeometry(VkCommandBuffer cmd) +{ + //begin a render pass connected to our draw image + VkRenderingAttachmentInfo colorAttachment = VulkanInit::AttachmentInfo(DrawImage->GetImageView(), nullptr, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + + VkRenderingInfo renderInfo = VulkanInit::RenderingInfo(DrawExtent, &colorAttachment, nullptr); + vkCmdBeginRendering(cmd, &renderInfo); + + vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, TrianglePipeline); + + //set dynamic viewport and scissor + VkViewport viewport = {}; + viewport.x = 0; + viewport.y = 0; + viewport.width = DrawExtent.width; + viewport.height = DrawExtent.height; + viewport.minDepth = 0.f; + viewport.maxDepth = 1.f; + + vkCmdSetViewport(cmd, 0, 1, &viewport); + + VkRect2D scissor = {}; + scissor.offset.x = 0; + scissor.offset.y = 0; + scissor.extent.width = DrawExtent.width; + scissor.extent.height = DrawExtent.height; + + vkCmdSetScissor(cmd, 0, 1, &scissor); + + //launch a draw command to draw 3 vertices + vkCmdDraw(cmd, 3, 1, 0, 0); + + vkCmdEndRendering(cmd); +} + void VkRenderer::InitImgui() { // 1: create descriptor pool for IMGUI @@ -514,20 +594,16 @@ void VkRenderer::Draw() { VK_CALL(vkWaitForFences(Device, 1, &GetCurrentFrame().RenderFence, true, 1000000000)); - //GetCurrentFrame().LocalDeletionQueue.flush(); + + if (SurfaceSize != Window::Get()->GetSize()) + { + RecreateSwapchain(); + return; + } //request image from the swapchain uint32_t swapchainImageIndex; VkResult result = vkAcquireNextImageKHR(Device, Swapchain, 1000000000, GetCurrentFrame().SwapchainSemaphore, nullptr, &swapchainImageIndex); - - if (result == VK_ERROR_OUT_OF_DATE_KHR || SurfaceSize != Window::Get()->GetSize()) - { - RecreateSwapchain(); - //DestroySwapchain(); - //CreateSwapchain(Window::Get()->GetSize()); - return; - } - VK_CALL(vkResetFences(Device, 1, &GetCurrentFrame().RenderFence)); @@ -541,9 +617,12 @@ void VkRenderer::Draw() DrawExtent.width = DrawImage->GetSize().x; DrawExtent.height = DrawImage->GetSize().y; + VkCommandBufferSubmitInfo cmdinfo; + // Create commands VK_CALL(vkBeginCommandBuffer(cmd, &cmdBeginInfo)); { + // Transfer rendering image to general layout VulkanUtil::TransitionImage(cmd, DrawImage->GetImage(), VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL); @@ -558,14 +637,13 @@ void VkRenderer::Draw() //VulkanUtil::TransitionImage(cmd, DrawImage->GetImage(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); VulkanUtil::TransitionImage(cmd, SwapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + DrawGeometry(cmd); + VulkanUtil::TransitionImage(cmd, DrawImage->GetImage(), VK_IMAGE_LAYOUT_GENERAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); - - { - } + //draw imgui into the swapchain image DrawImgui(cmd, SwapchainImageViews[swapchainImageIndex]); - // set swapchain image layout to Attachment Optimal so we can draw it VulkanUtil::TransitionImage(cmd, SwapchainImages[swapchainImageIndex], VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); @@ -577,7 +655,7 @@ void VkRenderer::Draw() } VK_CALL(vkEndCommandBuffer(cmd)); - VkCommandBufferSubmitInfo cmdinfo = VulkanInit::CommandBufferSubmitInfo(cmd); + cmdinfo = VulkanInit::CommandBufferSubmitInfo(cmd); // Wait for both semaphore of swapchain and the texture of the frame. VkSemaphoreSubmitInfo waitInfo = VulkanInit::SemaphoreSubmitInfo(VK_PIPELINE_STAGE_2_COLOR_ATTACHMENT_OUTPUT_BIT_KHR, GetCurrentFrame().SwapchainSemaphore); diff --git a/Nuake/src/Rendering/Vulkan/VulkanRenderer.h b/Nuake/src/Rendering/Vulkan/VulkanRenderer.h index 8ce3d044..b47db94a 100644 --- a/Nuake/src/Rendering/Vulkan/VulkanRenderer.h +++ b/Nuake/src/Rendering/Vulkan/VulkanRenderer.h @@ -161,8 +161,12 @@ namespace Nuake VkPipeline Pipeline; VkPipelineLayout PipelineLayout; - Ref BackgroundShader; + VkPipelineLayout TrianglePipelineLayout; + VkPipeline TrianglePipeline; + Ref BackgroundShader; + Ref TriangleVertShader; + Ref TriangleFragShader; // Imgui VkFence ImguiFence; VkCommandBuffer ImguiCommandBuffer; @@ -200,6 +204,8 @@ namespace Nuake void UpdateDescriptorSets(); void InitPipeline(); void InitBackgroundPipeline(); + void InitTrianglePipeline(); + void DrawGeometry(VkCommandBuffer cmd); void InitImgui(); void Draw(); diff --git a/Nuake/src/Rendering/Vulkan/VulkanTypes.h b/Nuake/src/Rendering/Vulkan/VulkanTypes.h new file mode 100644 index 00000000..df5f1fd0 --- /dev/null +++ b/Nuake/src/Rendering/Vulkan/VulkanTypes.h @@ -0,0 +1,32 @@ +#pragma once + +#include +#include "src/Rendering/Vulkan/VulkanAllocatedBuffer.h" + + +namespace Nuake +{ + struct Vertex + { + Vector3 position; + float uv_x; + Vector3 normal; + float uv_y; + Vector4 color; + }; + + // holds the resources needed for a mesh + struct GPUMeshBuffers + { + AllocatedBuffer indexBuffer; + AllocatedBuffer vertexBuffer; + VkDeviceAddress vertexBufferAddress; + }; + + // push constants for our mesh object draws + struct GPUDrawPushConstants + { + Matrix4 worldMatrix; + VkDeviceAddress vertexBuffer; + }; +} diff --git a/Resources/Shaders/Vulkan/test.vert b/Resources/Shaders/Vulkan/test.vert new file mode 100644 index 00000000..de1d9394 --- /dev/null +++ b/Resources/Shaders/Vulkan/test.vert @@ -0,0 +1,28 @@ +struct VSInput +{ +[[vk::location(0)]] float3 Position : POSITION0; +[[vk::location(1)]] float3 Color : COLOR0; +}; + +struct UBO +{ + float4x4 projectionMatrix; + float4x4 modelMatrix; + float4x4 viewMatrix; +}; + +cbuffer ubo : register(b0, space0) { UBO ubo; } + +struct VSOutput +{ + float4 Pos : SV_POSITION; +[[vk::location(0)]] float3 Color : COLOR0; +}; + +VSOutput main(VSInput input, uint VertexIndex : SV_VertexID) +{ + VSOutput output = (VSOutput)0; + output.Color = input.Color * float(VertexIndex); + output.Pos = mul(ubo.projectionMatrix, mul(ubo.viewMatrix, mul(ubo.modelMatrix, float4(input.Position.xyz, 1.0)))); + return output; +} \ No newline at end of file diff --git a/Resources/Shaders/Vulkan/triangle.frag b/Resources/Shaders/Vulkan/triangle.frag new file mode 100644 index 00000000..e2495957 --- /dev/null +++ b/Resources/Shaders/Vulkan/triangle.frag @@ -0,0 +1,9 @@ +struct PSInput { + float3 Color : TEXCOORD0; +}; + +float4 main(PSInput input) : SV_Target +{ + // Return color with alpha = 1.0f + return float4(input.Color, 1.0f); +} \ No newline at end of file diff --git a/Resources/Shaders/Vulkan/triangle.vert b/Resources/Shaders/Vulkan/triangle.vert new file mode 100644 index 00000000..6c992377 --- /dev/null +++ b/Resources/Shaders/Vulkan/triangle.vert @@ -0,0 +1,30 @@ +// HLSL version for Shader Model 6.1 +struct VSOutput { + float4 Position : SV_Position; + float3 Color : TEXCOORD0; +}; + +VSOutput main(uint vertexIndex : SV_VertexID) +{ + VSOutput output; + + // Constant array of positions for the triangle + float3 positions[3] = { + float3(1.0f, 1.0f, 0.0f), + float3(-1.0f, 1.0f, 0.0f), + float3(0.0f, -1.0f, 0.0f) + }; + + // Constant array of colors for the triangle + float3 colors[3] = { + float3(1.0f, 0.0f, 0.0f), // red + float3(0.0f, 1.0f, 0.0f), // green + float3(0.0f, 0.0f, 1.0f) // blue + }; + + // Output the position of each vertex + output.Position = float4(positions[vertexIndex], 1.0f); + output.Color = colors[vertexIndex]; + + return output; +} \ No newline at end of file diff --git a/Resources/Shaders/Vulkan/triangle.vert.hlsl b/Resources/Shaders/Vulkan/triangle.vert.hlsl new file mode 100644 index 00000000..35745b97 --- /dev/null +++ b/Resources/Shaders/Vulkan/triangle.vert.hlsl @@ -0,0 +1,39 @@ +struct Vertex +{ + float3 position; + float uv_x; + float3 normal; + float uv_y; + float4 color; +}; + +// Define the structured buffer for vertices +StructuredBuffer vertexBuffer : register(t0); // Binding of vertex buffer (example: t0) + +// Define push constants block +cbuffer PushConstants : register(b0) { // Push constants binding (example: b0) + float4x4 render_matrix; // Matrix for rendering + uint64_t vertexBufferAddress; // Buffer reference address (Vulkan-specific handling required) +}; + +// Outputs +struct VSOutput { + float4 Position : SV_Position; + float3 Color : TEXCOORD0; + float2 UV : TEXCOORD1; +}; + +// Main vertex shader +VSOutput main(uint vertexIndex : SV_VertexID) { + VSOutput output; + + // Load vertex data from the buffer + Vertex v = vertexBuffer[vertexIndex]; + + // Transform and output vertex data + output.Position = mul(render_matrix, float4(v.position, 1.0f)); + output.Color = v.color.xyz; + output.UV = float2(v.uv_x, v.uv_y); + + return output; +} \ No newline at end of file