diff --git a/src/pc/gfx/gfx_vulkan.cpp b/src/pc/gfx/gfx_vulkan.cpp index 42d0f52..255330e 100644 --- a/src/pc/gfx/gfx_vulkan.cpp +++ b/src/pc/gfx/gfx_vulkan.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "gfx_rendering_api.h" #include "gfx_pc.h" @@ -36,6 +37,9 @@ static uint32_t current_frame = 0; static uint32_t image_index = 0; static VkCommandBuffer current_cmd = VK_NULL_HANDLE; +static VkPipeline pipeline = VK_NULL_HANDLE; +static VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; + VKAPI_ATTR VkBool32 VKAPI_CALL gfx_vulkan_debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, @@ -51,13 +55,141 @@ static bool gfx_vulkan_renderer_z_is_from_0_to_1(void) { return false; } -static void gfx_vulkan_renderer_unload_shader(struct ShaderProgram *old_prg) { +static VkShaderModule gfx_vulkan_create_shader_module(const uint32_t* code, const int length) { + VkShaderModuleCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + create_info.codeSize = length; + create_info.pCode = reinterpret_cast(code); + + VkShaderModule shader_module; + vkCreateShaderModule(device, &create_info, nullptr, &shader_module); + + return shader_module; } -static void gfx_vulkan_renderer_load_shader(struct ShaderProgram *new_prg) { +// TODO: will be removed, just used for testing +static VkShaderModule gfx_vulkan_load_shader(const char* path) { + std::ifstream file(path, std::ios::ate | std::ios::binary); + + size_t fileSize = (size_t) file.tellg(); + std::vector buffer(fileSize); + + file.seekg(0); + file.read(buffer.data(), fileSize); + + return gfx_vulkan_create_shader_module(reinterpret_cast(buffer.data()), fileSize); +} + +// TODO: currently no-op for testing triangle draw +static void gfx_vulkan_create_pipeline() { + VkPipelineShaderStageCreateInfo vertex_stage = {}; + vertex_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertex_stage.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertex_stage.module = gfx_vulkan_load_shader("vert.spv"); + vertex_stage.pName = "main"; + + VkPipelineShaderStageCreateInfo fragment_stage = {}; + fragment_stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragment_stage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragment_stage.module = gfx_vulkan_load_shader("frag.spv"); + fragment_stage.pName = "main"; + + std::array shader_stages = { vertex_stage, fragment_stage }; + + VkVertexInputBindingDescription binding = {}; + binding.stride = sizeof(float) * 3; + + VkVertexInputAttributeDescription position_attribute = {}; + position_attribute.format = VK_FORMAT_R32G32B32_SFLOAT; + position_attribute.format = VK_FORMAT_R32G32B32_SFLOAT; + + const std::array attributes = { position_attribute }; + + VkPipelineVertexInputStateCreateInfo vertex_input_state = {}; + vertex_input_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertex_input_state.vertexBindingDescriptionCount = 1; + vertex_input_state.pVertexBindingDescriptions = &binding; + vertex_input_state.vertexAttributeDescriptionCount = attributes.size(); + vertex_input_state.pVertexAttributeDescriptions = attributes.data(); + + VkPipelineInputAssemblyStateCreateInfo input_assembly = {}; + input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + + VkViewport viewport = {}; + viewport.width = 640; + viewport.height = 480; + viewport.maxDepth = 1.0f; + + VkRect2D scissor = {}; + scissor.extent.width = 640; + scissor.extent.height = 480; + + VkPipelineViewportStateCreateInfo viewport_state = {}; + viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewport_state.viewportCount = 1; + viewport_state.pViewports = &viewport; + viewport_state.scissorCount = 1; + viewport_state.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizer = {}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + + VkPipelineMultisampleStateCreateInfo multisampling = {}; + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState color_blend_attachment = {}; + color_blend_attachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + + VkPipelineColorBlendStateCreateInfo color_blending = {}; + color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + color_blending.attachmentCount = 1; + color_blending.pAttachments = &color_blend_attachment; + + VkPipelineDynamicStateCreateInfo dynamic_state = {}; + dynamic_state.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + + VkPipelineLayoutCreateInfo pipeline_layout_create_info = {}; + pipeline_layout_create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + + vkCreatePipelineLayout(device, &pipeline_layout_create_info, nullptr, &pipeline_layout); + + VkPipelineDepthStencilStateCreateInfo depth_stencil = {}; + depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; + depth_stencil.depthTestEnable = VK_TRUE; + depth_stencil.depthWriteEnable = VK_TRUE; + depth_stencil.depthCompareOp = VK_COMPARE_OP_LESS; + depth_stencil.maxDepthBounds = 1.0f; + + VkGraphicsPipelineCreateInfo pipeline_create_info = {}; + pipeline_create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipeline_create_info.stageCount = shader_stages.size(); + pipeline_create_info.pStages = shader_stages.data(); + pipeline_create_info.pVertexInputState = &vertex_input_state; + pipeline_create_info.pInputAssemblyState = &input_assembly; + pipeline_create_info.pViewportState = &viewport_state; + pipeline_create_info.pRasterizationState = &rasterizer; + pipeline_create_info.pMultisampleState = &multisampling; + pipeline_create_info.pColorBlendState = &color_blending; + pipeline_create_info.pDynamicState = &dynamic_state; + pipeline_create_info.pDepthStencilState = &depth_stencil; + pipeline_create_info.layout = pipeline_layout; + pipeline_create_info.renderPass = render_pass; + + vkCreateGraphicsPipelines(device, + VK_NULL_HANDLE, + 1, + &pipeline_create_info, + nullptr, + &pipeline); } static struct ShaderProgram *gfx_vulkan_renderer_create_and_load_new_shader(uint32_t shader_id) { + gfx_vulkan_create_pipeline(); return NULL; } @@ -75,36 +207,6 @@ static uint32_t gfx_vulkan_renderer_new_texture(void) { return 0; } -static void gfx_vulkan_renderer_select_texture(int tile, uint32_t texture_id) { -} - -static void gfx_vulkan_renderer_upload_texture(const uint8_t *rgba32_buf, int width, int height) { -} - -static void gfx_vulkan_renderer_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { -} - -static void gfx_vulkan_renderer_set_depth_test(bool depth_test) { -} - -static void gfx_vulkan_renderer_set_depth_mask(bool z_upd) { -} - -static void gfx_vulkan_renderer_set_zmode_decal(bool zmode_decal) { -} - -static void gfx_vulkan_renderer_set_viewport(int x, int y, int width, int height) { -} - -static void gfx_vulkan_renderer_set_scissor(int x, int y, int width, int height) { -} - -static void gfx_vulkan_renderer_set_use_alpha(bool use_alpha) { -} - -static void gfx_vulkan_renderer_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) { -} - static uint32_t gfx_vulkan_find_memory_type(uint32_t type_filter, VkMemoryPropertyFlags properties) { VkPhysicalDeviceMemoryProperties memory_properties; vkGetPhysicalDeviceMemoryProperties(physical_device, &memory_properties); @@ -590,6 +692,50 @@ static void gfx_vulkan_renderer_start_frame(void) { vkCmdBeginRenderPass(current_cmd, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); } +/* draw commands */ + +static void gfx_vulkan_renderer_select_texture(int tile, uint32_t texture_id) { +} + +static void gfx_vulkan_renderer_upload_texture(const uint8_t *rgba32_buf, int width, int height) { +} + +static void gfx_vulkan_renderer_set_sampler_parameters(int tile, bool linear_filter, uint32_t cms, uint32_t cmt) { +} + +static void gfx_vulkan_renderer_set_depth_test(bool depth_test) { +} + +static void gfx_vulkan_renderer_set_depth_mask(bool z_upd) { +} + +static void gfx_vulkan_renderer_set_zmode_decal(bool zmode_decal) { +} + +static void gfx_vulkan_renderer_set_viewport(int x, int y, int width, int height) { +} + +static void gfx_vulkan_renderer_set_scissor(int x, int y, int width, int height) { +} + +static void gfx_vulkan_renderer_set_use_alpha(bool use_alpha) { +} + +static void gfx_vulkan_renderer_unload_shader(struct ShaderProgram *old_prg) { +} + +static void gfx_vulkan_renderer_load_shader(struct ShaderProgram *new_prg) { +} + +static void gfx_vulkan_renderer_draw_triangles(float buf_vbo[], size_t buf_vbo_len, size_t buf_vbo_num_tris) { + // FIXME: uh no + vkCmdBindPipeline(current_cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline); + + vkCmdDraw(current_cmd, buf_vbo_num_tris, 1, 0, 0); +} + +/* end draw commands */ + static void gfx_vulkan_renderer_end_frame(void) { vkCmdEndRenderPass(current_cmd); vkEndCommandBuffer(current_cmd);