Sign in to follow this  
BattleMetalChris

Altering vertex positions in the Vertex shader using constant buffer variables

Recommended Posts

I'm creating a screen-space quad for which I can just specify four clip-space coordinates when I create the quad and the code does all the rest for me. I also want the ability to dynamically move and resize these around the screen.

I thought, rather than create and alter vertex buffers at run-time, I could just leave position info out of the vertex buffer entirely and specify the coordinates to use with a constant buffer instead. Then I can just send the coodinates of the corners to the GPU (four float2s) before I draw. My intention was to have the vertex shader pick these up and set the vertices to the appropriate values.

A problem I hit was how to get the vertex shader to use a different coordinate for each vertex in the primitive. The solution I came up with was to have the screen space positions in an array in a constant buffer and have a static int representing the offset into this array. I then increment this static variable after each vertex has been processed, and have it loop back to zero once it reaches 4.

I thought this would work elegantly but it doesn't seem to be incrementing the offset. I've run it though PIX and it doesn't even seem to be compiling the offset factor into the shader code at all. Am I doing something wrong, or is there just no way to do it like this? Or am I being stupid doing it like this at all?

Here is my shader code:

[code]

// SHADER_QUAD

static int PosArrayCounter;

cbuffer posArray
{
float2 Positions[4];
};

Texture2D Image;

struct VS_OUTPUT
{
float4 PosH : SV_POSITION;
float2 Tex : TEXCOORD1;

};

SamplerState samLinear
{
Filter = MIN_MAG_MIP_LINEAR;
AddressU = Wrap;
AddressV = Wrap;
};

VS_OUTPUT VS(float2 Tex : TEXCOORD)
{
VS_OUTPUT output = (VS_OUTPUT)0;

output.PosH = float4(Positions[PosArrayCounter], 1, 1);
output.Tex = Tex;
PosArrayCounter++;
if (PosArrayCounter > 3)
{
PosArrayCounter = 0;
}
return output;
}

float4 PS( VS_OUTPUT input ) : SV_Target
{
float4 colour = Image.Sample(samLinear, input.Tex);

return colour;
}

//--------------------------------------------------------------------------------------
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );

}
}

[/code]

Share this post


Link to post
Share on other sites
MJP    19790
Yeah you can't increment a persistant variable like that in a vertex shader. The GPU will process many vertices in parallel rather than 1 at a time, and to make that sort of massively parallel programming easier for the for the programmer the runtime doesn't let different shader instances (threads) communicate with each other. The one exception is compute shaders, which can do so through shared memory.

Anway there's a really simple solution to your problem, which is to use SV_VertexID. This will give you the 0-3 index of the vertex you're processing, which you can use to look up the position from your constant buffer. In fact you can have no vertex buffer at all if you want, and put your texture coordinates in the constant buffer as well.

Share this post


Link to post
Share on other sites
Hmm... how do I get the vertex shader to pick up the SV_VertexID value? Pass it into the VS as a parameter? Do I then have to include it in the input layout or can I leave it out of there?

So far my google-fu has been fruitless.

Share this post


Link to post
Share on other sites
MJP    19790
Just pass it in to your vertex shader entry point, it doesn't need to be part of your input layout. The runtime will automatically generate it and pass it to your shader.

[code]
struct VSInput
{
float4 Position : POSITION;
float2 TexCoord : TEXCOORD;
uint VertexID : SV_VertexID;
};

VSOutput VSMain(in VSInput input)
{
...
}
[/code]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this