Jump to content

  • Log In with Google      Sign In   
  • Create Account

Constant Buffer scalar type data member problem


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
13 replies to this topic

#1 BrentChua   Crossbones+   -  Reputation: 1066

Like
1Likes
Like

Posted 20 February 2013 - 08:09 AM

In one of my shaders i have a cbuffer that contains two floats like this:

 

cbuffer cCameraParams
{
	float gfx_gCamProjA;
	float gfx_gCamProjB;
}

 

 

In my C++ app code, my shader update function individually assigns the value for gfx_gCamProjA and gfxCamProjB. Both of them have different values. When i debug my shader code using the Visual Studio Graphics Diagnostics Tool, i see that gfx_gCamProjA and gfx_gCamProjB both have the same values where they should not. The debug tool shows gfx_gCamProjB being replaced by the value of gfx_gCamProjA.

 

I don't understand because in my c++ code gfx_gCamProjB is assigned second but shader debug shows the value of gfx_gCamProjA for both. Adding 3 floats like the code below seems to fix the problem though:

 

cbuffer cCameraParams
{

	float gfx_gCamProjA;
	float pad1;
	float pad2;
	float pad3;
	float gfx_gCamProjB;
}

 

I'm using the shaderreflection to get each constant buffer variable's memory offset so i'm sure i'm using the right byte address offset to assign the value. Also, the values i'm assigning from are also floating point values(4-bytes). So i don't really know what or where i am doing wrong. Any help anyone can give is greatly appreciated.

 

Thanks!



Sponsor:

#2 mhagain   Crossbones+   -  Reputation: 8279

Like
2Likes
Like

Posted 20 February 2013 - 09:40 AM

You can do this instead:

 

cbuffer cCameraParams
{
	float gfx_gCamProjA : packoffset(c0.x);
	float gfx_gCamProjB : packoffset(c0.y);
}

That way you always know exactly where in the buffer your constants are, and you can always be certain to have them set right.


It appears that the gentleman thought C++ was extremely difficult and he was overjoyed that the machine was absorbing it; he understood that good C++ is difficult but the best C++ is well-nigh unintelligible.


#3 BrentChua   Crossbones+   -  Reputation: 1066

Like
1Likes
Like

Posted 20 February 2013 - 09:57 AM

Hi mhagain,

 

Thanks for your response. I tried your suggestion but i'm still getting the same problem. It seems it doesn't like being shared in one register. I know you can't fit one element that spans more than one register but in my example i only have two floats which shouldn't be a problem fitting in a four 4 bytes register... Am i correct?



#4 MJP   Moderators   -  Reputation: 11774

Like
1Likes
Like

Posted 20 February 2013 - 01:52 PM

Something is wrong here...with the constant buffer definition you posted the 2 floats should be tightly packed with no padding according to the HLSL packing rules for constant buffers. The only time there will be padding is if a single variable will cross a 16-byte boundary, in which case that variables gets aligned to the next 16-byte offset. Are you using a sub-10 feature level?



#5 BrentChua   Crossbones+   -  Reputation: 1066

Like
1Likes
Like

Posted 20 February 2013 - 08:55 PM

I'm using D3D_FEATURE_LEVEL_11_0. I double checked my code. I can verify its using the right memory offset and data size to copy the data over.

 

My C++ shader class is based on Jason Zink's Hieroglyph engine and also using his parameter system to pass the data to the constant buffer variables. I noticed that he doesn't even support a scalar parameter in his parameter system; Only vector4 and matrix4x4 types besides others. Is there a limitation to only write 16-byte values at a time?



#6 BrentChua   Crossbones+   -  Reputation: 1066

Like
0Likes
Like

Posted 20 February 2013 - 09:01 PM

I don't think it should really matter if i copy one variable at a time though since i only do map() and unmap() once after individually updating each variable.

 

If it helps here's my constant buffer update code:

{
	ConstantBuffer *pBuffer = m_constantBuffers[i];
	MappedResource mapRes;
				
	pBuffer->Map( &mapRes );

	for ( SIZE_T j = 0; j < numVariables; ++j )
	{
		ShaderVariable *pShaderVar = &pLayout->variables[j];
		IParameter *pParam = pLayout->m_parameters[j]; 
					
		pShaderVar->m_changeValue = pParam->GetChangeValue();

		if ( pShaderVar->type.classType == EShaderVariableClass::SCALAR )
		{
			void* pData = ((ParameterScalar*)pParam)->GetData();
			PSX_MemCopyPerByte( (void*)(mapRes.pData + pShaderVar->desc.offset), pData, pShaderVar->desc.size );
		}
		else if ( pShaderVar->type.classType == EShaderVariableClass::VECTOR )
		{
			// Vector3 or Vector4
			if ( pShaderVar->type.numColumns == 3 )
			{
				const Vector3 *pParamVec = ((ParameterVector3*)pParam)->GetVector();
				Vector3 *pBufferVec = (Vector3*)&mapRes.pData[pShaderVar->desc.offset];
						
				*pBufferVec = *pParamVec;
			}
			else
			{
				const Vector4 *pParamVec = ((ParameterVector4*)pParam)->GetVector();
				Vector4 *pBufferVec = (Vector4*)&mapRes.pData[pShaderVar->desc.offset];

				*pBufferVec = *pParamVec;
			}
		}
		else if ( pShaderVar->type.classType == EShaderVariableClass::MATRIX_ROWS ||
			pShaderVar->type.classType == EShaderVariableClass::MATRIX_COLUMNS )
		{
			// Is this an array of matrices or not
			if ( pShaderVar->type.numElements == 0 )
			{
				const Matrix4x4 *pMat = ((ParameterMatrix*)pParam)->GetMatrix();
				Matrix4x4 *pBufferMat = (Matrix4x4*)&mapRes.pData[pShaderVar->desc.offset];

				*pBufferMat = *pMat;
			}
			else
			{
				SIZE_T paramSize = ((ParameterMatrixArray*)pParam)->GetNumMatrices() * sizeof(Matrix4x4);
				if (  paramSize ==  pShaderVar->desc.size )
				{
					const Matrix4x4 *pMat = ((ParameterMatrixArray*)pParam)->GetMatrixArray();
					PSX_MemCopyPerByte( (void*)&mapRes.pData[pShaderVar->desc.offset], pMat, paramSize );
				}
				else
				{
					PSX_PushWarning( "Shader variable size and parameter matrix array size mismatch. Skipping this variable update." );
				}
			}
		}
		else
		{
			PSX_PushError( "Unsupported variable class type." );
		}
	}

	pBuffer->UnMap();
}


#7 Jason Z   Crossbones+   -  Reputation: 5352

Like
1Likes
Like

Posted 20 February 2013 - 09:42 PM

Constant buffers are required to have 16-byte aligned structures, which is why I never added support for scalar types.  Instead, if I only need a single scalar value, then I use a float4 and just grab a single channel component.

 

You can test if this is the issue by expanding your definition to include a total of four scalars, and then just copy the other extra values as 0.0 when you map the buffer.  If it works, then you likely have an issue with 16-byte alignment.  As a slight aside, do you get any warnings out of the debug output when you create or map your constant buffer?



#8 BrentChua   Crossbones+   -  Reputation: 1066

Like
0Likes
Like

Posted 20 February 2013 - 11:48 PM

Hi Jason,

 

Thanks for your suggestion. I'll try it out later when i get back home and let you know how it goes. 



#9 BrentChua   Crossbones+   -  Reputation: 1066

Like
0Likes
Like

Posted 21 February 2013 - 07:09 AM

I tried rearranging my constant buffer like this:

 

cbuffer cCameraParams
{
	float gfx_gCamProjA;
	float gfx_gCamProjB;
        float pad1;
        float pad2;
}

 

But i'm still getting the same problem as before. Forcing gfx_gCamProjB in the second register seems to fix the problem.

 

 

I tried rarranging my cbuffer to this:

cbuffer cCameraParams
{
	float gfx_gCamProjA;
	float gfx_gCamProjB;
	float3 pad;
}

 

Since variable pad won't fit in the first 16-byte register, variable pad's offset correctly aligned itself in the second register, 16 bytes, based on the ShaderReflection. So i don't think it has a problem with the 16-byte alignment.

 

Also calling constant buffer map and unmap method doesn't show any debug warnings. When i compile my shader i add the following shader flags: 

#ifdef PSX_DEBUG
		flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_WARNINGS_ARE_ERRORS ;
#endif

 

 

 

I'm beginning to think the Visual Studio graphics debugger tool isn't showing the values right. I'm following MJP's post on reconstructing view space position from depth. I compared the "right" and "wrong" constant buffer formats and both of them returned the same view space position values. Here's the shader code that's using the gfx_gCamProjA and gfx_gCamProjB values:

 

float3 GetPositionVS( in float2 screenTexCoord, in float3 viewRay )
{
	// Sample the depth and convert to linear view space Z (assume it gets sampled as
	// a floating point value of the range [0,1])
	float depth = gfx_gLPDepthBuffer.Sample( samPoint, screenTexCoord ).x;
	float linearDepth = gfx_gCamProjB / (depth - gfx_gCamProjA);
	float3 positionVS = viewRay * linearDepth;

	return positionVS;
}

 

As you might know, my attempt to extract view space position from depth isn't going well either. But that'll be in my next post; hoping MJP will help me out. biggrin.png


Edited by BrentChua, 21 February 2013 - 07:15 AM.


#10 Jason Z   Crossbones+   -  Reputation: 5352

Like
1Likes
Like

Posted 21 February 2013 - 09:04 PM

If you are still willing to experiment, you could also try using a float4 instead of four scalar floats.  I don't really expect a difference since they should be automatically compiled into a single vector anyways, but I am curious if it gives you the correct result.

 

One other thing you could try is using the original PIX tool from the DXSDK (assuming it will still run correctly with your current OS version).  Perhaps there is a difference with how the tools are interacting with your application.

 

Have you tried running the application with the reference device to see if you are working correctly excluding the driver?



#11 BrentChua   Crossbones+   -  Reputation: 1066

Like
1Likes
Like

Posted 22 February 2013 - 10:52 AM

Hi Jason,

 

I tried your suggestion using float4/vector4 and VS debugger showed the correct values. I should note however that i still believe that the VS debugger isn't showing the debug values correctly. I think the actual values for my constant buffer are correct even though the debugger shows that it isn't. I've tested this by switching/replacing MJPs formula in the shader code from:

float linearDepth = gfx_gCamProjB / (depth - gfx_gCamProjA);

to:

float linearDepth = gfx_gCamProjA / (depth - gfx_gCamProjA);

 

using CamProjA for both shouldn't affect the value since, according to the debugger, camProjA and camProjB have the same values but i got a different value from the original formula.

 

I thought the ref device only supports DX10?

 

As a side note, i managed to fix my problem with reconstructing view space pos from depth.... ermm... i forgot to set the worldView matrix... dry.png



#12 BrentChua   Crossbones+   -  Reputation: 1066

Like
1Likes
Like

Posted 22 February 2013 - 10:54 AM

Thank you everyone for your help! It is nice to have great people like you helping the community. :)



#13 Jason Z   Crossbones+   -  Reputation: 5352

Like
0Likes
Like

Posted 22 February 2013 - 07:15 PM

I thought the ref device only supports DX10?

Nope - it is supporting D3D11 (and D3D11.1 where available).  I was using that reference device way back when D3D11 was still in CTP.  It is a great thing to have for debugging, but it is slow as molasses.  That is great that you got everything worked out - can we see a screenshot from the victorious BrentChua???



#14 BrentChua   Crossbones+   -  Reputation: 1066

Like
2Likes
Like

Posted 24 February 2013 - 05:51 AM

Ah. Good to know. I thought i read it somewhere that the ref device only support DX10 feature level. But that was like a year ago i might have just misread it.

 

That is great that you got everything worked out - can we see a screenshot from the victorious BrentChua???

lol. Nothing really special. I'm working on my very first Light Pre-pass renderer and its not even done yet. I just finished my lighting pass for point lights and i still need to finish the final geometry/composite pass. Here's a screenshot of my light buffer though. tongue.png

 

Attached Thumbnails

  • LightBuffer2.png





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS