## Recommended Posts

##### Share on other sites
I've not seen/read your previous thread, but I've definitely implemented nearly this exact same code myself at some point in the distant past.

Quote:
 "Declaration can't map to fixed function FVF because position field is missing. Usage: D3DDECLUSAGE_POSITION, with usage index 0 is required for fixed function"This is confusing for a start, because I thought I was trying to use the programmable pipleline
Yes, I wouldn't be expecting that message. Maybe dig into PIX to see what state the pipeline is in - it may well be that with your order of pipeline configuration that it thinks you're using FF and later tell it otherwise. Or something silly like that.

Off the top of my head (don't have my old code to hand) the trick was creating two streams, one with a <D3DDECLUSAGE_POSITION, usage=0, size=float> and a <D3DDECLUSAGE_POSITION, usage=1, size=float2> and then the declaration in the VS can be something like:

struct vsi{    float y : POSITION0;    float2 xz : POSITION1;    // ...};vso vs( in vsi vertex ){    float3 pos = float3( vertex.xz.x, vertex.y, vertex.xz.y );    // ... }

If that fragment doesn't yield anything, can you post your declarations - both app and shader side?

hth
Jack

##### Share on other sites
Just off the top of my head, have you tried setting stream zero as D3DDECLUSAGE_POSITION with a float3 type containing (x,z,0) and stream one as D3DDECLUSAGE_TEXCOORD with a float type containing (y)?

##### Share on other sites
Thanks for the quick responses guys.

Quote:
 Off the top of my head (don't have my old code to hand) the trick was creating two streams, one with a and a and then the declaration in the VS can be something like:

Jack, that doesn't quite work in my configuration as when using POSITION as a usage, it requires a size of FLOAT3. Here is my exact usage at the moment:

D3DVERTEXELEMENT9 declTerrainXYZ[]={  {0, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},  {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 1},  D3DECL_END()};

When I call the DrawIndexPrimitive method using this declaration, I get

"Declaration can't map to fixed function FVF because position must use D3DDECLTYPE_FLOAT3". Here is the very simple shader fx file I'm using:

struct V_To_P{  float4 Position : POSITION;  float4 Color : COLOR0;};float4x4 xViewProjection;V_To_P SimpleVertexShader( float1 y : POSITION0, float2 xz : POSITION1){  V_To_P Output = (V_To_P)0;  ....  return Output;}technique Simplest{  pass Pass0  {    VertexShader = compile vs_3_0 SimpleVertexShader();    PixelShader = NULL;  }}

Here is the code to draw the primitives:

D3DXHandle technique = effect->GetTechniqueByName("Simplest");D3DXHandle matrix = effect->GetParameterByName(0, "xViewProjection");hr = effect->SetTechnique(technique");hr = effect->SetMatrix(...);hr = DXUTGetD3DDevice()->SetVertexDeclaration(<as above>);hr = DXUTGetD3DDevice()->SetStreamSource(0, <vertexbufferwithsinglefloats>, 0, sizeof(float));hr = DXUTGetD3DDevice()->SetStreamSource(0, <vertexbufferwithfloatpairs>, 0, sizeof(float) * 2);hr = DXUTGetD3DDevice()->SetIndices(<regular indices>);// then simple beginpass, drawindexprimitive, endpass, etc

Tim, if I specify FLOAT3 for both elements and use usagetypes of POSITION, it doesn't error, but how would I specify that my first FLOAT3 is only (x, y, 0) and the second is only (x, 0 ,0)?

Thanks guys, I'd really love to get to the bottom of this.

##### Share on other sites
When you create the VBs you need to fill them with 3 floats, either using three seperate floats or using a D3DXVECTOR3. Not quite sure how to describe it, this isn't my dev machine and I don't have any code here. I'm geussing you define a struct for your vertex data, fill an array of them and then memcopy into your VB. In this struct you need the three floats instead of one or two, when you fill in the instances of this struct in the array you set the unused values as 0.

Also you don't necessarily need to use FLOAT3 for texcoord, which is why i suggested it instead of position1, you can definately use FLOAT2, and i think you might be able to use just FLOAT.

Lastly, in your set stream source calls, the first parameter of the first call should be 1, not 0.

##### Share on other sites
Quote:
 Original post by RobMaddisonJack, that doesn't quite work in my configuration as when using POSITION as a usage, it requires a size of FLOAT3.
I did a bit of reading around on MSDN and I must be remembering my code wrong for exactly the reason you state. I am left wondering whether I just used TEXCOORD fields instead - they're about the only 'free form' field you can use with D3D9 as the rest all have quite strictly defined semantics.

It's been quite a while since I did any D3D9 work, but can you try your code using TEXCOORD instead of POSITION? A straight up substitution should suffice and the test will be whether the runtime throws a wobbly over not having a POSITION...

Quote:
 if I specify FLOAT3 for both elements and use usagetypes of POSITION, it doesn't error, but how would I specify that my first FLOAT3 is only (x, y, 0) and the second is only (x, 0 ,0)?
I'm pretty sure you can't - the IA stage would just lump through two float3's and you'd just burn the extra storage and bandwidth.

hth
Jack

##### Share on other sites
Hi Tim

Thanks for spotting the error in the SetStreamSource line, although that was a typo as my code is on my dev machine.

I see what you're saying about putting FLOAT3's (or vectors) into the vertex buffer, but the whole point of this exercise for me is to cut down on memory by reusing the x and z coordinates of each terrain patch as they are regular grids. The heights are individual and need to be stored in a buffer on their own. If I store 3 float vectors in the buffer, then I may as well store the x and z too in the unused parts. This would take up too much memory though, as my terrain at the highest LOD level is made up of 4096 65x65 patches.

Using the method I'm aiming at, the y values for the entire terrain would take up:

65x65 (verts) = 4225 total verts per patch
4225 x 4 bytes (y value float) = 16,900 bytes
16,900 x 4096 (patches) = 69.2mb

the x and z coordinates would only need to be stored for one patch - when drawing, they'll just be translated to the correct positon.

This is a totally acceptable amount of memory for what I need, but if I have to add the x and z into the mix, my vertex buffer(s) grow to over 200mb which I can't afford. Does that help to explain what I'm trying to achieve better?

Thanks

##### Share on other sites
Hi Jack

I tried using TEXCOORD instead of position and yes, it complains that it should have a POSITION:

"Declaration can't map to fixed function FVF because position field is missing. Usage: D3DDECLUSAGE_POSITION, with usage index 0 is required for fixed function"

(I had also changed the shader file to use TEXCOORD0 and TEXCOORD1 as the inputs).

It would appear to me that my engine somehow things I'm tryin to use the fixed function pipeline. Is there a way to tell which I'm using? I'm currently using the DXUT libraries just to get things up and running. If there's a "SetDeviceToUseFVF" or something similar I can just do a search for it in my code.

Thanks again for your input, it is much appreciated.

##### Share on other sites
OK sorry about that then, I thought there was some other reason you needed them seperated over two buffers. In that case I think you might want to look into hw instancing, if your target hardware supports it. I can't remember how to do it without looking at my old code, but the DX SDK has some pretty good info about it. The basic premise would be to still use FLOAT3 for the position with an empty value, also still use texcoord for the y's. However, you should be able to send one patch of position data and multiple patches of height data and tell d3d to draw multiple copies of the position VB. I'm not 100% sure this will be possible in this case. The way I did it was to have stream 0 contain the position VB, stream one contain a second position which was an offset for the whole patch and then store the height information as a texture using VTF. The problem is you will need three streams, each with a different stride, one for (x,z,0), one for patcht offset and one for height data. I know its designed for two, but I'm not sure about three, the docs will probably mention it.

##### Share on other sites
Tim

I believe you might be onto something here. If I put the FLOAT3 POSITION value first, that satisfies DX's need for it and my repeated xz values can just have a dummy 0 value added for the y - I can then hopefully make the second stream just use TEXCOORD with FLOAT1.

I'll let you know how I get on, thanks.

Rob

##### Share on other sites
Tim's idea for using instancing is a good one - I should imagine it'll work nicely on paper, but do be careful about performance testing it. A bit outdated now, but I know there were some earlier SM2/SM3 GPU's that weren't quite so instancing-friendly, especially with unaligned strides or something like that.

Quote:
 ...This would take up too much memory though, as my terrain at the highest LOD level is made up of 4096 65x65 patches.
Have you considered a streaming architecture? I've had success with a crude implementation years back and am currently toying with some code to take advantage of multithreading for this. You can potentially reduce the in-memory working set down to an acceptable level whilst effectively making the landscape unbounded in size...

Quote:
 Original post by RobMaddisonIt would appear to me that my engine somehow things I'm tryin to use the fixed function pipeline. Is there a way to tell which I'm using? I'm currently using the DXUT libraries just to get things up and running. If there's a "SetDeviceToUseFVF" or something similar I can just do a search for it in my code.
There is no such call unfortunately - that'd just make things far too easy [cool]

I'd recommend grabbing a single-frame capture using PIX and stepping through it to the offending Draw**() call. You should be able to pull up the device state at that point in time and find out what its basing that message on.

It's common enough in complex D3D apps to think you're setting pipeline state in a certain way only to find a leaked state ruining the party. PIX will tell you exactly what state the device is in and if this isn't what you expect then you've got an application bug - you could be lucky and find that the message is due to something like this.

The flipside of course is that the state matches what you're expecting and you've either proven that your app isn't setting the correct state or you simply cant do what you're trying to do - any of the 3 outcomes being quite useful to know!

hth
Jack

##### Share on other sites
Well, I'm getting close...

My vertex declaration looks like this:

D3DVERTEXELEMENT9 declTerrainXYZ[]={  {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},  {1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},  D3DECL_END()};

The inputs to my vertex shader are:

V_To_P SimpleVertexShader( float3 Position : POSITION, float2 yy : TEXCOORD){  V_To_P Output = (V_To_P)0;  float4 newPos = float4(Position.x, yy.x, Position.z, 1.0);  Output.Position = mul(newPos, xViewProjection);  ...  return Output;}

and a snippet of my c++ code:

hr = DXUTGetD3DDevice()->SetVertexDeclaration(<as above>);hr = DXUTGetD3DDevice()->SetStreamSource(0, <VertexBufferWithD2DXVECTOR3Verts>, 0, sizeof(D3DXVECTOR3));hr = DXUTGetD3DDevice()->SetStreamSource(1, <VertexBufferWithHeightFloatPairs>, 0, sizeof(float) * 2);hr = DXUTGetD3DDevice()->SetIndices(<regular indices>);

I am getting the correct triangles drawn, but the heights are not being picked up by the second stream, i.e. in the shader yy.x (and yy.y) is coming through as zero and the vertex buffer definitely contains heights.

Any ideas folks?

Thanks

##### Share on other sites
Shouldn't the first line of the shader have TEXCOORD0 not TEXCOORD? Other than that I don't know.

##### Share on other sites
Hi Tim

I did try that one and it didn't work. What I did do is pad the second stream out to D3DXVECTORS and supply it as a POSITION1 field which worked perfectly, but defeats the object of my exercise. So I know the shader and drawing code is correct, it's just I need to find a way to pass in 1 float as the second input.

Thanks
Rob

##### Share on other sites
Hmm, thats odd. I can't see anything obviously wrong with the code you posted, and the method works as I've used it myself, I'm not really sure what to suggest, sorry.

One thing I did notice is that you are using D3DDECLTYPE_FLOAT2 when the docs say that you should be able to use D3DDECLTYPE_FLOAT1 with D3DDECLUSAGE_TEXCOORD, which would halve the memory you need. Of course thats only true if it actually works.

##### Share on other sites
Hi Tim

Yes, I've tried it with just about every float including D3DDECLTYPE_FLOAT1 and nothing seems to work other than D3DDECLTYPE_FLOAT3 and POSITION(1). I'm now reinvestigating my vertex buffer creation just to be 100% sure it contains the height values. It's something I've checked and analyised twice before, but I'm running out of ideas!

Thanks

##### Share on other sites
Don't pass an FVF to CreateVertexBuffer, pass 0. This may make D3D complain if the FVF and your declaration are different. Other than that, the only reason I could see it complaining is that you haven't actually activated your effect before you draw. I have several shaders where my position is short2, and it works fine.

If you aren't using a shader, and have fixed pipeline vertex processing, your inputs have to be what the fixed pipe wants. For a shader you can input whatever you want. Since you have a shader, all I can think of is that it's not actually being used, and the fixed pipeline is complaining at you.

##### Share on other sites
Does the card that you're trying to run this on have hardware vertex processing? Did you enable it with D3DCREATE_HARDWARE_VERTEXPROCESSING?

If I remember correctly software vertex processing is much more restrictive on what you can put in the declarations.

##### Share on other sites
Quote:
 Does the card that you're trying to run this on have hardware vertex processing? Did you enable it with D3DCREATE_HARDWARE_VERTEXPROCESSING?If I remember correctly software vertex processing is much more restrictive on what you can put in the declarations.

I haven't explicitly set that flag (D3DCREATE_HARDWARE_VERTEXPROCESSING), I'll check - it certainly looks to be using hardware vertex processing (it's extremely fast).

Quote:
 Don't pass an FVF to CreateVertexBuffer, pass 0. This may make D3D complain if the FVF and your declaration are different.

I do pass zero in the FVF param of CreateVertexBuffer.

Quote:
 Other than that, the only reason I could see it complaining is that you haven't actually activated your effect before you draw. I have several shaders where my position is short2, and it works fine.

The actual drawing of the vertices is working fine with regard to the effect/shader. I am passing in untransformed world terrain vertices and the shader is transforming them to my viewport perfectly. The following line in my shader:

Output.Position = mul(newPos, xViewProjection);

Proves that theory. The terrain grid draws perfectly well, it's just flat.

One thing I've been musing over for the last few minutes is whether the elements I put into my vertex buffer need to be in a struct with an x accessor. It works with two streams of D3DXVECTOR3 types - I'm wondering whether my second vertex buffer should be filled with something like:

struct oneFloatVertex
{
float x;
};

At the moment, I just fill it with float types. I'm wondering if the vertex shader needs something with an accessor in order to use the yy.x accessor I've used in my shader.

Thanks for all the help so far guys.

##### Share on other sites
Thanks to everyone for their help on this, but I've figured it out (and how annoyingly simple is the fix!).

Essentially, the vertex buffers are fine but this declaration:

D3DVERTEXELEMENT9 declTerrainXYZ[]={  {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},  {1, 0, D3DDECLTYPE_FLOAT1, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},  D3DECL_END()};

Needs to be this in the vertex shader signature:

V_To_P SimpleVertexShader( float3 Position : POSITION, float4 Ypos : TEXCOORD){  V_To_P Output = (V_To_P)0;  float4 newPos = float4(Position.x, Ypos.x, Position.z, 1.0);  Output.Position = mul(newPos, xViewProjection);  ...  return Output;}

Notice that the Ypos TEXCOORD input type is a float4, not a float1 as you'd expect. I read somewhere that a D3DDECLTYPE_FLOAT1 expands to float4(x, 0.0, 0.0, 1.0).

Now working perfectly.

Thanks again

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628305
• Total Posts
2981962

• 9
• 12
• 11
• 12
• 11