Could not create graphics pipeline state! Error Code: The parameter is incorrect. (0x80070057)

I am on version 3.2.16 of SDL. I get the above error when targeting Direct3D12, but everything works flawlessly when targetting vulkan - this makes sense considering the error code is directx specific, but after searching online I couldn’t find much of an answer to it. The below snippet is minimal and just initializes a window and a graphics pipeline, and the error occurs on the check for whether pipeline is null (SDL_CreateGPUGraphicsPipeline returns null).

    SDL_Window *instance = SDL_CreateWindow("Temp", 1280, 720, SDL_WINDOW_HIDDEN);
  if (!instance) throw std::exception(std::format("Could not create window: {}.", SDL_GetError()).c_str());

  SDL_GPUDevice *gpu = SDL_CreateGPUDevice(SDL_GPU_SHADERFORMAT_SPIRV | SDL_GPU_SHADERFORMAT_DXIL, false, "direct3d12");
  if (!gpu) throw std::exception(std::format("Could not create GPU device for window: {}.", SDL_GetError()).c_str());
  if (!SDL_ClaimWindowForGPUDevice(gpu, instance))
    throw std::exception(std::format("Could not claim window for GPU device for window: {}.", SDL_GetError()).c_str());

  SDL_ShowWindow(instance);

  SDL_GPUShaderFormat current_format = SDL_GPU_SHADERFORMAT_INVALID;
  const SDL_GPUShaderFormat backend_formats = SDL_GetGPUShaderFormats(gpu);
  if (backend_formats & SDL_GPU_SHADERFORMAT_DXIL)
    current_format = SDL_GPU_SHADERFORMAT_DXIL;
  else if (backend_formats & SDL_GPU_SHADERFORMAT_SPIRV)
    current_format = SDL_GPU_SHADERFORMAT_SPIRV;
  else
    throw std::exception(std::format("Could not find supported shader format for object: {}.", SDL_GetError()).c_str());

  std::string vertex_shader_path;
  std::string fragment_shader_path;
  if (current_format == SDL_GPU_SHADERFORMAT_DXIL)
  {
    vertex_shader_path = "shader/main.vert.dxil";
    fragment_shader_path = "shader/main.frag.dxil";
  }
  else
  {
    vertex_shader_path = "shader/main.vert.spirv";
    fragment_shader_path = "shader/main.frag.spirv";
  }

  std::ifstream vertex_file(vertex_shader_path, std::ios::binary);
  if (!vertex_file)
    throw std::exception(std::format("Could not open vertex shader file: {}.", vertex_shader_path).c_str());
  std::vector<unsigned char> vertex_data((std::istreambuf_iterator<char>(vertex_file)),
                                         std::istreambuf_iterator<char>());
  vertex_file.close();

  std::ifstream fragment_file(fragment_shader_path, std::ios::binary);
  if (!fragment_file)
    throw std::exception(std::format("Could not open fragment shader file: {}.", fragment_shader_path).c_str());
  std::vector<unsigned char> fragment_data((std::istreambuf_iterator<char>(fragment_file)),
                                           std::istreambuf_iterator<char>());
  fragment_file.close();

  SDL_GPUShaderCreateInfo vertex_shader_info(vertex_data.size(), vertex_data.data(), "main", current_format,
                                             SDL_GPU_SHADERSTAGE_VERTEX, 0, 0, 0, 1);
  SDL_GPUShader *vertex_shader = SDL_CreateGPUShader(gpu, &vertex_shader_info);
  if (!vertex_shader) throw std::exception(std::format("Could not create vertex shader: {}.", SDL_GetError()).c_str());
  SDL_GPUShaderCreateInfo fragment_shader_info(fragment_data.size(), fragment_data.data(), "main", current_format,
                                               SDL_GPU_SHADERSTAGE_FRAGMENT, 1, 0, 0, 0);
  SDL_GPUShader *fragment_shader = SDL_CreateGPUShader(gpu, &fragment_shader_info);
  if (!fragment_shader)
    throw std::exception(std::format("Could not create fragment shader: {}.", SDL_GetError()).c_str());

  SDL_GPUVertexBufferDescription vertex_buffer_description(0, sizeof(vertex), SDL_GPU_VERTEXINPUTRATE_VERTEX, 0);
  std::array<SDL_GPUVertexAttribute, 3> vertex_attributes(
    {{0, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT3, 0},
     {1, 0, SDL_GPU_VERTEXELEMENTFORMAT_UBYTE4_NORM, sizeof(vertex::x) + sizeof(vertex::y) + sizeof(vertex::z)},
     {2, 0, SDL_GPU_VERTEXELEMENTFORMAT_FLOAT2,
      sizeof(vertex::x) + sizeof(vertex::y) + sizeof(vertex::z) + sizeof(vertex::r) + sizeof(vertex::g) +
        sizeof(vertex::b) + sizeof(vertex::a)}});

  SDL_GPUVertexInputState vertex_input_state(&vertex_buffer_description, 1, vertex_attributes.data(), 3);
  SDL_GPURasterizerState rasterizer_state(SDL_GPU_FILLMODE_FILL, SDL_GPU_CULLMODE_BACK,
                                          SDL_GPU_FRONTFACE_COUNTER_CLOCKWISE);
  SDL_GPUColorTargetDescription color_target_description(SDL_GetGPUSwapchainTextureFormat(gpu, instance));
  SDL_GPUGraphicsPipelineTargetInfo target_info(&color_target_description, 1);
  SDL_GPUGraphicsPipelineCreateInfo pipeline_info(vertex_shader, fragment_shader, vertex_input_state,
                                                  SDL_GPU_PRIMITIVETYPE_TRIANGLELIST, rasterizer_state,
                                                  SDL_GPUMultisampleState(), SDL_GPUDepthStencilState(), target_info);
  SDL_GPUGraphicsPipeline *pipeline = SDL_CreateGPUGraphicsPipeline(gpu, &pipeline_info);
  if (!pipeline) throw std::exception(std::format("Could not create graphics pipeline: {}.", SDL_GetError()).c_str());

  SDL_ReleaseGPUShader(gpu, fragment_shader);
  SDL_ReleaseGPUShader(gpu, vertex_shader);

  SDL_Log("Exiting normally.");
  return EXIT_SUCCESS;

The shaders main.vert and main.frag are as follows:

struct Input
{
  float3 position : TEXCOORD0;
  float4 color : TEXCOORD1;
  float2 texcoord : TEXCOORD2;
};

struct Output
{
  float4 position : SV_Position;
  float4 color : TEXCOORD0;
  float2 texcoord : TEXCOORD1;
};

cbuffer Matrices : register(b0, space1)
{
  float4x4 projection_matrix;
  float4x4 view_matrix;
  float4x4 model_matrix;
};

Output main(Input input)
{
  Output output;
  output.position = mul(projection_matrix, mul(view_matrix, mul(model_matrix, float4(input.position, 1.0f))));
  output.color = input.color;
  output.texcoord = input.texcoord;
  return output;
}
struct Input
{
  float4 color : TEXCOORD0;
  float2 texture : TEXCOORD1;
};

Texture2D<float4> Texture : register(t0, space2);
SamplerState Sampler : register(s0, space2);

float4 main(Input input) : SV_Target0
{
  float4 texture_color = Texture.Sample(Sampler, input.texture);
  if (texture_color.a == 0.0f) discard;
  return texture_color;
}

They were compiled using dxc, with the -spirv flag for testing with vulkan, and target profiles vs_6_0 and ps_6_0 accordingly.

I am lead to believe from everything I’ve seen online that it has something to do with the contents of the shaders, but there is nothing concrete, since I am new to writing HLSL help would be greatly appreciated.

At a glance, the thing that jumps out at me (since Vulkan works) is you should use SDL_shadercross to compile your shaders instead of directly invoking the shader compiler. It knows how to invoke the shader compiler to output things in the way SDL_GPU expects (assuming your shader is correct).

Another thing: use the reflection info that SDL_shadercross generates to fill in your SDL_GPUShaderCreateInfo struct instead of hard coding it.

Hi thanks for the response - I didn’t know shadercross generates reflection info, thanks for telling me.

As for this issue, I figured out about an hour ago that with the example code i have posted here, if i change the order of position, color and texcoord in the vertex shader Output struct to be color, texcoord and position instead, and do the same when setting the values of the struct in the main function, I dont get any errors anymore (??). However when i tried to apply these changes to my main project that uses the same framework, but compiles using shadercross instead of dxc, I get the error again.

So, when i compiled the shaders using dxc with my main project rather than using shadercross, it worked. Really confusing to me - thinking about just supporting vulkan instead of vulkan and directx.

It’s possible there’s a bug in the DX12 backend for SDL_GPU.

If you aren’t shipping on Xbox or the Windows Store (or whatever the hell it’s called) then you don’t really need to worry about DX12 AFAIK.

I am in a similar position. My HLSL shader compiles to SPIR-V and works fine with the Vulkan backend but emits this same error code when using DXIL in D3D12.

I am taking steps to build and use SDL_shadercross, but I was wondering: what is it about the DXIL shader that SDL GPU expects of it to work properly with D3D12? Particular way the inputs are laid out? Or something else?

1 Like