D3DXAssembleShader function was used in DirectX 9 for compiling shaders from Assembly. It's not supported in DirectX 11. Is there any alternative to create shaders from Assembler code?
I am aware of compiling from fx or hlsl files but for my project purposes, I should compile only using assembly.
The following code was used in DirectX 9:
static const char VertexShaderCode[] = \
"vs.3.0\n"
"dcl_position v0\n"
"dcl_position o0\n"
"mov o0, v0\n";
D3DXAssembleShader(VertexShaderCode,sizeof(VertexShaderCode), 0,0, DLL, &VSBuffer, 0);
I am looking for an alternative to the above code in DirectX11 using D3D11 dll's.
I want to modify my asm file like below and create vertex and pixel shaders:
dcl_output o0.xyzw -> dcl_output.o0.zw
Will I be able to do the same in fx or hlsl file?
FX file:
cbuffer ConstantBuffer : register( b0 )
{
matrix World;
matrix View;
matrix Projection;
}
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
VS_OUTPUT VS( float4 Pos : POSITION, float4 Color : COLOR )
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.Pos = mul( Pos, World );
output.Pos = mul( output.Pos, View );
output.Pos = mul( output.Pos, Projection );
output.Color = Color;
return output;
}
//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
float4 PS( VS_OUTPUT input ) : SV_Target
{
return input.Color;
}
Compiling from HLSL shader assembly isn't officially supported for Shader Model 4.0, 4.1, 5.0, or 5.1.
When you build with fxc.exe you get disassembly for debugging & optimization purposes
Related
I am trying to add a Geometry Shader to my DirectX 11 project in C++
There are no examples of this anywhere I look. There are millions of tutorials on OpenGL but nothing on geometry shaders in DirectX
I just wrote a basic shader below, but I get the following error when trying to build it
error X3514: 'LightGeometryShader' must have a max vertex count
Can anyone please advise on what this shader is missing to be able to compile?
////////////////////////////////////////////////////////////////////////////////
// Filename: light.gs
////////////////////////////////////////////////////////////////////////////////
//////////////
// TYPEDEFS //
//////////////
struct GeometryInputType
{
float4 position : POSITION;
float2 tex : TEXCOORD0;
float3 normal : NORMAL;
};
struct PixelInputType
{
float4 position : SV_POSITION;
float2 tex : TEXCOORD0;
float3 normal : NORMAL;
};
////////////////////////////////////////////////////////////////////////////////
// Geometry Shader
////////////////////////////////////////////////////////////////////////////////
PixelInputType LightGeometryShader(GeometryInputType input)
{
PixelInputType output;
output = input;
return output;
}
GeometryShader is not necessarily a 1:1 function, which is why you have to provide a max vertex count. See Microsoft Docs.
[maxvertexcount(3)]
void LightGeometryShader( triangle GeometryInputType input[3],
inout TriangleStream<PixelInputType> outStream )
{
PixelInputType output;
for( int v = 0; v < 3; v++ )
{
output.position = input[v].position;
output.tex = input[v].tex;
output.normal = input[v].normal;
outStream.Append( output );
}
}
Geometry Shader was introduced with Direct3D 10, so the bulk of the deved samples were in the legacy DirectX SDK at the time. You can find the latest copy of these samples buildable without the legacy DirectX SDK on GitHub.
I'm adding a geometry shader (a very simple one) to my DirectX 11 program. I've already got vertex and pixel shader written, and they work just as expected - no errors, no warnings. The shaders are simple, too. The vertex shader is:
cbuffer PerApplication : register(b0)
{
matrix projectionMatrix;
}
cbuffer PerFrame : register(b1)
{
matrix viewMatrix;
}
cbuffer PerObject : register(b2)
{
matrix worldMatrix;
}
struct VertexShaderInput
{
float4 position : POSITION;
float4 color: COLOR;
};
struct VertexShaderOutput
{
float4 color : COLOR;
float4 position : SV_POSITION;
};
//entry point
VertexShaderOutput SimpleVertexShader(VertexShaderInput IN)
{
VertexShaderOutput OUT;
matrix mvp = mul(projectionMatrix, mul(viewMatrix, worldMatrix));
OUT.color = IN.color;
OUT.position = mul(mvp, IN.position);
return OUT;
}
The pixel shader is:
struct PixelShaderInput
{
float4 color : COLOR;
};
float4 SimplePixelShader(PixelShaderInput IN) : SV_TARGET
{
return IN.color;
}
Well, as I've said, that's working pretty well. Then I'm adding a geometry shader, which doesn't actually do anything, it just takes a triangle and returns the same triangle. The geometry shader is:
struct VertexInput
{
float4 color : COLOR;
float4 position : POSITIONT;
};
struct VertexOutput
{
float4 color : COLOR;
float4 position : SV_Position;
};
[maxvertexcount(3)]
void SimpleGeometryShader(triangle VertexInput input[3], inout TriangleStream<VertexOutput> stream)
{
VertexOutput v1 = { input[0].color, input[0].position };
stream.Append(v1);
VertexOutput v2 = { input[1].color, input[1].position };
stream.Append(v2);
VertexOutput v3 = { input[2].color, input[2].position };
stream.Append(v3);
stream.RestartStrip();
}
Doing this also requires to change the vertex shader, which now returns
struct VertexShaderOutput
{
float4 color : COLOR;
float4 position : POSITIONT; //I'm not returning SV_Position in vertex shader anymore.
};
And the program itself works, and it works as expected, I see what I expect to see. But there are now two D3D11 errors:
D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: Vertex Shader - Geometry Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (POSITIONT,0) as input, but it is not provided by the output stage. [ EXECUTION ERROR #342: DEVICE_SHADER_LINKAGE_SEMANTICNAME_NOT_FOUND]
D3D11 ERROR: ID3D11DeviceContext::DrawIndexed: Geometry Shader - Pixel Shader linkage error: Signatures between stages are incompatible. The input stage requires Semantic/Index (TEXCOORD,0) as input, but it is not provided by the output stage. [ EXECUTION ERROR #342: DEVICE_SHADER_LINKAGE_SEMANTICNAME_NOT_FOUND]
Both are pretty strange. The vertex shader clearly returns a POSITIONT, and COLOR and POSITIONT are in the same order. What's my mistake?
The reason of the problem was that beside of rendering the scene using the shaders that I provided I was also drawing text using some library. Obviously, there were some vertex and pixel shaders involved in it with their own input and output signatures. Setting geometry shader to null solved my problem.
Its says: Invalid vs_2_0 output semantic SV_Target.
So for some reason Visual Studio 2017 is compiling my pixel shader as if it is a vertex shader. But in the properties panel I specified it to be a ps_5_0. Is there something I'm missing that should be specified?
Vertex shader:-
cbuffer ConstantBuffer : register(b0)
{
matrix World;
matrix View;
matrix Projection;
}
struct Input {
float3 Pos : POSITION;
float4 Color: COLOR;
};
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
};
VS_OUTPUT main(Input input)
{
VS_OUTPUT output = (VS_OUTPUT)0;
output.Pos = mul(input.Pos, World);
output.Pos = mul(output.Pos, View);
output.Pos = mul(output.Pos, Projection);
output.Color = input.Color;
return output;
}
Pixel shader:-
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
};
float4 main(VS_OUTPUT input) : SV_Target
{
return input.Color;
}
And here are my settings for the pixel shader.
I hope someone can help me.
Open the Property page for the .hlsl file, and in HLSL Compiler/General/Shader Type select Pixel Shader.
And don't forget to set this propertie for debug and release.
You can resolve the issue by modifying the shader property
properties -> HLSL Compiler -> General -> Shader Type -> Pixel Shader (/ps)
OR
Configuration properties -> General -> Excluded from Build = Yes.
I have searched a lot on Google and most of examples achieving gradient using texture coordinates. But I don't have texture coordinates with me. I am working on 3D text on which I want to apply gradient color. Is it possible? If yes, how? Is it necessary to have texture coordinates for obtaining color gradient?
Following is the part of my hlsl shader file :
struct VS_INPUT
{
float3 Pos : POSITION;
float3 Norm : NORMAL;
};
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float3 WorldNorm : TEXCOORD0;
float3 CameraPos : TEXCOORD1;
float3 WorldPos : TEXCOORD2;
};
//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
PS_INPUT VS( VS_INPUT input )
{
PS_INPUT output = (PS_INPUT)0;
float4 worldPos = mul( float4(input.Pos,1), World );
float4 cameraPos = mul( worldPos, View );
output.WorldPos = worldPos;
output.WorldNorm = normalize(mul( input.Norm, (float3x3)World ));
output.CameraPos = cameraPos;
output.Pos = mul( cameraPos, Projection );
return output;
}
//--------------------------------------------------------------------------------------
// Pixel Shader Without Light
//--------------------------------------------------------------------------------------
float4 PS( PS_INPUT input) : SV_Target
{
float4 finalColor = {1.0f, 0.0f, 0.0f, 1.0f};
return finalColor;
}
//--------------------------------------------------------------------------------------
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0_level_9_1, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0_level_9_1, PS() ) );
}
}
You don't need texture coordinates, because they are only one possible method (the most flexible) to save needed information about how your gradient should look like, as such origin, direction and length.
To have a gradient from left to right of your 3D-Text, you need to know where is left and right in your shader to take the appropriate color. I assume that your text is changing and such dynamically, so you need to transport this information into the shader, which either can be placed into the vertices directly by texture coordinates or with a constant buffer. Last method would only work if you draw at most one text per drawcall, because the gradient data is persistent over the whole drawing of all triangles in your drawcall.
If your situation is more special, as like your text is axis-aligned, you could take this axis and the worldposition in your pixelshader to determine the relative position for your gradient, but this method makes many assumptions as you still need the left and right maximum of your text.
I am trying to achieve deferred shading in DirectX 11 , c++. I have managed to create the G-Buffer and render my scene to it(Checked with "GPU PerfStudio"). I am having difficulty with final lighting stage. I am not able to read from textures(Diffuse,Normal,Specular) using SV_Position returned coordinates.
This is the pixel shader used to render light as shapes.
Texture2D<float4> Diffuse : register( t0 );
Texture2D<float4> Normal : register( t1 );
Texture2D<float4> Position : register( t2 );
cbuffer MaterialBuffer : register( b1 )
{
float4 ambient;
float4 diffuse;
float4 specular;
}
//--------------------------------------------------------------------------------------
struct VS_OUTPUT
{
float4 Pos : SV_POSITION;
float4 PosVS: POSITION;
float4 Color : COLOR0;
float4 normal : NORMAL;
};
float4 main(VS_OUTPUT input) : SV_TARGET
{
//return Diffuse[screenPosition.xy]+Normal[screenPosition.xy]+Position[screenPosition.xy];
//return float4(1.0f, 1.0f, 1.0f, 1.0f);
//--------------------------------------------------------------------------------------
//Problematic line
float4 b=Diffuse.Load(int3(input.Pos.xy,0));
//--------------------------------------------------------------------------------------
return b;
}
I have checked with "GPU PerfStudio" the input textures are properly bound.
The above code is returning the color I used to clear the texture.(From my debugging I have found that its returning value at pixel location 0,0)
If I replace the problematic line with:-
float4 b=Diffuse.Load(int3(350,300,0));
Then its rendering the value at 350,300 pixel location with the proper shape of light.
Thanks
Do you tried with the debug flag D3D11_CREATE_DEVICE_DEBUG at device creation and looked at the output log. You may experience signature mismatch between the Vertex and the Pixel stages. It would explain why the sv_position semantic do not behave correctly.
I solved the problem.I was using the same z-buffer for rendering light geometries that I had used previously for G-buffer.
Thank you for your response.