diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp index 2328f686..362b8e72 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.cpp @@ -8,6 +8,8 @@ #include "VulkanRenderer.h" +#include "MG_State/GLState/ProgramState/ProgramObject.h" + namespace MobileGL::MG_Backend::DirectVulkan { VkBool32 VulkanRenderer::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -54,6 +56,161 @@ namespace MobileGL::MG_Backend::DirectVulkan { Shutdown(); } + const char* demoFS = R"(#version 460 + layout(location = 0) in vec3 fragColor; + layout(location = 0) out vec4 outColor; + void main() { + outColor = vec4(fragColor, 1.0); + } +)"; + const char* demoVS = R"(#version 460 + layout(location = 0) out vec3 fragColor; + vec2 positions[3] = vec2[](vec2(0.0, -0.5), vec2(0.5, 0.5), vec2(-0.5, 0.5)); + vec3 colors[3] = vec3[](vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0)); + void main() { + gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0); + fragColor = colors[gl_VertexID]; + } +)"; + void VulkanRenderer::PrepareDemoPipeline() { + MGLOG_D("PrepareDemoRes called"); + + // Create shader&program object + auto programObject = MG_State::GLState::ProgramObject(0); + auto vsObject = MakeShared(ShaderStage::Vertex, 0); + vsObject->SetShaderSource(demoVS); + vsObject->Compile(); + if (!vsObject->GetCompileStatus()) { + MGLOG_E("Vertex shader compilation failed: %s", vsObject->GetInfoLog().c_str()); + return; + } + auto fsObject = MakeShared(ShaderStage::Fragment, 1); + fsObject->SetShaderSource(demoFS); + fsObject->Compile(); + if (!fsObject->GetCompileStatus()) { + MGLOG_E("Fragment shader compilation failed: %s", fsObject->GetInfoLog().c_str()); + return; + } + programObject.AttachShader(vsObject); + programObject.AttachShader(fsObject); + programObject.Link(); + if (!programObject.GetLinkStatus()) { + MGLOG_E("Program linking failed: %s", programObject.GetInfoLog().c_str()); + return; + } + + Vector vsSpv; + Vector fsSpv; + + auto& shaderSpirvs = programObject.GetGeneratedSpirv(); + auto& attachedShaders = programObject.GetAttachedShaders(); + for (int index = 0; index < attachedShaders.size(); ++index) { + auto& shader = attachedShaders[index]; + auto& spirvCode = shaderSpirvs[index]; + if (shader->GetShaderStage() == ShaderStage::Vertex) { + vsSpv = spirvCode; + } else if (shader->GetShaderStage() == ShaderStage::Fragment) { + fsSpv = spirvCode; + } + } + + VkShaderModuleCreateInfo smci{VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO}; + smci.codeSize = vsSpv.size() * sizeof(uint32_t); + smci.pCode = vsSpv.data(); + VkShaderModule vs; + VK_VERIFY(vkCreateShaderModule(m_device, &smci, nullptr, &vs), "vkCreateShaderModule VS"); + + smci.codeSize = fsSpv.size() * sizeof(uint32_t); + smci.pCode = fsSpv.data(); + VkShaderModule fs; + VK_VERIFY(vkCreateShaderModule(m_device, &smci, nullptr, &fs), "vkCreateShaderModule FS"); + + VkPipelineShaderStageCreateInfo stages[2]{}; + stages[0] = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; + stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + stages[0].module = vs; + stages[0].pName = "main"; + stages[1] = {VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO}; + stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + stages[1].module = fs; + stages[1].pName = "main"; + + VkPipelineLayoutCreateInfo plci{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO}; + VK_VERIFY(vkCreatePipelineLayout(m_device, &plci, nullptr, &m_pipelineLayout), "vkCreatePipelineLayout"); + + // Create the rest of pipeline component + VkPipelineVertexInputStateCreateInfo vertexInput{VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO}; + vertexInput.vertexBindingDescriptionCount = 0; + vertexInput.vertexAttributeDescriptionCount = 0; + + VkPipelineInputAssemblyStateCreateInfo ia{VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO}; + ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkViewport vp{}; + vp.x = 0; + vp.y = 0; + vp.width = (float)m_swapChainExtent.width; + vp.height = (float)m_swapChainExtent.height; + vp.minDepth = 0; + vp.maxDepth = 1; + VkRect2D scissor{{0, 0}, m_swapChainExtent}; + VkPipelineViewportStateCreateInfo vpci{VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO}; + vpci.viewportCount = 1; + vpci.pViewports = &vp; + vpci.scissorCount = 1; + vpci.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo raster{VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO}; + raster.polygonMode = VK_POLYGON_MODE_FILL; + raster.cullMode = VK_CULL_MODE_NONE; + raster.frontFace = VK_FRONT_FACE_CLOCKWISE; + raster.lineWidth = 1.0f; + + VkPipelineMultisampleStateCreateInfo ms{VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO}; + ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState colorAttach{}; + colorAttach.colorWriteMask = + VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorAttach.blendEnable = VK_FALSE; + VkPipelineColorBlendStateCreateInfo blend{VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO}; + blend.attachmentCount = 1; + blend.pAttachments = &colorAttach; + + // Create Pipeline + VkGraphicsPipelineCreateInfo gpi{VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO}; + gpi.stageCount = 2; + gpi.pStages = stages; + gpi.pVertexInputState = &vertexInput; + gpi.pInputAssemblyState = &ia; + gpi.pViewportState = &vpci; + gpi.pRasterizationState = &raster; + gpi.pMultisampleState = &ms; + gpi.pColorBlendState = &blend; + gpi.layout = m_pipelineLayout; + gpi.renderPass = m_renderPass; + gpi.subpass = 0; + + VK_VERIFY(vkCreateGraphicsPipelines(m_device, VK_NULL_HANDLE, 1, &gpi, nullptr, &m_pipeline), + "vkCreateGraphicsPipelines"); + + vkDestroyShaderModule(m_device, vs, nullptr); + vkDestroyShaderModule(m_device, fs, nullptr); + + MGLOG_I("PrepareDemoPipeline completed"); + + // VkPipeline trianglePipeline = MG_Backend::DirectVulkan::pVulkanRenderer->CreateGraphicsPipelineFromSpv( + // "TrianglePipeline", vsSpv, fsSpv); + // + // // Register render callback + // MG_Backend::DirectVulkan::pVulkanRenderer->RegisterRenderCallback( + // "DrawTriangle", [trianglePipeline](VkCommandBuffer cmd, uint32_t imageIndex, VkExtent2D extent) { + // vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, trianglePipeline); + // + // vkCmdDraw(cmd, 3, 1, 0, 0); + // }); + } + void VulkanRenderer::Initialize() { CreateInstance(); CreateSurface(); @@ -64,10 +221,19 @@ namespace MobileGL::MG_Backend::DirectVulkan { CreateCommandPool(); CreateCommandBuffer(); CreateDefaultRenderPass(); + PrepareDemoPipeline(); MGLOG_D("VulkanRenderer initialized"); } void VulkanRenderer::Shutdown() { + if (m_pipeline != VK_NULL_HANDLE) { + vkDestroyPipeline(m_device, m_pipeline, nullptr); + } + + if (m_pipelineLayout != VK_NULL_HANDLE) { + vkDestroyPipelineLayout(m_device, m_pipelineLayout, nullptr); + } + for (auto fb : m_framebuffers) { vkDestroyFramebuffer(m_device, fb, nullptr); } diff --git a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h index 2ca4e5a4..20c70cc4 100644 --- a/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h +++ b/MobileGL/MG_Backend/DirectVulkan/Renderer/VulkanRenderer.h @@ -99,6 +99,9 @@ namespace MobileGL::MG_Backend::DirectVulkan { VkRenderPass m_renderPass = VK_NULL_HANDLE; Vector m_framebuffers; + VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE; + VkPipeline m_pipeline = VK_NULL_HANDLE; + void CreateInstance(); VkResult SetupDebugMessenger(); VkResult DestroyDebugMessenger(); @@ -111,6 +114,7 @@ namespace MobileGL::MG_Backend::DirectVulkan { void CreateCommandPool(); void CreateCommandBuffer(); void CreateDefaultRenderPass(); + void PrepareDemoPipeline(); static Int GetPresentQueueFamilyIndex( const PhysicalDevice& physicalDevice, VkSurfaceKHR surface, diff --git a/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp b/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp index 19cb040f..d46d99bb 100644 --- a/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp +++ b/MobileGL/MG_Impl/EGLImpl/EGLForVulkan/EGLForVulkan.cpp @@ -15,83 +15,9 @@ namespace MobileGL { namespace MG_Impl::EGLImpl { // TODO: complete EGL impl for Vulkan - - const char* demoFS = R"(#version 460 - layout(location = 0) in vec3 fragColor; - layout(location = 0) out vec4 outColor; - void main() { - outColor = vec4(fragColor, 1.0); - } -)"; - const char* demoVS = R"(#version 460 - layout(location = 0) out vec3 fragColor; - vec2 positions[3] = vec2[](vec2(0.0, -0.5), vec2(0.5, 0.5), vec2(-0.5, 0.5)); - vec3 colors[3] = vec3[](vec3(1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, 0.0, 1.0)); - void main() { - gl_Position = vec4(positions[gl_VertexID], 0.0, 1.0); - fragColor = colors[gl_VertexID]; - } -)"; - void PrepareDemoRes() { - MGLOG_D("EGLForVulkan::PrepareDemoRes called"); - - // Create shader&program object - auto programObject = MG_State::GLState::ProgramObject(0); - auto vsObject = MakeShared(ShaderStage::Vertex, 0); - vsObject->SetShaderSource(demoVS); - vsObject->Compile(); - if (!vsObject->GetCompileStatus()) { - MGLOG_E("Vertex shader compilation failed: %s", vsObject->GetInfoLog().c_str()); - return; - } - auto fsObject = MakeShared(ShaderStage::Fragment, 1); - fsObject->SetShaderSource(demoFS); - fsObject->Compile(); - if (!fsObject->GetCompileStatus()) { - MGLOG_E("Fragment shader compilation failed: %s", fsObject->GetInfoLog().c_str()); - return; - } - programObject.AttachShader(vsObject); - programObject.AttachShader(fsObject); - programObject.Link(); - if (!programObject.GetLinkStatus()) { - MGLOG_E("Program linking failed: %s", programObject.GetInfoLog().c_str()); - return; - } - - Vector vsSpv; - Vector fsSpv; - - auto& shaderSpirvs = programObject.GetGeneratedSpirv(); - auto& attachedShaders = programObject.GetAttachedShaders(); - for (int index = 0; index < attachedShaders.size(); ++index) { - auto& shader = attachedShaders[index]; - auto& spirvCode = shaderSpirvs[index]; - if (shader->GetShaderStage() == ShaderStage::Vertex) { - vsSpv = spirvCode; - } else if (shader->GetShaderStage() == ShaderStage::Fragment) { - fsSpv = spirvCode; - } - } - - // Create pipeline - // VkPipeline trianglePipeline = MG_Backend::DirectVulkan::pVulkanRenderer->CreateGraphicsPipelineFromSpv( - // "TrianglePipeline", vsSpv, fsSpv); - // - // // Register render callback - // MG_Backend::DirectVulkan::pVulkanRenderer->RegisterRenderCallback( - // "DrawTriangle", [trianglePipeline](VkCommandBuffer cmd, uint32_t imageIndex, VkExtent2D extent) { - // vkCmdBindPipeline(cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, trianglePipeline); - // - // vkCmdDraw(cmd, 3, 1, 0, 0); - // }); - } - void CreateWindowSurfaceForVulkan(NativeWindowType window) { MG_Backend::DirectVulkan::pVulkanRenderer = MakeUnique(window); MG_Backend::DirectVulkan::pVulkanRenderer->Initialize(); - - PrepareDemoRes(); // for demo use } EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window,