|
|
@ -111,11 +111,7 @@ typedef struct GraphicsPipelineInfoStruct {
|
|
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutCreateInfo descriptor_info;
|
|
|
|
VkDescriptorSetLayoutCreateInfo descriptor_info;
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t input_bindings_count;
|
|
|
|
VkPipelineVertexInputStateCreateInfo input_info;
|
|
|
|
VkVertexInputBindingDescription* input_bindings;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t input_attributes_count;
|
|
|
|
|
|
|
|
VkVertexInputAttributeDescription* input_attributes;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t shader_stages_count;
|
|
|
|
uint32_t shader_stages_count;
|
|
|
|
VkPipelineShaderStageCreateInfo* shader_stages;
|
|
|
|
VkPipelineShaderStageCreateInfo* shader_stages;
|
|
|
@ -131,6 +127,7 @@ typedef struct GraphicsPipelineStruct {
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineLayout layout;
|
|
|
|
VkPipelineLayout layout;
|
|
|
|
VkPipeline pipeline;
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
|
|
|
VkPipeline offscreen_pipeline;
|
|
|
|
} GraphicsPipeline;
|
|
|
|
} GraphicsPipeline;
|
|
|
|
|
|
|
|
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
|
typedef struct VulkanContextStruct {
|
|
|
@ -184,9 +181,11 @@ typedef struct VulkanContextStruct {
|
|
|
|
uint32_t max_frames_in_flight;
|
|
|
|
uint32_t max_frames_in_flight;
|
|
|
|
|
|
|
|
|
|
|
|
// Per frame objects
|
|
|
|
// Per frame objects
|
|
|
|
|
|
|
|
VkCommandBuffer* offscreen_command_buffers;
|
|
|
|
VkCommandBuffer* swapchain_command_buffers;
|
|
|
|
VkCommandBuffer* swapchain_command_buffers;
|
|
|
|
VkSemaphore* image_available_semaphores;
|
|
|
|
VkSemaphore* image_available_semaphores;
|
|
|
|
VkSemaphore* render_finished_semaphores;
|
|
|
|
VkSemaphore* render_finished_semaphores;
|
|
|
|
|
|
|
|
VkSemaphore* offscreen_complete_semaphores;
|
|
|
|
VkFence* in_flight_fences;
|
|
|
|
VkFence* in_flight_fences;
|
|
|
|
|
|
|
|
|
|
|
|
VkRenderPass render_pass;
|
|
|
|
VkRenderPass render_pass;
|
|
|
@ -220,10 +219,6 @@ struct Vertex {
|
|
|
|
vec3 color;
|
|
|
|
vec3 color;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct ModelUBO {
|
|
|
|
|
|
|
|
mat4 model;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct SceneUBO {
|
|
|
|
struct SceneUBO {
|
|
|
|
mat4 test;
|
|
|
|
mat4 test;
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -1397,13 +1392,12 @@ void command_draw_object(Object object, VkCommandBuffer command_buffer) {
|
|
|
|
vkCmdDrawIndexed(command_buffer, mesh->index_count, 1, 0, 0, 0);
|
|
|
|
vkCmdDrawIndexed(command_buffer, mesh->index_count, 1, 0, 0, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void command_draw_pipeline(GraphicsPipeline pipeline, uint32_t object_count, Object* objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, struct ScenePC* scene_constants, VkDeviceAddress object_buffer_addr, VkCommandBuffer command_buffer) {
|
|
|
|
void command_draw_pipeline(GraphicsPipeline pipeline, uint32_t object_count, Object* objects, uint32_t frame_num, VkCommandBuffer command_buffer, int offscreen) {
|
|
|
|
|
|
|
|
if(offscreen) {
|
|
|
|
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.offscreen_pipeline);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
|
|
|
|
vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.pipeline);
|
|
|
|
vkCmdPushConstants(command_buffer, pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(struct ScenePC), scene_constants);
|
|
|
|
}
|
|
|
|
vkCmdPushConstants(command_buffer, pipeline.layout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(struct ScenePC), sizeof(VkDeviceAddress), &object_buffer_addr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Bind the scene descriptor
|
|
|
|
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 0, 1, &scene_descriptors[frame_num], 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if(pipeline.descriptors != NULL) {
|
|
|
|
if(pipeline.descriptors != NULL) {
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 1, 1, &pipeline.descriptors[frame_num], 0, 0);
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.layout, 1, 1, &pipeline.descriptors[frame_num], 0, 0);
|
|
|
@ -1414,7 +1408,39 @@ void command_draw_pipeline(GraphicsPipeline pipeline, uint32_t object_count, Obj
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult command_draw_scene(uint32_t pipelines_count, GraphicsPipeline* pipelines, uint32_t* object_counts, Object** objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, struct ScenePC* scene_constants, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent, VkDeviceAddress object_buffer_addr) {
|
|
|
|
// Setup a scene for vkCmdDrawIndexedIndirect
|
|
|
|
|
|
|
|
// Before the call is made the following needs to be ready:
|
|
|
|
|
|
|
|
// 1) Vertex data for entire scene in one vertex buffer
|
|
|
|
|
|
|
|
// 2) Index data for entire scene in one index buffer
|
|
|
|
|
|
|
|
// 3) Descriptor data in single descriptor set
|
|
|
|
|
|
|
|
// a) e.x. all textures for the draw call need to be in the bound pipeline descriptor set
|
|
|
|
|
|
|
|
// 4) Object Data populated per-instance into buffer which will be pushed by VkDeviceAddress
|
|
|
|
|
|
|
|
// 5) Buffer of draw command ordered by instance id(first is 0, increase by 1 every 'stride')
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Once that is setup, the call to vkCmdDrawIndexed will happen and then:
|
|
|
|
|
|
|
|
// 1) For each draw command read from the command buffer
|
|
|
|
|
|
|
|
// a) Consume the indices/vertices to run the vertex shaders
|
|
|
|
|
|
|
|
// i) Vertex shaders access the per-instance object data indexed by gl_instanceID
|
|
|
|
|
|
|
|
// ii) This object data can have indices for other descriptors
|
|
|
|
|
|
|
|
// x) e.x. a shader can read object data with int Z that tell it to use a sampler at binding Z
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// If I want to start by not worrying about dynamic object load/unload then I can create the above buffers
|
|
|
|
|
|
|
|
// when loading the scene, and free them all at once
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// If I want to start worrying about loading/unloading then I need to find a way to efficiently reconstruct
|
|
|
|
|
|
|
|
// these buffers on changes
|
|
|
|
|
|
|
|
// Ideas:
|
|
|
|
|
|
|
|
// - Mark objects as 'deleted' to cheaply cull during a compute cull/vertex shader
|
|
|
|
|
|
|
|
// - Would require only a 1-bit change per deletion
|
|
|
|
|
|
|
|
// - Would require defragmentation periodically(or whenever trying to add without space)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkResult create_scene(){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return VK_SUCCESS;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkResult command_draw_scene(uint32_t pipelines_count, GraphicsPipeline* pipelines, uint32_t* object_counts, Object** objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, struct ScenePC* scene_constants, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent, VkDeviceAddress object_buffer_addr, int offscreen) {
|
|
|
|
VkCommandBufferBeginInfo begin_info = {
|
|
|
|
VkCommandBufferBeginInfo begin_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
|
|
|
.flags = 0,
|
|
|
|
.flags = 0,
|
|
|
@ -1473,8 +1499,14 @@ VkResult command_draw_scene(uint32_t pipelines_count, GraphicsPipeline* pipeline
|
|
|
|
};
|
|
|
|
};
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdPushConstants(command_buffer, pipelines[0].layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(struct ScenePC), scene_constants);
|
|
|
|
|
|
|
|
vkCmdPushConstants(command_buffer, pipelines[0].layout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(struct ScenePC), sizeof(VkDeviceAddress), &object_buffer_addr);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Bind the scene descriptor
|
|
|
|
|
|
|
|
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[0].layout, 0, 1, &scene_descriptors[frame_num], 0, 0);
|
|
|
|
|
|
|
|
|
|
|
|
for(uint i = 0; i < pipelines_count; i++) {
|
|
|
|
for(uint i = 0; i < pipelines_count; i++) {
|
|
|
|
command_draw_pipeline(pipelines[i], object_counts[i], objects[i], frame_num, scene_descriptors, scene_constants, object_buffer_addr, command_buffer);
|
|
|
|
command_draw_pipeline(pipelines[i], object_counts[i], objects[i], frame_num, command_buffer, offscreen);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
vkCmdEndRenderPass(command_buffer);
|
|
|
|
vkCmdEndRenderPass(command_buffer);
|
|
|
@ -1575,7 +1607,8 @@ Object create_renderable(Mesh* mesh, GraphicsPipeline* pipeline) {
|
|
|
|
VkResult create_graphics_pipeline(
|
|
|
|
VkResult create_graphics_pipeline(
|
|
|
|
VkDevice device,
|
|
|
|
VkDevice device,
|
|
|
|
VkExtent2D extent,
|
|
|
|
VkExtent2D extent,
|
|
|
|
VkRenderPass render_pass,
|
|
|
|
VkRenderPass draw_render_pass,
|
|
|
|
|
|
|
|
VkRenderPass offscreen_render_pass,
|
|
|
|
GraphicsPipelineInfo pipeline_info,
|
|
|
|
GraphicsPipelineInfo pipeline_info,
|
|
|
|
uint32_t max_frames_in_flight,
|
|
|
|
uint32_t max_frames_in_flight,
|
|
|
|
GraphicsPipeline* out
|
|
|
|
GraphicsPipeline* out
|
|
|
@ -1685,14 +1718,6 @@ VkResult create_graphics_pipeline(
|
|
|
|
.pDynamicStates = dynamic_states,
|
|
|
|
.pDynamicStates = dynamic_states,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
|
|
|
|
.vertexBindingDescriptionCount = pipeline_info.input_bindings_count,
|
|
|
|
|
|
|
|
.pVertexBindingDescriptions = pipeline_info.input_bindings,
|
|
|
|
|
|
|
|
.vertexAttributeDescriptionCount = pipeline_info.input_attributes_count,
|
|
|
|
|
|
|
|
.pVertexAttributeDescriptions = pipeline_info.input_attributes,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
|
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
|
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
|
@ -1784,11 +1809,11 @@ VkResult create_graphics_pipeline(
|
|
|
|
.blendConstants[3] = 0.0f,
|
|
|
|
.blendConstants[3] = 0.0f,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
VkGraphicsPipelineCreateInfo info = {
|
|
|
|
VkGraphicsPipelineCreateInfo draw_pipeline_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
.stageCount = pipeline_info.shader_stages_count,
|
|
|
|
.stageCount = pipeline_info.shader_stages_count,
|
|
|
|
.pStages = pipeline_info.shader_stages,
|
|
|
|
.pStages = pipeline_info.shader_stages,
|
|
|
|
.pVertexInputState = &vertex_input_info,
|
|
|
|
.pVertexInputState = &pipeline_info.input_info,
|
|
|
|
.pInputAssemblyState = &input_assembly_info,
|
|
|
|
.pInputAssemblyState = &input_assembly_info,
|
|
|
|
.pViewportState = &viewport_state,
|
|
|
|
.pViewportState = &viewport_state,
|
|
|
|
.pRasterizationState = &raster_info,
|
|
|
|
.pRasterizationState = &raster_info,
|
|
|
@ -1797,13 +1822,56 @@ VkResult create_graphics_pipeline(
|
|
|
|
.pDepthStencilState = &depth_info,
|
|
|
|
.pDepthStencilState = &depth_info,
|
|
|
|
.pMultisampleState = &multisample_info,
|
|
|
|
.pMultisampleState = &multisample_info,
|
|
|
|
.layout = out->layout,
|
|
|
|
.layout = out->layout,
|
|
|
|
.renderPass = render_pass,
|
|
|
|
.renderPass = draw_render_pass,
|
|
|
|
|
|
|
|
.subpass = 0,
|
|
|
|
|
|
|
|
.basePipelineHandle = VK_NULL_HANDLE,
|
|
|
|
|
|
|
|
.basePipelineIndex = -1,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineColorBlendAttachmentState offscreen_attachment_states[] = {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
|
|
|
|
|
|
|
.blendEnable = VK_FALSE,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo offscreen_blend_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
|
|
|
|
|
|
.logicOpEnable = VK_FALSE,
|
|
|
|
|
|
|
|
.logicOp = VK_LOGIC_OP_COPY,
|
|
|
|
|
|
|
|
.attachmentCount = sizeof(offscreen_attachment_states)/sizeof(VkPipelineColorBlendAttachmentState),
|
|
|
|
|
|
|
|
.pAttachments = offscreen_attachment_states,
|
|
|
|
|
|
|
|
.blendConstants[0] = 0.0f,
|
|
|
|
|
|
|
|
.blendConstants[1] = 0.0f,
|
|
|
|
|
|
|
|
.blendConstants[2] = 0.0f,
|
|
|
|
|
|
|
|
.blendConstants[3] = 0.0f,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkGraphicsPipelineCreateInfo offscreen_pipeline_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
|
|
|
|
.stageCount = pipeline_info.shader_stages_count,
|
|
|
|
|
|
|
|
.pStages = pipeline_info.shader_stages, // TODO: offscreen stages
|
|
|
|
|
|
|
|
.pVertexInputState = &pipeline_info.input_info,
|
|
|
|
|
|
|
|
.pInputAssemblyState = &input_assembly_info,
|
|
|
|
|
|
|
|
.pViewportState = &viewport_state,
|
|
|
|
|
|
|
|
.pRasterizationState = &raster_info,
|
|
|
|
|
|
|
|
.pColorBlendState = &offscreen_blend_info,
|
|
|
|
|
|
|
|
.pDynamicState = &dynamic_info,
|
|
|
|
|
|
|
|
.pDepthStencilState = &depth_info,
|
|
|
|
|
|
|
|
.pMultisampleState = &multisample_info,
|
|
|
|
|
|
|
|
.layout = out->layout,
|
|
|
|
|
|
|
|
.renderPass = offscreen_render_pass,
|
|
|
|
.subpass = 0,
|
|
|
|
.subpass = 0,
|
|
|
|
.basePipelineHandle = VK_NULL_HANDLE,
|
|
|
|
.basePipelineHandle = VK_NULL_HANDLE,
|
|
|
|
.basePipelineIndex = -1,
|
|
|
|
.basePipelineIndex = -1,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &info, 0, &out->pipeline);
|
|
|
|
result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &draw_pipeline_info, 0, &out->pipeline);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &offscreen_pipeline_info, 0, &out->offscreen_pipeline);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1811,7 +1879,7 @@ VkResult create_graphics_pipeline(
|
|
|
|
return VK_SUCCESS;
|
|
|
|
return VK_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult create_simple_mesh_pipeline(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_layout, uint32_t max_frames_in_flight, GraphicsPipeline* out) {
|
|
|
|
VkResult create_simple_mesh_pipeline(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkRenderPass offscreen_render_pass, VkDescriptorSetLayout scene_layout, uint32_t max_frames_in_flight, GraphicsPipeline* out) {
|
|
|
|
if(out == NULL) {
|
|
|
|
if(out == NULL) {
|
|
|
|
return VK_ERROR_VALIDATION_FAILED_EXT;
|
|
|
|
return VK_ERROR_VALIDATION_FAILED_EXT;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1873,21 +1941,26 @@ VkResult create_simple_mesh_pipeline(VkDevice device, VkExtent2D extent, VkRende
|
|
|
|
.pNext = NULL,
|
|
|
|
.pNext = NULL,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo input_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
|
|
|
|
.pVertexBindingDescriptions = bindings,
|
|
|
|
|
|
|
|
.vertexBindingDescriptionCount = sizeof(bindings)/sizeof(VkVertexInputBindingDescription),
|
|
|
|
|
|
|
|
.pVertexAttributeDescriptions = attributes,
|
|
|
|
|
|
|
|
.vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
GraphicsPipelineInfo pipeline_info = {
|
|
|
|
GraphicsPipelineInfo pipeline_info = {
|
|
|
|
.descriptor_info = set_info,
|
|
|
|
.descriptor_info = set_info,
|
|
|
|
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
|
|
|
|
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
|
|
|
|
.shader_stages = shader_stages,
|
|
|
|
.shader_stages = shader_stages,
|
|
|
|
.scene_layout = scene_layout,
|
|
|
|
.scene_layout = scene_layout,
|
|
|
|
.input_bindings = bindings,
|
|
|
|
.input_info = input_info,
|
|
|
|
.input_bindings_count = sizeof(bindings)/sizeof(VkVertexInputBindingDescription),
|
|
|
|
|
|
|
|
.input_attributes = attributes,
|
|
|
|
|
|
|
|
.input_attributes_count = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription),
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
return create_graphics_pipeline(device, extent, render_pass, pipeline_info, max_frames_in_flight, out);
|
|
|
|
return create_graphics_pipeline(device, extent, render_pass, offscreen_render_pass, pipeline_info, max_frames_in_flight, out);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryProperties memories, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_layout, uint32_t max_frames_in_flight, VkCommandPool transfer_pool, VkQueue transfer_queue, VkQueue graphics_queue, VkCommandPool graphics_pool, uint32_t transfer_family, uint32_t graphics_family, GraphicsPipeline* out) {
|
|
|
|
VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryProperties memories, VkExtent2D extent, VkRenderPass render_pass, VkRenderPass offscreen_render_pass, VkDescriptorSetLayout scene_layout, uint32_t max_frames_in_flight, VkCommandPool transfer_pool, VkQueue transfer_queue, VkQueue graphics_queue, VkCommandPool graphics_pool, uint32_t transfer_family, uint32_t graphics_family, GraphicsPipeline* out) {
|
|
|
|
if(out == NULL) {
|
|
|
|
if(out == NULL) {
|
|
|
|
return VK_ERROR_VALIDATION_FAILED_EXT;
|
|
|
|
return VK_ERROR_VALIDATION_FAILED_EXT;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1968,15 +2041,20 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
|
|
|
|
.pNext = &set_flags_info,
|
|
|
|
.pNext = &set_flags_info,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo input_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
|
|
|
|
.pVertexBindingDescriptions = bindings,
|
|
|
|
|
|
|
|
.vertexBindingDescriptionCount = sizeof(bindings)/sizeof(VkVertexInputBindingDescription),
|
|
|
|
|
|
|
|
.pVertexAttributeDescriptions = attributes,
|
|
|
|
|
|
|
|
.vertexAttributeDescriptionCount = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription),
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
GraphicsPipelineInfo pipeline_info = {
|
|
|
|
GraphicsPipelineInfo pipeline_info = {
|
|
|
|
.descriptor_info = set_info,
|
|
|
|
.descriptor_info = set_info,
|
|
|
|
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
|
|
|
|
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
|
|
|
|
.shader_stages = shader_stages,
|
|
|
|
.shader_stages = shader_stages,
|
|
|
|
.scene_layout = scene_layout,
|
|
|
|
.scene_layout = scene_layout,
|
|
|
|
.input_bindings = bindings,
|
|
|
|
.input_info = input_info,
|
|
|
|
.input_bindings_count = sizeof(bindings)/sizeof(VkVertexInputBindingDescription),
|
|
|
|
|
|
|
|
.input_attributes = attributes,
|
|
|
|
|
|
|
|
.input_attributes_count = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription),
|
|
|
|
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
GPUPage* memory = NULL;
|
|
|
|
GPUPage* memory = NULL;
|
|
|
@ -1985,7 +2063,7 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = create_graphics_pipeline(device, extent, render_pass, pipeline_info, max_frames_in_flight, out);
|
|
|
|
result = create_graphics_pipeline(device, extent, render_pass, offscreen_render_pass, pipeline_info, max_frames_in_flight, out);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -2297,6 +2375,12 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->swapchain_command_buffers = swapchain_command_buffers;
|
|
|
|
context->swapchain_command_buffers = swapchain_command_buffers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context->offscreen_command_buffers = create_command_buffers(context->device, context->graphics_command_pool, context->max_frames_in_flight);
|
|
|
|
|
|
|
|
if(swapchain_command_buffers == VK_NULL_HANDLE) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to create vulkan swapchain command buffer\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkSemaphore* ia_semaphores = create_semaphores(context->device, 0, max_frames_in_flight);
|
|
|
|
VkSemaphore* ia_semaphores = create_semaphores(context->device, 0, max_frames_in_flight);
|
|
|
|
if(ia_semaphores == 0) {
|
|
|
|
if(ia_semaphores == 0) {
|
|
|
|
fprintf(stderr, "failed to create vulkan image available semaphores\n");
|
|
|
|
fprintf(stderr, "failed to create vulkan image available semaphores\n");
|
|
|
@ -2313,6 +2397,11 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
context->render_finished_semaphores = rf_semaphores;
|
|
|
|
context->render_finished_semaphores = rf_semaphores;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
context->offscreen_complete_semaphores = create_semaphores(context->device, 0, 1);
|
|
|
|
|
|
|
|
if(context->offscreen_complete_semaphores == NULL) {
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkFence* if_fences = create_fences(context->device, VK_FENCE_CREATE_SIGNALED_BIT, max_frames_in_flight);
|
|
|
|
VkFence* if_fences = create_fences(context->device, VK_FENCE_CREATE_SIGNALED_BIT, max_frames_in_flight);
|
|
|
|
if(if_fences == 0) {
|
|
|
|
if(if_fences == 0) {
|
|
|
|
fprintf(stderr, "failed to create vulkan in flight fence\n");
|
|
|
|
fprintf(stderr, "failed to create vulkan in flight fence\n");
|
|
|
@ -2328,7 +2417,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
|
|
|
|
|
|
|
|
VkImageCreateInfo g_pos_info = {
|
|
|
|
VkImageCreateInfo g_pos_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
|
|
|
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
|
|
|
.imageType = VK_IMAGE_TYPE_2D,
|
|
|
|
.imageType = VK_IMAGE_TYPE_2D,
|
|
|
|
.extent = {
|
|
|
|
.extent = {
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
@ -2368,6 +2457,168 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
|
|
|
|
return 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkExtent3D offscreen_extent = {
|
|
|
|
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
|
|
|
|
|
.height = context->swapchain_extent.height,
|
|
|
|
|
|
|
|
.depth = 1,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkImageCreateInfo offscreen_depth_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
|
|
|
|
|
|
|
.imageType = VK_IMAGE_TYPE_2D,
|
|
|
|
|
|
|
|
.pNext = NULL,
|
|
|
|
|
|
|
|
.extent = offscreen_extent,
|
|
|
|
|
|
|
|
.mipLevels = 1,
|
|
|
|
|
|
|
|
.arrayLayers = 1,
|
|
|
|
|
|
|
|
.format = context->depth_format,
|
|
|
|
|
|
|
|
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
|
|
|
|
|
|
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
|
|
|
.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
|
|
|
|
|
|
|
|
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
|
|
|
|
|
|
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
|
|
|
|
.flags = 0,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = gpu_image_malloc(context->device, context->g_buffer_page, &offscreen_depth_info, &context->g_image_depth);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to allocate g_image_depth\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkImageViewCreateInfo g_depth_view_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
|
|
|
|
|
|
|
|
.image = context->g_image_depth.handle,
|
|
|
|
|
|
|
|
.viewType = VK_IMAGE_VIEW_TYPE_2D,
|
|
|
|
|
|
|
|
.format = context->depth_format,
|
|
|
|
|
|
|
|
.components = {
|
|
|
|
|
|
|
|
.r = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
.g = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
.b = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
.a = VK_COMPONENT_SWIZZLE_IDENTITY,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
.subresourceRange = {
|
|
|
|
|
|
|
|
.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT,
|
|
|
|
|
|
|
|
.baseMipLevel = 0,
|
|
|
|
|
|
|
|
.levelCount = 1,
|
|
|
|
|
|
|
|
.baseArrayLayer = 0,
|
|
|
|
|
|
|
|
.layerCount = 1,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkCreateImageView(context->device, &g_depth_view_info, 0, &context->g_image_view_depth);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "Failed to allocate g_image_view_depth\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = command_transition_image_layout(context->device, context->extra_graphics_pool, context->queues.graphics, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, context->g_image_depth.handle, 0, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, VK_IMAGE_ASPECT_DEPTH_BIT);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "Failed to transition g_image_depth to VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkAttachmentDescription offscreen_attachments[] = {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.format = VK_FORMAT_R16G16B16A16_SFLOAT,
|
|
|
|
|
|
|
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
|
|
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
|
|
|
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
|
|
|
|
|
|
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
|
|
|
|
|
|
|
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
|
|
|
|
|
|
|
.finalLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.format = context->depth_format,
|
|
|
|
|
|
|
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
|
|
|
|
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
|
|
|
|
|
|
|
|
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
|
|
|
.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
|
|
|
|
|
|
|
|
.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE,
|
|
|
|
|
|
|
|
.initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
|
|
|
|
|
|
|
.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkAttachmentReference offscreen_attachment_refs[] = {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.attachment = 0,
|
|
|
|
|
|
|
|
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkAttachmentReference offscreen_depth_reference = {
|
|
|
|
|
|
|
|
.attachment = 1,
|
|
|
|
|
|
|
|
.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkSubpassDescription offscreen_pass_descs[] = {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
|
|
|
|
.colorAttachmentCount = sizeof(offscreen_attachment_refs)/sizeof(VkAttachmentReference),
|
|
|
|
|
|
|
|
.pColorAttachments = offscreen_attachment_refs,
|
|
|
|
|
|
|
|
.pDepthStencilAttachment = &offscreen_depth_reference,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkSubpassDependency offscreen_pass_dependencies[] = {
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
|
|
|
|
|
|
|
.dstSubpass = 0,
|
|
|
|
|
|
|
|
.srcStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
|
|
|
|
|
|
|
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
|
|
|
|
|
|
|
.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
|
|
|
|
|
|
|
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
|
|
|
|
|
|
|
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
.srcSubpass = 0,
|
|
|
|
|
|
|
|
.dstSubpass = VK_SUBPASS_EXTERNAL,
|
|
|
|
|
|
|
|
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT,
|
|
|
|
|
|
|
|
.dstStageMask = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
|
|
|
|
|
|
|
.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT,
|
|
|
|
|
|
|
|
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
|
|
|
|
|
|
|
|
.dependencyFlags = VK_DEPENDENCY_BY_REGION_BIT,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkRenderPassCreateInfo offscreen_pass_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
|
|
|
|
|
|
.attachmentCount = sizeof(offscreen_attachments)/sizeof(VkAttachmentDescription),
|
|
|
|
|
|
|
|
.pAttachments = offscreen_attachments,
|
|
|
|
|
|
|
|
.subpassCount = sizeof(offscreen_pass_descs)/sizeof(VkSubpassDescription),
|
|
|
|
|
|
|
|
.pSubpasses = offscreen_pass_descs,
|
|
|
|
|
|
|
|
.dependencyCount = sizeof(offscreen_pass_dependencies)/sizeof(VkSubpassDependency),
|
|
|
|
|
|
|
|
.pDependencies = offscreen_pass_dependencies,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkCreateRenderPass(context->device, &offscreen_pass_info, 0, &context->g_renderpass);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "Failed to create offscreen renderpass\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkImageView offscreen_fb_attachments[2] = {
|
|
|
|
|
|
|
|
context->g_image_view_position,
|
|
|
|
|
|
|
|
context->g_image_view_depth,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkFramebufferCreateInfo offscreen_framebuffer_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
|
|
|
|
|
|
|
|
.renderPass = context->g_renderpass,
|
|
|
|
|
|
|
|
.attachmentCount = sizeof(offscreen_fb_attachments)/sizeof(VkImageView),
|
|
|
|
|
|
|
|
.pAttachments = offscreen_fb_attachments,
|
|
|
|
|
|
|
|
.width = context->swapchain_extent.width,
|
|
|
|
|
|
|
|
.height = context->swapchain_extent.height,
|
|
|
|
|
|
|
|
.layers = 1,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkCreateFramebuffer(context->device, &offscreen_framebuffer_info, 0, &context->g_framebuffer);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
fprintf(stderr, "failed to allocate offscreen framebuffer\n");
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return context;
|
|
|
|
return context;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
@ -2740,7 +2991,7 @@ struct ScenePC get_scene_constants(vec3 world_position, versor world_rotation, f
|
|
|
|
return constants;
|
|
|
|
return constants;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t materials_count, GraphicsPipeline* pipelines, uint32_t* objects_counts, Object** objects, VkDeviceAddress object_buffer_addr) {
|
|
|
|
VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t pipelines_count, GraphicsPipeline* pipelines, uint32_t* objects_counts, Object** objects, VkDeviceAddress object_buffer_addr) {
|
|
|
|
struct ScenePC scene_constants = get_scene_constants(world_position, world_rotation, (float)context->swapchain_extent.width/(float)context->swapchain_extent.height, 0.01);
|
|
|
|
struct ScenePC scene_constants = get_scene_constants(world_position, world_rotation, (float)context->swapchain_extent.width/(float)context->swapchain_extent.height, 0.01);
|
|
|
|
|
|
|
|
|
|
|
|
VkResult result;
|
|
|
|
VkResult result;
|
|
|
@ -2765,23 +3016,49 @@ VkResult draw_frame(VulkanContext* context, SceneContext* scene, uint32_t materi
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = command_draw_scene(materials_count, pipelines, objects_counts, objects, context->current_frame, scene->descriptors, &scene_constants, context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent, object_buffer_addr);
|
|
|
|
result = command_draw_scene(pipelines_count, pipelines, objects_counts, objects, context->current_frame, scene->descriptors, &scene_constants, context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent, object_buffer_addr, 0);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkResetCommandBuffer(context->offscreen_command_buffers[context->current_frame], 0);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = command_draw_scene(pipelines_count, pipelines, objects_counts, objects, context->current_frame, scene->descriptors, &scene_constants, context->offscreen_command_buffers[context->current_frame], context->g_renderpass, context->g_framebuffer, context->swapchain_extent, object_buffer_addr, 1);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
|
|
|
VkPipelineStageFlags wait_stages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
|
|
|
|
VkSubmitInfo submit_info = {
|
|
|
|
VkSubmitInfo offscreen_submit_info = {
|
|
|
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
|
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
|
|
.waitSemaphoreCount = 1,
|
|
|
|
.waitSemaphoreCount = 1,
|
|
|
|
.pWaitSemaphores = &context->image_available_semaphores[context->current_frame],
|
|
|
|
.pWaitSemaphores = &context->image_available_semaphores[context->current_frame],
|
|
|
|
.pWaitDstStageMask = wait_stages,
|
|
|
|
.pWaitDstStageMask = wait_stages,
|
|
|
|
.commandBufferCount = 1,
|
|
|
|
.commandBufferCount = 1,
|
|
|
|
|
|
|
|
.pCommandBuffers = &context->offscreen_command_buffers[context->current_frame],
|
|
|
|
|
|
|
|
.signalSemaphoreCount = 1,
|
|
|
|
|
|
|
|
.pSignalSemaphores = &context->offscreen_complete_semaphores[0],
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkSubmitInfo submit_info = {
|
|
|
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
|
|
|
|
|
|
|
.waitSemaphoreCount = 1,
|
|
|
|
|
|
|
|
.pWaitSemaphores = &context->offscreen_complete_semaphores[0],
|
|
|
|
|
|
|
|
.pWaitDstStageMask = wait_stages,
|
|
|
|
|
|
|
|
.commandBufferCount = 1,
|
|
|
|
.pCommandBuffers = &context->swapchain_command_buffers[context->current_frame],
|
|
|
|
.pCommandBuffers = &context->swapchain_command_buffers[context->current_frame],
|
|
|
|
.signalSemaphoreCount = 1,
|
|
|
|
.signalSemaphoreCount = 1,
|
|
|
|
.pSignalSemaphores = &context->render_finished_semaphores[context->current_frame],
|
|
|
|
.pSignalSemaphores = &context->render_finished_semaphores[context->current_frame],
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
result = vkQueueSubmit(context->queues.graphics, 1, &offscreen_submit_info, 0);
|
|
|
|
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = vkQueueSubmit(context->queues.graphics, 1, &submit_info, context->in_flight_fences[context->current_frame]);
|
|
|
|
result = vkQueueSubmit(context->queues.graphics, 1, &submit_info, context->in_flight_fences[context->current_frame]);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
return result;
|
|
|
|
return result;
|
|
|
@ -2918,7 +3195,7 @@ void main_loop(PlyMesh ply_mesh, GLFWwindow* window, VulkanContext* context) {
|
|
|
|
|
|
|
|
|
|
|
|
GraphicsPipeline simple_mesh_pipeline = {0};
|
|
|
|
GraphicsPipeline simple_mesh_pipeline = {0};
|
|
|
|
GraphicsPipeline texture_mesh_pipeline = {0};
|
|
|
|
GraphicsPipeline texture_mesh_pipeline = {0};
|
|
|
|
VkResult result = create_simple_mesh_pipeline(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight, &simple_mesh_pipeline);
|
|
|
|
VkResult result = create_simple_mesh_pipeline(context->device, context->swapchain_extent, context->render_pass, context->g_renderpass, scene.descriptor_layout, context->max_frames_in_flight, &simple_mesh_pipeline);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
fprintf(stderr, "failed to create simple mesh material: %s\n", string_VkResult(result));
|
|
|
|
fprintf(stderr, "failed to create simple mesh material: %s\n", string_VkResult(result));
|
|
|
|
return;
|
|
|
|
return;
|
|
|
@ -2930,7 +3207,7 @@ void main_loop(PlyMesh ply_mesh, GLFWwindow* window, VulkanContext* context) {
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
result = create_texture_mesh_pipeline(context->device, context->memories, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight, context->transfer_command_pool, context->queues.transfer, context->queues.graphics, context->extra_graphics_pool, context->queue_indices.transfer_family, context->queue_indices.graphics_index, &texture_mesh_pipeline);
|
|
|
|
result = create_texture_mesh_pipeline(context->device, context->memories, context->swapchain_extent, context->render_pass, context->g_renderpass, scene.descriptor_layout, context->max_frames_in_flight, context->transfer_command_pool, context->queues.transfer, context->queues.graphics, context->extra_graphics_pool, context->queue_indices.transfer_family, context->queue_indices.graphics_index, &texture_mesh_pipeline);
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
if(result != VK_SUCCESS) {
|
|
|
|
fprintf(stderr, "failed to create texture mesh material\n");
|
|
|
|
fprintf(stderr, "failed to create texture mesh material\n");
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|