diff --git a/Makefile b/Makefile index 8792730..e4a2443 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,8 @@ OBJECTS = $(addsuffix .o, $(basename $(SOURCES))) VERT_SPV = $(addsuffix .vert.spv, $(basename $(wildcard shader_src/*.vert))) FRAG_SPV = $(addsuffix .frag.spv, $(basename $(wildcard shader_src/*.frag))) +export MVK_CONFIG_USE_METAL_ARGUMENT_BUFFERS=1 + .PHONY: all all: spacegame $(VERT_SPV) $(FRAG_SPV) diff --git a/shader_src/basic.vert b/shader_src/basic.vert index b9c5726..3ebfb31 100644 --- a/shader_src/basic.vert +++ b/shader_src/basic.vert @@ -1,12 +1,9 @@ #version 450 #extension GL_EXT_buffer_reference : require -struct Object { - mat4 model; -}; layout(buffer_reference, buffer_reference_align = 16) buffer ObjectBuffer { - Object objects[]; + mat4 model[]; }; layout( push_constant ) uniform constants { @@ -25,6 +22,6 @@ layout(location = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; void main() { - gl_Position = scene.proj * scene.view * scene.objects.objects[0].model * vec4(inPosition, 1.0); + gl_Position = scene.proj * scene.view * scene.objects.model[0] * vec4(inPosition, 1.0); fragColor = inColor; } diff --git a/shader_src/texture.frag b/shader_src/texture.frag index 3ce44fd..43b4014 100644 --- a/shader_src/texture.frag +++ b/shader_src/texture.frag @@ -4,7 +4,8 @@ layout(location = 0) in vec3 fragColor; layout(location = 1) in vec2 fragTex; layout(location = 0) out vec4 outColor; +layout(set = 1, binding = 0) uniform sampler2D texSampler; void main() { - outColor = vec4(fragTex, 1.0, 1.0); + outColor = texture(texSampler, fragTex); } diff --git a/shader_src/texture.vert b/shader_src/texture.vert index af59d35..2d6cba1 100644 --- a/shader_src/texture.vert +++ b/shader_src/texture.vert @@ -1,9 +1,15 @@ #version 450 +#extension GL_EXT_buffer_reference : require + +layout(buffer_reference, buffer_reference_align = 16) buffer ObjectBuffer { + mat4 model[]; +}; layout( push_constant ) uniform constants { mat4 view; mat4 proj; -} scene_pc; + ObjectBuffer objects; +} scene; layout(set = 0, binding = 0) uniform SceneUniformBuffer { mat4 test; @@ -17,7 +23,7 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTex; void main() { - gl_Position = scene_pc.proj * scene_pc.view * vec4(inPosition, 1.0); + gl_Position = scene.proj * scene.view * scene.objects.model[1] * vec4(inPosition, 1.0); fragColor = inColor; fragTex = inTex; } diff --git a/src/main.c b/src/main.c index f7a2f51..e779fab 100644 --- a/src/main.c +++ b/src/main.c @@ -109,8 +109,7 @@ typedef struct MeshStruct { typedef struct GraphicsPipelineInfoStruct { VkDescriptorSetLayout scene_layout; - VkDescriptorSetLayoutBinding* descriptor_bindings; - uint32_t descriptor_bindings_count; + VkDescriptorSetLayoutCreateInfo descriptor_info; uint32_t input_bindings_count; VkVertexInputBindingDescription* input_bindings; @@ -426,6 +425,7 @@ VkResult get_best_physical_device(VkInstance instance, VkPhysicalDevice* device) VkPhysicalDeviceProperties properties; vkGetPhysicalDeviceProperties(devices[i], &properties); + fprintf(stderr, "%d\n", properties.limits.maxPerStageResources); VkPhysicalDeviceFeatures features; vkGetPhysicalDeviceFeatures(devices[i], &features); @@ -580,7 +580,7 @@ VkResult create_instance(VkInstance* instance) { VkResult result = vkCreateInstance(&instance_info, 0, instance); if(result != VK_SUCCESS) { - fprintf(stderr, "vkCreateInstance: 0x%02x\n", result); + fprintf(stderr, "vkCreateInstance: %s\n", string_VkResult(result)); return result; } @@ -635,6 +635,7 @@ VkResult create_logical_device(VkPhysicalDevice physical_device, QueueIndices qu .descriptorBindingVariableDescriptorCount = VK_TRUE, .descriptorBindingUniformBufferUpdateAfterBind = VK_TRUE, .descriptorBindingStorageBufferUpdateAfterBind = VK_TRUE, + .descriptorBindingSampledImageUpdateAfterBind = VK_TRUE, }; VkPhysicalDeviceFeatures device_features = { @@ -1586,34 +1587,28 @@ VkResult create_graphics_pipeline( out->max_frames_in_flight = max_frames_in_flight; - VkDescriptorSetLayoutCreateInfo descriptor_layout_info = { - .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, - .bindingCount = pipeline_info.descriptor_bindings_count, - .pBindings = pipeline_info.descriptor_bindings, - }; - - VkResult result = vkCreateDescriptorSetLayout(device, &descriptor_layout_info, 0, &out->descriptors_layout); + VkResult result = vkCreateDescriptorSetLayout(device, &pipeline_info.descriptor_info, 0, &out->descriptors_layout); if(result != VK_SUCCESS) { return result; } - if(pipeline_info.descriptor_bindings_count > 0) { - VkDescriptorPoolSize* pool_sizes = malloc(sizeof(VkDescriptorPool)*(1 + pipeline_info.descriptor_bindings_count)); + if(pipeline_info.descriptor_info.bindingCount > 0) { + VkDescriptorPoolSize* pool_sizes = malloc(sizeof(VkDescriptorPool)*(1 + pipeline_info.descriptor_info.bindingCount)); if(pool_sizes == 0) { return VK_ERROR_OUT_OF_HOST_MEMORY; } - for(uint32_t i = 0; i < pipeline_info.descriptor_bindings_count; i++) { + for(uint32_t i = 0; i < pipeline_info.descriptor_info.bindingCount; i++) { VkDescriptorPoolSize pool_size = { - .type = pipeline_info.descriptor_bindings[i].descriptorType, - .descriptorCount = pipeline_info.descriptor_bindings[i].descriptorCount*max_frames_in_flight, + .type = pipeline_info.descriptor_info.pBindings[i].descriptorType, + .descriptorCount = pipeline_info.descriptor_info.pBindings[i].descriptorCount*max_frames_in_flight, }; pool_sizes[i] = pool_size; } VkDescriptorPoolCreateInfo pool_info = { .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, - .poolSizeCount = pipeline_info.descriptor_bindings_count, + .poolSizeCount = pipeline_info.descriptor_info.bindingCount, .maxSets = max_frames_in_flight, .pPoolSizes = pool_sizes, .flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT, @@ -1816,7 +1811,7 @@ VkResult create_graphics_pipeline( return VK_SUCCESS; } -VkResult create_simple_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryProperties memories, 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, VkDescriptorSetLayout scene_layout, uint32_t max_frames_in_flight, GraphicsPipeline* out) { if(out == NULL) { return VK_ERROR_VALIDATION_FAILED_EXT; } @@ -1861,7 +1856,7 @@ VkResult create_simple_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryProp }, }; - VkDescriptorSetLayoutBinding descriptor_bindings[] = { + VkDescriptorSetLayoutBinding set_bindings[] = { { .binding = 0, .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, @@ -1871,9 +1866,15 @@ VkResult create_simple_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryProp }, }; + VkDescriptorSetLayoutCreateInfo set_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pBindings = set_bindings, + .bindingCount = sizeof(set_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .pNext = NULL, + }; + GraphicsPipelineInfo pipeline_info = { - .descriptor_bindings_count = sizeof(descriptor_bindings)/sizeof(VkDescriptorSetLayoutBinding), - .descriptor_bindings = descriptor_bindings, + .descriptor_info = set_info, .shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), .shader_stages = shader_stages, .scene_layout = scene_layout, @@ -1883,16 +1884,10 @@ VkResult create_simple_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryProp .input_attributes_count = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), }; - GPUPage* memory = NULL; - VkResult result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, &memory); - if(result != VK_SUCCESS) { - return result; - } - return create_graphics_pipeline(device, extent, 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, GraphicsPipeline* 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) { if(out == NULL) { return VK_ERROR_VALIDATION_FAILED_EXT; } @@ -1945,18 +1940,36 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro }; // TODO: use bindless descriptors for textures, so each draw command will bind a large buffer that is indexed by object ID to get the address of the texture in GPU memory - VkDescriptorSetLayoutBinding mesh_set_bindings[] = { + VkDescriptorSetLayoutBinding set_bindings[] = { { .binding = 0, - .descriptorCount = 1, + .descriptorCount = 1000, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .pImmutableSamplers = 0, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, }, }; - (void)mesh_set_bindings; + + VkDescriptorBindingFlags set_binding_flags[] = { + VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT | VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT, + }; + + VkDescriptorSetLayoutBindingFlagsCreateInfo set_flags_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO, + .bindingCount = sizeof(set_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .pBindingFlags = set_binding_flags, + }; + + VkDescriptorSetLayoutCreateInfo set_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO, + .pBindings = set_bindings, + .bindingCount = sizeof(set_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT, + .pNext = &set_flags_info, + }; GraphicsPipelineInfo pipeline_info = { + .descriptor_info = set_info, .shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), .shader_stages = shader_stages, .scene_layout = scene_layout, @@ -1972,7 +1985,92 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro return result; } - return create_graphics_pipeline(device, extent, render_pass, pipeline_info, max_frames_in_flight, out); + result = create_graphics_pipeline(device, extent, render_pass, pipeline_info, max_frames_in_flight, out); + if(result != VK_SUCCESS) { + return result; + } + + GPUPage* tex_memory = NULL; + result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, &tex_memory); + if(result != VK_SUCCESS) { + return result; + } + + VkExtent2D texture_size = { + .width = 10, + .height = 10, + }; + (void)texture_size; + + struct __attribute__((__packed__)) texel { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + }; + + struct texel WHT = {255, 255, 255, 255}; + struct texel BLK = {0, 0, 0, 255}; + struct texel RED = {255, 0, 0, 255}; + struct texel GRN = {0, 255, 0, 255}; + struct texel BLU = {0, 0, 255, 255}; + + struct texel texture_data[100] = { + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, + RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, + }; + (void)texture_data; + + GPUPage* texture_memory = NULL; + result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, 0, &texture_memory); + if(result != VK_SUCCESS) { + return result; + } + + GPUPage* staging_memory = NULL; + result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, &staging_memory); + if(result != VK_SUCCESS) { + return result; + } + + GPUBuffer staging = {0}; + result = gpu_buffer_malloc(device, staging_memory, 100000, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, &staging); + if(result != VK_SUCCESS) { + return result; + } + + Texture test_texture = load_texture(device, texture_memory, staging, transfer_pool, transfer_queue, graphics_pool, graphics_queue, texture_size, VK_FORMAT_R8G8B8A8_SRGB, texture_data, transfer_family, graphics_family); + + for(uint32_t i = 0; i < out->max_frames_in_flight; i++) { + VkDescriptorImageInfo image_info = { + .sampler = test_texture.sampler, + .imageView = test_texture.view, + .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + }; + + VkWriteDescriptorSet descriptor_write = { + .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, + .dstSet = out->descriptors[i], + .dstBinding = 0, + .dstArrayElement = 0, + .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, + .descriptorCount = 1, + .pBufferInfo = 0, + .pImageInfo = &image_info, + .pTexelBufferView = 0, + }; + + vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0); + } + return VK_SUCCESS; } VkResult command_copy_to_buffer(VkDevice device, GPUBuffer staging, VkBuffer destination, void* data, VkDeviceSize size, VkDeviceSize offset, VkCommandPool pool, VkQueue queue) { @@ -2809,64 +2907,6 @@ Object create_texture_mesh_object(GraphicsPipeline* texture_mesh_pipeline, VkPhy return zero; } - VkExtent2D texture_size = { - .width = 10, - .height = 10, - }; - (void)texture_size; - - struct __attribute__((__packed__)) texel { - uint8_t r; - uint8_t g; - uint8_t b; - uint8_t a; - }; - - struct texel WHT = {255, 255, 255, 255}; - struct texel BLK = {0, 0, 0, 255}; - struct texel RED = {255, 0, 0, 255}; - struct texel GRN = {0, 255, 0, 255}; - struct texel BLU = {0, 0, 255, 255}; - - struct texel texture_data[100] = { - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, WHT, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, - RED, WHT, GRN, WHT, BLU, WHT, RED, WHT, GRN, BLK, - }; - (void)texture_data; - - /* - Texture test_texture = load_texture(device, mesh_memory, transfer_buffer, transfer_pool, transfer_queue, graphics_pool, graphics_queue, texture_size, VK_FORMAT_R8G8B8A8_SRGB, texture_data, transfer_family, graphics_family); - - for(uint32_t i = 0; i < max_frames_in_flight; i++) { - VkDescriptorImageInfo image_info = { - .sampler = test_texture.sampler, - .imageView = test_texture.view, - .imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - }; - - VkWriteDescriptorSet descriptor_write = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = sets[i], - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, - .descriptorCount = 1, - .pBufferInfo = 0, - .pImageInfo = &image_info, - .pTexelBufferView = 0, - }; - - vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0); - }*/ // TODO: bindless textures - return object; } @@ -2878,7 +2918,7 @@ void main_loop(PlyMesh ply_mesh, GLFWwindow* window, VulkanContext* context) { GraphicsPipeline simple_mesh_pipeline = {0}; GraphicsPipeline texture_mesh_pipeline = {0}; - VkResult result = create_simple_mesh_pipeline(context->device, context->memories, 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, scene.descriptor_layout, context->max_frames_in_flight, &simple_mesh_pipeline); if(result != VK_SUCCESS) { fprintf(stderr, "failed to create simple mesh material: %s\n", string_VkResult(result)); return; @@ -2890,7 +2930,7 @@ void main_loop(PlyMesh ply_mesh, GLFWwindow* window, VulkanContext* context) { return; } - result = create_texture_mesh_pipeline(context->device, context->memories, context->swapchain_extent, context->render_pass, scene.descriptor_layout, context->max_frames_in_flight, &texture_mesh_pipeline); + 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); if(result != VK_SUCCESS) { fprintf(stderr, "failed to create texture mesh material\n"); return; @@ -2918,10 +2958,12 @@ void main_loop(PlyMesh ply_mesh, GLFWwindow* window, VulkanContext* context) { return; } - mat4* tmp = memory->ptr + buffer.memory->offset; - glm_mat4_identity(*tmp); - vec3 scale = {2.0f, 2.0f, 2.0f}; - glm_scale(*tmp, scale); + mat4* model_1 = memory->ptr + buffer.memory->offset; + mat4* model_2 = memory->ptr + buffer.memory->offset + sizeof(mat4); + glm_mat4_identity(*model_1); + glm_translate_x(*model_1, 1.0f); + glm_mat4_identity(*model_2); + glm_translate_x(*model_2, -1.0f); VkBufferDeviceAddressInfo addr_info = { .sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO,