9 Replies Latest reply on Oct 11, 2016 2:17 PM by silverlan

    Vulkan - "Initialization failed" in 'createGraphicsPipelines' when using certain output block locations

    silverlan

      I have been able to replicate this problem on three different AMD GPUs (on different PCs). (1 from the R9 200 series, 1 from the R9 300 series and 1 from the R5 series.)

      The problem does not occur on Nvidia GPUs and seems to be a driver bug.

      I'm on the latest AMD drivers, 16.30.2311-160718a-305076C.

      To replicate the issue, I've created a minimal adaptation of the cube demo from the Vulkan SDK. The full program is attached to this post.

       

      The only changes I've made to the demo are the shaders, "cube.vert", and "cube.frag", and their respective .spv-files, no other files have been modified.

      Here are the changes for the shader stages:

      Vertex Shader: [OpenGL Shading] AMD location bug - GLSL Cube Vertex Shader - Pastebin.com

      Fragment Shader: [OpenGL Shading] AMD location bug - GLSL Cube Fragment Shader - Pastebin.com

       

      All the changes I've made from the original shaders are within the "/* Changed shader code block */" blocks. The interesting part is inside the vertex shader.

      At line 44, there's an output block at location 5:

      layout(location = 5) out LightData vs_light_out[8];
      

       

      The block is accessed at line 57:

      vs_light_out[0].light_dir_cs = vec3(0,gl_Position.x,gl_Position.y);
      

       

      This line is what causes the crash. Without it, no crash occurs. This only happens if the location of the output block is >= 5, no crash happens if the location is lower than that.

      Strangely enough, there is also no crash if some larger locations are used (e.g. 40), which shouldn't work in the first place.

       

      According to the Vulkan specification, the maximum number of output locations you can have in a vertex shader is "maxVertexOutputComponents / 4" and the maximum input locations for a fragment shader is "maxFragmentInputComponents / 4".

      The maximum vertex output and fragment input component number for my GPU is 128, so I should have 32 locations available.

       

      This is what the Vulkan specification says about location consumption:

      Inputs and outputs of the following types consume a single interface location:

       

      32-bit scalar and vector types, and

      64-bit scalar and 2-component vector types.

      64-bit three- and four-component vectors consume two consecutive locations.

       

      If a declared input or output is an array of size n and each element takes m locations, it will be assigned m × n consecutive locations starting with the location specified.

       

      The "LightData" structure from the shader code has 3 vector-members:

      struct LightData {     
          vec3 light_dir_cs; // Light direction in camera space     
          vec3 light_dir_ts; // Light direction in tangent space     
          vec4 vert_pos_ls; // Vertex Position in light space 
      };
      

       

      That means the entire block should consume 8 *3 = 24 locations. If we add the location origin (5) to that, we end up at 29, which is still well within the limits.