Shader data flow questions
Two questions:
1. Is there any decent way to get a small chunk of data (4-8 bytes) from a vertex shader back to the CPU? I would only do this in direct response to a mouse click, so it need not be fast, just possible.
2. The MSDN reference material
here would suggest that a variable declared
static could carry information from one shader invocation to the next, so that one could, for example, calculate a running min, max, or average of some property over all vertices. But in practice it seems that my static variable is zeroed afresh for every vertex.
Below are the bones of my test case. The CPU program is providing each vertex with the "extra" variable, of which extra.x is a unique id for each vertex, starting with 0.0 for the first, counting by 1.0 each time. This information is demonstrably getting through. However, reading the documentation would suggest that the line labelled "HERE'S THE ACTION" should give me all vertices red. In fact, I get only one red vertex, namely the first, suggesting that pickd is NOT retaining a value.
Am I missing something really obvious? Should I be reading a different reference? Is there one document somewhere that is The Definitive Reference for HLSL?
[using DirectX 9 (June SDK), 6800 Ultra graphics card, Windows XP Pro, using D3DXCreateEffectFromFile to set up the shader.]
uniform extern float4x4 gWVP;
OutputVS MyDemoVS(float3 posL : POSITION0, float2 extra : TEXCOORD0) {
static float pickd = 0;
if (extra.x == 0) pickd = 100; // reset picking algorithm, once per frame
OutputVS outVS = (OutputVS)0;
outVS.color.y = extra.x / 4000.0; // visually demonstrates that the ID is getting through
// Transform to homogeneous clip space:
outVS.posH = mul(float4(posL, 1.0f), gWVP); if (pickd == 100) outVS.color = red; // HERE'S THE ACTION
return outVS;
}
1. With Direct3D 9 there is no way to do this directly. But you can move the values forward to a pixel shader write them to a render target. Then you can use GetRenderTarget to read them back. Direct3D 10 will support this with the new Stream Out function.
2. The meaning of static is different here. If you write functions that are called from other functions all local variables in these are normally not persistent. If you use static the will hold the values if called multiple times for the same vertex/pixel. But they are not hold for the next vertex/pixel.
What you are trying to do? Maybe there is another solution.
What I'm trying to do: it would be very convenient, for my purpose, to use a vertex shader for picking, given the 2D position of a mouse click. The shader has the right information at the right time to find the 2D proximity of the mouse to a vertex. I don't even
have to get the pick information back to the CPU to do some cool stuff. If I could find
any way to carry information across vertices I could find the vertex with the minimum 2D distance to the mouse position.
So, is there any? Any class of variable at all that will be shared among all vertices, that the shader can actually modify?
Well, there is no way to keep values persistent inside the shaders. A shader unit’s work with a SIMD approach it would be nearly impossible to build such a thing effective.
But I believe I have a possible solution for your problem.
If I understand you right you want to test if your vertex inputs match special criteria (set as shader constant). If it does you want to write some calculated values in a buffer that can later access from the CPU. Unfortunately there can be more than one positive match in the shader and you need to find the best.
You can try the following:
Make your check as before but set the sort criteria to the Z value. Than the Z-Buffer will find your best match for you. Make sure that you use Z values that macth your viewport settings.