diff --git a/src/gpu/vulkan/vk_gpu.c b/src/gpu/vulkan/vk_gpu.c index 958270d..cfd1db3 100644 --- a/src/gpu/vulkan/vk_gpu.c +++ b/src/gpu/vulkan/vk_gpu.c @@ -7,9 +7,9 @@ #include "../../window/window_inc.h" #include "../../wapp/wapp.h" #include "../../cglm/struct.h" -#include #define STB_IMAGE_IMPLEMENTATION #include "../../stb_image/stb_image.h" +#include #include #ifdef USE_SDL_WINDOW_BACKEND @@ -315,6 +315,7 @@ wp_intern VkAttachmentStoreOp vkAttachmentStoreOpFromGpuAttachmentStore wp_intern GpuAttachmentStoreOp gpuAttachmentStoreOpFromVkAttachmentStoreOp(VkAttachmentStoreOp op); wp_intern VkResolveModeFlagBits vkResolveModeFlagsFromGpuResolveModeFlags(GpuResolveModeFlags flags); wp_intern GpuResolveModeFlags gpuResolveModeFlagsFromVkResolveModeFlags(VkResolveModeFlags flags); +wp_intern u32 calcMaxMipLevelsForSize(ivec3s size); GpuInstance *gpuInit(const WpAllocator *allocator, GpuInitRequest request) { assertWithLogger(volkInitialize() == VK_SUCCESS, &logger, "Failed to initialise volk"); @@ -869,6 +870,7 @@ GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest req GpuImage *output = wpMemAllocatorAlloc(allocator, sizeof(GpuImage)); assertWithLogger(output != NULL, &logger, "Failed to allocate image"); + u32 mip_levels = min(calcMaxMipLevelsForSize(request.size), request.subresource.level_count); VkFormat format = vkFormatFromGpuFormat(request.format); VkImageCreateInfo image_create_info = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, @@ -877,7 +879,7 @@ GpuImage *gpuCreateImage(const WpAllocator *allocator, GpuImageCreateRequest req .extent = (VkExtent3D){ .width = request.size.x, .height = request.size.y, .depth = request.size.z }, - .mipLevels = request.subresource.level_count, + .mipLevels = mip_levels, .arrayLayers = request.subresource.layer_count, .samples = vkSampleCountFromGpuSampleCount(request.samples), .tiling = vkImageTilingFromGpuImageTiling(request.tiling), @@ -954,8 +956,24 @@ GpuImage *gpuLoadImageFromFile(const WpAllocator *allocator, const WpAllocator * }; GpuImage *output = gpuCreateImage(allocator, img_request); + u64 data_size = width * height * channels * sizeof(u8); + GpuBufferCreateRequest temp_buf_request = { + .device = request.command_pool->device, + .size = data_size, + .usage = GPU_BUFFER_USAGE_TRANSFER_SRC, + }; + GpuBuffer temp_storage = gpuCreateBuffer(allocator, temp_buf_request); + memcpy(temp_storage.cpu_mapping, data, data_size); + stbi_image_free((void *)data); + GpuCommandBufferAllocateRequest cb_request = { + .pool = request.command_pool, + .buffer_count = 1, + }; + GpuCommandBufferPtrArray cbs = gpuAllocateCommandBuffers(allocator, temp, cb_request); + GpuCommandBuffer *cb = cbs[0]; + return output; } @@ -3555,3 +3573,8 @@ wp_intern GpuResolveModeFlags gpuResolveModeFlagsFromVkResolveModeFlags(VkResolv return output; } + +wp_intern u32 calcMaxMipLevelsForSize(ivec3s size) { + f32 max_dim = max(max(size.x, size.y), size.z); + return (u32)(floorf(log2f(max_dim)) + 1.0f); +} diff --git a/src/main.c b/src/main.c index 6e5d31b..b607cdc 100644 --- a/src/main.c +++ b/src/main.c @@ -20,12 +20,16 @@ enum Errors { typedef struct Vertex { vec3s position; vec3s color; + // vec2s uv; } Vertex; typedef Vertex *VertexArray; +typedef vec3s *Vec3sArray; + typedef struct ShaderData { mat4s mvp; } ShaderData; +typedef ShaderData *ShaderDataArray; typedef struct Camera { vec3s position; @@ -43,29 +47,26 @@ typedef struct Projection { wp_intern const VertexArray vertices = wpArray( Vertex, (Vertex){ - .position = (vec3s){ .x = 0.0f, .y = 0.5f, .z = 0.0f }, - .color = (vec3s){ .r = 1.0f, .g = 0.0f, .b = 0.0f }, + .position = (vec3s){ .x = -0.5f, .y = -0.5f, .z = 0.0f }, + .color = (vec3s){ .r = 1.0f, .g = 0.0f, .b = 0.0f }, }, (Vertex){ - .position = (vec3s){ .x = -0.5f, .y = -0.5f, .z = 0.0f }, - .color = (vec3s){ .r = 0.0f, .g = 1.0f, .b = 0.0f }, + .position = (vec3s){ .x = -0.5f, .y = 0.5f, .z = 0.0f }, + .color = (vec3s){ .r = 0.0f, .g = 1.0f, .b = 0.0f }, }, (Vertex){ .position = (vec3s){ .x = 0.5f, .y = -0.5f, .z = 0.0f }, .color = (vec3s){ .r = 0.0f, .g = 0.0f, .b = 1.0f }, }, (Vertex){ - .position = (vec3s){ .x = 0.25f, .y = 0.5f, .z = -1.0f }, - .color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f }, + .position = (vec3s){ .x = 0.5f, .y = 0.5f, .z = 0.0f }, + .color = (vec3s){ .r = 1.0f, .g = 1.0f, .b = 1.0f }, }, - (Vertex){ - .position = (vec3s){ .x = -0.25f, .y = -0.5f, .z = -1.0f }, - .color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f }, - }, - (Vertex){ - .position = (vec3s){ .x = 0.75f, .y = -0.5f, .z = -1.0f }, - .color = (vec3s){ .r = 1.00f, .g = 0.5f, .b = 0.0f }, - } +); +wp_intern const WpU16Array indices = wpArray( + u16, + 0, 1, 2, + 1, 3, 2, ); wp_intern mat4s modelViewProjection(mat4s model, mat4s view, mat4s proj); @@ -129,17 +130,20 @@ i32 main(void) { wpStr8Format(&msg, "Created swapchain %p with %" PRIu64 " images", swapchain, swapchain_image_count); wpLogInfo(&logger, msg); - u64 vertices_size = sizeof(Vertex) * wpArrayCount(vertices); + u64 vertices_size = wpArrayItemSize(vertices) * wpArrayCount(vertices); + u64 indices_size = wpArrayItemSize(indices) * wpArrayCount(indices); GpuBufferCreateRequest vert_idx_buf_request = { .device = device, - .usage = GPU_BUFFER_USAGE_VERTEX_BUFFER, - .size = vertices_size, + .usage = GPU_BUFFER_USAGE_VERTEX_BUFFER | GPU_BUFFER_USAGE_INDEX_BUFFER, + .size = vertices_size + indices_size, }; - GpuBuffer vertex_buffer = gpuCreateBuffer(&arena, vert_idx_buf_request); - memcpy(vertex_buffer.cpu_mapping, vertices, vertices_size); + GpuBuffer vert_idx_buffer = gpuCreateBuffer(&arena, vert_idx_buf_request); + void *idx_buf_start = (void *)((uptr)vert_idx_buffer.cpu_mapping + vertices_size); + memcpy(vert_idx_buffer.cpu_mapping, vertices, vertices_size); + memcpy(idx_buf_start, indices, indices_size); wpStr8Format(&msg, "Created buffer with size %" PRIu64 " (CPU: %p, GPU: %" PRIu64 ")", - vertex_buffer.size, vertex_buffer.cpu_mapping, vertex_buffer.gpu_device_address); + vert_idx_buffer.size, vert_idx_buffer.cpu_mapping, vert_idx_buffer.gpu_device_address); wpLogInfo(&logger, msg); GpuCommandPool *pool = gpuCreateCommandPool(&arena, device); @@ -160,11 +164,11 @@ i32 main(void) { wpFileRead(code, spirv, code_size); - GpuLoadImageFromFileRequest load_img_req = { - .command_pool = pool, - .filename = wpStr8LitRo("assets/collections.png"), - }; - GpuImage *texture = gpuLoadImageFromFile(&arena, &temp_arena, load_img_req); + // GpuLoadImageFromFileRequest load_img_req = { + // .command_pool = pool, + // .filename = wpStr8LitRo("assets/collections.png"), + // }; + // GpuImage *texture = gpuLoadImageFromFile(&arena, &temp_arena, load_img_req); GpuShaderCreateRequest shader_request = { .device = device, @@ -176,10 +180,15 @@ i32 main(void) { wpFileClose(spirv); + Vec3sArray translations = wpArray( + vec3s, + (vec3s){}, + (vec3s){ .x = 1.0f, .z = -1.0f }, + ); + GpuBufferCreateRequest shader_data_req = { .device = device, - .size = sizeof(ShaderData), - .usage = GPU_BUFFER_USAGE_STORAGE_BUFFER | - GPU_BUFFER_USAGE_SHADER_DEVICE_ADDRESS }; + .size = sizeof(ShaderData) * wpArrayCount(translations), + .usage = GPU_BUFFER_USAGE_STORAGE_BUFFER }; GpuBuffer shader_data = gpuCreateBuffer(&arena, shader_data_req); Camera camera = { @@ -193,22 +202,76 @@ i32 main(void) { .near = 0.1f, .far = 100.0f, }; - ShaderData data = { - .mvp = modelViewProjection( - glms_mat4_identity(), - glms_lookat(camera.position, camera.target, camera.up), - glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + + ShaderDataArray data = wpArray( + ShaderData, + (ShaderData){ + .mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[0]), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ), + }, + (ShaderData){ + .mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[1]), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ), + }, + ); + memcpy(shader_data.cpu_mapping, &data, wpArrayItemSize(data) * wpArrayCount(data)); + + GpuDescriptorPoolSizeArray pool_sizes = wpArray( + GpuDescriptorPoolSize, + (GpuDescriptorPoolSize){ .type = GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER, .count = wpArrayCount(data) } + ); + GpuDescriptorPoolCreateRequest desc_pool_req = { + .descriptor_pool_sizes = pool_sizes, + .device = device, + .max_sets = 20, + }; + GpuDescriptorPool *desc_pool = gpuCreateDescriptorPool(&arena, desc_pool_req); + + GpuDescriptorSetBindingArray bindings = wpArray( + GpuDescriptorSetBinding, + (GpuDescriptorSetBinding){ + .binding = 0, + .type = GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .descriptor_count = wpArrayCount(data), + .stages = GPU_SHADER_STAGE_VERTEX, + } + ); + GpuDescriptorSetLayoutCreateRequest desc_set_layout_req = { + .device = device, + .bindings = bindings, + }; + GpuDescriptorSetLayout *desc_set_layout = gpuCreateDescriptorSetLayout(&arena, &temp_arena, desc_set_layout_req); + + GpuDescriptorSetAllocateRequest desc_sets_req = { + .pool = desc_pool, + .layouts = wpArray(GpuDescriptorSetLayout *, desc_set_layout), + }; + GpuDescriptorSetPtrArray descriptor_sets = gpuAllocateDescriptorSets(&arena, &temp_arena, desc_sets_req); + + GpuDescriptorSetWriteInfo shader_data_write_info = { + .set = descriptor_sets[0], + .descriptor_type = GPU_DESCRIPTOR_TYPE_STORAGE_BUFFER, + .buffer_infos = wpArray( + GpuDescriptorBufferInfo, + (GpuDescriptorBufferInfo){ .buffer = &shader_data, .range = sizeof(ShaderData) }, + (GpuDescriptorBufferInfo){ .buffer = &shader_data, .offset = sizeof(ShaderData), .range = sizeof(ShaderData) }, ), }; - memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); - - GpuPushConstantRange push_constants = { - .stages = GPU_SHADER_STAGE_VERTEX, - .size = sizeof(shader_data.gpu_device_address), + GpuDescriptorSetWriteRequest desc_set_req = { + .device = device, + .write_infos = wpArray(GpuDescriptorSetWriteInfo, shader_data_write_info), }; + gpuWriteDescriptorSets(&temp_arena, desc_set_req); + GpuPipelineLayoutCreateRequest graphics_pipeline_layout_request = { - .device = device, - .push_constants = wpArray(GpuPushConstantRange, push_constants), + .device = device, + .descriptor_set_layouts = wpArray(GpuDescriptorSetLayout *, desc_set_layout), }; GpuPipelineLayout *layout = gpuCreatePipelineLayout(&arena, &temp_arena, graphics_pipeline_layout_request); @@ -231,6 +294,12 @@ i32 main(void) { .offset = offsetof(Vertex, color), .format = GPU_FORMAT_R32G32B32_SFLOAT, }, + // (GpuVertexInputAttribute){ + // .location = 2, + // .binding = 0, + // .offset = offsetof(Vertex, uv), + // .format = GPU_FORMAT_R32G32_SFLOAT, + // }, ); GpuPipelineVertexInputStateInfo vert_info = { .bindings = wpArray(GpuVertexInputBinding, vert_binding), @@ -387,15 +456,6 @@ i32 main(void) { }; gpuCmdBeginRendering(&temp_arena, render_request); - GpuCmdPushConstantsRequest push_const_req = { - .command_buffer = buffers[0], - .layout = layout, - .stage_flags = GPU_SHADER_STAGE_VERTEX, - .values = &shader_data.gpu_device_address, - .total_size_in_bytes = sizeof(shader_data.gpu_device_address), - }; - gpuCmdPushConstants(push_const_req); - GpuViewportArray viewports = wpArray( GpuViewport, (GpuViewport){ .x = 0, .y = 0, @@ -416,18 +476,34 @@ i32 main(void) { GpuCmdBindVertexBuffersRequest vert_bind_req = { .command_buffer = buffers[0], - .vertex_buffers = wpArray(GpuBuffer, vertex_buffer), + .vertex_buffers = wpArray(GpuBuffer, vert_idx_buffer), .offsets = wpArray(u64, 0), }; gpuCmdBindVertexBuffers(&temp_arena, vert_bind_req); + GpuCmdBindIndexBufferRequest idx_bind_req = { + .index_buffer = vert_idx_buffer, + .command_buffer = buffers[0], + .offset = vertices_size, + .index_type = GPU_INDEX_TYPE_UINT16, + }; + gpuCmdBindIndexBuffer(idx_bind_req); + + GpuCmdBindDescriptorSetsRequest bind_desc_sets_req = { + .command_buffer = buffers[0], + .layout = layout, + .sets = descriptor_sets, + .bind_point = GPU_PIPELINE_BIND_POINT_GRAPHICS, + }; + gpuCmdBindDescriptorSets(&temp_arena, bind_desc_sets_req); + gpuCmdBindPipeline((GpuCmdBindPipelineRequest){ .command_buffer = buffers[0], .bind_point = GPU_PIPELINE_BIND_POINT_GRAPHICS, .pipeline = pipelines[0] }); - gpuCmdDraw((GpuCmdDrawRequest){ .command_buffer = buffers[0], - .vertex_count = wpArrayCount(vertices), - .instance_count = 1 }); + gpuCmdDrawIndexed((GpuCmdDrawIndexedRequest){ .command_buffer = buffers[0], + .instance_count = wpArrayCount(translations), + .index_count = wpArrayCount(indices) }); gpuCmdEndRendering(buffers[0]); @@ -473,41 +549,61 @@ i32 main(void) { if (windowIsKeyPressed(KEYBOARD_KEY_UP)) { camera.position.z -= 0.01f; - data.mvp = modelViewProjection( - glms_mat4_identity(), + data[0].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[0]), glms_lookat(camera.position, camera.target, camera.up), glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) ); - memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + data[1].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[1]), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, wpArrayItemSize(data) * wpArrayCount(data)); } if (windowIsKeyPressed(KEYBOARD_KEY_DOWN)) { camera.position.z += 0.01f; - data.mvp = modelViewProjection( - glms_mat4_identity(), + data[0].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[0]), glms_lookat(camera.position, camera.target, camera.up), glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) ); - memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + data[1].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[1]), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, wpArrayItemSize(data) * wpArrayCount(data)); } if (windowIsKeyPressed(KEYBOARD_KEY_RIGHT)) { camera.position.x += 0.01f; camera.target.x += 0.01f; - data.mvp = modelViewProjection( - glms_mat4_identity(), + data[0].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[0]), glms_lookat(camera.position, camera.target, camera.up), glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) ); - memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + data[1].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[1]), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, wpArrayItemSize(data) * wpArrayCount(data)); } if (windowIsKeyPressed(KEYBOARD_KEY_LEFT)) { camera.position.x -= 0.01f; camera.target.x -= 0.01f; - data.mvp = modelViewProjection( - glms_mat4_identity(), + data[0].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[0]), glms_lookat(camera.position, camera.target, camera.up), glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) ); - memcpy(shader_data.cpu_mapping, &data, sizeof(ShaderData)); + data[1].mvp = modelViewProjection( + glms_translate(glms_mat4_identity(), translations[1]), + glms_lookat(camera.position, camera.target, camera.up), + glms_perspective(glm_rad(projection.fov_deg), projection.aspect, projection.near, projection.far) + ); + memcpy(shader_data.cpu_mapping, &data, wpArrayItemSize(data) * wpArrayCount(data)); } } @@ -521,11 +617,13 @@ i32 main(void) { gpuDestroyPipeline(pipelines[i]); } gpuDestroyPipelineLayout(layout); + gpuDestroyDescriptorSetLayout(desc_set_layout); + gpuDestroyDescriptorPool(desc_pool); gpuDestroyBuffer(&shader_data); gpuDestroyShader(shader); - gpuDestroyImage(texture); + // gpuDestroyImage(texture); gpuDestroyCommandPool(pool); - gpuDestroyBuffer(&vertex_buffer); + gpuDestroyBuffer(&vert_idx_buffer); gpuDestroySwapchain(swapchain); gpuDestroySurface(surface); gpuDestroyDevice(device); diff --git a/src/shaders/shader.slang b/src/shaders/shader.slang index 2913fea..3481d5b 100644 --- a/src/shaders/shader.slang +++ b/src/shaders/shader.slang @@ -1,11 +1,13 @@ struct VSInput { float3 Pos; float3 Color; + // float2 Uv; }; struct ShaderData { float4x4 mvp; }; +StructuredBuffer data; struct VertexOutput { float3 Color; @@ -13,10 +15,10 @@ struct VertexOutput { }; [shader("vertex")] -VertexOutput vertMain(VSInput input, uniform ShaderData *data, uint vid : SV_VertexID) { +VertexOutput vertMain(VSInput input, uint idx: SV_InstanceID) { VertexOutput output; output.Color = input.Color; - output.sv_position = mul(data->mvp, float4(input.Pos, 1.0)); + output.sv_position = mul(data[idx].mvp, float4(input.Pos, 1.0)); return output; }