From f7f5d4b3a4c03f2a4ba01926cb1fe9a74276a17f Mon Sep 17 00:00:00 2001 From: Greg Wells Date: Tue, 1 Jul 2025 12:19:26 -0400 Subject: [PATCH] uniform buffer rebinding --- .../src/commands/commands/metal_commands.m | 14 ++++-- .../metal_graphics_pipeline.h | 2 +- .../metal_graphics_pipeline.m | 1 + .../src/shader_module/metal_shader_module.h | 1 + .../src/shader_module/metal_shader_module.m | 44 ++++++++++++++----- 5 files changed, 46 insertions(+), 16 deletions(-) diff --git a/projects/apis/metal/src/commands/commands/metal_commands.m b/projects/apis/metal/src/commands/commands/metal_commands.m index 199a640..556ee1a 100644 --- a/projects/apis/metal/src/commands/commands/metal_commands.m +++ b/projects/apis/metal/src/commands/commands/metal_commands.m @@ -115,10 +115,16 @@ void metalBindUniform(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t if (uniform->uniform->bindings[i].type == GN_UNIFORM_BUFFER_DESCRIPTOR) { gnBufferUniformInfo info = *(gnBufferUniformInfo*)uniform->uniform->bindings[i].data; - [encoder setVertexBuffer:info.buffer->buffer->buffer - offset:info.offset - atIndex:(info.binding + 1) - ]; + for (int c = 0; c < buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->vertexShaderMaps.uniformBufferMaps.count; c++) { + metalBindingMap map = buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->vertexShaderMaps.uniformBufferMaps.data[c]; + if (map.set == set && map.binding == uniform->uniform->bindings[i].binding) { + [encoder setVertexBuffer:info.buffer->buffer->buffer + offset:info.offset + atIndex:1 + ]; + break; + } + } } else if (uniform->uniform->bindings[i].type == GN_IMAGE_DESCRIPTOR) { for (int c = 0; c < buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->fragmentShaderMaps.textureMaps.count; c++) { metalBindingMap map = buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->fragmentShaderMaps.textureMaps.data[c]; diff --git a/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.h b/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.h index 589f863..b0aad98 100644 --- a/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.h +++ b/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.h @@ -5,7 +5,7 @@ typedef struct gnPlatformGraphicsPipeline_t { id graphicsPipeline; - metalBindingMaps fragmentShaderMaps; + metalBindingMaps vertexShaderMaps, fragmentShaderMaps; } gnPlatformGraphicsPipeline; gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info); diff --git a/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m b/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m index 356f895..e6d8f35 100644 --- a/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m +++ b/projects/apis/metal/src/pipelines/graphics_pipeline/metal_graphics_pipeline.m @@ -62,6 +62,7 @@ gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gn for (int i = 0; i < info.shaderModuleCount; i++) { if (info.shaderModules[i]->info.stage == GN_VERTEX_SHADER_MODULE) { [descriptor setVertexFunction:info.shaderModules[i]->shaderModule->function]; + graphicsPipeline->graphicsPipeline->vertexShaderMaps = info.shaderModules[i]->shaderModule->maps; } else if (info.shaderModules[i]->info.stage == GN_FRAGMENT_SHADER_MODULE) { [descriptor setFragmentFunction:info.shaderModules[i]->shaderModule->function]; graphicsPipeline->graphicsPipeline->fragmentShaderMaps = info.shaderModules[i]->shaderModule->maps; diff --git a/projects/apis/metal/src/shader_module/metal_shader_module.h b/projects/apis/metal/src/shader_module/metal_shader_module.h index f4e9181..410c3b1 100644 --- a/projects/apis/metal/src/shader_module/metal_shader_module.h +++ b/projects/apis/metal/src/shader_module/metal_shader_module.h @@ -11,6 +11,7 @@ typedef struct metalBindingMap { GN_ARRAY_LIST(metalBindingMap); typedef struct metalBindingMaps { + metalBindingMapArrayList uniformBufferMaps; metalBindingMapArrayList textureMaps; } metalBindingMaps; diff --git a/projects/apis/metal/src/shader_module/metal_shader_module.m b/projects/apis/metal/src/shader_module/metal_shader_module.m index 00a3875..3ece068 100644 --- a/projects/apis/metal/src/shader_module/metal_shader_module.m +++ b/projects/apis/metal/src/shader_module/metal_shader_module.m @@ -35,6 +35,35 @@ metalBindingMapArrayList loadTextureBindingInformation(spvc_resources resources, return bindings; } +metalBindingMapArrayList loadUniformBufferInformation(spvc_resources resources, spvc_compiler compiler, gnShaderModuleStage stage) { + metalBindingMapArrayList bindings = metalBindingMapArrayListCreate(); + + const spvc_reflected_resource *list = NULL; + size_t count; + + spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count); + + for (int i = 0; i < count; i++){ + uint32_t set = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationDescriptorSet), + binding = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationBinding); + + uint32_t realBinding = binding; + + // if ((stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) + realBinding += 1; + + metalBindingMap map = { + .set = set, .binding = binding, + .metalBindingIndex = realBinding + }; + metalBindingMapArrayListAdd(&bindings, map); + + spvc_compiler_unset_decoration(compiler, list[i].id, SpvDecorationBinding); + spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, realBinding); + } + return bindings; +} + gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo) { module->shaderModule = malloc(sizeof(struct gnPlatformShaderModule_t)); @@ -53,23 +82,13 @@ gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnS spvc_context_create_compiler(context, SPVC_BACKEND_MSL, ir, SPVC_CAPTURE_MODE_COPY, &compiler); spvc_compiler_create_shader_resources(compiler, &resources); - spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count); - - for (int i = 0; i < count; i++){ - uint32_t set = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationDescriptorSet), - binding = spvc_compiler_get_decoration(compiler, list[i].id, SpvDecorationBinding); - - if ((shaderModuleInfo.stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) - binding += 1; - spvc_compiler_unset_decoration(compiler, list[i].id, SpvDecorationBinding); - spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, binding); - } spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_PUSH_CONSTANT, &list, &count); for (int i = 0; i < count; i++) { // TODO: get the buffer index } + module->shaderModule->maps.uniformBufferMaps = loadUniformBufferInformation(resources, compiler, shaderModuleInfo.stage); module->shaderModule->maps.textureMaps = loadTextureBindingInformation(resources, compiler); spvc_compiler_create_compiler_options(compiler, &options); @@ -116,6 +135,9 @@ gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnS return GN_FAILED_TO_FIND_ENTRY_POINT; } + printf("%s", result); + + NSString* functionName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding]; module->shaderModule->function = [shaderLib newFunctionWithName:functionName];