Shader Input Layout Invalid - c++

I am trying to add things to my working code, but it is returning an error [Invalid Arg] when calling CreateInputLayout().
It works before I add the texture stuff, but fails when I add it.
The shader file compiled with no errors.
I think the way I made the layout is bad. Is this correct?
C++ Vertex structure:
struct VertexData{
XMFLOAT3 Pos;
XMFLOAT4 Color;
XMFLOAT2 TexCoord;
};
C++ Layout:
D3D11_INPUT_ELEMENT_DESC inputLayout[]={
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 28, D3D11_INPUT_PER_VERTEX_DATA, 0 },
}; uint lSize=sizeof(inputLayout)/sizeof(inputLayout[0]);
Shader code:
// Stuff from DX Tutorial 7
Texture2D txDiffuse : register( t0 );
SamplerState samLinear : register( s0 );
cbuffer ViewData : register(b0){
matrix World;
matrix View;
matrix Projection;
}
struct VS_INPUT{
float4 pos : SV_POSITION;
float4 color : COLOR0;
float2 tex : TEXCOORD0;
};
struct PS_INPUT{
float4 pos : SV_POSITION;
float4 color : COLOR0;
float2 tex : TEXCOORD0;
};
PS_INPUT VS(VS_INPUT input){
PS_INPUT output=(PS_INPUT)0;
output.pos=mul(input.pos, World);
output.pos=mul(output.pos, View);
output.pos=mul(output.pos, Projection);
output.color = input.color;
output.tex = input.tex;
return output;
}
float4 PS(PS_INPUT input) : SV_Target {
return input.color;
}
Edit:
After a bunch of twiddling with the shader code, I found that if I change the semantics of the...
1st position to: float4 pos : POSITION;
2nd position to: float4 pos : SV_POSITION;
...the input layout successfully creates.
I tried both without the SV_ [system value] prefix, but that also failed. I dont know why I cant have them be the same.
The Semantics seem a bit magical. Not sure if I should answer my own Q with this, or wait for someone smarter to answer better.

Your structs do not match:
struct VertexData
{
XMFLOAT3 Pos; // float3 here
XMFLOAT4 Color;
XMFLOAT2 TexCoord;
};
struct VS_INPUT{
float4 pos : SV_POSITION; // float4 here
float4 color : COLOR0;
float2 tex : TEXCOORD0;
};
For position in 3D space I prefer to use float3. So, as your input layout:
"POSITION", 0, R32G32B32_FLOAT
About semantics magic:
Names in HLSL must match input layout names. For example:
Layout:
{ "POSITION", 0, .. }
Vertex Shader:
float4 pos : POSITION0;
The only exception is that pixel shader must always have float4 pos : SV_POSITION semantics for the input position of pixel (It is a one of the System Value semantics).
And as a bonus, some commonly used stuff I'd like to recommend:
int size = ARRYSIZE(inputayoutDesc);
use D3D11_APPEND_ALIGNED_ELEMENT instead of 12, 28, numbers as alignment offset.

Input semantics shouldn't be SV_POSITION if they are in your input vertices, they should be POSITION I think.
Also you declare this -
struct VS_INPUT{
float4 pos : SV_POSITION;
Shouldn't this be float3 pos : POSITION;
Your input layout only has 3 floats for that item. Not sure if it's the problem but it doesn't look quite right.

Related

CreateInputLayout returns E_INVALIDARG

I am writing a program in C++ using DirectX11. Now I wanted to start with shaders and for that I also need the ID3D11InputLayout
//in main
shader.Bind(DeviceContext);
ID3D11InputLayout *pLayout;
D3D11_INPUT_ELEMENT_DESC ied[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
HRESULT hh = Device->CreateInputLayout(ied, 2, shader.GetVSBlob()->GetBufferPointer(), shader.GetVSBlob()->GetBufferSize(), &pLayout);
DeviceContext->IASetInputLayout(pLayout);
//Vertex Shader
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
VOut main(float4 position : POSITION, float4 color : COLOR)
{
VOut output;
output.position = position;
output.color = color;
return output;
}
//pixel shader
struct VOut
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
float4 main(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
return color;
}
Device->CreateInputLayout() returns E_INVALIDARG.
Enable the Direct3D Debug Device and look for debug output.
D3D11 ERROR: ID3D11Device::CreateInputLayout: The provided input signature expects
to read an element with SemanticName/Index: 'SV_Position'/0, but the declaration
doesn't provide a matching name.
[ STATE_CREATION ERROR #163: CREATEINPUTLAYOUT_MISSINGELEMENT]
In this case you'd see that you used the legacy "POSITION" semantic in the layout, but "SV_Position" in the shader. They need to be consistent.
In your description you have POSITION defined as R32G32B32, but the shader is expected a float4, is that why?
Either that, or there is something wrong with blob data. I assume shaders blob data is for a Vertex shader and not a pixel shader?

DirectX HLSL - Constant Buffer empty in Pixel Shader but not Vertex Shader

I am in the process of implementing lighting in my DirectX 11 project. The problem I have is that when I try to access a cbuffer value from the Pixel Shader function it's just returning float3(0, 0, 0) meanwhile when I access the same value in the Vertex Shader function it returns the correct value. Here is the shader:
/*********************************************\
VERTEX SHADER
\*********************************************/
//Constant buffers
cbuffer Object : register(cb0) {
float4x4 WorldMatrix;
};
cbuffer Camera : register(cb1) {
float4x4 ViewMatrix;
float4x4 ProjectionMatrix;
};
cbuffer LightBuffer : register(cb2) {
float3 AmbientColor;
}
//IO Structs
struct VS_INPUT {
float3 Position : POSITION;
float2 UV : TEXCOORD;
float3 Normal : NORMAL;
};
struct VS_OUTPUT {
float4 Position : SV_POSITION;
float2 UV : TEXCOORD;
float3 Normal : NORMAL;
};
VS_OUTPUT VS(VS_INPUT input){
VS_OUTPUT output;
float4 Position;
//Multiply position with AmbientColor (should be 1, 1, 1), position unchanged
Position = mul(ViewMatrix, float4(input.Position * AmbientColor, 1));
Position = mul(ProjectionMatrix, Position);
Position = mul(WorldMatrix, Position);
output.Position = Position;
output.UV = input.UV;
output.Normal = mul(WorldMatrix, input.Normal);
return output;
}
/*********************************************\
PIXEL SHADER
\*********************************************/
SamplerState TextureState;
Texture2D<float4> Texture;
float4 PS(VS_OUTPUT input) : SV_TARGET {
float4 MaterialColor = Texture.Sample(TextureState, input.UV);
//Multiply color with AmbientColor (should be 1, 1, 1), returns black
float3 FinalColor = MaterialColor.xyz * AmbientColor;
return float4(FinalColor, MaterialColor.a);
}
Here's is the value I'm sending (c++):
_LightsUniform.AmbientColor = XMFLOAT3(1, 1, 1);
DeviceContext->UpdateSubresource(_LightBuffer, 0, NULL, &_LightsUniform, 0, 0);
DeviceContext->VSSetConstantBuffers(2, 1, &_LightBuffer);
DeviceContext->PSSetConstantBuffers(2, 1, &_LightBuffer);
Here is the result:
http://i.gyazo.com/357f1ed3ea33e6569ad2346b368cd975.png
And result without multiplying color: http://gyazo.com/b60b385daa94d3373e9552a523928e3f
I can't see what is wrong. Anybody else had the same issue?
I found the problem. Turns out that the registers for my cbuffer(s) were wrong, I used cb# where b# should be used. (I misunderstood what was written here: https://msdn.microsoft.com/en-us/library/windows/desktop/hh447212(v=vs.85).aspx)
Wrong code:
cbuffer LightBuffer : register(cb2) {
Changed to:
cbuffer LightBuffer : register(b2) {

Set uniform color to pixel shader

I am a newbie in DirectX11, so sorry for a dull question.
I have a pixel shader:
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
Texture2D s_texture : register(t0);
SamplerState s_sampleParams
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
float4 t = s_texture.Sample(s_sampleParams, input.texCoord);
return t;
}
Now I want to add a color to my shader:
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
Texture2D s_texture : register(t0);
float4 s_color;
SamplerState s_sampleParams
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = CLAMP;
AddressV = CLAMP;
};
float4 main(PixelShaderInput input) : SV_TARGET
{
float4 t = s_texture.Sample(s_sampleParams, input.texCoord);
return t * s_color;
}
How do I set s_color from C++ code? Do I have to use m_d3dContext->PSSetConstantBuffers? In this case I should change
`float4 s_color;`
to
cbuffer ColorOnlyConstantBuffer : register(b0)
{
float4 m_color;
};
, right?
Or I can keep simple definition float4 s_color; and set it from C++ somehow else?
As far as I remember, you specify input items for vertex shader by using specific structure:
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[2] =
{
{ "Position",
0,
DXGI_FORMAT_R32G32B32_FLOAT,
0,
D3D11_APPEND_ALIGNED_ELEMENT,
D3D11_INPUT_PER_VERTEX_DATA,
0
},
{ "Color",
0,
DXGI_FORMAT_R32G32B32_FLOAT,
0,
D3D11_APPEND_ALIGNED_ELEMENT,
D3D11_INPUT_PER_VERTEX_DATA,
0
}
};
This structure is being used to create ID3D11InputLayout:
const UINT inputLayoutDescCount = 2;
hr = device->CreateInputLayout(
inputLayoutDesc,
inputLayoutDescCount,
compiledVsShader->GetBufferPointer(),
compiledVsShader->GetBufferSize(),
&inputLayout);
You can then use semantics to specify, which element represents which entry:
struct VS_INPUT
{
float4 Pos : POSITION;
float4 Col : COLOR;
};
Edit: in response to comments.
Sorry, didn't get that. You'll need a constant buffer. Relevant (sample) parts of code follows. Just modify them to your needs:
struct PixelConstantBuffer
{
XMFLOAT4 lightPos;
XMFLOAT4 observerPos;
};
// ***
D3D11_BUFFER_DESC pixelConstantBufferDesc;
pixelConstantBufferDesc.ByteWidth = sizeof(PixelConstantBuffer);
pixelConstantBufferDesc.Usage = D3D11_USAGE_DEFAULT;
pixelConstantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
pixelConstantBufferDesc.CPUAccessFlags = 0;
pixelConstantBufferDesc.MiscFlags = 0;
pixelConstantBufferDesc.StructureByteStride = 0;
hr = device->CreateBuffer(&pixelConstantBufferDesc, nullptr, &pixelConstantBuffer);
// ***
context->PSSetConstantBuffers(1, 1, &pixelConstantBuffer);
context->PSSetShader(pixelShader, nullptr, 0);
// ***
PixelConstantBuffer pcBuffer;
pcBuffer.lightPos = XMFLOAT4(lightPos.m128_f32[0], lightPos.m128_f32[1], lightPos.m128_f32[2], lightPos.m128_f32[3]);
pcBuffer.observerPos = XMFLOAT4(camPos.m128_f32[0], camPos.m128_f32[1], camPos.m128_f32[2], camPos.m128_f32[3]);
context->UpdateSubresource(pixelConstantBuffer, 0, nullptr, &pcBuffer, 0, 0);
// *** (hlsl)
cbuffer PixelConstantBuffer : register(b1)
{
float4 LightPos;
float4 ObserverPos;
}

Getting the color of a vertex in HLSL?

I have the following vertex and pixel shaders:
struct VS_INPUT
{
float4 Position : POSITION0;
float2 TexCoord : TEXCOORD0;
float4 Color : TEXCOORD1;
};
struct VS_OUTPUT
{
float4 Position : POSITION0;
float4 Color : COLOR0;
float2 TexCoord : TEXCOORD0;
};
float4x4 projview_matrix;
VS_OUTPUT vs_main(VS_INPUT Input)
{
VS_OUTPUT Output;
Output.Position = mul(Input.Position, projview_matrix);
Output.Color = Input.Color;
Output.TexCoord = Input.TexCoord;
return Output;
}
px
texture tex;
sampler2D s = sampler_state {
texture = <tex>;
};
float4 ps_main(VS_OUTPUT Input) : COLOR0
{
float4 pixel = tex2D(s, Input.TexCoord.xy);
return pixel;
}
This is for a 2d game. The vertices of the quads contain tinting colors that I want to use to tint the bitmap. How can I obtain the color of the current vertex so I can multiply it in the pixel shader by the current pixel color?
Thanks
In your pixel shader, do:
float4 pixel = tex2D(s, Input.TexCoord.xy) * Input.Color;
The Input.Color value will be linearly interpreted across your plane for you, just like Input.TexCoord is. To blend two color vectors together, you simply multiply them together. It may also be advisable to do:
float4 pixel = tex2D(s, Input.TexCoord.xy) * Input.Color;
pixel = saturate(pixel);
The saturate() function will clip each RGB value in your color in the range of 0.0 to 1.0, which may avoid any possible display artifacts.

Geometry Shader won't compile in DirectX10 HLSL

I've been trying to code a geometry shader in order to generate billboard systems as explained in Frank Luna's book Introduction to 3D Game Programming with DirectX. I insert the shader into my technique as follows:
pass P3
{
SetVertexShader(CompileShader(vs_4_0, VS()));
SetGeometryShader(CompileShader(gs_4_0, GS()));
SetPixelShader(CompileShader( ps_4_0, PS_NoSpecular()));
SetBlendState(SrcAlphaBlendingAdd, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
}
However, this gives the error 1>D3DEffectCompiler : error : No valid VertexShader-GeometryShader combination could be found in Technique render, Pass P3.
The structs for both VS and GS are given below:
struct GS_INPUT
{
float4 PosH : SV_POSITION;
float4 PosW : POSITION;
float2 Tex : TEXCOORD;
float3 N : NORMAL;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
struct VS_INPUT
{
float4 Pos : POSITION;
float2 Tex : TEXCOORD;
float3 N : NORMAL;
float3 Tangent : TANGENT;
float3 Binormal : BINORMAL;
};
Should they be the same?
The problem lies with the struct used to input and output from the vertex shader, geometry shader and pixel shader. If the vertex shader outputs a PS_INPUT type, then the geometry shader needs to use that PS_INPUT as its input type.