support dynamic uniform buffers on metal

This commit is contained in:
Gregory Wells
2025-07-23 16:36:39 -04:00
parent bb19d855f5
commit 3661e39ac1
3 changed files with 56 additions and 14 deletions

View File

@@ -8,6 +8,8 @@ typedef struct metalUniformBinding {
gnUniformType type;
uint32_t binding;
void* data;
gnBool isDynamic;
} metalUniformBinding;
typedef id<MTLResource> mtlResource;
@@ -17,13 +19,21 @@ typedef struct gnPlatformUniform_t {
gnShaderModuleStage stageUsed[MAX_METAL_BINDINGS];
id<MTLArgumentEncoder> encoders[mtlMaxStage];
id<MTLBuffer> argumentBuffers[mtlMaxStage];
mtlResource usedResources[MAX_METAL_BINDINGS];
int indexMap[MAX_METAL_BINDINGS];
uint32_t usedResourceCount;
gnBool isDynamic[MAX_METAL_BINDINGS];
} gnPlatformUniform;
void updateMetalBufferUniform(gnUniform uniform, gnBufferUniformInfo* info);
void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info);
void updateMetalImageUniform(gnUniform uniform, gnImageUniformInfo* info);
typedef struct mtlBufferUniformInfo {
gnBufferUniformInfo* baseInfo;
id<MTLBuffer> buffer;
} mtlBufferUniformInfo;
void mtlUpdateMetalBufferUniform(gnUniformHandle uniform, mtlBufferUniformInfo* info);

View File

@@ -4,16 +4,25 @@
#include "texture/metal_texture.h"
#include <buffer/metal_buffer.h>
void updateMetalBufferUniform(gnUniform uniform, gnBufferUniformInfo* info) {
if (uniform->uniform->indexMap[info->binding] == -1) {
uniform->uniform->indexMap[info->binding] = uniform->uniform->usedResourceCount;
void mtlUpdateMetalBufferUniform(gnUniformHandle uniform, mtlBufferUniformInfo* info) {
if (uniform->uniform->indexMap[info->baseInfo->binding] == -1) {
uniform->uniform->indexMap[info->baseInfo->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]];
uniform->uniform->isDynamic[info->baseInfo->binding] = info->baseInfo->dynamic;
uniform->uniform->usedResources[uniform->uniform->indexMap[info->baseInfo->binding]] = info->buffer;
if ((uniform->uniform->stageUsed[info->baseInfo->binding] & GN_VERTEX_SHADER_MODULE) == GN_VERTEX_SHADER_MODULE)
[uniform->uniform->encoders[mtlVertex] setBuffer:info->buffer offset:info->baseInfo->offset atIndex:uniform->uniform->indexMap[info->baseInfo->binding]];
if ((uniform->uniform->stageUsed[info->baseInfo->binding] & GN_FRAGMENT_SHADER_MODULE) == GN_FRAGMENT_SHADER_MODULE)
[uniform->uniform->encoders[mtlFragment] setBuffer:info->buffer offset:info->baseInfo->offset atIndex:uniform->uniform->index[info->baseInfo->binding]];
}
void updateMetalBufferUniform(gnUniform uniform, gnBufferUniformInfo* info) {
mtlBufferUniformInfo mtlInfo = {
.baseInfo = info,
.buffer = info->buffer->buffer->buffer
};
mtlUpdateMetalBufferUniform(uniform, &mtlInfo);
}
void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) {
if (uniform->uniform->indexMap[info->binding] == -1) {
@@ -22,9 +31,9 @@ void updateMetalStorageUniform(gnUniform uniform, gnStorageUniformInfo* info) {
}
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]];
[uniform->uniform->encoders[mtlVertex] setBuffer:info->buffer->buffer->buffer offset:info->offset 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]];
[uniform->uniform->encoders[mtlFragment] setBuffer:info->buffer->buffer->buffer offset:info->offset atIndex:uniform->uniform->index[info->binding]];
}
void updateMetalImageUniform(gnUniform uniform, gnImageUniformInfo* info) {