metal storage buffers + rework of shader maps
This commit is contained in:
@@ -48,6 +48,7 @@ gnDeviceFunctions loadMetalDeviceFunctions() {
|
||||
._gnDestroyUniformPool = destroyMetalUniformPool,
|
||||
|
||||
._gnUpdateBufferUniform = updateMetalBufferUniform,
|
||||
._gnUpdateStorageUniform = updateMetalStorageUniform,
|
||||
._gnUpdateImageUniform = updateMetalImageUniform,
|
||||
|
||||
._gnCreateTexture = createMetalTexture,
|
||||
|
@@ -115,31 +115,25 @@ void metalBindUniform(gnCommandBufferHandle buffer, gnUniform uniform, uint32_t
|
||||
for (int i = 0; i < uniform->uniform->bindingCount; i++) {
|
||||
if (uniform->uniform->bindings[i].type == GN_UNIFORM_BUFFER_DESCRIPTOR) {
|
||||
gnBufferUniformInfo info = *(gnBufferUniformInfo*)uniform->uniform->bindings[i].data;
|
||||
|
||||
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:map.metalBindingIndex
|
||||
atIndex:buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->vertexShaderMaps.sets[set].bindings[info.binding]
|
||||
];
|
||||
} else if (uniform->uniform->bindings[i].type == GN_SHADER_STORE_BUFFER_DESCRIPTOR) {
|
||||
gnStorageUniformInfo info = *(gnStorageUniformInfo*)uniform->uniform->bindings[i].data;
|
||||
[encoder setVertexBuffer:info.buffer->buffer->buffer
|
||||
offset:info.offset
|
||||
atIndex:buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->vertexShaderMaps.sets[set].bindings[info.binding]
|
||||
];
|
||||
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];
|
||||
if (map.set == set && map.binding == uniform->uniform->bindings[i].binding) {
|
||||
gnImageUniformInfo info = *(gnImageUniformInfo*)uniform->uniform->bindings[i].data;
|
||||
[encoder setFragmentTexture:info.texture->texture->texture atIndex:map.metalBindingIndex];
|
||||
break;
|
||||
}
|
||||
}
|
||||
[encoder setFragmentTexture:info.texture->texture->texture atIndex:
|
||||
buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->fragmentShaderMaps.sets[set].bindings[info.binding]];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void metalBindVertexBytes(gnCommandBufferHandle buffer, gnPushConstantLayout layout, void* data) {
|
||||
id<MTLRenderCommandEncoder> encoder = (id<MTLRenderCommandEncoder>)buffer->commandBuffer->encoder;
|
||||
[encoder setVertexBytes:data length:layout.size atIndex:buffer->commandBuffer->boundGraphcisPipeline->graphicsPipeline->vertexShaderMaps.pushConstantIndex]; // TODO: fix this
|
||||
[encoder setVertexBytes:data length:layout.size atIndex:1]; // TODO: fix this
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@
|
||||
typedef struct gnPlatformGraphicsPipeline_t {
|
||||
id<MTLRenderPipelineState> graphicsPipeline;
|
||||
id<MTLDepthStencilState> depthState;
|
||||
metalBindingMaps vertexShaderMaps, fragmentShaderMaps;
|
||||
metalShaderMap vertexShaderMaps, fragmentShaderMaps;
|
||||
} gnPlatformGraphicsPipeline;
|
||||
|
||||
gnReturnCode createMetalGraphicsPipeline(gnGraphicsPipeline graphicsPipeline, gnOutputDevice device, gnGraphicsPipelineInfo info);
|
||||
|
@@ -75,10 +75,10 @@ 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;
|
||||
graphicsPipeline->graphicsPipeline->vertexShaderMaps = info.shaderModules[i]->shaderModule->map;
|
||||
} 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;
|
||||
graphicsPipeline->graphicsPipeline->fragmentShaderMaps = info.shaderModules[i]->shaderModule->map;
|
||||
} else {
|
||||
return GN_UNSUPPORTED_SHADER_MODULE;
|
||||
}
|
||||
|
@@ -3,23 +3,21 @@
|
||||
#include "utils/lists/gryphn_array_list.h"
|
||||
#import <Metal/Metal.h>
|
||||
|
||||
typedef struct metalBindingMap {
|
||||
uint32_t set;
|
||||
uint32_t binding;
|
||||
uint32_t metalBindingIndex;
|
||||
} metalBindingMap;
|
||||
GN_ARRAY_LIST(metalBindingMap);
|
||||
#define METAL_MAX_SET_COUNT 16
|
||||
#define METAL_MAX_BINDING_COUNT 16
|
||||
|
||||
typedef struct metalBindingMaps {
|
||||
metalBindingMapArrayList uniformBufferMaps;
|
||||
uint32_t pushConstantIndex;
|
||||
metalBindingMapArrayList textureMaps;
|
||||
} metalBindingMaps;
|
||||
typedef struct metalSetMap {
|
||||
uint32_t bindings[METAL_MAX_BINDING_COUNT];
|
||||
} metalSetMap;
|
||||
|
||||
typedef struct metalShaderMap {
|
||||
metalSetMap sets[METAL_MAX_SET_COUNT];
|
||||
uint32_t pushConstantBufferIndex;
|
||||
} metalShaderMap;
|
||||
|
||||
typedef struct gnPlatformShaderModule_t {
|
||||
id<MTLFunction> function;
|
||||
uint32_t pushConstantIndex;
|
||||
metalBindingMaps maps;
|
||||
metalShaderMap map;
|
||||
} gnPlatformShaderModule;
|
||||
|
||||
gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnShaderModuleInfo shaderModuleInfo);
|
||||
|
@@ -8,62 +8,10 @@
|
||||
void mtlSpirVErrorCallback(void *userdata, const char *error) {
|
||||
gnDebugger debugger = (gnDebugger)userdata;
|
||||
gnDebuggerSetErrorMessage(debugger, (gnMessageData){
|
||||
.message = gnCreateString(error)
|
||||
.message = gnCombineStrings(gnCreateString("shader compilation error MSL "), gnCreateString(error))
|
||||
});
|
||||
}
|
||||
|
||||
metalBindingMapArrayList loadTextureBindingInformation(spvc_resources resources, spvc_compiler compiler) {
|
||||
metalBindingMapArrayList bindings = metalBindingMapArrayListCreate();
|
||||
|
||||
const spvc_reflected_resource *list = NULL;
|
||||
size_t count;
|
||||
|
||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_SAMPLED_IMAGE, &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);
|
||||
|
||||
metalBindingMap map = {
|
||||
.set = set, .binding = binding,
|
||||
.metalBindingIndex = i
|
||||
};
|
||||
metalBindingMapArrayListAdd(&bindings, map);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
@@ -83,14 +31,50 @@ gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnS
|
||||
|
||||
spvc_compiler_create_shader_resources(compiler, &resources);
|
||||
|
||||
module->shaderModule->maps.uniformBufferMaps = loadUniformBufferInformation(resources, compiler, shaderModuleInfo.stage);
|
||||
module->shaderModule->maps.textureMaps = loadTextureBindingInformation(resources, compiler);
|
||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_SHADER_RECORD_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),
|
||||
mslBinding = spvc_compiler_msl_get_automatic_resource_binding(compiler, list[i].id);
|
||||
printf("%s: set %ui, binding %ui, mslBinding %ui\n", list[i].name, set, binding, mslBinding);
|
||||
}
|
||||
|
||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_UNIFORM_BUFFER, &list, &count);
|
||||
// [[buffer(0)]] is reserved for stage_in, [[buffer(1)]] is reserved for push_constant
|
||||
uint32_t currentBufferBinding = 2, currentTextureBinding = 0;
|
||||
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);
|
||||
spvc_compiler_unset_decoration(compiler, list[i].id, SpvDecorationBinding);
|
||||
spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, currentBufferBinding);
|
||||
module->shaderModule->map.sets[set].bindings[binding] = currentBufferBinding;
|
||||
currentBufferBinding++;
|
||||
}
|
||||
|
||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_SAMPLED_IMAGE, &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);
|
||||
spvc_compiler_unset_decoration(compiler, list[i].id, SpvDecorationBinding);
|
||||
spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, currentTextureBinding);
|
||||
module->shaderModule->map.sets[set].bindings[binding] = currentTextureBinding;
|
||||
currentTextureBinding++;
|
||||
}
|
||||
|
||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_STORAGE_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);
|
||||
spvc_compiler_unset_decoration(compiler, list[i].id, SpvDecorationBinding);
|
||||
spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, currentBufferBinding);
|
||||
module->shaderModule->map.sets[set].bindings[binding] = currentBufferBinding;
|
||||
currentBufferBinding++;
|
||||
}
|
||||
|
||||
spvc_resources_get_resource_list_for_type(resources, SPVC_RESOURCE_TYPE_PUSH_CONSTANT, &list, &count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
spvc_compiler_unset_decoration(compiler, list[i].id, SpvDecorationBinding);
|
||||
module->shaderModule->maps.pushConstantIndex = module->shaderModule->maps.uniformBufferMaps.data[module->shaderModule->maps.uniformBufferMaps.count - 1].metalBindingIndex + 1;
|
||||
spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, module->shaderModule->maps.pushConstantIndex);
|
||||
spvc_compiler_set_decoration(compiler, list[i].id, SpvDecorationBinding, 1);
|
||||
}
|
||||
|
||||
spvc_compiler_create_compiler_options(compiler, &options);
|
||||
@@ -143,6 +127,8 @@ gnReturnCode createMetalShaderModule(gnShaderModule module, gnDevice device, gnS
|
||||
|
||||
[shaderLib release];
|
||||
|
||||
printf("%s\n", result);
|
||||
|
||||
spvc_context_destroy(context);
|
||||
return GN_SUCCESS;
|
||||
}
|
||||
|
@@ -14,4 +14,5 @@ typedef struct gnPlatformUniform_t {
|
||||
} gnPlatformUniform;
|
||||
|
||||
void updateMetalBufferUniform(gnUniform uniform, gnBufferUniformInfo* info);
|
||||
void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info);
|
||||
void updateMetalImageUniform(gnUniform uniform, gnImageUniformInfo* info);
|
||||
|
@@ -11,6 +11,16 @@ void updateMetalBufferUniform(gnUniform uniform, gnBufferUniformInfo* info) {
|
||||
}
|
||||
}
|
||||
|
||||
void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) {
|
||||
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) {
|
||||
for (int i = 0; i < uniform->uniform->bindingCount; i++) {
|
||||
if (uniform->uniform->bindings[i].binding == info->binding) {
|
||||
|
Reference in New Issue
Block a user