Jump to content
  • Advertisement
Sign in to follow this  
cozzie

Comparing id3d11inputlayouts

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi all,
Can someone give me some pointers on how to approach the following:
- I have X shaders which need Y (less then X) unique inputlayouts
- therefor I will only store the unique inputlayouts and give each shader the ID for the unique and corresponding inputlayout
(this is managed by my shadermanager class).

Now, what would be the best way to compare one inputlayout to another? To determine if they're the same or not.
I thought of storing the elements array and create a unique key based on these, then compare those keys. But I was hoping there might be an easier/ more straightforward way.

Any input is appreciated.

Share this post


Link to post
Share on other sites
Advertisement

For what it's worth, D3D11 does de-duplicate input layouts at the driver level. There's a translation from semantic name/index into a register value (which you might see in the shader disassembly). Once that's done, the de-duplication is pretty straightforward.

 

At the API level, you won't be able to compare pointers to determine equality, because they do have different strings for semantic names, but the comment I made in the other thread about D3D11 turning redundant sets into no-ops applies to the de-duplicated layouts at the driver level. I'm not saying don't do it, but it might not be the most pressing thing to investigate.

Share this post


Link to post
Share on other sites

In the past I've taken a hash of the elements array.  It doesn't need to be a cryptographically secure hash, but does need a sufficiently low number of possible collisions.

Share this post


Link to post
Share on other sites
Thanks. I've chosen not to store and use them all and depend on the API.

@mhagain: can you give me some rough outline/ pointers on how to create a hash 'key'/ value based on the elements's name and dxgi formats? (Unfortunately no hashing experience here)

Share this post


Link to post
Share on other sites

@mhagain: can you give me some rough outline/ pointers on how to create a hash 'key'/ value based on the elements's name and dxgi formats? (Unfortunately no hashing experience here)

 

Just take the array of D3D11_INPUT_ELEMENT_DESC and pass it into your hashing function.  The name and format is insufficient; you need all of the D3D11_INPUT_ELEMENT_DESC members to ensure uniqueness.  It's just a lump of binary data so do something like:

 

D3D11_INPUT_ELEMENT_DESC layoutElements[] = {.......};

 

// assume that HASH is the type of hash generated by your hashing function and

// that the signature of HashFunction is (void *data, size_t length)

HASH hash = HashFunction (layoutElements, sizeof (layoutElements));

 

For a hashing library I've found that MD5 is probably sufficient for this purpose; CRC16 is definitely not good enough.  See this StackOverflow question for other suggestions and discussion: http://stackoverflow.com/questions/4678447/md5-and-sha1-c-hashing-library

 

From there the concept is that rather than storing the input elements in your ShaderManager class you instead store the hash (16 bytes) and compare the incoming hash with stored hashes to determine equality.

Share this post


Link to post
Share on other sites

v0.1 below, it's working but the hash function is probably not very solid, is it?

It's just an example I dug up, couldn't find a 'easy to understand' MD5 hash function.

 

What would be the improvement in results when I replace the hash function below with a MD5 or other hash function?

I believe the one I have no is an 'RS' hash function.

unsigned int GetHashFromString(const std::string& str)
{
	unsigned int b    = 378551;
	unsigned int a    = 63689;
	unsigned int hash = 0;

	for(std::size_t i = 0;i<str.length();i++)
	{
		hash = hash * a + str[i];
		a    = a * b;
	}
    return (hash & 0x7FFFFFFF);
}

unsigned int GetHashFromInputElementDesc(const D3D11_INPUT_ELEMENT_DESC &pElementDesc)
{
	unsigned int result = 0;
	
	result = GetHashFromString(pElementDesc.SemanticName) + 
			 pElementDesc.SemanticIndex + 
			 pElementDesc.Format + 
			 pElementDesc.InputSlot + 
			 pElementDesc.AlignedByteOffset +
			 pElementDesc.InputSlotClass + 
			 pElementDesc.InstanceDataStepRate;
	
	return result;
}

// somewhere later

		// TESTING: CREATE HASH OF THE ELEMENTDESC'S IN THE ARRAY
		unsigned int hashTotal = 0;
		for(size_t i=0;i<inputLayoutDesc.size();i++)
		{
			hashTotal += GetHashFromInputElementDesc(inputLayoutDesc[i]);
		}

Share this post


Link to post
Share on other sites

I've used the RSA code in the past; it's old-style C but should be more-or-less drop 'n' go.  I'll need to hunt around for a project that has it if you'd like to see samples though.

 

I think the C++ isms in your code are hurting you here.  You don't need strings or references or vectors or overloading the + operator or anything like that.  With an appropriate hashing function you should be just able to pass it a raw pointer (and the length of the buffer) to unsigned char*, then iterate through the buffer,.  The RSA code expects that kind of input.  Just document that it's the responsibility of the caller to ensure that everything is correct and you're good to go.

Edited by mhagain

Share this post


Link to post
Share on other sites

Thanks, I've just made some changes and replaced the 'RSHASH' by the std::hash function.

Like you said, it's probably better/ easier to 'convert' a elementDesc object or even the array, to a big unsigned char * (array) and use std::hash on that.

unsigned int GetHashFromInputElementDesc(const D3D11_INPUT_ELEMENT_DESC &pElementDesc)
{
	unsigned int result = 0;
	
	result = (unsigned int)std::hash<std::string>{}(pElementDesc.SemanticName) +
			 pElementDesc.SemanticIndex + 
			 pElementDesc.Format + 
			 pElementDesc.InputSlot + 
			 pElementDesc.AlignedByteOffset +
			 pElementDesc.InputSlotClass + 
			 pElementDesc.InstanceDataStepRate;

	return result;
}

		unsigned int hashTotal = 0;
		for(size_t i=0;i<inputLayoutDesc.size();i++)
		{
			hashTotal += GetHashFromInputElementDesc(inputLayoutDesc[i]);
		}

Share this post


Link to post
Share on other sites

Std::hash won't work on a char * I think, in that case it will hash the pointer instead of the array it points too.

 

I believe I could create my own template for std::hash for the elementDesc type (or even an array of them), but I haven't used templates so far.

So probably I'll go for my v0.3 below.

 

Do you see any reasons not too (incorrect/ is summing up hash totals OK? etc.)

unsigned int GetHashFromInputElementDesc(const D3D11_INPUT_ELEMENT_DESC &pElementDesc)
{
	size_t result = 0;
	
	result = std::hash<std::string>{}(pElementDesc.SemanticName) +
			 std::hash<UINT>{}(pElementDesc.SemanticIndex) + 
			 std::hash<UINT>{}(pElementDesc.Format) + 
			 std::hash<UINT>{}(pElementDesc.InputSlot) + 
			 std::hash<UINT>{}(pElementDesc.AlignedByteOffset) +
			 std::hash<UINT>{}(pElementDesc.InputSlotClass) + 
			 std::hash<UINT>{}(pElementDesc.InstanceDataStepRate);

	return (unsigned int)result;
}

		unsigned int hashTotal = 0;
		for(size_t i=0;i<inputLayoutDesc.size();i++)
		{
			hashTotal += GetHashFromInputElementDesc(inputLayoutDesc[i]);
		}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!