Advertisement

Silly Input Layout Problem

Started by September 21, 2018 05:58 PM
10 comments, last by MJP 6 years, 4 months ago

Hi all, I was changing my instance input from a D3DVector3 to D3DXMATRIX and I'm running into trouble.

I chose DXGI_FORMAT_R16G16B16A16_FLOAT as the format for my matrix input, I don't know if this is right but it's not complaining, its for 64 bits and my matrix is 64 bits

 

So I am running into this error:

D3D11 ERROR: ID3D11Device::CreateInputLayout: The provided input signature expects to read an element with SemanticName/Index: 'INSTANCE'/1, but the declaration doesn't provide a matching name. [ STATE_CREATION ERROR #163: CREATEINPUTLAYOUT_MISSINGELEMENT]
 

Actually 3 of them, 'INSTANCE'/1 'INSTANCE'/2 'INSTANCE'3

 

It's saying the declaration doesn't provide a matching name, I'm assuming its talking about this?

 


VOut VShader(float4 position : POSITION, float4 color : COLOR, float4x4 instancePosition : INSTANCE)

 

But its there?

 

Here is all the code, this is probably a really silly oversight:

 

My instance struct in my C++ code:


	struct Instance
	{
		D3DXMATRIX position;
	};

 

The input layout creation:


bool Renderer::createInputLayout(ID3D11Device * dev, ID3D11DeviceContext * devcon, ID3D10Blob * Shader)
{
	HRESULT hr;
	// create the input layout object
	D3D11_INPUT_ELEMENT_DESC ied[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "INSTANCE", 0, DXGI_FORMAT_R16G16B16A16_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
	};

	hr = dev->CreateInputLayout(ied, 3, Shader->GetBufferPointer(), Shader->GetBufferSize(), &pLayout);
	if (!FAILED(hr))
	{
		devcon->IASetInputLayout(pLayout);
		return true;
	}
	else
	{

		return false;
	}

}

 

Finally, the shader code (Note, I also still need to figure out what to do with my new float4x4 as opposed to my float3 I was previously using):


cbuffer ProjectionConstantBuffer : register(b0)
{
	float4x4 projection;
}

cbuffer WorldConstantBuffer : register(b1)
{
	float4x4 world;
}

struct VOut
{
	float4 position : SV_POSITION;
	float4 color : COLOR;
};



VOut VShader(float4 position : POSITION, float4 color : COLOR, float4x4 instancePosition : INSTANCE)
{
	VOut output;

	// Apply all instance position translations

	//position.x += instancePosition.x;
	//position.y += instancePosition.y;
	//position.z += instancePosition.z;

	output.position = position;
	output.position = mul(position, world);			// Apply world translation matrix
	output.position = mul(position, instancePosition);			// Apply instance translation matrix
	output.position = mul(output.position, projection); // Apply ortho projection matrix
	output.color = color; // Apply color from vertex input

	return output;
}

 

Thanks for your help!

 

EDIT:

 

I learned that 'INSTANCE'/1, 'INSTANCE'/2, and 'INSTANCE'/3

could possibly be referring to something like this:


	D3D11_INPUT_ELEMENT_DESC ied[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "INSTANCE", 0,DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 1,DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 2,DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 3,DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
	};

But unfortunately, I'm still missing something, as I am getting the same error. Is there something I need to do with the aligned byte offset? There is some science here I'm definitely not picking up on.

1 hour ago, JWColeman said:

I chose DXGI_FORMAT_R16G16B16A16_FLOAT as the format for my matrix input, I don't know if this is right but it's not complaining, its for 64 bits and my matrix is 64 bits

A 4x4 matrix of float is 64 bytes, not bits.

That's actually 512 bits. One single float is 32 bits and there's 4x4 of them. You represent those like in the last part of your post, so 4x R32G32B32A32_FLOAT.

 

1 hour ago, JWColeman said:

But unfortunately, I'm still missing something, as I am getting the same error. Is there something I need to do with the aligned byte offset? There is some science here I'm definitely not picking up on.

 

It's the offset of the element in bytes. If your first element is a R32G32B32A32_FLOAT then it means that it's using 16 bytes of data. So your next element should be at the offset 16 and so on.

 

Advertisement

Thanks for the assist Chuck, I've made changes as you recommended but I 'm still getting the same errors:

 


	D3D11_INPUT_ELEMENT_DESC ied[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "INSTANCE", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 2, DXGI_FORMAT_R32G32B32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 3, DXGI_FORMAT_R32G32B32_FLOAT, 1, 48, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
	};

You are in fact helping me understand the concept at work here.

 

A float4 is 16 bytes, im trying to pass a D3DXMatrix which is 64 bytes, and the target data type is a float4x4, which is a float4 (16 bytes) * 4, which is 64 bytes. 

 

So I have to adjust my input layout accordingly, wouldn't it be nice if there was just a single DXGI_FORMAT for the D3DXMatrix?

 

Anyways, Any idea why I might be getting the same error?

1 hour ago, JWColeman said:

Thanks for the assist Chuck, I've made changes as you recommended but I 'm still getting the same errors:

 



	D3D11_INPUT_ELEMENT_DESC ied[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "INSTANCE", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 16, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 2, DXGI_FORMAT_R32G32B32_FLOAT, 1, 32, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 3, DXGI_FORMAT_R32G32B32_FLOAT, 1, 48, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
	};

You are in fact helping me understand the concept at work here.

 

A float4 is 16 bytes, im trying to pass a D3DXMatrix which is 64 bytes, and the target data type is a float4x4, which is a float4 (16 bytes) * 4, which is 64 bytes. 

 

So I have to adjust my input layout accordingly, wouldn't it be nice if there was just a single DXGI_FORMAT for the D3DXMatrix?

 

Anyways, Any idea why I might be getting the same error?

Between now and your first post you switched the format from DXGI_FORMAT_R32G32B32A32_FLOAT (float4) to DXGI_FORMAT_R32G32B32_FLOAT (float3).

You are now assuming a 3x4 matrix. Put DXGI_FORMAT_R32G32B32A32_FLOAT back there for 4x4.

Okay, switched it up, makes sense what you said:

Same error :(

 

image.thumb.png.08c6782bca9f09d5104beff84c6dd85d.png

You're passing a hardcoded 3 as the number of elements. Maybe try _countof(ied) or ARRAYSIZE(ied).

Advertisement
21 minutes ago, SoldierOfLight said:

You're passing a hardcoded 3 as the number of elements. Maybe try _countof(ied) or ARRAYSIZE(ied).

Hey you got it man, that fixed the input layout problem, now unfortunately I don't think my shader is correct :(.

12 minutes ago, JWColeman said:

Hey you got it man, that fixed the input layout problem, now unfortunately I don't think my shader is correct :(.

Well indeed you still have few misconception about instances it seems. Let's take a look at this part :

 


output.position = mul(position, world);			// Apply world translation matrix
output.position = mul(position, instancePosition);			// Apply instance translation matrix

instancePosition  is basically a world matrix there.

You are multiplying twice in a row with a world matrix. One that come from your instance and one that come from your constant buffer.

When you draw your stuff you are either using instancing or not.

When not using instancing you should take the world matrix in the constant buffer.

When using instancing you should take the world matrix in the vertex layout.

Don't use both at the same time. You need 2 version of that vertex shader, one for when you draw with instancing and one for regular draws.

 

EDIT: Nevermind you are actually overwriting the position and not using the result of the first multiply.

Do you see anything at all on the screen?

Did you make sure to transpose your matrix?

How do you store the data in your instance buffer?

What do your call to SetVertexBuffers look like?

How do you issue your draw call?

5 minutes ago, ChuckNovice said:

Well indeed you still have few misconception about instances it seems. Let's take a look at this part :

 



output.position = mul(position, world);			// Apply world translation matrix
output.position = mul(position, instancePosition);			// Apply instance translation matrix

instancePosition  is basically a world matrix there.

You are multiplying twice in a row with a world matrix. One that come from your instance and one that come from your constant buffer.

When you draw your stuff you are either using instancing or not.

When not using instancing you should take the world matrix in the constant buffer.

When using instancing you should take the world matrix in the vertex layout.

 Don't use both at the same time. You need 2 version of that vertex shader, one for when you draw with instancing and one for regular draws.

 

EDIT: Nevermind you are actually overwriting the position and not using the result of the first multiply

You're not wrong chuck, I finally got it working...

 


	Instance * instances;
	UINT instanceCount = 1;
	instances = new Instance[instanceCount];
	D3DXMatrixTranslation(&instances[0].position, 100, 0, 0);
	D3DXMatrixTranspose(&instances[0].position, &instances[0].position);
	for (int i = 0; i < instanceCount; i++)
	{
		InstanceBuffer.data_container.push_back(instances[i]);
	}
	InstanceBuffer.Initialize(dev, D3D11_USAGE_DYNAMIC, D3D11_BIND_VERTEX_BUFFER, D3D11_CPU_ACCESS_WRITE);
	InstanceBuffer.Update(devcon);

 


	D3D11_INPUT_ELEMENT_DESC ied[] =
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
		{ "INSTANCE", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
		{ "INSTANCE", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_INSTANCE_DATA, 1 },
	};

	hr = dev->CreateInputLayout(ied, ARRAYSIZE(ied), Shader->GetBufferPointer(), Shader->GetBufferSize(), &pLayout);

 

Finally the shader multiplications you are mentioning:

 


VOut VShader(float4 position : POSITION, float4 color : COLOR, float4x4 instancePosition : INSTANCE)
{
	VOut output;

	// Apply all instance position translations

	//position.x += instancePosition.x;
	//position.y += instancePosition.y;
	//position.z += instancePosition.z;
	//output.position = position;
	//output.position = mul(position, world);			// Apply world translation matrix
	output.position = position;
	output.position = mul(output.position, instancePosition); // apply instance translation matrix
	output.position = mul(output.position, projection); // Apply ortho projection matrix
	output.color = color; // Apply color from vertex input

	return output;
}

 

This draws my single instanced quad :).

You don't get access to them by a float4x4 in your shader, you retrieve your ins. matrix by four "float4 INSTANCEx" and then you assemble those into a matrix again :)

Something like this:


struct VS_INPUT
{
	.....
	float4 World0 : MWORLD0;
	float4 World1 : MWORLD1;
	float4 World2 : MWORLD2;
	float4 World3 : MWORLD3;
};

cbuffer Buffer1 : register(b0)
{
	float4x4 MatrixWorld;
	.....
};

VS_OUTPUT main(VS_INPUT Input)
{
	VS_OUTPUT Output;
	float4x4 mworld = float4x4(Input.World0, Input.World1, Input.World2, Input.World3);
	mworld = mul(MatrixWorld, mworld);

	.....

 

.:vinterberg:.

This topic is closed to new replies.

Advertisement