From 1f85aa30bd68477eaa58f49226d040971ca2d60e Mon Sep 17 00:00:00 2001 From: Gregory Wells Date: Mon, 21 Jul 2025 13:27:40 -0400 Subject: [PATCH] finish redoing metal shader workflow --- .../src/commands/commands/metal_commands.m | 4 +- .../metal_graphics_pipeline.h | 1 - .../metal_graphics_pipeline.m | 41 +++++-- .../src/shader_module/metal_shader_compiler.h | 70 +++++++---- .../shader_module/metal_shader_compiler.mm | 112 +++++++++--------- .../src/shader_module/metal_shader_module.h | 13 +- .../src/shader_module/metal_shader_module.m | 56 +++------ .../apis/metal/src/uniforms/metal_uniform.h | 6 +- .../apis/metal/src/uniforms/metal_uniform.m | 78 +++++------- .../metal/src/uniforms/metal_uniform_pool.m | 83 +++++++------ .../src/shader_module/gryphn_shader_module.h | 6 +- 11 files changed, 242 insertions(+), 228 deletions(-) diff --git a/projects/apis/metal/src/commands/commands/metal_commands.m b/projects/apis/metal/src/commands/commands/metal_commands.m index 174f127..38ea3c8 100644 --- a/projects/apis/metal/src/commands/commands/metal_commands.m +++ b/projects/apis/metal/src/commands/commands/metal_commands.m @@ -117,8 +117,8 @@ void metalBindUniform(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t [encoder useResources:uniform->uniform->usedResources count:uniform->uniform->usedResourceCount usage:MTLResourceUsageRead stages:MTLRenderStageVertex | MTLRenderStageFragment]; - [encoder setVertexBuffer:uniform->uniform->argumentBuffer offset:0 atIndex:(set + 1)]; - [encoder setFragmentBuffer:uniform->uniform->argumentBuffer offset:0 atIndex:(set + 1)]; + [encoder setVertexBuffer:uniform->uniform->argumentBuffers[mtlVertex] offset:0 atIndex:(set + 1)]; + [encoder setFragmentBuffer:uniform->uniform->argumentBuffers[mtlFragment] offset:0 atIndex:(set + 1)]; } void metalBindVertexBytes(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data) { 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 62bff05..8ce9935 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 @@ -6,7 +6,6 @@ typedef struct gnPlatformGraphicsPipeline_t { id graphicsPipeline; id depthState; - mtlShaderMap 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 417ecc5..9f3905a 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 @@ -71,15 +71,40 @@ 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->shaderMap; - } 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->shaderMap; - } else { - return GN_UNSUPPORTED_SHADER_MODULE; + const char* shaderCode = mtlCompilerShader(info.shaderModules[i]->shaderModule->compiler, &info.uniformLayout); + printf("shader code: %s\n", shaderCode); + + NSError* error = nil; + MTLCompileOptions* mtloptions = nil; + NSString* sourceCode = [NSString stringWithCString:shaderCode encoding:NSUTF8StringEncoding]; + id shaderLib = [device->outputDevice->device newLibraryWithSource:sourceCode options:mtloptions error:&error]; + if (!shaderLib) { + const char* errorString = error.localizedDescription.UTF8String; + gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){ + .message = gnCombineStrings(gnCreateString("Failed to compile metal library "), errorString) + }); + [shaderLib release]; + free((void*)shaderCode); + return GN_FAILED_TO_CREATE_SHADER_MODULE; } + + + const char* name = info.shaderModules[i]->info.entryPoint.value; + if (strcmp(name, "main") == 0) name = "main0"; + + gnBool foundFunction = false; + for (int i = 0; i < shaderLib.functionNames.count; i++) { + if (strcmp([shaderLib.functionNames objectAtIndex:0].UTF8String, name) == 0) { + foundFunction = true; + break; + } + } + if (!foundFunction) return GN_FAILED_TO_FIND_ENTRY_POINT; + + NSString* functionName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding]; + id function = [shaderLib newFunctionWithName:functionName]; + if (info.shaderModules[i]->info.stage == GN_VERTEX_SHADER_MODULE) [descriptor setVertexFunction:function]; + if (info.shaderModules[i]->info.stage == GN_FRAGMENT_SHADER_MODULE) [descriptor setFragmentFunction:function]; } MTLVertexDescriptor* vertexDescriptor = [[MTLVertexDescriptor alloc] init]; diff --git a/projects/apis/metal/src/shader_module/metal_shader_compiler.h b/projects/apis/metal/src/shader_module/metal_shader_compiler.h index d713499..f1f2869 100644 --- a/projects/apis/metal/src/shader_module/metal_shader_compiler.h +++ b/projects/apis/metal/src/shader_module/metal_shader_compiler.h @@ -2,40 +2,62 @@ #include "stdint.h" #include "stdlib.h" #include "utils/gryphn_bool.h" +#include + +#ifdef __cplusplus +#define GN_CPP_FUNCTION extern "C" +#else +#define GN_CPP_FUNCTION +#endif #define MAX_METAL_SETS 32 #define MAX_METAL_BINDINGS 16 +typedef struct mtlCompiler_t* mtlCompiler; + typedef enum mtlShaderModuleStage { - vertex, fragment + mtlVertex, mtlFragment, mtlMaxStage } mtlShaderModuleStage; -typedef struct mtlShaderOptions { - gnBool useArgumentBuffers; - mtlShaderModuleStage stage; +typedef struct mtlCompilerInfo { + uint32_t* code; + int wordCount; const char* entryPoint; -} mtlShaderOptions; + mtlShaderModuleStage stage; -typedef struct mtlBinding { - uint32_t spvBinding; - uint32_t metalID; -} mtlBinding; + int mslMajorVersion, minorVersion; + gnBool useArgumentBuffers; +} mtlCompilerInfo; -typedef struct mtlSetMap { - uint32_t setIndex, mtlSetIndex; - mtlBinding bindings[MAX_METAL_BINDINGS]; -} mtlSetMap; +GN_CPP_FUNCTION mtlCompiler mtlCreateCompiler(mtlCompilerInfo* info); +GN_CPP_FUNCTION const char* mtlCompilerShader(mtlCompiler compiler, gnUniformLayout* uniformLayout); -typedef struct mtlShaderMap { - mtlSetMap sets[MAX_METAL_SETS]; -} mtlShaderMap; +// typedef struct mtlShaderOptions { +// gnBool useArgumentBuffers; +// mtlShaderModuleStage stage; +// const char* entryPoint; +// } mtlShaderOptions; -typedef struct mtlShader { - const char* code; - mtlShaderMap map; -} mtlShader; +// typedef struct mtlBinding { +// uint32_t spvBinding; +// uint32_t metalID; +// } mtlBinding; -#ifdef __cplusplus -extern "C" -#endif -mtlShader mtlCompileShader(uint32_t* code, size_t wordCount, mtlShaderOptions* options); +// typedef struct mtlSetMap { +// uint32_t setIndex, mtlSetIndex; +// mtlBinding bindings[MAX_METAL_BINDINGS]; +// } mtlSetMap; + +// typedef struct mtlShaderMap { +// mtlSetMap sets[MAX_METAL_SETS]; +// } mtlShaderMap; + +// typedef struct mtlShader { +// const char* code; +// mtlShaderMap map; +// } mtlShader; + +// #ifdef __cplusplus +// extern "C" +// #endif +// mtlShader mtlCompileShader(uint32_t* code, size_t wordCount, mtlShaderOptions* options); diff --git a/projects/apis/metal/src/shader_module/metal_shader_compiler.mm b/projects/apis/metal/src/shader_module/metal_shader_compiler.mm index 77c9209..a4d852e 100644 --- a/projects/apis/metal/src/shader_module/metal_shader_compiler.mm +++ b/projects/apis/metal/src/shader_module/metal_shader_compiler.mm @@ -1,71 +1,77 @@ #include "metal_shader_compiler.h" #include "spirv_msl.hpp" -#include "iostream" +// #include "iostream" -void handle_resources(spirv_cross::CompilerMSL& compiler, spirv_cross::SmallVector& resources, mtlShaderMap* map) { +typedef struct mtlCompiler_t { + spirv_cross::CompilerMSL* mslCompiler; + bool usingArgumentBuffers = false; + mtlShaderModuleStage stage; +} mtlInternalCompiler; + +void handle_resources(spirv_cross::CompilerMSL& compiler, spirv_cross::SmallVector& resources) { for (int i = 0; i < resources.size(); i++) { uint32_t set = compiler.get_decoration(resources[i].id, spv::DecorationDescriptorSet); compiler.unset_decoration(resources[i].id, spv::DecorationDescriptorSet); compiler.set_decoration(resources[i].id, spv::DecorationDescriptorSet, set + 1); - map->sets[set].setIndex = set; - map->sets[set].mtlSetIndex = set + 1; } } -void improve_map(spirv_cross::CompilerMSL& compiler, spirv_cross::SmallVector& resources, mtlShaderMap* map) { - for (int i = 0; i < resources.size(); i++) { - uint32_t set = compiler.get_decoration(resources[i].id, spv::DecorationDescriptorSet); - uint32_t binding = compiler.get_decoration(resources[i].id, spv::DecorationBinding); - map->sets[(set - 1)].bindings[binding].spvBinding = binding; - map->sets[(set - 1)].bindings[binding].metalID = compiler.get_automatic_msl_resource_binding(resources[i].id); - } +GN_CPP_FUNCTION mtlCompiler mtlCreateCompiler(mtlCompilerInfo* info) { + mtlInternalCompiler* compiler = (mtlInternalCompiler*)malloc(sizeof(mtlInternalCompiler)); + compiler->mslCompiler = new spirv_cross::CompilerMSL(info->code, info->wordCount); + + spirv_cross::CompilerMSL::Options options = compiler->mslCompiler->get_msl_options(); + options.argument_buffers = (bool)info->useArgumentBuffers; + options.set_msl_version(info->mslMajorVersion, info->minorVersion); + compiler->mslCompiler->set_msl_options(options); + + compiler->usingArgumentBuffers = (info->mslMajorVersion >= 2 && info->useArgumentBuffers); + compiler->stage = info->stage; + + return compiler; } -extern "C" mtlShader mtlCompileShader(uint32_t* code, size_t wordCount, mtlShaderOptions* inOptions) { - spirv_cross::CompilerMSL compiler(code, wordCount); +GN_CPP_FUNCTION const char* mtlCompilerShader(mtlCompiler compiler, gnUniformLayout* uniformLayout) { + if (uniformLayout->setCount == 0) goto compile; - spirv_cross::CompilerMSL::Options options; - options.enable_base_index_zero = false; - if (inOptions->useArgumentBuffers) { - options.set_msl_version(3); - options.argument_buffers = true; - } else { - options.set_msl_version(1); - return {}; - } - compiler.set_msl_options(options); - if (inOptions->stage == vertex) - compiler.set_entry_point(inOptions->entryPoint, spv::ExecutionModelVertex); - else if (inOptions->stage == fragment) - compiler.set_entry_point(inOptions->entryPoint, spv::ExecutionModelFragment); - else { - return {}; - } - - mtlShaderMap map; - for (int i = 0; i < MAX_METAL_SETS; i++) { - map.sets[i].mtlSetIndex = -1; - map.sets[i].setIndex = -1; - for (int c = 0; c < MAX_METAL_BINDINGS; c++) { - map.sets[i].bindings[c].spvBinding = -1; - map.sets[i].bindings[c].metalID = -1; + if (compiler->usingArgumentBuffers) { + // std::vector bindings; + for (int i = 0; i < uniformLayout->setCount; i++) { + uint32_t currentBinding = 0; + for (int c = 0; c < uniformLayout->sets[i].uniformBindingCount; c++) { + gnUniformBinding gryphnBinding = uniformLayout->sets[i].uniformBindings[c]; + spirv_cross::MSLResourceBinding binding = { + .binding = gryphnBinding.binding, + .count = 1, + .desc_set = ((uint32_t)i + 1), + .stage = (compiler->stage == mtlVertex) ? spv::ExecutionModelVertex : spv::ExecutionModelFragment, + }; + if (gryphnBinding.type == GN_COMBINED_IMAGE_SAMPLER_DESCRIPTOR) { + binding.msl_texture = currentBinding; + binding.msl_sampler = currentBinding + 1; + currentBinding += 2; + } else if (gryphnBinding.type == GN_SHADER_STORE_BUFFER_DESCRIPTOR || gryphnBinding.type == GN_UNIFORM_BUFFER_DESCRIPTOR) { + binding.msl_buffer = currentBinding; + currentBinding++; + } + // bindings.push_back(binding); + compiler->mslCompiler->add_msl_resource_binding(binding); + } } + } else { + printf("please add support for not using argument buffers on metal\n"); + goto compile; } - auto arg_buffers = compiler.get_shader_resources(); - handle_resources(compiler, arg_buffers.uniform_buffers, &map); - handle_resources(compiler, arg_buffers.storage_buffers, &map); - handle_resources(compiler, arg_buffers.sampled_images, &map); - std::string returnedCode = compiler.compile(); +compile: + auto arg_buffers = compiler->mslCompiler->get_shader_resources(); + handle_resources(*compiler->mslCompiler, arg_buffers.uniform_buffers); + handle_resources(*compiler->mslCompiler, arg_buffers.storage_buffers); + handle_resources(*compiler->mslCompiler, arg_buffers.sampled_images); - improve_map(compiler, arg_buffers.uniform_buffers, &map); - improve_map(compiler, arg_buffers.storage_buffers, &map); - improve_map(compiler, arg_buffers.sampled_images, &map); - - char* returnString = (char*)malloc(sizeof(char) * (returnedCode.size() + 1)); - strcpy(returnString, returnedCode.c_str()); - return { - .code = returnString, - .map = map - }; + std::string output = compiler->mslCompiler->compile(); + char* copied_output = (char*)malloc(sizeof(char*) * (output.size() + 1)); + strcpy(copied_output, output.c_str()); + copied_output[output.size()] = '\0'; + return copied_output; } 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 9c5131e..d114c93 100644 --- a/projects/apis/metal/src/shader_module/metal_shader_module.h +++ b/projects/apis/metal/src/shader_module/metal_shader_module.h @@ -5,15 +5,8 @@ #import typedef struct gnPlatformShaderModule_t { - id function; - mtlShaderMap shaderMap; + mtlCompiler compiler; } gnPlatformShaderModule; -#ifdef __cplusplus -extern "C" { -#endif - gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo); - void destroyMetalShaderModule(gnShaderModule module); -#ifdef __cplusplus -} -#endif +gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo); +void destroyMetalShaderModule(gnShaderModule module); 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 489f325..e27771c 100644 --- a/projects/apis/metal/src/shader_module/metal_shader_module.m +++ b/projects/apis/metal/src/shader_module/metal_shader_module.m @@ -9,50 +9,22 @@ gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo) { module->shaderModule = malloc(sizeof(gnPlatformShaderModule)); - mtlShaderOptions options = { - .useArgumentBuffers = (device->outputDevice->device.argumentBuffersSupport == MTLArgumentBuffersTier2), - .stage = vertex, - .entryPoint = shaderModuleInfo.entryPoint.value + mtlCompilerInfo info = { + .code = shaderModuleInfo.code, + .wordCount = shaderModuleInfo.size / 4, + .entryPoint = shaderModuleInfo.entryPoint.value, + .stage = (shaderModuleInfo.stage == GN_FRAGMENT_SHADER_MODULE) ? mtlFragment : mtlVertex }; - if (shaderModuleInfo.stage == GN_FRAGMENT_SHADER_MODULE) options.stage = fragment; - - mtlShader shader = mtlCompileShader(shaderModuleInfo.code, shaderModuleInfo.size / 4, &options); - const char* res = shader.code; - if (res == NULL) return GN_FAILED_TO_CONVERT_SHADER_CODE; - printf("res: %s\n", res); - - NSError* error = nil; - MTLCompileOptions* mtloptions = nil; - NSString* sourceCode = [NSString stringWithCString:res encoding:NSUTF8StringEncoding]; - id shaderLib = [device->outputDevice->device newLibraryWithSource:sourceCode options:mtloptions error:&error]; - if (!shaderLib) { - const char* errorString = error.localizedDescription.UTF8String; - gnDebuggerSetErrorMessage(device->instance->debugger, (gnMessageData){ - .message = gnCombineStrings(gnCreateString("Failed to compile metal library "), errorString) - }); - [shaderLib release]; - free((void*)res); - return GN_FAILED_TO_CREATE_SHADER_MODULE; + if ((device->outputDevice->device.argumentBuffersSupport == MTLArgumentBuffersTier2)) { + info.mslMajorVersion = 3; + info.minorVersion = 0; + info.useArgumentBuffers = true; + } else { + info.mslMajorVersion = 1; + info.minorVersion = 0; + info.useArgumentBuffers = false; } - - const char* name = shaderModuleInfo.entryPoint.value; - if (strcmp(name, "main") == 0) name = "main0"; - - gnBool foundFunction = false; - for (int i = 0; i < shaderLib.functionNames.count; i++) { - if (strcmp([shaderLib.functionNames objectAtIndex:0].UTF8String, name) == 0) { - foundFunction = true; - break; - } - } - if (!foundFunction) return GN_FAILED_TO_FIND_ENTRY_POINT; - - NSString* functionName = [NSString stringWithCString:name encoding:NSUTF8StringEncoding]; - module->shaderModule->function = [shaderLib newFunctionWithName:functionName]; - - [shaderLib release]; - if (options.stage == vertex) free((void*)res); - module->shaderModule->shaderMap = shader.map; + module->shaderModule->compiler = mtlCreateCompiler(&info); return GN_SUCCESS; } diff --git a/projects/apis/metal/src/uniforms/metal_uniform.h b/projects/apis/metal/src/uniforms/metal_uniform.h index 404471c..75e5884 100644 --- a/projects/apis/metal/src/uniforms/metal_uniform.h +++ b/projects/apis/metal/src/uniforms/metal_uniform.h @@ -14,8 +14,10 @@ typedef id mtlResource; typedef struct gnPlatformUniform_t { uint32_t index[MAX_METAL_BINDINGS]; - id encoder; - id argumentBuffer; + gnShaderModuleStage stageUsed[MAX_METAL_BINDINGS]; + id encoders[mtlMaxStage]; + id argumentBuffers[mtlMaxStage]; + mtlResource usedResources[MAX_METAL_BINDINGS]; int indexMap[MAX_METAL_BINDINGS]; diff --git a/projects/apis/metal/src/uniforms/metal_uniform.m b/projects/apis/metal/src/uniforms/metal_uniform.m index 148d56c..955d54e 100644 --- a/projects/apis/metal/src/uniforms/metal_uniform.m +++ b/projects/apis/metal/src/uniforms/metal_uniform.m @@ -5,54 +5,40 @@ #include void updateMetalBufferUniform(gnUniform uniform, gnBufferUniformInfo* info) { - // [uniform->uniform->encoder setBuffer:info->buffer->buffer->buffer offset:0 atIndex:0]; -} - -void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) { - // [uniform->uniform->encoder setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->index[info->binding]]; - // for (int i = 0; i < uniform->uniform->bindingCount; i++) { - // if (uniform->uniform->bindings[i].binding == info->binding) { - // uniform->uniform->bindings[i].data = malloc(sizeof(gnStorageUniformInfo)); - // memcpy(uniform->uniform->bindings[i].data, info, sizeof(gnStorageUniformInfo)); - // break; - // } - // } -} - -void updateMetalImageUniform(gnUniform uniform, gnImageUniformInfo* info) { - // mtlResource usedResources[MAX_METAL_BINDINGS]; - // uint32_t indexMap[MAX_METAL_BINDINGS]; - // uint32_t usedResourceCount; - if (uniform->uniform->indexMap[info->binding] == -1) { uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount; uniform->uniform->usedResourceCount++; } - - uniform->uniform->usedResources[uniform->uniform->indexMap[info->binding]] = info->texture->texture->texture; - - [uniform->uniform->encoder setTexture:info->texture->texture->texture atIndex:uniform->uniform->index[info->binding]]; - [uniform->uniform->encoder setSamplerState:info->texture->texture->sampler atIndex:uniform->uniform->index[info->binding] + 1]; - - // uniform->uniform->resources = mtlResourceArrayListCreate(); - // mtlResourceArrayListAdd(&uniform->uniform->resources, info->texture->texture->texture); - // mtlResourceArrayListAdd(&uniform->uniform->resources, info->texture->texture->sampler); - - - // printf("updating metal image uniform %i\n", uniform->uniform->index[info->binding]); - - // printf("binding: %i\n", info->binding); - // printf("mapped index: %i\n", uniform->uniform->index[info->binding]); - // id buffer = [uniform->pool->device->outputDevice->device newBufferWithLength:sizeof(int) options:MTLResourceStorageModeShared]; - // printf("uniform %p | uniform->uniform %p | encoder %p\n", uniform, uniform->uniform, uniform->uniform->encoder); - // [uniform->uniform->encoder setBuffer:buffer offset:0 atIndex:0]; - //info->binding - - // for (int i = 0; i < uniform->uniform->bindingCount; i++) { - // if (uniform->uniform->bindings[i].binding == info->binding) { - // uniform->uniform->bindings[i].data = malloc(sizeof(gnImageUniformInfo)); - // memcpy(uniform->uniform->bindings[i].data, info, sizeof(gnImageUniformInfo)); - // break; - // } - // } + uniform->uniform->usedResources[uniform->uniform->indexMap[info->binding]] = info->buffer->buffer->buffer; + if ((uniform->uniform->stageUsed[info->binding] & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) + [uniform->uniform->encoders[mtlVertex] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->indexMap[info->binding]]; + if ((uniform->uniform->stageUsed[info->binding] & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) + [uniform->uniform->encoders[mtlFragment] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->index[info->binding]]; +} +void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) { + if (uniform->uniform->indexMap[info->binding] == -1) { + uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount; + uniform->uniform->usedResourceCount++; + } + uniform->uniform->usedResources[uniform->uniform->indexMap[info->binding]] = info->buffer->buffer->buffer; + if ((uniform->uniform->stageUsed[info->binding] & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) + [uniform->uniform->encoders[mtlVertex] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->indexMap[info->binding]]; + if ((uniform->uniform->stageUsed[info->binding] & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) + [uniform->uniform->encoders[mtlFragment] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->index[info->binding]]; +} + +void updateMetalImageUniform(gnUniform uniform, gnImageUniformInfo* info) { + if (uniform->uniform->indexMap[info->binding] == -1) { + uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount; + uniform->uniform->usedResourceCount++; + } + uniform->uniform->usedResources[uniform->uniform->indexMap[info->binding]] = info->texture->texture->texture; + if ((uniform->uniform->stageUsed[info->binding] & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) { + [uniform->uniform->encoders[mtlVertex] setTexture:info->texture->texture->texture atIndex:uniform->uniform->indexMap[info->binding]]; + [uniform->uniform->encoders[mtlVertex] setSamplerState:info->texture->texture->sampler atIndex:uniform->uniform->indexMap[info->binding] + 1]; + } + if ((uniform->uniform->stageUsed[info->binding] & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) { + [uniform->uniform->encoders[mtlFragment] setTexture:info->texture->texture->texture atIndex:uniform->uniform->index[info->binding]]; + [uniform->uniform->encoders[mtlFragment] setSamplerState:info->texture->texture->sampler atIndex:uniform->uniform->index[info->binding] + 1]; + } } diff --git a/projects/apis/metal/src/uniforms/metal_uniform_pool.m b/projects/apis/metal/src/uniforms/metal_uniform_pool.m index 0a0c4de..fb285ac 100644 --- a/projects/apis/metal/src/uniforms/metal_uniform_pool.m +++ b/projects/apis/metal/src/uniforms/metal_uniform_pool.m @@ -12,55 +12,64 @@ gnUniform* allocateMetalUniforms(gnUniformPool pool, const gnUniformAllocationIn for (int i = 0; i < allocInfo.setCount; i++) { uniforms[i] = malloc(sizeof(struct gnUniform_t)); uniforms[i]->uniform = malloc(sizeof(gnPlatformUniform)); - int currentIndex = 0; - NSMutableArray* arguments = [NSMutableArray arrayWithCapacity:allocInfo.sets[i].uniformBindingCount]; - + NSMutableArray* totalArguments = [NSMutableArray arrayWithCapacity:allocInfo.sets[i].uniformBindingCount]; + NSMutableArray* vertexArguments = [NSMutableArray arrayWithCapacity:allocInfo.sets[i].uniformBindingCount]; + NSMutableArray* fragmentArguments = [NSMutableArray arrayWithCapacity:allocInfo.sets[i].uniformBindingCount]; for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) { - if (allocInfo.sets[i].uniformBindings[c].type == GN_COMBINED_IMAGE_SAMPLER_DESCRIPTOR) { - MTLArgumentDescriptor* textureDescriptor = [[MTLArgumentDescriptor alloc] init]; - textureDescriptor.dataType = MTLDataTypeTexture; - textureDescriptor.index = 0; - textureDescriptor.arrayLength = 1; - textureDescriptor.access = MTLBindingAccessReadOnly; - textureDescriptor.textureType = MTLTextureType2DMultisample; - [arguments addObject:textureDescriptor]; + gnUniformBinding binding = allocInfo.sets[i].uniformBindings[c]; + if (binding.type == GN_UNIFORM_BUFFER_DESCRIPTOR || + binding.type == GN_SHADER_STORE_BUFFER_DESCRIPTOR) { + MTLArgumentDescriptor* descriptor = [[MTLArgumentDescriptor alloc] init]; + descriptor.dataType = MTLDataTypePointer; + descriptor.index = 0; + descriptor.arrayLength = 1; + descriptor.access = MTLBindingAccessReadOnly; - MTLArgumentDescriptor* samplerDescriptor = [[MTLArgumentDescriptor alloc] init]; - samplerDescriptor.dataType = MTLDataTypeSampler; - samplerDescriptor.index = 1; - samplerDescriptor.arrayLength = 1; - samplerDescriptor.access = MTLBindingAccessReadOnly; - [arguments addObject:samplerDescriptor]; - uniforms[i]->uniform->index[allocInfo.sets[i].uniformBindings[c].binding] = currentIndex; + if ((binding.stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) [vertexArguments addObject:descriptor]; + if ((binding.stage & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) [fragmentArguments addObject:descriptor]; + [totalArguments addObject:descriptor]; - currentIndex += 2; - } - - } - for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) { - if (allocInfo.sets[i].uniformBindings[c].type == GN_UNIFORM_BUFFER_DESCRIPTOR || - allocInfo.sets[i].uniformBindings[c].type == GN_SHADER_STORE_BUFFER_DESCRIPTOR) { - MTLArgumentDescriptor* bufferDescriptor = [[MTLArgumentDescriptor alloc] init]; - bufferDescriptor.dataType = MTLDataTypePointer; - bufferDescriptor.index = currentIndex; - bufferDescriptor.arrayLength = 1; - bufferDescriptor.access = MTLBindingAccessReadOnly; - [arguments addObject:bufferDescriptor]; uniforms[i]->uniform->index[allocInfo.sets[i].uniformBindings[c].binding] = currentIndex; - currentIndex++; + } else if (allocInfo.sets[i].uniformBindings[c].type == GN_COMBINED_IMAGE_SAMPLER_DESCRIPTOR) { + MTLArgumentDescriptor* textureDescriptor = [[MTLArgumentDescriptor alloc] init]; + textureDescriptor.dataType = MTLDataTypeTexture; + textureDescriptor.index = 1; + textureDescriptor.arrayLength = 1; + textureDescriptor.access = MTLBindingAccessReadOnly; + if ((binding.stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) [vertexArguments addObject:textureDescriptor]; + if ((binding.stage & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) [fragmentArguments addObject:textureDescriptor]; + [totalArguments addObject:textureDescriptor]; + + MTLArgumentDescriptor* samplerDescriptor = [[MTLArgumentDescriptor alloc] init]; + samplerDescriptor.dataType = MTLDataTypeSampler; + samplerDescriptor.index = 2; + samplerDescriptor.arrayLength = 1; + samplerDescriptor.access = MTLBindingAccessReadOnly; + if ((binding.stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) [vertexArguments addObject:samplerDescriptor]; + if ((binding.stage & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) [fragmentArguments addObject:samplerDescriptor]; + [totalArguments addObject:samplerDescriptor]; + uniforms[i]->uniform->index[binding.binding] = currentIndex; + currentIndex += 2; } + uniforms[i]->uniform->stageUsed[binding.binding] = binding.stage; } - if (arguments.count > 0) { - uniforms[i]->uniform->encoder = [pool->device->outputDevice->device newArgumentEncoderWithArguments:arguments]; - uniforms[i]->uniform->argumentBuffer = [pool->device->outputDevice->device newBufferWithLength:uniforms[i]->uniform->encoder.encodedLength options:MTLResourceStorageModeShared]; - [uniforms[i]->uniform->encoder setArgumentBuffer:uniforms[i]->uniform->argumentBuffer offset:0]; + if (vertexArguments.count > 0) { + uniforms[i]->uniform->encoders[mtlVertex] = [pool->device->outputDevice->device newArgumentEncoderWithArguments:vertexArguments]; + uniforms[i]->uniform->argumentBuffers[mtlVertex] = [pool->device->outputDevice->device newBufferWithLength:uniforms[i]->uniform->encoders[mtlVertex].encodedLength options:MTLResourceStorageModeShared]; + [uniforms[i]->uniform->encoders[mtlVertex] setArgumentBuffer:uniforms[i]->uniform->argumentBuffers[mtlVertex] offset:0]; } - for (int k = 0; k < arguments.count; k++) [[arguments objectAtIndex:k] release]; + if (fragmentArguments.count > 0) { + uniforms[i]->uniform->encoders[mtlFragment] = [pool->device->outputDevice->device newArgumentEncoderWithArguments:fragmentArguments]; + uniforms[i]->uniform->argumentBuffers[mtlFragment] = [pool->device->outputDevice->device newBufferWithLength:uniforms[i]->uniform->encoders[mtlFragment].encodedLength options:MTLResourceStorageModeShared]; + [uniforms[i]->uniform->encoders[mtlFragment] setArgumentBuffer:uniforms[i]->uniform->argumentBuffers[mtlFragment] offset:0]; + } + for (int k = 0; k < totalArguments.count; k++) [[totalArguments objectAtIndex:k] release]; + [totalArguments release]; for (int g = 0; g < MAX_METAL_BINDINGS; g++) uniforms[i]->uniform->indexMap[g] = -1; } return uniforms; diff --git a/projects/core/src/shader_module/gryphn_shader_module.h b/projects/core/src/shader_module/gryphn_shader_module.h index 9ebe7f2..fa092db 100644 --- a/projects/core/src/shader_module/gryphn_shader_module.h +++ b/projects/core/src/shader_module/gryphn_shader_module.h @@ -5,9 +5,9 @@ #include "gryphn_handles.h" typedef enum gnShaderModuleStage { - GN_VERTEX_SHADER_MODULE = 0x00000001, - GN_FRAGMENT_SHADER_MODULE = 0x00000002, - GN_ALL_SHADER_MODULE = 0xffffffff + GN_VERTEX_SHADER_MODULE = 1 << 0, + GN_FRAGMENT_SHADER_MODULE = 1 << 1, + GN_ALL_SHADER_MODULE = GN_VERTEX_SHADER_MODULE | GN_FRAGMENT_SHADER_MODULE } gnShaderModuleStage; typedef struct gnShaderModuleInfo {