# Is there any other option to implement materials?

This topic is 1063 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi!

Well, I actually already have my code for drawing objects with materials. There is a constant buffer like this:

cbuffer cbChangesEveryFrame: register(b1)
{
matrix World;
matrix View;
matrix Projection;
float4 DiffuseColor;
float4 SpecularColor;
float SpecularPower;
float4 AmbientColor;
}

(later I'm gonna put View and Projection matrices in another buffer because they can change only once in a frame).

So, for each object, my code fills up a structure and calls ID3D11DeviceContext::UpdateSubresource.

But I was wondering if this is really the best method to do something like this.

I know I could use something like a per-vertex material data, but that would waste too much memory. (Besides, if I need some color to change...)

EDIT: Sorry for my bad English.

Edited by LHLaurini

##### Share on other sites

I was wondering if this is really the best method to do something like this.

It's not obvious what you mean by doing "something." Your post mentions updating buffers, using materials in various ways, using different colors, etc. Can you describe what you want to do, rather than how you want to do it?

If you're just looking for an alternative way to transfer data to a shader buffer, take a look at ID3D11DeviceContext::Map and ::Unmap. For simply transferring data from the CPU to GPU, that's faster than UpdateSubresource.

that would waste too much memory.

If a method does what you want it to, and the memory is available, the memory isn't "wasted." It may take more time to load and access more data. Is that really your concern?

##### Share on other sites

Y es. There is another way.

Materials don't really change too often. Keep them in a separate cbuffer as an array of materials, and in the per-object buffer only send an index to that array (plus the world matrix).

Also, I would prefer using map discard instead of UpdateSubresource because internally that means more memcpy (and thus bandwidth) if the buffer is still in use by the gpu while you were updating it.

##### Share on other sites

I was wondering if this is really the best method to do something like this.

It's not obvious what you mean by doing "something." Your post mentions updating buffers, using materials in various ways, using different colors, etc. Can you describe what you want to do, rather than how you want to do it?

If you're just looking for an alternative way to transfer data to a shader buffer, take a look at ID3D11DeviceContext::Map and ::Unmap. For simply transferring data from the CPU to GPU, that's faster than UpdateSubresource.

that would waste too much memory.

If a method does what you want it to, and the memory is available, the memory isn't "wasted." It may take more time to load and access more data. Is that really your concern?

Sorry if wasn't specific enough. What I meant was "I was wondering if using UpdateSubresource is really the best method to 'feed' material data to a shader.".

Y es. There is another way.

Materials don't really change too often. Keep them in a separate cbuffer as an array of materials, and in the per-object buffer only send an index to that array (plus the world matrix).

Also, I would prefer using map discard instead of UpdateSubresource because internally that means more memcpy (and thus bandwidth) if the buffer is still in use by the gpu while you were updating it.

That's a good idea. I'm probably going to try it.

For both, thanks for the Map() + Release() tip. I really never thought about it. Thanks for your answers.

EDIT: It seems constant buffers are limited to 64KB, so if I eventually need more space I'm going to use multiple buffers or PSSetConstantBuffers1.

Edited by LHLaurini

##### Share on other sites

EDIT: It seems constant buffers are limited to 64KB, so if I eventually need more space I'm going to use multiple buffers or PSSetConstantBuffers1.

Indeed. Note PSSetConstantBuffers1 is only available in D3D11.1 running on Windows 8.1

Otherwise you're going to need multiple buffers and end up mapping multiple times (both OpenGL and D3D12 solve / will solve this problem)

Also note that 64kb is still a lot.
According to your data, that's an array of 1024 materials per cbuffer; also 1024 world matrices and material indices per cbuffer (a world matrix only needs a float3x4; and the last 4 floats are consumed by the material index).

You can also use tbuffers for the world matrix and the material index which doesn't have this 64kb limitation and is likely to perform just as fast. Edited by Matias Goldberg