• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
MrCodeSushi

Constant Buffer scalar type data member problem

13 posts in this topic

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!

1

Share this post


Link to post
Share on other sites

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.

2

Share this post


Link to post
Share on other sites

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?

1

Share this post


Link to post
Share on other sites

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?

1

Share this post


Link to post
Share on other sites

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?

1

Share this post


Link to post
Share on other sites

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();
}
0

Share this post


Link to post
Share on other sites

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?

1

Share this post


Link to post
Share on other sites

Hi Jason,

 

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

0

Share this post


Link to post
Share on other sites

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
0

Share this post


Link to post
Share on other sites

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?

1

Share this post


Link to post
Share on other sites

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

1

Share this post


Link to post
Share on other sites

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???

0

Share this post


Link to post
Share on other sites

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

 

2

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  
Followers 0