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.

         

        Cheers

        Stainless

        • 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)

              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);
                      }
                  }