diff --git a/Core/Core/RenderEngine.cpp b/Core/Core/RenderEngine.cpp index ec943fc..e86e6de 100644 --- a/Core/Core/RenderEngine.cpp +++ b/Core/Core/RenderEngine.cpp @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include "CoreInstance.h" #include "Log/Log.h" @@ -171,6 +171,18 @@ VkExtent2D RenderEngine::choose_extent(const VkSurfaceCapabilitiesKHR& capabilit } } +VkShaderModule RenderEngine::create_shader_module(const std::string code) +{ + VkShaderModuleCreateInfo shader_module_info{}; + shader_module_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + shader_module_info.codeSize = code.size(); + shader_module_info.pCode = reinterpret_cast(code.c_str()); + + VkShaderModule shader_module; + VK_CHECK(vkCreateShaderModule(device_, &shader_module_info, nullptr, &shader_module)); + return shader_module; +} + void RenderEngine::create_instance() { std::vector extensions = get_required_extensions(); @@ -351,6 +363,117 @@ void RenderEngine::create_image_views() } } +void RenderEngine::create_graphycs_pipleline() +{ + std::ifstream vertex_shader_file("Shaders/vertex.spv", std::ios::binary); + if (!vertex_shader_file.is_open()) + throw std::runtime_error("Vertex shader not found"); + std::ifstream fragment_shader_file("Shaders/fragment.spv", std::ios::binary); + if (!fragment_shader_file.is_open()) { + vertex_shader_file.close(); + throw std::runtime_error("Fragment shader not found"); + } + + std::string vertex_shader_code((std::istreambuf_iterator(vertex_shader_file)), std::istreambuf_iterator()); + std::string fragment_shader_code((std::istreambuf_iterator(fragment_shader_file)), std::istreambuf_iterator()); + vertex_shader_file.close(); + fragment_shader_file.close(); + + VkShaderModule vertex_shader = create_shader_module(vertex_shader_code); + VkShaderModule fragment_shader = create_shader_module(fragment_shader_code); + + VkPipelineShaderStageCreateInfo vertex_shader_stage_info{}; + vertex_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertex_shader_stage_info.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertex_shader_stage_info.module = vertex_shader; + vertex_shader_stage_info.pName = "main"; + + VkPipelineShaderStageCreateInfo fragment_shader_stage_info{}; + vertex_shader_stage_info.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertex_shader_stage_info.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + vertex_shader_stage_info.module = fragment_shader; + vertex_shader_stage_info.pName = "main"; + + VkPipelineShaderStageCreateInfo shader_stages[] = {vertex_shader_stage_info, fragment_shader_stage_info}; + const std::vector dynamic_states = { + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR + }; + + VkPipelineDynamicStateCreateInfo dynamic_state_info{}; + dynamic_state_info.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + dynamic_state_info.dynamicStateCount = static_cast(dynamic_states.size()); + dynamic_state_info.pDynamicStates = dynamic_states.data(); + + VkPipelineVertexInputStateCreateInfo vertex_input_info{}; + vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_input_info.vertexAttributeDescriptionCount = 0; + vertex_input_info.pVertexAttributeDescriptions = nullptr; + vertex_input_info.vertexBindingDescriptionCount = 0; + vertex_input_info.pVertexBindingDescriptions = nullptr; + + VkPipelineInputAssemblyStateCreateInfo input_assembly_info{}; + input_assembly_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly_info.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + input_assembly_info.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = static_cast(swapchain_extent_.width); + viewport.height = static_cast(swapchain_extent_.height); + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = swapchain_extent_; + + VkPipelineViewportStateCreateInfo viewport_info{}; + viewport_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_info.viewportCount = 1; + viewport_info.pViewports = &viewport; + viewport_info.scissorCount = 1; + viewport_info.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterization_info{}; + rasterization_info.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterization_info.depthClampEnable = VK_FALSE; + rasterization_info.rasterizerDiscardEnable = VK_FALSE; + rasterization_info.polygonMode = VK_POLYGON_MODE_FILL; + rasterization_info.lineWidth = 1.0f; + rasterization_info.cullMode = VK_CULL_MODE_BACK_BIT; + rasterization_info.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterization_info.depthBiasEnable = VK_FALSE; + + VkPipelineColorBlendAttachmentState color_blend_attachment_state{}; + color_blend_attachment_state.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + color_blend_attachment_state.blendEnable = VK_TRUE; + color_blend_attachment_state.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA; + color_blend_attachment_state.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + color_blend_attachment_state.colorBlendOp = VK_BLEND_OP_ADD; + color_blend_attachment_state.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; + color_blend_attachment_state.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; + color_blend_attachment_state.alphaBlendOp = VK_BLEND_OP_ADD; + + VkPipelineColorBlendStateCreateInfo color_blend_info{}; + color_blend_info.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blend_info.logicOpEnable = VK_FALSE; + color_blend_info.attachmentCount = 1; + color_blend_info.blendConstants[0] = 0.0f; + color_blend_info.blendConstants[1] = 0.0f; + color_blend_info.blendConstants[2] = 0.0f; + color_blend_info.blendConstants[3] = 0.0f; + + VkPipelineLayoutCreateInfo pipeline_layout_info{}; + pipeline_layout_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + + VK_CHECK(vkCreatePipelineLayout(device_, &pipeline_layout_info, nullptr, &pipeline_layout_)); + + vkDestroyShaderModule(device_, vertex_shader, nullptr); + vkDestroyShaderModule(device_, fragment_shader, nullptr); +} + void RenderEngine::create_surface() { VK_CHECK(glfwCreateWindowSurface(instance_, window_, nullptr, &surface_)); @@ -369,10 +492,14 @@ window_(window) create_logical_device(); create_swapchain(desired_present_mode); create_image_views(); + create_graphycs_pipleline(); } RenderEngine::~RenderEngine() { + if (pipeline_layout_ != VK_NULL_HANDLE) + vkDestroyPipelineLayout(device_, pipeline_layout_, nullptr); + for (auto image_view : swapchain_image_views_) vkDestroyImageView(device_, image_view, nullptr); swapchain_image_views_.clear(); diff --git a/Core/Core/RenderEngine.h b/Core/Core/RenderEngine.h index 4a841d2..17cc08f 100644 --- a/Core/Core/RenderEngine.h +++ b/Core/Core/RenderEngine.h @@ -4,6 +4,7 @@ #include #define GLFW_INCLUDE_VULKAN +#include #include #include @@ -47,6 +48,7 @@ class RenderEngine VkFormat swapchain_image_format_; VkExtent2D swapchain_extent_; std::vector swapchain_image_views_; + VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE; #ifdef _DEBUG VkResult enable_layer_validation(VkDebugUtilsMessengerCreateInfoEXT* create_info); @@ -61,6 +63,7 @@ class RenderEngine static VkSurfaceFormatKHR choose_surface_format(const std::vector& surface_formats); static VkPresentModeKHR choose_present_mode(const std::vector& present_modes, VkPresentModeKHR desired_present_mode); static VkExtent2D choose_extent(const VkSurfaceCapabilitiesKHR& capabilities, GLFWwindow* window); + VkShaderModule create_shader_module(const std::string code); void create_instance(); void create_surface(); @@ -68,6 +71,7 @@ class RenderEngine void create_logical_device(); void create_swapchain(VkPresentModeKHR desired_present_mode); void create_image_views(); + void create_graphycs_pipleline(); public: // Can throw the exception RenderEngine(CoreInstance& core, GLFWwindow* window, VkPresentModeKHR desired_present_mode = VK_PRESENT_MODE_MAILBOX_KHR); diff --git a/TestGame/CMakeLists.txt b/TestGame/CMakeLists.txt index bd5b200..ae41ece 100644 --- a/TestGame/CMakeLists.txt +++ b/TestGame/CMakeLists.txt @@ -45,3 +45,30 @@ add_custom_command( ${OUTPUT_PATH}/Resources COMMENT "Copying Resources directory" ) + +add_custom_command( + TARGET ${GAME_NAME} + PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPUT_PATH}/Shaders + COMMENT "Creating Shaders directory" +) + +add_custom_command( + TARGET ${GAME_NAME} + POST_BUILD + COMMAND $ENV{VULKAN_SDK}/Bin/glslc.exe + ${CMAKE_CURRENT_SOURCE_DIR}/Shaders/vertex.vert + -o ${OUTPUT_PATH}/Shaders/vertex.spv + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Shaders/vertex.vert + COMMENT "Building vertex shader" +) + +add_custom_command( + TARGET ${GAME_NAME} + POST_BUILD + COMMAND $ENV{VULKAN_SDK}/Bin/glslc.exe + ${CMAKE_CURRENT_SOURCE_DIR}/Shaders/fragment.frag + -o ${OUTPUT_PATH}/Shaders/fragment.spv + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/Shaders/fragment.frag + COMMENT "Building fragment shader" +) diff --git a/TestGame/Shaders/fragment.frag b/TestGame/Shaders/fragment.frag new file mode 100644 index 0000000..e948fd6 --- /dev/null +++ b/TestGame/Shaders/fragment.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) in vec3 fragColor; +layout(location = 0) out vec4 outColor; + +void main() { + outColor = vec4(fragColor, 1.0); +} \ No newline at end of file diff --git a/TestGame/Shaders/vertex.vert b/TestGame/Shaders/vertex.vert new file mode 100644 index 0000000..fe613ef --- /dev/null +++ b/TestGame/Shaders/vertex.vert @@ -0,0 +1,20 @@ +#version 450 + +layout(location = 0) out vec3 fragColor; + +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) +); + +vec2 positions[3] = vec2[]( + vec2(0.0, -0.5), + vec2(0.5, 0.5), + vec2(-0.5, 0.5) +); + +void main() { + gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); + fragColor = colors[gl_VertexIndex]; +} \ No newline at end of file