Advertisement

Do we need to rebind a descriptor table after CopyDescriptors operation?

Started by September 21, 2017 12:37 PM
6 comments, last by Alex Dunn 7 years, 4 months ago

I am working on optimizing our descriptor management code. Currently, I am following most of the guidelines like sorting descriptors by update frequency,...

I have two types of descriptor ranges: Static (DESCRIPTOR_RANGE_FLAG_NONE) and Dynamic(DESCRIPTORS_VOLATILE). So lets say I have this scenario:


pCmd->bindDescriptorTable(pTable);

for (uint32_t i = 0; i < meshCount; ++i)
{
  	// descriptor is created in a range with flag DESCRIPTORS_VOLATILE
  	// setDescriptor will call CopyDescriptorsSimple to copy descriptor handle pDescriptor to the appropriate location in pTable
	pTable->setDescriptor("descriptor", pDescriptor[i]);
}

Do I need to call bindDescriptorTable inside the loop?

As long as the descriptor is marked VOLATILE, then the guarantee is the hardware will read the contents of the descriptor at execution time. No need to re-apply the same descriptor handle to the command list.

Advertisement

Thanks for the info. Since we are on the topic, just curious to know whether it's optimal to use:

  • The DESCRIPTORS_VOLATILE flag, create one big descriptor table and let the driver manage the versioning
  • Separate the tables based on update frequency?

The first scenario will have only one SetRootDescriptorTable call from app code. Not sure about driver code.

The second scenario will have multiple SetRootDescriptorTable calls depending on the update frequency and the driver has to do no versioning since the app manages it.

Thanks

You know that you can't overwrite the descriptors while they're in use by the GPU, right? There's no automatic driver versioning.

This makes it more confusing xD What is an example use case of the VOLATILE flag?

DESCRIPTORS_VOLATILE is the default behavior of root signature 1.0. It requires that drivers cannot read the descriptors at all until the GPU is executing. This means I can do something like:


commandList->SetGraphicsRootDescriptorTable(foo);
commandList->Close();
commandQueue->Wait(fence, 1);
commandQueue->ExecuteCommandLists(&commandList);
device->CopyDescriptors(foo, bar);
fence->Signal(1);

This would be valid, and the GPU would read the updated descriptors when it becomes unblocked. If you did that in root signature 1.1 without the DESCRIPTORS_VOLATILE flag, that would be invalid, because the descriptors changed from the point of recording the command in the command list, and the GPU executing those commands. It is a hint to the driver that they can read the descriptors on the CPU and potentially make optimizations off of that information - whether that means that they embed the entire contents of the descriptor in the command list or not is a driver implementation detail (and unless it's a buffer, I don't think anyone can do that today).

Advertisement

@SoldierOfLight Unfortunately, the above example is not valid, we expect descriptors to be "set in stone" by ExecuteCommandLists (submission) time.  This is in accordance with the documentation below:

https://msdn.microsoft.com/en-us/library/windows/desktop/mt709473(v=vs.85).aspx#descriptors_volatile

"With this flag set, the descriptors in a descriptor heap pointed to by a root descriptor table can be changed by the application any time except while the command list / bundles that bind the descriptor table have been submitted and have not finished executing. For instance, recording a command list and subsequently changing descriptors in a descriptor heap it refers to before submitting the command list for execution is valid. This is the only supported behavior of Root Signature version 1.0."

This topic is closed to new replies.

Advertisement