3 Replies
      Latest reply on Oct 7, 2019 6:00 AM by DanDanger
      Stainless Level 1 Level 1 (0 points)

        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.




        • Re: Reflection problem
          Stainless Level 1 Level 1 (0 points)

          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.

            • Re: Reflection problem
              Stainless Level 1 Level 1 (0 points)

              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.

            • Re: Reflection problem
              DanDanger Level 1 Level 1 (0 points)



              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()
                      if ( error != nil )
                          zDbgLogInternal("ERROR: Shader Reflection on [" + getName() + "]" );
                          NSLog(@"ERROR: %@", [error localizedDescription] );
                      for (MTLArgument *arg in reflection.vertexArguments)
                      for (MTLArgument *arg in reflection.fragmentArguments)