finish redoing metal shader workflow

This commit is contained in:
Gregory Wells
2025-07-21 13:27:40 -04:00
parent 46d1c2e802
commit 1f85aa30bd
11 changed files with 242 additions and 228 deletions

View File

@@ -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 useResources:uniform->uniform->usedResources count:uniform->uniform->usedResourceCount usage:MTLResourceUsageRead stages:MTLRenderStageVertex | MTLRenderStageFragment];
[encoder setVertexBuffer:uniform->uniform->argumentBuffer offset:0 atIndex:(set + 1)]; [encoder setVertexBuffer:uniform->uniform->argumentBuffers[mtlVertex] offset:0 atIndex:(set + 1)];
[encoder setFragmentBuffer:uniform->uniform->argumentBuffer offset:0 atIndex:(set + 1)]; [encoder setFragmentBuffer:uniform->uniform->argumentBuffers[mtlFragment] offset:0 atIndex:(set + 1)];
} }
void metalBindVertexBytes(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data) { void metalBindVertexBytes(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data) {

View File

@@ -6,7 +6,6 @@
typedef struct gnPlatformGraphicsPipeline_t { typedef struct gnPlatformGraphicsPipeline_t {
id<MTLRenderPipelineState> graphicsPipeline; id<MTLRenderPipelineState> graphicsPipeline;
id<MTLDepthStencilState> depthState; id<MTLDepthStencilState> depthState;
mtlShaderMap vertexShaderMaps, fragmentShaderMaps;
} gnPlatformGraphicsPipeline; } gnPlatformGraphicsPipeline;
gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info); gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info);

View File

@@ -71,15 +71,40 @@ gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gn
} }
for (int i = 0; i < info.shaderModuleCount; i++) { for (int i = 0; i < info.shaderModuleCount; i++) {
if (info.shaderModules[i]->info.stage == GN_VERTEX_SHADER_MODULE) { const char* shaderCode = mtlCompilerShader(info.shaderModules[i]->shaderModule->compiler, &info.uniformLayout);
[descriptor setVertexFunction:info.shaderModules[i]->shaderModule->function]; printf("shader code: %s\n", shaderCode);
graphicsPipeline->graphicsPipeline->vertexShaderMaps = info.shaderModules[i]->shaderModule->shaderMap;
} else if (info.shaderModules[i]->info.stage == GN_FRAGMENT_SHADER_MODULE) { NSError* error = nil;
[descriptor setFragmentFunction:info.shaderModules[i]->shaderModule->function]; MTLCompileOptions* mtloptions = nil;
graphicsPipeline->graphicsPipeline->fragmentShaderMaps = info.shaderModules[i]->shaderModule->shaderMap; NSString* sourceCode = [NSString stringWithCString:shaderCode encoding:NSUTF8StringEncoding];
} else { id<MTLLibrary> shaderLib = [device->outputDevice->device newLibraryWithSource:sourceCode options:mtloptions error:&error];
return GN_UNSUPPORTED_SHADER_MODULE; 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<MTLFunction> 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]; MTLVertexDescriptor* vertexDescriptor = [[MTLVertexDescriptor alloc] init];

View File

@@ -2,40 +2,62 @@
#include "stdint.h" #include "stdint.h"
#include "stdlib.h" #include "stdlib.h"
#include "utils/gryphn_bool.h" #include "utils/gryphn_bool.h"
#include <core/src/uniforms/gryphn_uniform_layout.h>
#ifdef __cplusplus
#define GN_CPP_FUNCTION extern "C"
#else
#define GN_CPP_FUNCTION
#endif
#define MAX_METAL_SETS 32 #define MAX_METAL_SETS 32
#define MAX_METAL_BINDINGS 16 #define MAX_METAL_BINDINGS 16
typedef struct mtlCompiler_t* mtlCompiler;
typedef enum mtlShaderModuleStage { typedef enum mtlShaderModuleStage {
vertex, fragment mtlVertex, mtlFragment, mtlMaxStage
} mtlShaderModuleStage; } mtlShaderModuleStage;
typedef struct mtlShaderOptions { typedef struct mtlCompilerInfo {
gnBool useArgumentBuffers; uint32_t* code;
mtlShaderModuleStage stage; int wordCount;
const char* entryPoint; const char* entryPoint;
} mtlShaderOptions; mtlShaderModuleStage stage;
typedef struct mtlBinding { int mslMajorVersion, minorVersion;
uint32_t spvBinding; gnBool useArgumentBuffers;
uint32_t metalID; } mtlCompilerInfo;
} mtlBinding;
typedef struct mtlSetMap { GN_CPP_FUNCTION mtlCompiler mtlCreateCompiler(mtlCompilerInfo* info);
uint32_t setIndex, mtlSetIndex; GN_CPP_FUNCTION const char* mtlCompilerShader(mtlCompiler compiler, gnUniformLayout* uniformLayout);
mtlBinding bindings[MAX_METAL_BINDINGS];
} mtlSetMap;
typedef struct mtlShaderMap { // typedef struct mtlShaderOptions {
mtlSetMap sets[MAX_METAL_SETS]; // gnBool useArgumentBuffers;
} mtlShaderMap; // mtlShaderModuleStage stage;
// const char* entryPoint;
// } mtlShaderOptions;
typedef struct mtlShader { // typedef struct mtlBinding {
const char* code; // uint32_t spvBinding;
mtlShaderMap map; // uint32_t metalID;
} mtlShader; // } mtlBinding;
#ifdef __cplusplus // typedef struct mtlSetMap {
extern "C" // uint32_t setIndex, mtlSetIndex;
#endif // mtlBinding bindings[MAX_METAL_BINDINGS];
mtlShader mtlCompileShader(uint32_t* code, size_t wordCount, mtlShaderOptions* options); // } 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);

View File

@@ -1,71 +1,77 @@
#include "metal_shader_compiler.h" #include "metal_shader_compiler.h"
#include "spirv_msl.hpp" #include "spirv_msl.hpp"
#include "iostream" // #include "iostream"
void handle_resources(spirv_cross::CompilerMSL& compiler, spirv_cross::SmallVector<spirv_cross::Resource>& 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<spirv_cross::Resource>& resources) {
for (int i = 0; i < resources.size(); i++) { for (int i = 0; i < resources.size(); i++) {
uint32_t set = compiler.get_decoration(resources[i].id, spv::DecorationDescriptorSet); uint32_t set = compiler.get_decoration(resources[i].id, spv::DecorationDescriptorSet);
compiler.unset_decoration(resources[i].id, spv::DecorationDescriptorSet); compiler.unset_decoration(resources[i].id, spv::DecorationDescriptorSet);
compiler.set_decoration(resources[i].id, spv::DecorationDescriptorSet, set + 1); 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<spirv_cross::Resource>& resources, mtlShaderMap* map) { GN_CPP_FUNCTION mtlCompiler mtlCreateCompiler(mtlCompilerInfo* info) {
for (int i = 0; i < resources.size(); i++) { mtlInternalCompiler* compiler = (mtlInternalCompiler*)malloc(sizeof(mtlInternalCompiler));
uint32_t set = compiler.get_decoration(resources[i].id, spv::DecorationDescriptorSet); compiler->mslCompiler = new spirv_cross::CompilerMSL(info->code, info->wordCount);
uint32_t binding = compiler.get_decoration(resources[i].id, spv::DecorationBinding);
map->sets[(set - 1)].bindings[binding].spvBinding = binding; spirv_cross::CompilerMSL::Options options = compiler->mslCompiler->get_msl_options();
map->sets[(set - 1)].bindings[binding].metalID = compiler.get_automatic_msl_resource_binding(resources[i].id); 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) { GN_CPP_FUNCTION const char* mtlCompilerShader(mtlCompiler compiler, gnUniformLayout* uniformLayout) {
spirv_cross::CompilerMSL compiler(code, wordCount); if (uniformLayout->setCount == 0) goto compile;
spirv_cross::CompilerMSL::Options options; if (compiler->usingArgumentBuffers) {
options.enable_base_index_zero = false; // std::vector<spirv_cross::MSLResourceBinding> bindings;
if (inOptions->useArgumentBuffers) { for (int i = 0; i < uniformLayout->setCount; i++) {
options.set_msl_version(3); uint32_t currentBinding = 0;
options.argument_buffers = true; for (int c = 0; c < uniformLayout->sets[i].uniformBindingCount; c++) {
} else { gnUniformBinding gryphnBinding = uniformLayout->sets[i].uniformBindings[c];
options.set_msl_version(1); spirv_cross::MSLResourceBinding binding = {
return {}; .binding = gryphnBinding.binding,
} .count = 1,
compiler.set_msl_options(options); .desc_set = ((uint32_t)i + 1),
if (inOptions->stage == vertex) .stage = (compiler->stage == mtlVertex) ? spv::ExecutionModelVertex : spv::ExecutionModelFragment,
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;
}
}
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();
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
}; };
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;
}
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);
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;
} }

View File

@@ -5,15 +5,8 @@
#import <Metal/Metal.h> #import <Metal/Metal.h>
typedef struct gnPlatformShaderModule_t { typedef struct gnPlatformShaderModule_t {
id<MTLFunction> function; mtlCompiler compiler;
mtlShaderMap shaderMap;
} gnPlatformShaderModule; } gnPlatformShaderModule;
#ifdef __cplusplus
extern "C" {
#endif
gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo); gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo);
void destroyMetalShaderModule(gnShaderModule module); void destroyMetalShaderModule(gnShaderModule module);
#ifdef __cplusplus
}
#endif

View File

@@ -9,50 +9,22 @@
gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo) { gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo) {
module->shaderModule = malloc(sizeof(gnPlatformShaderModule)); module->shaderModule = malloc(sizeof(gnPlatformShaderModule));
mtlShaderOptions options = { mtlCompilerInfo info = {
.useArgumentBuffers = (device->outputDevice->device.argumentBuffersSupport == MTLArgumentBuffersTier2), .code = shaderModuleInfo.code,
.stage = vertex, .wordCount = shaderModuleInfo.size / 4,
.entryPoint = shaderModuleInfo.entryPoint.value .entryPoint = shaderModuleInfo.entryPoint.value,
.stage = (shaderModuleInfo.stage == GN_FRAGMENT_SHADER_MODULE) ? mtlFragment : mtlVertex
}; };
if (shaderModuleInfo.stage == GN_FRAGMENT_SHADER_MODULE) options.stage = fragment; if ((device->outputDevice->device.argumentBuffersSupport == MTLArgumentBuffersTier2)) {
info.mslMajorVersion = 3;
mtlShader shader = mtlCompileShader(shaderModuleInfo.code, shaderModuleInfo.size / 4, &options); info.minorVersion = 0;
const char* res = shader.code; info.useArgumentBuffers = true;
if (res == NULL) return GN_FAILED_TO_CONVERT_SHADER_CODE; } else {
printf("res: %s\n", res); info.mslMajorVersion = 1;
info.minorVersion = 0;
NSError* error = nil; info.useArgumentBuffers = false;
MTLCompileOptions* mtloptions = nil;
NSString* sourceCode = [NSString stringWithCString:res encoding:NSUTF8StringEncoding];
id<MTLLibrary> 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;
} }
module->shaderModule->compiler = mtlCreateCompiler(&info);
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;
return GN_SUCCESS; return GN_SUCCESS;
} }

View File

@@ -14,8 +14,10 @@ typedef id<MTLResource> mtlResource;
typedef struct gnPlatformUniform_t { typedef struct gnPlatformUniform_t {
uint32_t index[MAX_METAL_BINDINGS]; uint32_t index[MAX_METAL_BINDINGS];
id<MTLArgumentEncoder> encoder; gnShaderModuleStage stageUsed[MAX_METAL_BINDINGS];
id<MTLBuffer> argumentBuffer; id<MTLArgumentEncoder> encoders[mtlMaxStage];
id<MTLBuffer> argumentBuffers[mtlMaxStage];
mtlResource usedResources[MAX_METAL_BINDINGS]; mtlResource usedResources[MAX_METAL_BINDINGS];
int indexMap[MAX_METAL_BINDINGS]; int indexMap[MAX_METAL_BINDINGS];

View File

@@ -5,54 +5,40 @@
#include <buffer/metal_buffer.h> #include <buffer/metal_buffer.h>
void updateMetalBufferUniform(gnUniform uniform, gnBufferUniformInfo* info) { 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) { if (uniform->uniform->indexMap[info->binding] == -1) {
uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount; uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount;
uniform->uniform->usedResourceCount++; uniform->uniform->usedResourceCount++;
} }
uniform->uniform->usedResources[uniform->uniform->indexMap[info->binding]] = info->buffer->buffer->buffer;
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] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->indexMap[info->binding]];
[uniform->uniform->encoder setTexture:info->texture->texture->texture atIndex:uniform->uniform->index[info->binding]]; if ((uniform->uniform->stageUsed[info->binding] & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE)
[uniform->uniform->encoder setSamplerState:info->texture->texture->sampler atIndex:uniform->uniform->index[info->binding] + 1]; [uniform->uniform->encoders[mtlFragment] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->index[info->binding]];
}
// uniform->uniform->resources = mtlResourceArrayListCreate(); void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) {
// mtlResourceArrayListAdd(&uniform->uniform->resources, info->texture->texture->texture); if (uniform->uniform->indexMap[info->binding] == -1) {
// mtlResourceArrayListAdd(&uniform->uniform->resources, info->texture->texture->sampler); uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount;
uniform->uniform->usedResourceCount++;
}
// printf("updating metal image uniform %i\n", uniform->uniform->index[info->binding]); 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)
// printf("binding: %i\n", info->binding); [uniform->uniform->encoders[mtlVertex] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->indexMap[info->binding]];
// printf("mapped index: %i\n", uniform->uniform->index[info->binding]); if ((uniform->uniform->stageUsed[info->binding] & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE)
// id<MTLBuffer> buffer = [uniform->pool->device->outputDevice->device newBufferWithLength:sizeof(int) options:MTLResourceStorageModeShared]; [uniform->uniform->encoders[mtlFragment] setBuffer:info->buffer->buffer->buffer offset:0 atIndex:uniform->uniform->index[info->binding]];
// 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 void updateMetalImageUniform(gnUniform uniform, gnImageUniformInfo* info) {
if (uniform->uniform->indexMap[info->binding] == -1) {
// for (int i = 0; i < uniform->uniform->bindingCount; i++) { uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount;
// if (uniform->uniform->bindings[i].binding == info->binding) { uniform->uniform->usedResourceCount++;
// uniform->uniform->bindings[i].data = malloc(sizeof(gnImageUniformInfo)); }
// memcpy(uniform->uniform->bindings[i].data, info, sizeof(gnImageUniformInfo)); uniform->uniform->usedResources[uniform->uniform->indexMap[info->binding]] = info->texture->texture->texture;
// break; 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];
}
} }

View File

@@ -12,55 +12,64 @@ gnUniform* allocateMetalUniforms(gnUniformPool pool, const gnUniformAllocationIn
for (int i = 0; i < allocInfo.setCount; i++) { for (int i = 0; i < allocInfo.setCount; i++) {
uniforms[i] = malloc(sizeof(struct gnUniform_t)); uniforms[i] = malloc(sizeof(struct gnUniform_t));
uniforms[i]->uniform = malloc(sizeof(gnPlatformUniform)); uniforms[i]->uniform = malloc(sizeof(gnPlatformUniform));
int currentIndex = 0; 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++) { for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) {
if (allocInfo.sets[i].uniformBindings[c].type == GN_COMBINED_IMAGE_SAMPLER_DESCRIPTOR) { 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;
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];
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]; MTLArgumentDescriptor* textureDescriptor = [[MTLArgumentDescriptor alloc] init];
textureDescriptor.dataType = MTLDataTypeTexture; textureDescriptor.dataType = MTLDataTypeTexture;
textureDescriptor.index = 0; textureDescriptor.index = 1;
textureDescriptor.arrayLength = 1; textureDescriptor.arrayLength = 1;
textureDescriptor.access = MTLBindingAccessReadOnly; textureDescriptor.access = MTLBindingAccessReadOnly;
textureDescriptor.textureType = MTLTextureType2DMultisample; if ((binding.stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) [vertexArguments addObject:textureDescriptor];
[arguments addObject:textureDescriptor]; if ((binding.stage & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE) [fragmentArguments addObject:textureDescriptor];
[totalArguments addObject:textureDescriptor];
MTLArgumentDescriptor* samplerDescriptor = [[MTLArgumentDescriptor alloc] init]; MTLArgumentDescriptor* samplerDescriptor = [[MTLArgumentDescriptor alloc] init];
samplerDescriptor.dataType = MTLDataTypeSampler; samplerDescriptor.dataType = MTLDataTypeSampler;
samplerDescriptor.index = 1; samplerDescriptor.index = 2;
samplerDescriptor.arrayLength = 1; samplerDescriptor.arrayLength = 1;
samplerDescriptor.access = MTLBindingAccessReadOnly; samplerDescriptor.access = MTLBindingAccessReadOnly;
[arguments addObject:samplerDescriptor]; if ((binding.stage & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE) [vertexArguments addObject:samplerDescriptor];
uniforms[i]->uniform->index[allocInfo.sets[i].uniformBindings[c].binding] = currentIndex; 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; currentIndex += 2;
} }
uniforms[i]->uniform->stageUsed[binding.binding] = binding.stage;
} }
for (int c = 0; c < allocInfo.sets[i].uniformBindingCount; c++) { if (vertexArguments.count > 0) {
if (allocInfo.sets[i].uniformBindings[c].type == GN_UNIFORM_BUFFER_DESCRIPTOR || uniforms[i]->uniform->encoders[mtlVertex] = [pool->device->outputDevice->device newArgumentEncoderWithArguments:vertexArguments];
allocInfo.sets[i].uniformBindings[c].type == GN_SHADER_STORE_BUFFER_DESCRIPTOR) { uniforms[i]->uniform->argumentBuffers[mtlVertex] = [pool->device->outputDevice->device newBufferWithLength:uniforms[i]->uniform->encoders[mtlVertex].encodedLength options:MTLResourceStorageModeShared];
MTLArgumentDescriptor* bufferDescriptor = [[MTLArgumentDescriptor alloc] init]; [uniforms[i]->uniform->encoders[mtlVertex] setArgumentBuffer:uniforms[i]->uniform->argumentBuffers[mtlVertex] offset:0];
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++;
}
}
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];
} }
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; for (int g = 0; g < MAX_METAL_BINDINGS; g++) uniforms[i]->uniform->indexMap[g] = -1;
} }
return uniforms; return uniforms;

View File

@@ -5,9 +5,9 @@
#include "gryphn_handles.h" #include "gryphn_handles.h"
typedef enum gnShaderModuleStage { typedef enum gnShaderModuleStage {
GN_VERTEX_SHADER_MODULE = 0x00000001, GN_VERTEX_SHADER_MODULE = 1 << 0,
GN_FRAGMENT_SHADER_MODULE = 0x00000002, GN_FRAGMENT_SHADER_MODULE = 1 << 1,
GN_ALL_SHADER_MODULE = 0xffffffff GN_ALL_SHADER_MODULE = GN_VERTEX_SHADER_MODULE | GN_FRAGMENT_SHADER_MODULE
} gnShaderModuleStage; } gnShaderModuleStage;
typedef struct gnShaderModuleInfo { typedef struct gnShaderModuleInfo {