在 Metal 中反射着色器统一名称
Reflecting shader uniform names in Metal
假设我的着色器中有以下统一缓冲区:
typedef struct
{
matrix_float4x4 modelview_projection_matrix;
float someValue;
} uniforms_t;
如何在 C++ 或 Objective-C 中获取 someValue 的位置?我想做这样的事情:
void Shader::SetFloat( const char* name, float value )
名称为 'someValue'.
看看Specifying Resources for a Render Command Encoder section of Apple's Metal Programming Guide。
作为一个非常基本的解释...
将您的 uniforms_t
结构(通常是包含特定着色器函数的所有制服的单个结构)声明为 Metal[=36 的参数=] 着色器函数,并将其与特定缓冲区索引(例如 [[ buffer(0) ]]
)相关联,作为着色器函数声明的一部分。
从您的应用程序代码中,将 uniforms_t
结构的内容复制到 MTLBuffer
中,以某个偏移量。
从您的应用程序代码中,调用 MTLRenderCommandEncoder
setVertexBuffer:offset:atIndex:
或 setFragmentBuffer:offset:atIndex:
方法来关联 MTLBuffer
的内容(在偏移量处您使用在着色器函数中声明的缓冲区索引复制了 uniforms_t
结构)。这基本上告诉着色器函数在哪个 MTLBuffer
中查找(以及在该缓冲区中的哪个位置)该函数参数的值。
我通过检查 BGFX 的源代码得出了一个解决方案:
NSError* error = NULL;
MTLRenderPipelineReflection* reflectionObj;
MTLPipelineOption option = MTLPipelineOptionBufferTypeInfo | MTLPipelineOptionArgumentInfo;
id <MTLRenderPipelineState> pso = [device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor options:option reflection:&reflectionObj error:&error];
for (MTLArgument *arg in reflectionObj.vertexArguments)
{
NSLog(@"Found arg: %@\n", arg.name);
if (arg.bufferDataType == MTLDataTypeStruct)
{
for( MTLStructMember* uniform in arg.bufferStructType.members )
{
NSLog(@"uniform: %@ type:%lu, location: %lu", uniform.name, (unsigned long)uniform.dataType, (unsigned long)uniform.offset);
}
}
}
假设我的着色器中有以下统一缓冲区:
typedef struct
{
matrix_float4x4 modelview_projection_matrix;
float someValue;
} uniforms_t;
如何在 C++ 或 Objective-C 中获取 someValue 的位置?我想做这样的事情:
void Shader::SetFloat( const char* name, float value )
名称为 'someValue'.
看看Specifying Resources for a Render Command Encoder section of Apple's Metal Programming Guide。
作为一个非常基本的解释...
将您的
uniforms_t
结构(通常是包含特定着色器函数的所有制服的单个结构)声明为 Metal[=36 的参数=] 着色器函数,并将其与特定缓冲区索引(例如[[ buffer(0) ]]
)相关联,作为着色器函数声明的一部分。从您的应用程序代码中,将
uniforms_t
结构的内容复制到MTLBuffer
中,以某个偏移量。从您的应用程序代码中,调用
MTLRenderCommandEncoder
setVertexBuffer:offset:atIndex:
或setFragmentBuffer:offset:atIndex:
方法来关联MTLBuffer
的内容(在偏移量处您使用在着色器函数中声明的缓冲区索引复制了uniforms_t
结构)。这基本上告诉着色器函数在哪个MTLBuffer
中查找(以及在该缓冲区中的哪个位置)该函数参数的值。
我通过检查 BGFX 的源代码得出了一个解决方案:
NSError* error = NULL;
MTLRenderPipelineReflection* reflectionObj;
MTLPipelineOption option = MTLPipelineOptionBufferTypeInfo | MTLPipelineOptionArgumentInfo;
id <MTLRenderPipelineState> pso = [device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor options:option reflection:&reflectionObj error:&error];
for (MTLArgument *arg in reflectionObj.vertexArguments)
{
NSLog(@"Found arg: %@\n", arg.name);
if (arg.bufferDataType == MTLDataTypeStruct)
{
for( MTLStructMember* uniform in arg.bufferStructType.members )
{
NSLog(@"uniform: %@ type:%lu, location: %lu", uniform.name, (unsigned long)uniform.dataType, (unsigned long)uniform.offset);
}
}
}