Implicit transitions of read only resources

Started by
3 comments, last by BKustel 5 years, 2 months ago

Hi,

I'm looking into how to manage state transitions of read only resources.

 

Lets say I have the following scenario with buffer A:

Draw Call #1 - Reads from buffer A in PS.

Draw Call #2 - Reads from buffer A in VS.

 

So the state will be:

Initial - Common

Draw Call #1 - Implicit transition to NON_PIXEL_SHADER_RESOURCE

Draw Call #2 - Transition from NON_PIXEL_SHADER_RESOURCE to PIXEL_SHADER_RESOURCE.

End of command list - Implicit decay to D3D12_RESOURCE_STATE_COMMON.

 

Is this the optimal way to do it? Or should I do a single transition to NON_PIXEL_SHADER_RESOURCE | PIXEL_SHADER_RESOURCE at the beginning of every frame?

Would it be more expensive to simply explicitly transition to GENERIC_READ at the beginning of every frame? This would make a lot easier to manage read only resources...

 

Thanks!

Advertisement

On the MSDN page about implicit state transitions, GENERIC_READ is not in the table of supported implicit transitions: https://docs.microsoft.com/en-us/windows/desktop/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#implicit-state-transitions which is a bit confusing.

But it mentions that: 
"All buffer resources as well as textures with the D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS flag set are implicitly promoted from D3D12_RESOURCE_STATE_COMMON to the relevant state on first GPU access, including GENERIC_READ to cover any read scenario. Any resource in the COMMON state can be accessed as through it were in a single state with
1 WRITE flag, or 1 or more READ flags"

My take on this is that it is safe to assume that from COMMON state, the resource will be implicitly promoted to first PIXEL_SHADER_RESOURCE then NON_PIXEL_SHADER_RESOURCE in your case because multiple read flags can be combined. In my experience it is safe to rely on this, so for read only textures (eg. assets), vertex buffers, etc. you don't ever need to care about transitioning explicitly. Maybe when you first copy data into them, their state will be left as COPY_DEST, but unless you do that on your main rendering command list (you probably shouldn't), then by the time you bind it to a shader, they are decayed into COMMON already.

This way I never saw any problems with it, but maybe a more experienced person can correct me.

@turanszkij is mostly correct. A resource in the COMMON state can be incrementally promoted to multiple read-only states without the need for explicit resource barriers.  Such resources will also decay back to COMMON when the associated ExecuteCommandLists operation completes.  Therefore, it is true that static textures can be left in the COMMON state indefinitely, never needing resource barriers once they are initialized. 

However, non-simultaneous-access textures only decay to COMMON if they were written to in a COPY command queue.  DIRECT command queues can promote textures from COMMON to COPY_DEST, but these will not decay back to COMMON.  This is because DIRECT command queues may perform copy operations as a render op, resulting in compressed texture data that may need to be decompressed to allow read-access, requiring a resource state barrier.  If possible, I suggest creating static textures in the COMMON state and use a COPY queue to initialize the data.  This way you will never need a resource barrier for these textures.

Let me know if you have any additional questions.

Hi @billkris: 

1) You mention above 

Quote

A resource in the COMMON state can be incrementally promoted to multiple read-only states without the need for explicit resource barriers.  Such resources will also decay back to COMMON when the associated ExecuteCommandLists operation completes.

I have seen this mentioned in the documentation (i.e., the multiple read-only or 1 write state limitation). Is this true of any resource or perhaps just buffers and allow_simultaneous_access textures? I found the documentation to be unclear on this point, especially since it later describes a case that requires an explicit barrier which I interpret to be "promotion to multiple read-only states"?

 

Quote
When this access occurs the promotion acts like an implicit resource barrier. For subsequent accesses, resource barriers will be required to change the resource state if necessary. For example, if a resource in the common state is promoted to PIXEL_SHADER_RESOURCE in a Draw call and is then used as a copy source, a resource state transition barrier from PIXEL_SHADER_RESOURCE to COPY_SOURCE is needed.

Since both of the latter states are included in GENERIC_READ, I had assumed a barrier would not be needed for the second transition either (based on the multiple read-only, 1 write state rule), yet the word 'needed' seems to contradict my assumption.

 

2) About Decay of a non-simultaneous access textures, something you discussed in your 2nd paragraph above, I have some questions. I find the "4th Decay condition" in the documentation to be slightly unclear, and also somewhat at odds with another nearby statement:

 

Quote

 

The following resources will decay when an   ExecuteCommandLists   operation is completed on the GPU:

* Resources being accessed on a Copy queue, or

* Buffer resources on any queue type, or

* Texture resources on any queue type that have the D3D12_RESOURCE_FLAG_ALLOW_SIMULTANEOUS_ACCESS flag set, or

* Any resource implicitly promoted to a read-only state.

Like common state promotion, the decay is free in that no additional synchronization is needed. Combining common state promotion and decay can help to eliminate many unnecessary  ResourceBarrier  transitions. In some cases, this can provide significant performance improvements.

Resources will decay to the common state regardless of whether they were explicitly transitioned using resource barriers or implicitly promoted.

 

 

 

I'll list a few examples...

Example 2A) (Your example) A non-simul-access texture promoting to COPY_DEST on a DIRECT (or COMPUTE) queue, I would completely agree that the documentation is quite clear that it would not decay to COMMON. So no question about this case.

Example 2B) A non-simul-access texture implicitly promoting to multiple read-only states on a DIRECT (or COMPUTE) queue, I assume this WILL decay although the documentation seems to imply there can be at most one promotion. My latest interpretation is that as long is there is no promotion to a writable state, then decay will happen.

Example 2C) A non-simul-access texture explicitly transitioned to a read-only state on a DIRECT (or COMPUTE) queue. I'm unsure if an explicit use of a resource barrier would prevent the decay. The documentation seems to say implicit promotion is required, but then later that implicit promotion should not be a requirement (see the highlighted lines in the quote above).

Example 2D) A non-simul-access texture implicitly promoted to a read-only state and then explicitly transitioned to another read-only state on a DIRECT (or COMPUTE) queue. Here too, as in the previous case I'm unsure if an explicit use of a resource barrier at any point would prevent the decay. 

I guess I feel the 4th rule of Decay (in the quote above) needs clarification. What happens if explicit barriers are used? What happens if multiple implicit transitions occur to read-only states? What if there is a mixture? What if it is transitioned to a writable state but then back to a read-only state? My current assumption is that regardless of its final state, if it ever gets transitioned to a writable state then decay won't happen but I'm not fully sure.

 

3) I'm not sure if you're in a position to know this, but I'll keep my fingers crossed. I find that the D3D12 debug validation layer tells me different things on different devices. For example, when testing Promotion and Decay, cases that pass without any error on the MS Reference D3D12 device (and which I strongly feel are correct) report intermittent D3D12 Errors on my GPU (Nv GTX 1070 tested on many recent driver versions). Are drivers known to be buggy in this area? The problems I have seen reported by the GPU are intermittent but frequent cases where the Debug layer claims an "allow-simul-access" texture does not Decay To COMMON. I have not seen evidence the operations fail, only that the debug layer reports state inconsistency errors.

This topic is closed to new replies.

Advertisement