Reflection problem

Hi all,


So I am porting a DX9 game to metal, and I need to be able to parse the compiled shader to find out what goes where.


All the shaders take a bunch of parameters in a single global structure which is generated by game data setup by artists, so it's dynamic.


So when the shader has been loaded into a libray and the vertex and fragment functions have been created, I tried to create a dummy render pipeline state so I can get the MTLRenderPipelineReflection structure and work everything out.


But the render pipeline fails to compile. I think this is because I haven't setup the vertex inputs etc yet, which I cannot do until I have the reflection structure.


So I am stuck in a chicken and egg situation.


I need to setup the pipeline before I can get the information I need to setup the pipeline.


Any ideas?


Really stuck on this one.


Cheers

Stainless

Accepted Reply

Okay I have talked to my contacts at Apple, and it is not possible to get the structure of a buffer from a compiled shader.


The API does not support it.


So... I am screwed and have to do something completely different.

Replies

More details.


I have used vertFunc.GetVertexAttributes(); to build a VertexDescriptor, but the key thing is the globals buffer at the head of each shader.


When trying to get a reflection pointer to parse this I get the error.


Attribute at index 0 references a buffer at index 0 that has no stride.


But I need the reflection to be able to work out the stride.

Okay I have talked to my contacts at Apple, and it is not possible to get the structure of a buffer from a compiled shader.


The API does not support it.


So... I am screwed and have to do something completely different.

Hello.


We have a similar setup as you describe for our shaders.

I got the reflection thing working by setting up dummy vertex attributes (see lines 7 to 12).

I am able to read all the uniforms, structures and offsets with this code.



    {
        MTLRenderPipelineReflection* reflection;


        // Make fake descriptor
        MTLVertexDescriptor *vd = [MTLVertexDescriptor new];
        for ( int i = 0; i < 10; ++i )
        {
            vd.attributes[i].format = MTLVertexFormatFloat;
            vd.attributes[i].bufferIndex = 0;
            vd.attributes[i].offset = i*4;
        }
        vd.layouts[0].stride = (int)10*4;
        vd.layouts[0].stepFunction = MTLVertexStepFunctionPerVertex;
        
        // Create pipeline to get refelction info
        MTLRenderPipelineDescriptor *descriptor = [MTLRenderPipelineDescriptor new];
        descriptor.vertexDescriptor = vd;
        descriptor.vertexFunction = functionVertex;
        descriptor.fragmentFunction = functionFragment;
        descriptor.colorAttachments[0].pixelFormat = MTLPixelFormatRGBA8Unorm;
        
        // Create a pipeline, only interested in the reflection information
        id  renderPS = [r->getMetalDevice()
                                                newRenderPipelineStateWithDescriptor:descriptor
                                                options:MTLPipelineOptionArgumentInfo|MTLPipelineOptionBufferTypeInfo
                                                reflection:&reflection
                                                error:&error];


        if ( error != nil )
        {
            zDbgLogInternal("ERROR: Shader Reflection on [" + getName() + "]" );
            NSLog(@"ERROR: %@", [error localizedDescription] );
            return;
        }
        
        for (MTLArgument *arg in reflection.vertexArguments)
        {
            processUniform(arg,0);
        }


        for (MTLArgument *arg in reflection.fragmentArguments)
        {
            processUniform(arg,1);
        }
    }