|
|
@ -59,30 +59,16 @@ typedef struct MeshStruct {
|
|
|
|
uint32_t index_count;
|
|
|
|
uint32_t index_count;
|
|
|
|
AllocatedBuffer index_buffer;
|
|
|
|
AllocatedBuffer index_buffer;
|
|
|
|
|
|
|
|
|
|
|
|
void* data;
|
|
|
|
VkDescriptorSet mesh_descriptors;
|
|
|
|
} Mesh;
|
|
|
|
} Mesh;
|
|
|
|
|
|
|
|
|
|
|
|
typedef void (*MaterialBindFunc)(VkCommandBuffer, void*);
|
|
|
|
|
|
|
|
typedef void (*MeshBindFunc)(Mesh, VkCommandBuffer, void*);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct MaterialStruct {
|
|
|
|
typedef struct MaterialStruct {
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
VkPipeline pipeline;
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
|
|
|
|
|
|
|
MaterialBindFunc material_bind;
|
|
|
|
VkDescriptorSet material_descriptors;
|
|
|
|
MeshBindFunc mesh_bind;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void* data;
|
|
|
|
|
|
|
|
} Material;
|
|
|
|
} Material;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct TextureMaterialDataStruct {
|
|
|
|
|
|
|
|
// Store pool to allocate new texture descriptor sets
|
|
|
|
|
|
|
|
} TextureMaterialData;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct TextureMeshDataStruct {
|
|
|
|
|
|
|
|
// Store allocated texture descriptor set
|
|
|
|
|
|
|
|
} TextureMeshData;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
VkInstance instance;
|
|
|
|
VkInstance instance;
|
|
|
|
VkDebugUtilsMessengerEXT debug_messenger;
|
|
|
|
VkDebugUtilsMessengerEXT debug_messenger;
|
|
|
@ -180,30 +166,6 @@ void glfw_error(int error, const char* description) {
|
|
|
|
fprintf(stderr, "GLFW_ERR: 0x%02x - %s\n", error, description);
|
|
|
|
fprintf(stderr, "GLFW_ERR: 0x%02x - %s\n", error, description);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription vertex_bindings[1];
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription* vertex_binding_descriptions() {
|
|
|
|
|
|
|
|
vertex_bindings[0].binding = 0;
|
|
|
|
|
|
|
|
vertex_bindings[0].stride = sizeof(struct Vertex);
|
|
|
|
|
|
|
|
vertex_bindings[0].inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return vertex_bindings;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription vertex_attributes[2];
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription* vertex_attribute_descriptions() {
|
|
|
|
|
|
|
|
vertex_attributes[0].binding = 0;
|
|
|
|
|
|
|
|
vertex_attributes[0].location = 0;
|
|
|
|
|
|
|
|
vertex_attributes[0].format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
|
|
|
|
|
|
vertex_attributes[0].offset = offsetof(struct Vertex, pos);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vertex_attributes[1].binding = 0;
|
|
|
|
|
|
|
|
vertex_attributes[1].location = 1;
|
|
|
|
|
|
|
|
vertex_attributes[1].format = VK_FORMAT_R32G32B32_SFLOAT;
|
|
|
|
|
|
|
|
vertex_attributes[1].offset = offsetof(struct Vertex, color);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return vertex_attributes;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
GLFWwindow* init_window(int width, int height) {
|
|
|
|
GLFWwindow* init_window(int width, int height) {
|
|
|
|
glfwInit();
|
|
|
|
glfwInit();
|
|
|
|
glfwSetErrorCallback(glfw_error);
|
|
|
|
glfwSetErrorCallback(glfw_error);
|
|
|
@ -1075,7 +1037,18 @@ AllocatedBuffer create_populated_buffer(VkPhysicalDevice physical_device, VkDevi
|
|
|
|
return vertex_buffer;
|
|
|
|
return vertex_buffer;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipelineLayout layout, VkRenderPass render_pass, uint32_t shader_stage_count, VkPipelineShaderStageCreateInfo* shader_stages) {
|
|
|
|
VkPipeline create_graphics_pipeline(
|
|
|
|
|
|
|
|
VkDevice device,
|
|
|
|
|
|
|
|
VkExtent2D extent,
|
|
|
|
|
|
|
|
VkPipelineLayout layout,
|
|
|
|
|
|
|
|
VkRenderPass render_pass,
|
|
|
|
|
|
|
|
uint32_t shader_stage_count,
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo* shader_stages,
|
|
|
|
|
|
|
|
uint32_t bindings_count,
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription* bindings,
|
|
|
|
|
|
|
|
uint32_t attributes_count,
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription* attributes
|
|
|
|
|
|
|
|
) {
|
|
|
|
VkDynamicState dynamic_states[] = {
|
|
|
|
VkDynamicState dynamic_states[] = {
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_VIEWPORT,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
|
VK_DYNAMIC_STATE_SCISSOR,
|
|
|
@ -1089,10 +1062,10 @@ VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipeli
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input_info = {};
|
|
|
|
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
|
|
|
vertex_input_info.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
|
|
|
vertex_input_info.vertexBindingDescriptionCount = 1;
|
|
|
|
vertex_input_info.vertexBindingDescriptionCount = bindings_count;
|
|
|
|
vertex_input_info.pVertexBindingDescriptions = vertex_binding_descriptions();
|
|
|
|
vertex_input_info.pVertexBindingDescriptions = bindings;
|
|
|
|
vertex_input_info.vertexAttributeDescriptionCount = 2;
|
|
|
|
vertex_input_info.vertexAttributeDescriptionCount = attributes_count;
|
|
|
|
vertex_input_info.pVertexAttributeDescriptions = vertex_attribute_descriptions();
|
|
|
|
vertex_input_info.pVertexAttributeDescriptions = attributes;
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assemvly_info = {};
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assemvly_info = {};
|
|
|
|
input_assemvly_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
|
|
input_assemvly_info.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
|
|
@ -1204,16 +1177,6 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) {
|
|
|
|
return command_pool;
|
|
|
|
return command_pool;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) {
|
|
|
|
|
|
|
|
VkBuffer vertex_buffers[] = {mesh.vertex_buffer.buffer};
|
|
|
|
|
|
|
|
VkDeviceSize offsets[] = {0};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
|
|
|
|
|
|
|
|
vkCmdBindIndexBuffer(command_buffer, mesh.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkResult recreate_swap_chain(VulkanContext* context, VkExtent2D new_extent) {
|
|
|
|
VkResult recreate_swap_chain(VulkanContext* context, VkExtent2D new_extent) {
|
|
|
|
for(uint32_t i = 0; i < context->swapchain_image_count; i++) {
|
|
|
|
for(uint32_t i = 0; i < context->swapchain_image_count; i++) {
|
|
|
|
vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0);
|
|
|
|
vkDestroyFramebuffer(context->device, context->swapchain_framebuffers[i], 0);
|
|
|
@ -1273,18 +1236,21 @@ VkResult recreate_swap_chain(VulkanContext* context, VkExtent2D new_extent) {
|
|
|
|
return VK_SUCCESS;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) {
|
|
|
|
|
|
|
|
VkBuffer vertex_buffers[] = {mesh.vertex_buffer.buffer};
|
|
|
|
|
|
|
|
VkDeviceSize offsets[] = {0};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
|
|
|
|
|
|
|
|
vkCmdBindIndexBuffer(command_buffer, mesh.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) {
|
|
|
|
void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) {
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline);
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline);
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline_layout, 0, 1, &scene_ubo_descriptor, 0, 0);
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline_layout, 0, 1, &scene_ubo_descriptor, 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
if(material.material_bind != 0) {
|
|
|
|
|
|
|
|
material.material_bind(command_buffer, material.data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for(uint32_t i = 0; i < mesh_count; i++) {
|
|
|
|
for(uint32_t i = 0; i < mesh_count; i++) {
|
|
|
|
if(material.mesh_bind != 0) {
|
|
|
|
|
|
|
|
material.mesh_bind(meshes[i], command_buffer, material.data);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
record_command_buffer_mesh(meshes[i], command_buffer);
|
|
|
|
record_command_buffer_mesh(meshes[i], command_buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1437,9 +1403,10 @@ Material create_material(
|
|
|
|
VkDescriptorSetLayout* set_layouts,
|
|
|
|
VkDescriptorSetLayout* set_layouts,
|
|
|
|
uint32_t pcr_count,
|
|
|
|
uint32_t pcr_count,
|
|
|
|
VkPushConstantRange* pcrs,
|
|
|
|
VkPushConstantRange* pcrs,
|
|
|
|
MaterialBindFunc material_bind,
|
|
|
|
uint32_t bindings_count,
|
|
|
|
MeshBindFunc mesh_bind,
|
|
|
|
VkVertexInputBindingDescription* bindings,
|
|
|
|
void* data
|
|
|
|
uint32_t attributes_count,
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription* attributes
|
|
|
|
) {
|
|
|
|
) {
|
|
|
|
Material zero_material = {
|
|
|
|
Material zero_material = {
|
|
|
|
.pipeline = VK_NULL_HANDLE,
|
|
|
|
.pipeline = VK_NULL_HANDLE,
|
|
|
@ -1472,7 +1439,7 @@ Material create_material(
|
|
|
|
return zero_material;
|
|
|
|
return zero_material;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass, shader_stage_count, shader_stages);
|
|
|
|
VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass, shader_stage_count, shader_stages, bindings_count, bindings, attributes_count, attributes);
|
|
|
|
if(pipeline == VK_NULL_HANDLE) {
|
|
|
|
if(pipeline == VK_NULL_HANDLE) {
|
|
|
|
return zero_material;
|
|
|
|
return zero_material;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1480,9 +1447,6 @@ Material create_material(
|
|
|
|
Material material = {
|
|
|
|
Material material = {
|
|
|
|
.pipeline_layout = pipeline_layout,
|
|
|
|
.pipeline_layout = pipeline_layout,
|
|
|
|
.pipeline = pipeline,
|
|
|
|
.pipeline = pipeline,
|
|
|
|
.material_bind = material_bind,
|
|
|
|
|
|
|
|
.mesh_bind = mesh_bind,
|
|
|
|
|
|
|
|
.data = data,
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return material;
|
|
|
|
return material;
|
|
|
@ -1737,7 +1701,30 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
shader_stages[1].module = frag_shader;
|
|
|
|
shader_stages[1].module = frag_shader;
|
|
|
|
shader_stages[1].pName = "main";
|
|
|
|
shader_stages[1].pName = "main";
|
|
|
|
|
|
|
|
|
|
|
|
Material simple_mesh_material = create_material(context->device, context->swapchain_extent, context->render_pass, 2, shader_stages, context->scene_ubo_layout, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
VkVertexInputBindingDescription bindings[1] = {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.binding = 0,
|
|
|
|
|
|
|
|
.stride = sizeof(struct Vertex),
|
|
|
|
|
|
|
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription attributes[2] = {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.binding = 0,
|
|
|
|
|
|
|
|
.location = 0,
|
|
|
|
|
|
|
|
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
|
|
|
|
|
|
|
.offset = offsetof(struct Vertex, pos),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.binding = 0,
|
|
|
|
|
|
|
|
.location = 1,
|
|
|
|
|
|
|
|
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
|
|
|
|
|
|
|
.offset = offsetof(struct Vertex, color),
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Material simple_mesh_material = create_material(context->device, context->swapchain_extent, context->render_pass, 2, shader_stages, context->scene_ubo_layout, 0, 0, 0, 0, 1, bindings, 2, attributes);
|
|
|
|
if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
|
|
|
|
if(simple_mesh_material.pipeline == VK_NULL_HANDLE) {
|
|
|
|
fprintf(stderr, "failed to create simple mesh material\n");
|
|
|
|
fprintf(stderr, "failed to create simple mesh material\n");
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|