|
|
|
|
@ -3,88 +3,22 @@
|
|
|
|
|
#include <math.h>
|
|
|
|
|
#include "../../l1/system/fileio.h"
|
|
|
|
|
#include <time.h>
|
|
|
|
|
#include "r0_assets.h"
|
|
|
|
|
// Only for linux
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
|
|
|
|
|
// todo: generate this class in l2
|
|
|
|
|
typedef struct {
|
|
|
|
|
vec3 pos;
|
|
|
|
|
vec2 tex;
|
|
|
|
|
} OA_Vertex;
|
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
VkDescriptorSetLayout descriptor_set_layout;
|
|
|
|
|
} PipelineHands;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
vec3 s;
|
|
|
|
|
float _0;
|
|
|
|
|
} MyUbo;
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
VkBuffer vbo;
|
|
|
|
|
VkBuffer ebo;
|
|
|
|
|
// If topology is triangle list,then this is trice the amount of triangles
|
|
|
|
|
size_t indices;
|
|
|
|
|
} OA_ObjectOnScene;
|
|
|
|
|
|
|
|
|
|
#define OA_ObjectOnScene_drop(vp) {}
|
|
|
|
|
#define OA_ObjectOnScene_clone(vp) (*(vp))
|
|
|
|
|
|
|
|
|
|
VecT_trivmove_struct_Definition(OA_ObjectOnScene)
|
|
|
|
|
VecT_trivmove_method_Definition(OA_ObjectOnScene)
|
|
|
|
|
VecT_primitive_zeroinit_method_Definition(OA_ObjectOnScene)
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
VecOA_ObjectOnScene oa_objects;
|
|
|
|
|
VkClearColorValue color;
|
|
|
|
|
} Scene;
|
|
|
|
|
|
|
|
|
|
// todo: generate this function in l2
|
|
|
|
|
VkRenderPass create_render_pass_1(VkDevice logical_device, VkFormat image_format) {
|
|
|
|
|
// Color attachments array for our render pass
|
|
|
|
|
VkAttachmentDescription all_attachments[1] = { (VkAttachmentDescription){
|
|
|
|
|
.format = image_format,
|
|
|
|
|
.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_PRESENT_SRC_KHR,
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
// For our one single render subpass
|
|
|
|
|
VkAttachmentReference color_attachment_refs[1] = { (VkAttachmentReference){
|
|
|
|
|
.attachment = 0,
|
|
|
|
|
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){
|
|
|
|
|
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
|
.colorAttachmentCount = ARRAY_SIZE(color_attachment_refs),
|
|
|
|
|
.pColorAttachments = color_attachment_refs,
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
VkSubpassDependency subpass_dependencies[1] = {
|
|
|
|
|
// subpass_0_external
|
|
|
|
|
(VkSubpassDependency) {
|
|
|
|
|
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
|
|
|
|
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
|
.srcAccessMask = 0,
|
|
|
|
|
.dstSubpass = 0,
|
|
|
|
|
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
|
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
VkRenderPassCreateInfo render_pass_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
|
|
|
.attachmentCount = ARRAY_SIZE(all_attachments),
|
|
|
|
|
.pAttachments = all_attachments,
|
|
|
|
|
.subpassCount = ARRAY_SIZE(subpasses_descr),
|
|
|
|
|
.pSubpasses = subpasses_descr,
|
|
|
|
|
.dependencyCount = ARRAY_SIZE(subpass_dependencies),
|
|
|
|
|
.pDependencies = subpass_dependencies,
|
|
|
|
|
};
|
|
|
|
|
VkRenderPass render_pass;
|
|
|
|
|
if (vkCreateRenderPass(logical_device, &render_pass_crinfo, NULL, &render_pass) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreateRenderPass");
|
|
|
|
|
return render_pass;
|
|
|
|
|
void destroy_graphics_pipeline_hands(VkDevice device, PipelineHands hands) {
|
|
|
|
|
vkDestroyPipeline(device, hands.pipeline, NULL);
|
|
|
|
|
vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL);
|
|
|
|
|
vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// todo: generate this function in l2
|
|
|
|
|
@ -139,19 +73,228 @@ VkRenderPass create_render_pass_0(VkDevice logical_device, VkFormat image_format
|
|
|
|
|
return render_pass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// todo: generate this class in l2
|
|
|
|
|
typedef struct {
|
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
VkDescriptorSetLayout descriptor_set_layout;
|
|
|
|
|
} PipelineHands;
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(Vertex)
|
|
|
|
|
|
|
|
|
|
void destroy_graphics_pipeline_hands(VkDevice device, PipelineHands hands) {
|
|
|
|
|
vkDestroyPipeline(device, hands.pipeline, NULL);
|
|
|
|
|
vkDestroyPipelineLayout(device, hands.pipeline_layout, NULL);
|
|
|
|
|
vkDestroyDescriptorSetLayout(device, hands.descriptor_set_layout, NULL);
|
|
|
|
|
PipelineHands create_graphics_pipeline_0(
|
|
|
|
|
VkDevice device, VkRenderPass render_pass, uint32_t subpass
|
|
|
|
|
) {
|
|
|
|
|
VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/0/vert.spv");
|
|
|
|
|
VecU8 frag_bin_code = read_whole_file_or_abort("test_shaders/spv/0/frag.spv");
|
|
|
|
|
VkShaderModule vert_module = margaret_VkShaderModule_new(device, vert_bin_code);
|
|
|
|
|
VkShaderModule frag_module = margaret_VkShaderModule_new(device, frag_bin_code);
|
|
|
|
|
VecU8_drop(vert_bin_code);
|
|
|
|
|
VecU8_drop(frag_bin_code);
|
|
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages_crinfo[2] = {
|
|
|
|
|
margaret_shader_stage_vertex_crinfo(vert_module),
|
|
|
|
|
margaret_shader_stage_fragment_crinfo(frag_module)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription vertex_bindings[1] = { {
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.stride = sizeof(Vertex),
|
|
|
|
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
|
|
|
|
|
} };
|
|
|
|
|
VkVertexInputAttributeDescription vertex_attributes[2] = {
|
|
|
|
|
{
|
|
|
|
|
.location = 0,
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
|
|
|
|
.offset = offsetof(Vertex, pos),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.location = 1,
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.format = VK_FORMAT_R32G32_SFLOAT,
|
|
|
|
|
.offset = offsetof(Vertex, tex),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
|
.vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings),
|
|
|
|
|
.pVertexBindingDescriptions = vertex_bindings,
|
|
|
|
|
.vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes),
|
|
|
|
|
.pVertexAttributeDescriptions = vertex_attributes,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
|
|
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
|
|
|
.primitiveRestartEnable = VK_FALSE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineViewportStateCreateInfo viewport_state = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
|
|
|
// We are using dynamic viewport and scissors, that is why we do not attach viewport/scissor values
|
|
|
|
|
// when creating a rendering pipeline. We will do that later
|
|
|
|
|
.viewportCount = 1,
|
|
|
|
|
.scissorCount = 1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineRasterizationStateCreateInfo rasterizer_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
|
|
|
.depthClampEnable = VK_FALSE,
|
|
|
|
|
.polygonMode = VK_POLYGON_MODE_FILL,
|
|
|
|
|
// .cullMode = VK_CULL_MODE_BACK_BIT,
|
|
|
|
|
.cullMode = VK_CULL_MODE_NONE,
|
|
|
|
|
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
|
|
|
|
.depthBiasEnable = VK_FALSE,
|
|
|
|
|
.depthBiasConstantFactor = 0.0f,
|
|
|
|
|
.depthBiasClamp = 0.0f,
|
|
|
|
|
.depthBiasSlopeFactor = 0.0f,
|
|
|
|
|
.lineWidth = 1.0f,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineMultisampleStateCreateInfo multisampling_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
|
|
|
.sampleShadingEnable = VK_FALSE,
|
|
|
|
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
|
.minSampleShading = 1.0f,
|
|
|
|
|
.pSampleMask = NULL,
|
|
|
|
|
.alphaToCoverageEnable = VK_FALSE,
|
|
|
|
|
.alphaToOneEnable = VK_FALSE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// For one framebuffer
|
|
|
|
|
VkPipelineColorBlendAttachmentState color_blend_attachments[1] = {(VkPipelineColorBlendAttachmentState){
|
|
|
|
|
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
|
|
|
|
.blendEnable = VK_FALSE,
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
// For the entire pipeline
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo color_blending_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
|
|
|
.logicOpEnable = VK_FALSE,
|
|
|
|
|
.logicOp = VK_LOGIC_OP_COPY,
|
|
|
|
|
.attachmentCount = ARRAY_SIZE(color_blend_attachments),
|
|
|
|
|
.pAttachments = color_blend_attachments,
|
|
|
|
|
// Blend constants specified heres
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
|
|
|
|
|
VkPipelineDynamicStateCreateInfo dynamic_state_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
|
|
|
.dynamicStateCount = ARRAY_SIZE(dynamic_states),
|
|
|
|
|
.pDynamicStates = dynamic_states,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = {
|
|
|
|
|
{
|
|
|
|
|
// Binding in shader
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
|
// our shader variable is not an array of descriptors, so this stays 1
|
|
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.binding = 1,
|
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
VkDescriptorSetLayoutCreateInfo descriptor_set_layout_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
|
|
|
.bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout),
|
|
|
|
|
.pBindings = bindings_for_my_descr_set_layout,
|
|
|
|
|
};
|
|
|
|
|
VkDescriptorSetLayout my_descriptor_set_layout;
|
|
|
|
|
if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreateDescriptorSetLayout");
|
|
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo layout_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
|
|
|
.setLayoutCount = 1,
|
|
|
|
|
.pSetLayouts = &my_descriptor_set_layout,
|
|
|
|
|
.pushConstantRangeCount = 0,
|
|
|
|
|
.pPushConstantRanges = NULL,
|
|
|
|
|
};
|
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
|
if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreatePipelineLayout");
|
|
|
|
|
VkGraphicsPipelineCreateInfo pipeline_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
|
.stageCount = ARRAY_SIZE(shader_stages_crinfo),
|
|
|
|
|
.pStages = shader_stages_crinfo,
|
|
|
|
|
.pVertexInputState = &vertex_input_crinfo,
|
|
|
|
|
.pInputAssemblyState = &input_assembly_crinfo,
|
|
|
|
|
.pViewportState = &viewport_state,
|
|
|
|
|
.pRasterizationState = &rasterizer_crinfo,
|
|
|
|
|
.pMultisampleState = &multisampling_crinfo,
|
|
|
|
|
.pDepthStencilState = NULL,
|
|
|
|
|
.pColorBlendState = &color_blending_crinfo,
|
|
|
|
|
.pDynamicState = &dynamic_state_crinfo,
|
|
|
|
|
.layout = pipeline_layout,
|
|
|
|
|
.renderPass = render_pass,
|
|
|
|
|
.subpass = subpass,
|
|
|
|
|
.basePipelineHandle = VK_NULL_HANDLE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_crinfo, NULL, &pipeline) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreateGraphicsPipelines");
|
|
|
|
|
|
|
|
|
|
vkDestroyShaderModule(device, frag_module, NULL);
|
|
|
|
|
vkDestroyShaderModule(device, vert_module, NULL);
|
|
|
|
|
return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// todo: generate this function in l2
|
|
|
|
|
VkRenderPass create_render_pass_1(VkDevice logical_device, VkFormat image_format) {
|
|
|
|
|
// Color attachments array for our render pass
|
|
|
|
|
VkAttachmentDescription all_attachments[1] = { (VkAttachmentDescription){
|
|
|
|
|
.format = image_format,
|
|
|
|
|
.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_PRESENT_SRC_KHR,
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
// For our one single render subpass
|
|
|
|
|
VkAttachmentReference color_attachment_refs[1] = { (VkAttachmentReference){
|
|
|
|
|
.attachment = 0,
|
|
|
|
|
.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
VkSubpassDescription subpasses_descr[1] = { (VkSubpassDescription){
|
|
|
|
|
.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
|
|
|
|
|
.colorAttachmentCount = ARRAY_SIZE(color_attachment_refs),
|
|
|
|
|
.pColorAttachments = color_attachment_refs,
|
|
|
|
|
} };
|
|
|
|
|
|
|
|
|
|
VkSubpassDependency subpass_dependencies[1] = {
|
|
|
|
|
// subpass_0_external
|
|
|
|
|
(VkSubpassDependency) {
|
|
|
|
|
.srcSubpass = VK_SUBPASS_EXTERNAL,
|
|
|
|
|
.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
|
.srcAccessMask = 0,
|
|
|
|
|
.dstSubpass = 0,
|
|
|
|
|
.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
|
|
|
|
|
.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
VkRenderPassCreateInfo render_pass_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
|
|
|
|
|
.attachmentCount = ARRAY_SIZE(all_attachments),
|
|
|
|
|
.pAttachments = all_attachments,
|
|
|
|
|
.subpassCount = ARRAY_SIZE(subpasses_descr),
|
|
|
|
|
.pSubpasses = subpasses_descr,
|
|
|
|
|
.dependencyCount = ARRAY_SIZE(subpass_dependencies),
|
|
|
|
|
.pDependencies = subpass_dependencies,
|
|
|
|
|
};
|
|
|
|
|
VkRenderPass render_pass;
|
|
|
|
|
if (vkCreateRenderPass(logical_device, &render_pass_crinfo, NULL, &render_pass) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreateRenderPass");
|
|
|
|
|
return render_pass;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// todo: generate this function in l2
|
|
|
|
|
PipelineHands create_graphics_pipeline_1(
|
|
|
|
|
VkDevice device, VkRenderPass render_pass, uint32_t subpass
|
|
|
|
|
@ -226,7 +369,7 @@ PipelineHands create_graphics_pipeline_1(
|
|
|
|
|
.logicOp = VK_LOGIC_OP_COPY,
|
|
|
|
|
.attachmentCount = ARRAY_SIZE(color_blend_attachments),
|
|
|
|
|
.pAttachments = color_blend_attachments,
|
|
|
|
|
// Blend constants specified heres
|
|
|
|
|
// Blend constants specified here
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
|
|
|
|
|
@ -253,22 +396,24 @@ PipelineHands create_graphics_pipeline_1(
|
|
|
|
|
if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreateDescriptorSetLayout");
|
|
|
|
|
|
|
|
|
|
VkPushConstantRange used_region_sz_push_const = {
|
|
|
|
|
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
|
.offset = 0, .size = sizeof(vec2)
|
|
|
|
|
VkPushConstantRange used_region_sz_push_const[2] = {
|
|
|
|
|
{ .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
|
.offset = 0, .size = sizeof(Pipeline1PushRangeVertex) },
|
|
|
|
|
{ .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
.offset = sizeof(Pipeline1PushRangeVertex), .size = sizeof(Pipeline1PushRangeFragment) },
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo layout_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
|
|
|
.setLayoutCount = 1,
|
|
|
|
|
.pSetLayouts = &my_descriptor_set_layout,
|
|
|
|
|
.pushConstantRangeCount = 1,
|
|
|
|
|
.pPushConstantRanges = &used_region_sz_push_const,
|
|
|
|
|
.pushConstantRangeCount = ARRAY_SIZE(used_region_sz_push_const),
|
|
|
|
|
.pPushConstantRanges = used_region_sz_push_const,
|
|
|
|
|
};
|
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
|
if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreatePipelineLayout");
|
|
|
|
|
// todo: kill myself (update: still todo (update: still not done )) update: work in progress
|
|
|
|
|
// todo: kill myself (update: still todo (update: still not done )) update: work in progress (update: medium priority)
|
|
|
|
|
VkGraphicsPipelineCreateInfo pipeline_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
|
.stageCount = ARRAY_SIZE(shader_stages_crinfo),
|
|
|
|
|
@ -296,173 +441,6 @@ PipelineHands create_graphics_pipeline_1(
|
|
|
|
|
return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PipelineHands create_graphics_pipeline_0(
|
|
|
|
|
VkDevice device, VkRenderPass render_pass, uint32_t subpass
|
|
|
|
|
) {
|
|
|
|
|
VecU8 vert_bin_code = read_whole_file_or_abort("test_shaders/spv/0/vert.spv");
|
|
|
|
|
VecU8 frag_bin_code = read_whole_file_or_abort("test_shaders/spv/0/frag.spv");
|
|
|
|
|
VkShaderModule vert_module = margaret_VkShaderModule_new(device, vert_bin_code);
|
|
|
|
|
VkShaderModule frag_module = margaret_VkShaderModule_new(device, frag_bin_code);
|
|
|
|
|
VecU8_drop(vert_bin_code);
|
|
|
|
|
VecU8_drop(frag_bin_code);
|
|
|
|
|
|
|
|
|
|
VkPipelineShaderStageCreateInfo shader_stages_crinfo[2] = {
|
|
|
|
|
margaret_shader_stage_vertex_crinfo(vert_module),
|
|
|
|
|
margaret_shader_stage_fragment_crinfo(frag_module)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkVertexInputBindingDescription vertex_bindings[1] = { {
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.stride = sizeof(OA_Vertex),
|
|
|
|
|
.inputRate = VK_VERTEX_INPUT_RATE_VERTEX,
|
|
|
|
|
} };
|
|
|
|
|
VkVertexInputAttributeDescription vertex_attributes[2] = {
|
|
|
|
|
{
|
|
|
|
|
.location = 0,
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.format = VK_FORMAT_R32G32B32_SFLOAT,
|
|
|
|
|
.offset = offsetof(OA_Vertex, pos),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.location = 1,
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.format = VK_FORMAT_R32G32_SFLOAT,
|
|
|
|
|
.offset = offsetof(OA_Vertex, tex),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineVertexInputStateCreateInfo vertex_input_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
|
|
|
|
.vertexBindingDescriptionCount = ARRAY_SIZE(vertex_bindings),
|
|
|
|
|
.pVertexBindingDescriptions = vertex_bindings,
|
|
|
|
|
.vertexAttributeDescriptionCount = ARRAY_SIZE(vertex_attributes),
|
|
|
|
|
.pVertexAttributeDescriptions = vertex_attributes,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineInputAssemblyStateCreateInfo input_assembly_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
|
|
|
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
|
|
|
|
.primitiveRestartEnable = VK_FALSE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineViewportStateCreateInfo viewport_state = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
|
|
|
|
// We are using dynamic viewport and scissors, that is why we do not attach viewport/scissor values
|
|
|
|
|
// when creating a rendering pipeline. We will do that later
|
|
|
|
|
.viewportCount = 1,
|
|
|
|
|
.scissorCount = 1,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineRasterizationStateCreateInfo rasterizer_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
|
|
|
|
.depthClampEnable = VK_FALSE,
|
|
|
|
|
.polygonMode = VK_POLYGON_MODE_FILL,
|
|
|
|
|
.cullMode = VK_CULL_MODE_BACK_BIT,
|
|
|
|
|
.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE,
|
|
|
|
|
.depthBiasEnable = VK_FALSE,
|
|
|
|
|
.depthBiasConstantFactor = 0.0f,
|
|
|
|
|
.depthBiasClamp = 0.0f,
|
|
|
|
|
.depthBiasSlopeFactor = 0.0f,
|
|
|
|
|
.lineWidth = 1.0f,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkPipelineMultisampleStateCreateInfo multisampling_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
|
|
|
|
|
.sampleShadingEnable = VK_FALSE,
|
|
|
|
|
.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT,
|
|
|
|
|
.minSampleShading = 1.0f,
|
|
|
|
|
.pSampleMask = NULL,
|
|
|
|
|
.alphaToCoverageEnable = VK_FALSE,
|
|
|
|
|
.alphaToOneEnable = VK_FALSE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// For one framebuffer
|
|
|
|
|
VkPipelineColorBlendAttachmentState color_blend_attachments[1] = {(VkPipelineColorBlendAttachmentState){
|
|
|
|
|
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT,
|
|
|
|
|
.blendEnable = VK_FALSE,
|
|
|
|
|
}};
|
|
|
|
|
|
|
|
|
|
// For the entire pipeline
|
|
|
|
|
VkPipelineColorBlendStateCreateInfo color_blending_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
|
|
|
|
|
.logicOpEnable = VK_FALSE,
|
|
|
|
|
.logicOp = VK_LOGIC_OP_COPY,
|
|
|
|
|
.attachmentCount = ARRAY_SIZE(color_blend_attachments),
|
|
|
|
|
.pAttachments = color_blend_attachments,
|
|
|
|
|
// Blend constants specified heres
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkDynamicState dynamic_states[2] = {VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR};
|
|
|
|
|
VkPipelineDynamicStateCreateInfo dynamic_state_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
|
|
|
|
|
.dynamicStateCount = ARRAY_SIZE(dynamic_states),
|
|
|
|
|
.pDynamicStates = dynamic_states,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
VkDescriptorSetLayoutBinding bindings_for_my_descr_set_layout[] = {
|
|
|
|
|
{
|
|
|
|
|
// Binding in shader
|
|
|
|
|
.binding = 0,
|
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
|
|
|
|
// our shader variable is not an array of descriptors, so this stays 1
|
|
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
.binding = 1,
|
|
|
|
|
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
|
|
|
|
.descriptorCount = 1,
|
|
|
|
|
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
VkDescriptorSetLayoutCreateInfo descriptor_set_layout_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
|
|
|
|
.bindingCount = ARRAY_SIZE(bindings_for_my_descr_set_layout),
|
|
|
|
|
.pBindings = bindings_for_my_descr_set_layout,
|
|
|
|
|
};
|
|
|
|
|
VkDescriptorSetLayout my_descriptor_set_layout;
|
|
|
|
|
if (vkCreateDescriptorSetLayout(device, &descriptor_set_layout_crinfo, NULL, &my_descriptor_set_layout) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreateDescriptorSetLayout");
|
|
|
|
|
|
|
|
|
|
VkPipelineLayoutCreateInfo layout_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
|
|
|
|
.setLayoutCount = 1,
|
|
|
|
|
.pSetLayouts = &my_descriptor_set_layout,
|
|
|
|
|
.pushConstantRangeCount = 0,
|
|
|
|
|
.pPushConstantRanges = NULL,
|
|
|
|
|
};
|
|
|
|
|
VkPipelineLayout pipeline_layout;
|
|
|
|
|
if (vkCreatePipelineLayout(device, &layout_crinfo, NULL, &pipeline_layout) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreatePipelineLayout");
|
|
|
|
|
VkGraphicsPipelineCreateInfo pipeline_crinfo = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
|
|
|
|
.stageCount = ARRAY_SIZE(shader_stages_crinfo),
|
|
|
|
|
.pStages = shader_stages_crinfo,
|
|
|
|
|
.pVertexInputState = &vertex_input_crinfo,
|
|
|
|
|
.pInputAssemblyState = &input_assembly_crinfo,
|
|
|
|
|
.pViewportState = &viewport_state,
|
|
|
|
|
.pRasterizationState = &rasterizer_crinfo,
|
|
|
|
|
.pMultisampleState = &multisampling_crinfo,
|
|
|
|
|
.pDepthStencilState = NULL,
|
|
|
|
|
.pColorBlendState = &color_blending_crinfo,
|
|
|
|
|
.pDynamicState = &dynamic_state_crinfo,
|
|
|
|
|
.layout = pipeline_layout,
|
|
|
|
|
.renderPass = render_pass,
|
|
|
|
|
.subpass = subpass,
|
|
|
|
|
.basePipelineHandle = VK_NULL_HANDLE,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// todo: actually use this function
|
|
|
|
|
|
|
|
|
|
VkPipeline pipeline;
|
|
|
|
|
if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipeline_crinfo, NULL, &pipeline) != VK_SUCCESS)
|
|
|
|
|
abortf("vkCreateGraphicsPipelines");
|
|
|
|
|
|
|
|
|
|
vkDestroyShaderModule(device, frag_module, NULL);
|
|
|
|
|
vkDestroyShaderModule(device, vert_module, NULL);
|
|
|
|
|
return (PipelineHands){.pipeline_layout = pipeline_layout, .pipeline = pipeline, .descriptor_set_layout = my_descriptor_set_layout};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VkFramebuffer create_IT1_framebuffer(VkDevice device, VkImageView IT1_view, VkRenderPass render_pass_0, VkExtent2D MAX_WIN_SIZE) {
|
|
|
|
|
VkImageView attachments[1] = {IT1_view};
|
|
|
|
|
@ -523,17 +501,17 @@ void reset_and_record_command_buffer_0(
|
|
|
|
|
.extent = image_extent,
|
|
|
|
|
};
|
|
|
|
|
vkCmdSetScissor(command_buffer, 0, 1, &scissor);
|
|
|
|
|
for (size_t i = 0; i < scene->oa_objects.len; i++) {
|
|
|
|
|
const OA_ObjectOnScene* obj = VecOA_ObjectOnScene_cat(&scene->oa_objects, i);
|
|
|
|
|
VkBuffer attached_buffers[1] = { obj->vbo };
|
|
|
|
|
for (size_t i = 0; i < scene->models.len; i++) {
|
|
|
|
|
const ModelOnScene* models = VecModelOnScene_cat(&scene->models, i);
|
|
|
|
|
VkBuffer attached_buffers[1] = { models->vbo };
|
|
|
|
|
// We use our whole buffer, no need for offset
|
|
|
|
|
VkDeviceSize offsets_in_buffers[1] = {0};
|
|
|
|
|
vkCmdBindVertexBuffers(command_buffer, 0, 1, attached_buffers, offsets_in_buffers);
|
|
|
|
|
vkCmdBindIndexBuffer(command_buffer, obj->ebo, 0, VK_INDEX_TYPE_UINT32);
|
|
|
|
|
vkCmdBindIndexBuffer(command_buffer, models->ebo, 0, VK_INDEX_TYPE_UINT32);
|
|
|
|
|
vkCmdBindDescriptorSets(
|
|
|
|
|
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout->pipeline_layout, 0,
|
|
|
|
|
1, &my_descriptor_set, 0, NULL);
|
|
|
|
|
vkCmdDrawIndexed(command_buffer, obj->indices, 1, 0, 0, 0);
|
|
|
|
|
vkCmdDrawIndexed(command_buffer, models->indexes, 1, 0, 0, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
vkCmdEndRenderPass(command_buffer);
|
|
|
|
|
@ -545,7 +523,7 @@ void reset_and_record_command_buffer_1(
|
|
|
|
|
VkCommandBuffer command_buffer, VkRenderPass render_pass_1,
|
|
|
|
|
const PipelineHands* pipeline_and_layout_1,
|
|
|
|
|
VkFramebuffer swapchain_image_framebuffer, VkExtent2D image_extent,
|
|
|
|
|
VkExtent2D max_win_size,
|
|
|
|
|
VkExtent2D max_win_size, const Scene* scene,
|
|
|
|
|
VkDescriptorSet descriptor_set_for_pipeline_1
|
|
|
|
|
) {
|
|
|
|
|
if (vkResetCommandBuffer(command_buffer, 0) != VK_SUCCESS)
|
|
|
|
|
@ -554,15 +532,12 @@ void reset_and_record_command_buffer_1(
|
|
|
|
|
if (vkBeginCommandBuffer(command_buffer, &info_begin) != VK_SUCCESS)
|
|
|
|
|
abortf("vkBeginCommandBuffer");
|
|
|
|
|
|
|
|
|
|
// VkClearValue clear_color[1] = {{.color = scene->color}};
|
|
|
|
|
VkRenderPassBeginInfo renderpass_begin = {
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
|
|
|
|
|
.renderPass = render_pass_1,
|
|
|
|
|
.framebuffer = swapchain_image_framebuffer,
|
|
|
|
|
.renderArea.offset = (VkOffset2D){0, 0},
|
|
|
|
|
.renderArea.extent = image_extent,
|
|
|
|
|
.clearValueCount = 0,
|
|
|
|
|
.pClearValues = NULL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
vkCmdBeginRenderPass(command_buffer, &renderpass_begin, VK_SUBPASS_CONTENTS_INLINE);
|
|
|
|
|
@ -586,10 +561,20 @@ void reset_and_record_command_buffer_1(
|
|
|
|
|
command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline_and_layout_1->pipeline_layout, 0,
|
|
|
|
|
1, &descriptor_set_for_pipeline_1, 0, NULL);
|
|
|
|
|
|
|
|
|
|
vec2 region_tex_scale = {(float)image_extent.width / (float)max_win_size.width,
|
|
|
|
|
(float)image_extent.height / (float)max_win_size.height};
|
|
|
|
|
vkCmdPushConstants(command_buffer, pipeline_and_layout_1->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vec2), ®ion_tex_scale);
|
|
|
|
|
|
|
|
|
|
Pipeline1PushRangeVertex reg_and_params_vertex = {.win_scale = {
|
|
|
|
|
(float)image_extent.width / (float)max_win_size.width,
|
|
|
|
|
(float)image_extent.height / (float)max_win_size.height},
|
|
|
|
|
};
|
|
|
|
|
Pipeline1PushRangeFragment reg_and_params_fragment = {
|
|
|
|
|
.gamma_correction_factor = scene->gamma_correction_factor,
|
|
|
|
|
.hdr_factor = scene->hdr_factor,
|
|
|
|
|
.lsd_factor = scene->lsd_factor,
|
|
|
|
|
.anim_time = scene->anim_time
|
|
|
|
|
};
|
|
|
|
|
vkCmdPushConstants(command_buffer, pipeline_and_layout_1->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT,
|
|
|
|
|
0, sizeof(Pipeline1PushRangeVertex), ®_and_params_vertex);
|
|
|
|
|
vkCmdPushConstants(command_buffer, pipeline_and_layout_1->pipeline_layout, VK_SHADER_STAGE_FRAGMENT_BIT,
|
|
|
|
|
sizeof(Pipeline1PushRangeVertex), sizeof(Pipeline1PushRangeFragment), ®_and_params_fragment);
|
|
|
|
|
vkCmdDraw(command_buffer, 3, 1, 0, 0);
|
|
|
|
|
|
|
|
|
|
vkCmdEndRenderPass(command_buffer);
|
|
|
|
|
@ -598,6 +583,7 @@ void reset_and_record_command_buffer_1(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// todo: add here deletion and recreation of several synchronization primitives
|
|
|
|
|
void recreate_swapchain(
|
|
|
|
|
VkPhysicalDevice physical_device, VkDevice device, MargaretChosenQueueFamilies queue_fam, VkSurfaceKHR surface,
|
|
|
|
|
VkRenderPass render_pass, MargaretSwapchainBundle* swfb) {
|
|
|
|
|
@ -616,7 +602,6 @@ void recreate_swapchain(
|
|
|
|
|
*swfb = new_swfb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_vbo_Definition(OA_Vertex)
|
|
|
|
|
|
|
|
|
|
void prepare_shaders() {
|
|
|
|
|
int ret = system("./test_shader_compile.sh");
|
|
|
|
|
@ -687,65 +672,31 @@ int main() {
|
|
|
|
|
MargaretSwapchainBundle swfb = MargaretSwapchainBundle_new(device, queue_fam, swapchain_details, surface, render_pass_1, NULL);
|
|
|
|
|
|
|
|
|
|
// Filling scene info
|
|
|
|
|
const OA_Vertex obj1_vertexes[] = {
|
|
|
|
|
(OA_Vertex){ .pos = {-1, -0.5f, 0}, .tex = {0, 1} },
|
|
|
|
|
(OA_Vertex){ .pos = {0.3f, -0.5f, 0}, .tex = {1, 1} },
|
|
|
|
|
(OA_Vertex){ .pos = {-3.f, 3.f, 0}, .tex = {1, 0} },
|
|
|
|
|
(OA_Vertex){ .pos = {-0.5f, .4f, 0}, .tex = {0, 0} },
|
|
|
|
|
};
|
|
|
|
|
const uint32_t obj1_indices[] = { 0, 2, 1, 0, 3, 2 };
|
|
|
|
|
const OA_Vertex obj2_vertexes[] = {
|
|
|
|
|
(OA_Vertex){ .pos = {0.9f, 0.9f}, .tex = {1.f, 0} },
|
|
|
|
|
(OA_Vertex){ .pos = {0.4f, -0.9f, 0}, .tex = {0, 1.f} },
|
|
|
|
|
(OA_Vertex){ .pos = {-0.2f, 1.f}, .tex = {0, 0} },
|
|
|
|
|
};
|
|
|
|
|
const uint32_t obj2_indices[] = {0, 1, 2};
|
|
|
|
|
|
|
|
|
|
const U32 wood_texture_width = 100;
|
|
|
|
|
const U32 wood_texture_height = 100;
|
|
|
|
|
color8rgba wood_texture_data[wood_texture_height][wood_texture_width];
|
|
|
|
|
for (U32 y = 0; y < wood_texture_height; y++) {
|
|
|
|
|
for (U32 col = 0; col < wood_texture_width; col++) {
|
|
|
|
|
wood_texture_data[y][col] = (color8rgba){150, 30, 50, 255};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (U32 i = 0; i < 10; i++) {
|
|
|
|
|
for (U32 y = 0; y < wood_texture_height; y++) {
|
|
|
|
|
U32 col = 3 + i * 10 + ((30 < y + 3 * i && y - i < 60) ? 1 : 0);
|
|
|
|
|
wood_texture_data[y][col] = (color8rgba){130, 25, 40, 255};
|
|
|
|
|
wood_texture_data[y][col + 1] = (color8rgba){80, 10, 15, 255};
|
|
|
|
|
wood_texture_data[y][col + 2] = (color8rgba){70, 11, 12, 255};
|
|
|
|
|
wood_texture_data[y][col + 3] = (color8rgba){125, 20, 20, 255};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (U32 y = 0; y < 10; y++) {
|
|
|
|
|
for (U32 col = 0; col < 10; col++) {
|
|
|
|
|
wood_texture_data[13 + y][4 + col] = (color8rgba){140, 50, 20, 255};
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ModelTopology cylinder_1 = generate_one_fourth_of_a_cylinder(10, 2, 6);
|
|
|
|
|
ModelTopology cylinder_2 = generate_one_fourth_of_a_cylinder(5, 5, 10);
|
|
|
|
|
TextureDataR8G8B8A8 wood_texture_data = generate_wood_texture();
|
|
|
|
|
|
|
|
|
|
// We have only one staging buffer in host memory (because we don't really need more)
|
|
|
|
|
MargaretBufferInMemoryInfo host_mem_buffer = (MargaretBufferInMemoryInfo){ .sz =
|
|
|
|
|
MAX_U64(sizeof(obj1_vertexes),
|
|
|
|
|
MAX_U64(sizeof(obj1_indices),
|
|
|
|
|
MAX_U64(sizeof(obj2_vertexes),
|
|
|
|
|
MAX_U64(sizeof(obj2_indices),
|
|
|
|
|
MAX_U64(sizeof(MyUbo),
|
|
|
|
|
MAX_U64(sizeof(wood_texture_data), 0))))))
|
|
|
|
|
MAX_U64(ModelTopology_get_space_needed_for_staging_buffer(&cylinder_1),
|
|
|
|
|
MAX_U64(ModelTopology_get_space_needed_for_staging_buffer(&cylinder_2),
|
|
|
|
|
MAX_U64(sizeof(Pipeline0UBO),
|
|
|
|
|
MAX_U64(TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(&wood_texture_data), 0))))
|
|
|
|
|
, .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT };
|
|
|
|
|
VkDeviceMemory host_mem = margaret_initialize_buffers_and_images(physical_device, device,
|
|
|
|
|
(SpanMargaretBufferInMemoryInfo){.data = &host_mem_buffer, .len = 1}, (SpanMargaretImageInMemoryInfo){ 0 },
|
|
|
|
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
|
|
|
|
|
|
|
|
|
MargaretBufferInMemoryInfo device_mem_buffers[] = {
|
|
|
|
|
OA_Vertex_buffer_crinfo_of_gpu_vbo(ARRAY_SIZE(obj1_vertexes)),
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_ebo(ARRAY_SIZE(obj1_indices)),
|
|
|
|
|
OA_Vertex_buffer_crinfo_of_gpu_vbo(ARRAY_SIZE(obj2_vertexes)),
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_ebo(ARRAY_SIZE(obj2_indices)),
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(MyUbo)),
|
|
|
|
|
Vertex_buffer_crinfo_of_gpu_vbo(cylinder_1.vertices.len),
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_ebo(cylinder_1.indexes.len),
|
|
|
|
|
Vertex_buffer_crinfo_of_gpu_vbo(cylinder_2.vertices.len),
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_ebo(cylinder_2.indexes.len),
|
|
|
|
|
margaret_prep_buffer_mem_info_of_gpu_ubo(sizeof(Pipeline0UBO)),
|
|
|
|
|
};
|
|
|
|
|
MargaretImageInMemoryInfo device_mem_images[] = {
|
|
|
|
|
margaret_prep_image_mem_info_of_gpu_texture_rgba(wood_texture_width, wood_texture_height),
|
|
|
|
|
margaret_prep_image_mem_info_of_gpu_texture_rgba(wood_texture_data.width,
|
|
|
|
|
TextureDataR8G8B8A8_get_height(&wood_texture_data)),
|
|
|
|
|
margaret_prep_image_mem_info_of_colorbuffer(MAX_WIN_WIDTH, MAX_WIN_HEIGHT, swapchain_details.surface_format.format),
|
|
|
|
|
};
|
|
|
|
|
VkDeviceMemory device_mem = margaret_initialize_buffers_and_images(physical_device, device,
|
|
|
|
|
@ -758,7 +709,7 @@ int main() {
|
|
|
|
|
MargaretBufferInMemoryInfo device_ebo_2_buffer = device_mem_buffers[3];
|
|
|
|
|
MargaretBufferInMemoryInfo device_ubo_my_buffer = device_mem_buffers[4];
|
|
|
|
|
MargaretImageInMemoryInfo device_wood_texture = device_mem_images[0];
|
|
|
|
|
MargaretImageInMemoryInfo device_IT1_image = device_mem_images[1]; // todo: use it in my shenanigans
|
|
|
|
|
MargaretImageInMemoryInfo device_IT1_image = device_mem_images[1];
|
|
|
|
|
|
|
|
|
|
VkCommandPool command_pool = margaret_create_resettable_command_pool(device, queue_fam.for_graphics);
|
|
|
|
|
VkCommandBuffer rendering_command_buffer_0 = margaret_allocate_command_buffer(device, command_pool);
|
|
|
|
|
@ -766,25 +717,38 @@ int main() {
|
|
|
|
|
|
|
|
|
|
VkCommandBuffer uniform_transfer_command_buffer = margaret_allocate_command_buffer(device, command_pool);
|
|
|
|
|
margaret_record_buf_copying_command_buf(device, uniform_transfer_command_buffer,
|
|
|
|
|
device_ubo_my_buffer.buffer, host_mem_buffer.buffer, sizeof(MyUbo));
|
|
|
|
|
device_ubo_my_buffer.buffer, host_mem_buffer.buffer, sizeof(Pipeline0UBO));
|
|
|
|
|
|
|
|
|
|
void* host_mem_buffer_mem;
|
|
|
|
|
if (vkMapMemory(device, host_mem, 0, VK_WHOLE_SIZE, 0, &host_mem_buffer_mem) != VK_SUCCESS)
|
|
|
|
|
abortf("vkMapMemory");
|
|
|
|
|
// Now this is what we will do for each buffer: we first memcpy it into mapped region, then we submit a copying command
|
|
|
|
|
memcpy(host_mem_buffer_mem, obj1_vertexes, sizeof(obj1_vertexes));
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_vbo_1_buffer.buffer, host_mem_buffer.buffer, sizeof(obj1_vertexes));
|
|
|
|
|
memcpy(host_mem_buffer_mem, obj1_indices, sizeof(obj1_indices));
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_ebo_1_buffer.buffer, host_mem_buffer.buffer, sizeof(obj1_indices));
|
|
|
|
|
memcpy(host_mem_buffer_mem, obj2_vertexes, sizeof(obj2_vertexes));
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_vbo_2_buffer.buffer, host_mem_buffer.buffer, sizeof(obj2_vertexes));
|
|
|
|
|
memcpy(host_mem_buffer_mem, obj2_indices, sizeof(obj2_indices));
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_ebo_2_buffer.buffer, host_mem_buffer.buffer, sizeof(obj2_indices));
|
|
|
|
|
memcpy(host_mem_buffer_mem, wood_texture_data, sizeof(wood_texture_data));
|
|
|
|
|
{
|
|
|
|
|
size_t size = cylinder_1.vertices.len * sizeof(Vertex);
|
|
|
|
|
memcpy(host_mem_buffer_mem, cylinder_1.vertices.buf, size);
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_vbo_1_buffer.buffer, host_mem_buffer.buffer, size);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
size_t size = cylinder_1.indexes.len * sizeof(U32);
|
|
|
|
|
memcpy(host_mem_buffer_mem, cylinder_1.indexes.buf, size);
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_ebo_1_buffer.buffer, host_mem_buffer.buffer, size);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
size_t size = cylinder_2.vertices.len * sizeof(Vertex);
|
|
|
|
|
memcpy(host_mem_buffer_mem, cylinder_2.vertices.buf, size);
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_vbo_2_buffer.buffer, host_mem_buffer.buffer, size);
|
|
|
|
|
}
|
|
|
|
|
{
|
|
|
|
|
size_t size = cylinder_2.indexes.len * sizeof(U32);
|
|
|
|
|
memcpy(host_mem_buffer_mem, cylinder_2.indexes.buf, size);
|
|
|
|
|
margaret_copy_buffer_imm(device, command_pool, graphics_queue,
|
|
|
|
|
device_ebo_2_buffer.buffer, host_mem_buffer.buffer, size);
|
|
|
|
|
}
|
|
|
|
|
memcpy(host_mem_buffer_mem, wood_texture_data.pixels.buf,
|
|
|
|
|
TextureDataR8G8B8A8_get_space_needed_for_staging_buffer(&wood_texture_data));
|
|
|
|
|
margaret_copy_buffer_to_texture_for_frag_shader_imm(device, command_pool, graphics_queue,
|
|
|
|
|
&device_wood_texture, host_mem_buffer.buffer);
|
|
|
|
|
// We sent everything we needed. but host_mem_buffer_mem may be used later
|
|
|
|
|
@ -794,17 +758,15 @@ int main() {
|
|
|
|
|
|
|
|
|
|
/* Here we create an image view into a temporary IT1 texture and a framebuffer for scene rendering */
|
|
|
|
|
VkImageView IT1_view = margaret_create_view_for_image(device, &device_IT1_image, VK_IMAGE_ASPECT_COLOR_BIT);
|
|
|
|
|
// todo: I will get back here soon
|
|
|
|
|
VkFramebuffer IT1_framebuffer = create_IT1_framebuffer(device, IT1_view, render_pass_0,
|
|
|
|
|
(VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT});
|
|
|
|
|
|
|
|
|
|
Scene scene;
|
|
|
|
|
scene.oa_objects = VecOA_ObjectOnScene_new_zeroinit(2);
|
|
|
|
|
*VecOA_ObjectOnScene_at(&scene.oa_objects, 0) = (OA_ObjectOnScene){
|
|
|
|
|
.vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indices = ARRAY_SIZE(obj1_indices) };
|
|
|
|
|
*VecOA_ObjectOnScene_at(&scene.oa_objects, 1) = (OA_ObjectOnScene){
|
|
|
|
|
.vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indices = ARRAY_SIZE(obj2_indices) };
|
|
|
|
|
// device_vbo/ebo_1/2_buffer won't be used only intrinsically by vulkan, not by us
|
|
|
|
|
scene.models = VecModelOnScene_new_zeroinit(2);
|
|
|
|
|
*VecModelOnScene_at(&scene.models, 0) = (ModelOnScene){
|
|
|
|
|
.vbo = device_vbo_1_buffer.buffer, .ebo = device_ebo_1_buffer.buffer, .indexes = cylinder_1.indexes.len };
|
|
|
|
|
// *VecModelOnScene_at(&scene.models, 1) = (ModelOnScene){
|
|
|
|
|
// .vbo = device_vbo_2_buffer.buffer, .ebo = device_ebo_2_buffer.buffer, .indexes = cylinder_2.indexes.len };
|
|
|
|
|
|
|
|
|
|
// Sampler is global for a lot of my future textures
|
|
|
|
|
VkSampler my_texture_sampler = margaret_create_sampler(physical_device, device);
|
|
|
|
|
@ -817,7 +779,7 @@ int main() {
|
|
|
|
|
VkDescriptorBufferInfo buffer_info_for_descriptor_0_in_set_0 = {
|
|
|
|
|
.buffer = device_ubo_my_buffer.buffer,
|
|
|
|
|
.offset = 0,
|
|
|
|
|
.range = sizeof(MyUbo),
|
|
|
|
|
.range = sizeof(Pipeline0UBO),
|
|
|
|
|
};
|
|
|
|
|
VkDescriptorImageInfo image_info_for_descriptor_1_in_set_0 = {
|
|
|
|
|
.sampler = my_texture_sampler,
|
|
|
|
|
@ -849,7 +811,6 @@ int main() {
|
|
|
|
|
.pImageInfo = &image_info_for_descriptor_1_in_set_0,
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
|
|
|
|
.dstSet = descriptor_set_for_pipeline_1,
|
|
|
|
|
@ -862,18 +823,56 @@ int main() {
|
|
|
|
|
};
|
|
|
|
|
vkUpdateDescriptorSets(device, ARRAY_SIZE(writes_in_descriptor_sets), writes_in_descriptor_sets, 0, NULL);
|
|
|
|
|
|
|
|
|
|
CamControlInfo my_cam_control_info = CamControlInfo_new();
|
|
|
|
|
|
|
|
|
|
// Mainloop
|
|
|
|
|
margaret_ns_time start = margaret_clock_gettime_monotonic_raw();
|
|
|
|
|
margaret_ns_time prev_key_frame_time = start;
|
|
|
|
|
int frame_count_since_key = 0;
|
|
|
|
|
margaret_ns_time prev_frame_timestamp = start;
|
|
|
|
|
|
|
|
|
|
bool pressed_first_0x80[0x80] = {0};
|
|
|
|
|
while (true) {
|
|
|
|
|
margaret_ns_time frame_A0 = margaret_clock_gettime_monotonic_raw();
|
|
|
|
|
float fl = margaret_ns_time_sec_diff(prev_frame_timestamp, frame_A0);
|
|
|
|
|
prev_frame_timestamp = frame_A0;
|
|
|
|
|
|
|
|
|
|
VecXlib_Event events = margaret_read_x_events(x.dpy);
|
|
|
|
|
for (size_t i = 0; i < events.len; i++)
|
|
|
|
|
Margaret_WEP_update_with_new_event(&wep, VecXlib_Event_cat(&events, i));
|
|
|
|
|
if (wep.should_stop)
|
|
|
|
|
break;
|
|
|
|
|
for (size_t i = 0; i < events.len; i++) {
|
|
|
|
|
Xlib_Event* ev = VecXlib_Event_at(&events, i);
|
|
|
|
|
// printf("%lu %lu\n", ev->xany.window, wep.win);
|
|
|
|
|
if (ev->xany.window != wep.win)
|
|
|
|
|
continue;
|
|
|
|
|
Margaret_WEP_update_with_new_event(&wep, ev);
|
|
|
|
|
if (ev->xany.type == MotionNotify) {
|
|
|
|
|
CamControlInfo_update_direction(&my_cam_control_info, wep.width, wep.height, ev->xmotion.x, ev->xmotion.y);
|
|
|
|
|
}
|
|
|
|
|
if (ev->xany.type == KeyPress) {
|
|
|
|
|
KeySym keysym = XLookupKeysym(&ev->xkey, 0);
|
|
|
|
|
if (keysym < 0x80)
|
|
|
|
|
pressed_first_0x80[keysym] = true;
|
|
|
|
|
}
|
|
|
|
|
if (ev->xany.type == KeyRelease) {
|
|
|
|
|
KeySym keysym = XLookupKeysym(&ev->xkey, 0);
|
|
|
|
|
if (keysym < 0x80)
|
|
|
|
|
pressed_first_0x80[keysym] = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (pressed_first_0x80[XK_w])
|
|
|
|
|
CamControlInfo_forward(&my_cam_control_info, fl);
|
|
|
|
|
if (pressed_first_0x80[XK_s])
|
|
|
|
|
CamControlInfo_backward(&my_cam_control_info, fl);
|
|
|
|
|
if (pressed_first_0x80[XK_a])
|
|
|
|
|
CamControlInfo_left(&my_cam_control_info, fl);
|
|
|
|
|
if (pressed_first_0x80[XK_d])
|
|
|
|
|
CamControlInfo_right(&my_cam_control_info, fl);
|
|
|
|
|
if (pressed_first_0x80[XK_q])
|
|
|
|
|
CamControlInfo_down(&my_cam_control_info, fl);
|
|
|
|
|
if (pressed_first_0x80[XK_e])
|
|
|
|
|
CamControlInfo_up(&my_cam_control_info, fl);
|
|
|
|
|
|
|
|
|
|
// Rendering
|
|
|
|
|
vkWaitForFences(device, 1, &swfb.in_flight_fence, VK_TRUE, UINT64_MAX);
|
|
|
|
|
uint32_t ij;
|
|
|
|
|
@ -895,12 +894,17 @@ int main() {
|
|
|
|
|
|
|
|
|
|
vkResetFences(device, 1, &swfb.in_flight_fence);
|
|
|
|
|
|
|
|
|
|
float ae = sinf(margaret_ns_time_sec_diff(start, frame_A0));
|
|
|
|
|
scene.color = (VkClearColorValue){{0.5f, fabsf(ae), .3f, 1.0f}};
|
|
|
|
|
vec3 SS = {ae * ae, 0.5f + 0.5f * ae, 0};
|
|
|
|
|
|
|
|
|
|
float ae = margaret_ns_time_sec_diff(start, frame_A0);
|
|
|
|
|
scene.anim_time = ae;
|
|
|
|
|
scene.color = (VkClearColorValue){{0.5f, fabsf(sinf(ae)), .3f, 1.0f}};
|
|
|
|
|
mat4 projection_matrix = margaret_perspective_projection_fov_mat4((float)wep.width, (float)wep.height,
|
|
|
|
|
my_cam_control_info.fov, 0.01f, 1000);
|
|
|
|
|
mat4 camera_rotation_matrix = margaret_mat3_to_mat4_transposed(my_cam_control_info.cam_basis);
|
|
|
|
|
mat4 camera_translation_matrix = margaret_translation_mat4(vec3_minus(my_cam_control_info.pos));
|
|
|
|
|
mat4 t_mat = mat4_mul_mat4(projection_matrix, mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix));
|
|
|
|
|
// mat4 t_mat = mat4_mul_mat4(camera_rotation_matrix, camera_translation_matrix);
|
|
|
|
|
{
|
|
|
|
|
*(MyUbo *)host_mem_buffer_mem = (MyUbo){ .s = SS };
|
|
|
|
|
*(Pipeline0UBO*)host_mem_buffer_mem = (Pipeline0UBO){.t = t_mat};
|
|
|
|
|
VkCommandBuffer command_buffers[1] = { uniform_transfer_command_buffer };
|
|
|
|
|
VkSemaphore signaling_semaphores[1] = { swfb.in_frame_transfer_complete };
|
|
|
|
|
VkSubmitInfo ubo_copying_cmd_buffer_submit = {
|
|
|
|
|
@ -918,7 +922,7 @@ int main() {
|
|
|
|
|
|
|
|
|
|
reset_and_record_command_buffer_1(rendering_command_buffer_1, render_pass_1, &pipeline_hands_1,
|
|
|
|
|
*VecVkFramebuffer_cat(&swfb.framebuffers, ij),
|
|
|
|
|
swfb.extent, (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}, descriptor_set_for_pipeline_1);
|
|
|
|
|
swfb.extent, (VkExtent2D){.width = MAX_WIN_WIDTH, .height = MAX_WIN_HEIGHT}, &scene, descriptor_set_for_pipeline_1);
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
VkSemaphore waiting_for_semaphores[2] = {
|
|
|
|
|
@ -1025,7 +1029,9 @@ int main() {
|
|
|
|
|
vkDeviceWaitIdle(device);
|
|
|
|
|
// The End
|
|
|
|
|
// dropping scene
|
|
|
|
|
VecOA_ObjectOnScene_drop(scene.oa_objects);
|
|
|
|
|
Scene_drop(scene);
|
|
|
|
|
ModelTopology_drop(cylinder_1);
|
|
|
|
|
ModelTopology_drop(cylinder_2);
|
|
|
|
|
// destroying vulkan objects
|
|
|
|
|
vkDestroyDescriptorPool(device, descriptor_pool, NULL);
|
|
|
|
|
vkDestroySampler(device, my_texture_sampler, NULL);
|
|
|
|
|
|