Implement texture subresource on D3D12

When we use a texture for different purpose, we need to add proper
barrier(s) in order to make it ready. Previously, the barrier is
done per entire texture. So it is invalid to sample/read/copy from
one subresource (say a mip/array slice) and render/write/copy to
another subresource of the same texture at the same time.

With this patch, barrier is set per each texture subresource. So it is
valid to use a subresource as source and use another subresource of the
same texture as destination at the same time.

However, planar slices like depth/stencil planes are not handled
gracefully. This is a TODO task. Another task is to combine barriers
into one if they can be combined. I will do this optimization in
another patch in near future.

Bug: dawn:157

Change-Id: I783a76cb88fcdffb60c307ddfb89d50f1583201a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22101
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Yunchao He <yunchao.he@intel.com>
This commit is contained in:
Yunchao He 2020-06-09 16:18:04 +00:00 committed by Commit Bot service account
parent c8000bb02b
commit 182af0a4c2
6 changed files with 257 additions and 144 deletions

View File

@ -169,20 +169,26 @@ namespace dawn_native { namespace d3d12 {
wgpu::BufferUsage::Storage);
break;
case wgpu::BindingType::ReadonlyStorageTexture:
ToBackend(static_cast<TextureView*>(mBindings[index][binding])
->GetTexture())
->TrackUsageAndTransitionNow(commandContext,
kReadonlyStorageTexture);
case wgpu::BindingType::ReadonlyStorageTexture: {
TextureViewBase* view =
static_cast<TextureViewBase*>(mBindings[index][binding]);
ToBackend(view->GetTexture())
->TrackUsageAndTransitionNow(
commandContext, kReadonlyStorageTexture,
view->GetBaseMipLevel(), view->GetLevelCount(),
view->GetBaseArrayLayer(), view->GetLayerCount());
break;
case wgpu::BindingType::WriteonlyStorageTexture:
ToBackend(static_cast<TextureView*>(mBindings[index][binding])
->GetTexture())
->TrackUsageAndTransitionNow(commandContext,
wgpu::TextureUsage::Storage);
}
case wgpu::BindingType::WriteonlyStorageTexture: {
TextureViewBase* view =
static_cast<TextureViewBase*>(mBindings[index][binding]);
ToBackend(view->GetTexture())
->TrackUsageAndTransitionNow(
commandContext, wgpu::TextureUsage::Storage,
view->GetBaseMipLevel(), view->GetLevelCount(),
view->GetBaseArrayLayer(), view->GetLayerCount());
break;
}
case wgpu::BindingType::StorageTexture:
// Not implemented.
@ -434,15 +440,19 @@ namespace dawn_native { namespace d3d12 {
continue;
}
Texture* colorTexture =
ToBackend(renderPass->colorAttachments[i].view->GetTexture());
TextureViewBase* colorView = renderPass->colorAttachments[i].view.Get();
Texture* colorTexture = ToBackend(colorView->GetTexture());
Texture* resolveTexture = ToBackend(resolveTarget->GetTexture());
// Transition the usages of the color attachment and resolve target.
colorTexture->TrackUsageAndTransitionNow(commandContext,
D3D12_RESOURCE_STATE_RESOLVE_SOURCE);
resolveTexture->TrackUsageAndTransitionNow(commandContext,
D3D12_RESOURCE_STATE_RESOLVE_DEST);
colorTexture->TrackUsageAndTransitionNow(
commandContext, D3D12_RESOURCE_STATE_RESOLVE_SOURCE,
colorView->GetBaseMipLevel(), colorView->GetLevelCount(),
colorView->GetBaseArrayLayer(), colorView->GetLayerCount());
resolveTexture->TrackUsageAndTransitionNow(
commandContext, D3D12_RESOURCE_STATE_RESOLVE_DEST,
resolveTarget->GetBaseMipLevel(), resolveTarget->GetLevelCount(),
resolveTarget->GetBaseArrayLayer(), resolveTarget->GetLayerCount());
// Do MSAA resolve with ResolveSubResource().
ID3D12Resource* colorTextureHandle = colorTexture->GetD3D12Resource();
@ -510,12 +520,9 @@ namespace dawn_native { namespace d3d12 {
wgpu::TextureUsage textureUsages = wgpu::TextureUsage::None;
for (size_t i = 0; i < usages.textures.size(); ++i) {
D3D12_RESOURCE_BARRIER barrier;
if (ToBackend(usages.textures[i])
->TrackUsageAndGetResourceBarrier(commandContext, &barrier,
usages.textureUsages[i].usage)) {
barriers.push_back(barrier);
}
ToBackend(usages.textures[i])
->TrackUsageAndGetResourceBarrierForPass(
commandContext, &barriers, usages.textureUsages[i].subresourceUsages);
textureUsages |= usages.textureUsages[i].usage;
}
@ -593,8 +600,9 @@ namespace dawn_native { namespace d3d12 {
}
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopySrc);
texture->TrackUsageAndTransitionNow(commandContext,
wgpu::TextureUsage::CopyDst);
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst,
copy->destination.mipLevel, 1,
copy->destination.arrayLayer, 1);
auto copySplit = ComputeTextureCopySplit(
copy->destination.origin, copy->copySize, texture->GetFormat(),
@ -629,8 +637,9 @@ namespace dawn_native { namespace d3d12 {
texture->EnsureSubresourceContentInitialized(
commandContext, copy->source.mipLevel, 1, copy->source.arrayLayer, 1);
texture->TrackUsageAndTransitionNow(commandContext,
wgpu::TextureUsage::CopySrc);
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopySrc,
copy->source.mipLevel, 1,
copy->source.arrayLayer, 1);
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
TextureCopySplit copySplit = ComputeTextureCopySplit(
@ -680,9 +689,12 @@ namespace dawn_native { namespace d3d12 {
commandContext, copy->destination.mipLevel, 1,
copy->destination.arrayLayer, copy->copySize.depth);
}
source->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopySrc);
destination->TrackUsageAndTransitionNow(commandContext,
wgpu::TextureUsage::CopyDst);
source->TrackUsageAndTransitionNow(
commandContext, wgpu::TextureUsage::CopySrc, copy->source.mipLevel, 1,
copy->source.arrayLayer, copy->copySize.depth);
destination->TrackUsageAndTransitionNow(
commandContext, wgpu::TextureUsage::CopyDst, copy->destination.mipLevel, 1,
copy->destination.arrayLayer, copy->copySize.depth);
if (CanUseCopyResource(source, destination, copy->copySize)) {
commandList->CopyResource(destination->GetD3D12Resource(),
@ -870,7 +882,11 @@ namespace dawn_native { namespace d3d12 {
ToBackend(resolveDestinationView->GetTexture());
resolveDestinationTexture->TrackUsageAndTransitionNow(
commandContext, D3D12_RESOURCE_STATE_RESOLVE_DEST);
commandContext, D3D12_RESOURCE_STATE_RESOLVE_DEST,
resolveDestinationView->GetBaseMipLevel(),
resolveDestinationView->GetLevelCount(),
resolveDestinationView->GetBaseArrayLayer(),
resolveDestinationView->GetLayerCount());
renderPassBuilder->SetRenderTargetEndingAccessResolve(i, attachmentInfo.storeOp,
view, resolveDestinationView);

View File

@ -61,7 +61,7 @@ namespace dawn_native { namespace d3d12 {
// common state right before command list submission. TransitionUsageNow itself ensures
// no unnecessary transitions happen if the resources is already in the common state.
for (Texture* texture : mSharedTextures) {
texture->TrackUsageAndTransitionNow(this, D3D12_RESOURCE_STATE_COMMON);
texture->TrackAllUsageAndTransitionNow(this, D3D12_RESOURCE_STATE_COMMON);
}
MaybeError error =

View File

@ -55,7 +55,7 @@ namespace dawn_native { namespace d3d12 {
DAWN_TRY_ASSIGN(commandContext, device->GetPendingCommandContext());
// Perform the necessary transition for the texture to be presented.
ToBackend(texture)->TrackUsageAndTransitionNow(commandContext, mTextureUsage);
ToBackend(texture)->TrackAllUsageAndTransitionNow(commandContext, mTextureUsage);
DAWN_TRY(device->ExecutePendingCommandContext());

View File

@ -486,10 +486,17 @@ namespace dawn_native { namespace d3d12 {
return {};
}
Texture::Texture(Device* device, const TextureDescriptor* descriptor, TextureState state)
: TextureBase(device, descriptor, state),
mSubresourceStateAndDecay(
GetSubresourceCount(),
{D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COMMON, UINT64_MAX, false}) {
}
Texture::Texture(Device* device,
const TextureDescriptor* descriptor,
ComPtr<ID3D12Resource> nativeTexture)
: TextureBase(device, descriptor, TextureState::OwnedExternal) {
: Texture(device, descriptor, TextureState::OwnedExternal) {
AllocationInfo info;
info.mMethod = AllocationMethod::kExternal;
// When creating the ResourceHeapAllocation, the resource heap is set to nullptr because the
@ -546,126 +553,185 @@ namespace dawn_native { namespace d3d12 {
}
}
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors.
bool Texture::TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
wgpu::TextureUsage newUsage) {
return TrackUsageAndGetResourceBarrier(commandContext, barrier,
D3D12TextureUsage(newUsage, GetFormat()));
void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage,
uint32_t mipLevel,
uint32_t levelCount,
uint32_t arrayLayer,
uint32_t layerCount) {
TrackUsageAndTransitionNow(commandContext, D3D12TextureUsage(usage, GetFormat()), mipLevel,
levelCount, arrayLayer, layerCount);
}
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors.
bool Texture::TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState) {
void Texture::TrackAllUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage) {
TrackUsageAndTransitionNow(commandContext, D3D12TextureUsage(usage, GetFormat()), 0,
GetNumMipLevels(), 0, GetArrayLayers());
}
void Texture::TrackAllUsageAndTransitionNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState) {
TrackUsageAndTransitionNow(commandContext, newState, 0, GetNumMipLevels(), 0,
GetArrayLayers());
}
void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount) {
if (mResourceAllocation.GetInfo().mMethod != AllocationMethod::kExternal) {
// Track the underlying heap to ensure residency.
Heap* heap = ToBackend(mResourceAllocation.GetResourceHeap());
commandContext->TrackHeapUsage(heap, GetDevice()->GetPendingCommandSerial());
}
// Return the resource barrier.
return TransitionUsageAndGetResourceBarrier(commandContext, barrier, newState);
}
std::vector<D3D12_RESOURCE_BARRIER> barriers;
barriers.reserve(levelCount * layerCount);
void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage) {
D3D12_RESOURCE_BARRIER barrier;
if (TrackUsageAndGetResourceBarrier(commandContext, &barrier, usage)) {
commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
TransitionUsageAndGetResourceBarrier(commandContext, &barriers, newState, baseMipLevel,
levelCount, baseArrayLayer, layerCount);
if (barriers.size()) {
commandContext->GetCommandList()->ResourceBarrier(barriers.size(), barriers.data());
}
}
void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState) {
D3D12_RESOURCE_BARRIER barrier;
if (TrackUsageAndGetResourceBarrier(commandContext, &barrier, newState)) {
commandContext->GetCommandList()->ResourceBarrier(1, &barrier);
void Texture::TransitionSingleSubresource(std::vector<D3D12_RESOURCE_BARRIER>* barriers,
D3D12_RESOURCE_STATES newState,
uint32_t index,
const Serial pendingCommandSerial) {
StateAndDecay* state = &mSubresourceStateAndDecay[index];
// Avoid transitioning the texture when it isn't needed.
// TODO(cwallez@chromium.org): Need some form of UAV barriers at some point.
if (state->lastState == newState) {
return;
}
D3D12_RESOURCE_STATES lastState = state->lastState;
// The COMMON state represents a state where no write operations can be pending, and
// where all pixels are uncompressed. This makes it possible to transition to and
// from some states without synchronization (i.e. without an explicit
// ResourceBarrier call). Textures can be implicitly promoted to 1) a single write
// state, or 2) multiple read states. Textures will implicitly decay to the COMMON
// state when all of the following are true: 1) the texture is accessed on a command
// list, 2) the ExecuteCommandLists call that uses that command list has ended, and
// 3) the texture was promoted implicitly to a read-only state and is still in that
// state.
// https://docs.microsoft.com/en-us/windows/desktop/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#implicit-state-transitions
// To track implicit decays, we must record the pending serial on which that
// transition will occur. When that texture is used again, the previously recorded
// serial must be compared to the last completed serial to determine if the texture
// has implicity decayed to the common state.
if (state->isValidToDecay && pendingCommandSerial > state->lastDecaySerial) {
lastState = D3D12_RESOURCE_STATE_COMMON;
}
// Update the tracked state.
state->lastState = newState;
// Destination states that qualify for an implicit promotion for a
// non-simultaneous-access texture: NON_PIXEL_SHADER_RESOURCE,
// PIXEL_SHADER_RESOURCE, COPY_SRC, COPY_DEST.
{
static constexpr D3D12_RESOURCE_STATES kD3D12PromotableReadOnlyStates =
D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
if (lastState == D3D12_RESOURCE_STATE_COMMON) {
if (newState == (newState & kD3D12PromotableReadOnlyStates)) {
// Implicit texture state decays can only occur when the texture was implicitly
// transitioned to a read-only state. isValidToDecay is needed to differentiate
// between resources that were implictly or explicitly transitioned to a
// read-only state.
state->isValidToDecay = true;
state->lastDecaySerial = pendingCommandSerial;
return;
} else if (newState == D3D12_RESOURCE_STATE_COPY_DEST) {
state->isValidToDecay = false;
return;
}
}
}
D3D12_RESOURCE_BARRIER barrier;
barrier.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier.Transition.pResource = GetD3D12Resource();
barrier.Transition.StateBefore = lastState;
barrier.Transition.StateAfter = newState;
barrier.Transition.Subresource = index;
barriers->push_back(barrier);
// TODO(yunchao.he@intel.com): support subresource for depth/stencil. Depth stencil
// texture has different plane slices. While the current implementation only has differernt
// mip slices and array slices for subresources.
// This is a hack because Dawn doesn't handle subresource of multiplanar resources
// correctly. We force the transition to be the same for all planes to match what the
// frontend validation checks for. This hack might be incorrect for stencil-only texture
// because we always set transition barrier for depth plane.
if (newState == D3D12_RESOURCE_STATE_DEPTH_WRITE && GetFormat().HasStencil()) {
D3D12_RESOURCE_BARRIER barrierStencil = barrier;
barrierStencil.Transition.Subresource += GetArrayLayers() * GetNumMipLevels();
barriers->push_back(barrierStencil);
}
state->isValidToDecay = false;
}
// When true is returned, a D3D12_RESOURCE_BARRIER has been created and must be used in a
// ResourceBarrier call. Failing to do so will cause the tracked state to become invalid and can
// cause subsequent errors.
bool Texture::TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState) {
void Texture::HandleTransitionSpecialCases(CommandRecordingContext* commandContext) {
// Textures with keyed mutexes can be written from other graphics queues. Hence, they
// must be acquired before command list submission to ensure work from the other queues
// has finished. See Device::ExecuteCommandContext.
if (mDxgiKeyedMutex != nullptr) {
commandContext->AddToSharedTextureList(this);
}
}
// Avoid transitioning the texture when it isn't needed.
// TODO(cwallez@chromium.org): Need some form of UAV barriers at some point.
if (mLastState == newState) {
return false;
}
void Texture::TransitionUsageAndGetResourceBarrier(
CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barriers,
D3D12_RESOURCE_STATES newState,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount) {
HandleTransitionSpecialCases(commandContext);
D3D12_RESOURCE_STATES lastState = mLastState;
// The COMMON state represents a state where no write operations can be pending, and where
// all pixels are uncompressed. This makes it possible to transition to and from some states
// without synchronization (i.e. without an explicit ResourceBarrier call). Textures can be
// implicitly promoted to 1) a single write state, or 2) multiple read states. Textures will
// implicitly decay to the COMMON state when all of the following are true: 1) the texture
// is accessed on a command list, 2) the ExecuteCommandLists call that uses that command
// list has ended, and 3) the texture was promoted implicitly to a read-only state and is
// still in that state.
// https://docs.microsoft.com/en-us/windows/desktop/direct3d12/using-resource-barriers-to-synchronize-resource-states-in-direct3d-12#implicit-state-transitions
// To track implicit decays, we must record the pending serial on which that transition will
// occur. When that texture is used again, the previously recorded serial must be compared
// to the last completed serial to determine if the texture has implicity decayed to the
// common state.
const Serial pendingCommandSerial = ToBackend(GetDevice())->GetPendingCommandSerial();
if (mValidToDecay && pendingCommandSerial > mLastUsedSerial) {
lastState = D3D12_RESOURCE_STATE_COMMON;
}
for (uint32_t arrayLayer = 0; arrayLayer < layerCount; ++arrayLayer) {
for (uint32_t mipLevel = 0; mipLevel < levelCount; ++mipLevel) {
uint32_t index =
GetSubresourceIndex(baseMipLevel + mipLevel, baseArrayLayer + arrayLayer);
// Update the tracked state.
mLastState = newState;
// Destination states that qualify for an implicit promotion for a non-simultaneous-access
// texture: NON_PIXEL_SHADER_RESOURCE, PIXEL_SHADER_RESOURCE, COPY_SRC, COPY_DEST.
{
static constexpr D3D12_RESOURCE_STATES kD3D12TextureReadOnlyStates =
D3D12_RESOURCE_STATE_COPY_SOURCE | D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE |
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE;
if (lastState == D3D12_RESOURCE_STATE_COMMON) {
if (newState == (newState & kD3D12TextureReadOnlyStates)) {
// Implicit texture state decays can only occur when the texture was implicitly
// transitioned to a read-only state. mValidToDecay is needed to differentiate
// between resources that were implictly or explicitly transitioned to a
// read-only state.
mValidToDecay = true;
mLastUsedSerial = pendingCommandSerial;
return false;
} else if (newState == D3D12_RESOURCE_STATE_COPY_DEST) {
mValidToDecay = false;
return false;
}
TransitionSingleSubresource(barriers, newState, index, pendingCommandSerial);
}
}
}
barrier->Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION;
barrier->Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE;
barrier->Transition.pResource = GetD3D12Resource();
barrier->Transition.StateBefore = lastState;
barrier->Transition.StateAfter = newState;
barrier->Transition.Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES;
void Texture::TrackUsageAndGetResourceBarrierForPass(
CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barriers,
const std::vector<wgpu::TextureUsage>& subresourceUsages) {
HandleTransitionSpecialCases(commandContext);
mValidToDecay = false;
const Serial pendingCommandSerial = ToBackend(GetDevice())->GetPendingCommandSerial();
for (uint32_t arrayLayer = 0; arrayLayer < GetArrayLayers(); ++arrayLayer) {
for (uint32_t mipLevel = 0; mipLevel < GetNumMipLevels(); ++mipLevel) {
uint32_t index = GetSubresourceIndex(mipLevel, arrayLayer);
return true;
// Skip if this subresource is not used during the current pass
if (subresourceUsages[index] == wgpu::TextureUsage::None) {
continue;
}
D3D12_RESOURCE_STATES newState =
D3D12TextureUsage(subresourceUsages[index], GetFormat());
TransitionSingleSubresource(barriers, newState, index, pendingCommandSerial);
}
}
}
D3D12_RENDER_TARGET_VIEW_DESC Texture::GetRTVDescriptor(uint32_t mipLevel,
@ -741,7 +807,8 @@ namespace dawn_native { namespace d3d12 {
if (GetFormat().isRenderable) {
if (GetFormat().HasDepthOrStencil()) {
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE);
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_DEPTH_WRITE,
baseMipLevel, levelCount, baseArrayLayer, layerCount);
D3D12_CLEAR_FLAGS clearFlags = {};
@ -775,7 +842,8 @@ namespace dawn_native { namespace d3d12 {
}
}
} else {
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET);
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_RENDER_TARGET,
baseMipLevel, levelCount, baseArrayLayer, layerCount);
const float clearColorRGBA[4] = {fClearColor, fClearColor, fClearColor,
fClearColor};
@ -818,7 +886,8 @@ namespace dawn_native { namespace d3d12 {
uploader->Allocate(bufferSize, device->GetPendingCommandSerial()));
memset(uploadHandle.mappedBuffer, clearColor, bufferSize);
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST);
TrackUsageAndTransitionNow(commandContext, D3D12_RESOURCE_STATE_COPY_DEST, baseMipLevel,
levelCount, baseArrayLayer, layerCount);
for (uint32_t level = baseMipLevel; level < baseMipLevel + levelCount; ++level) {
// compute d3d12 texture copy locations for texture and buffer

View File

@ -60,15 +60,29 @@ namespace dawn_native { namespace d3d12 {
uint32_t baseArrayLayer,
uint32_t layerCount);
bool TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
wgpu::TextureUsage newUsage);
void TrackUsageAndGetResourceBarrierForPass(
CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barrier,
const std::vector<wgpu::TextureUsage>& subresourceUsages);
void TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage);
wgpu::TextureUsage usage,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount);
void TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState);
D3D12_RESOURCE_STATES newState,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount);
void TrackAllUsageAndTransitionNow(CommandRecordingContext* commandContext,
wgpu::TextureUsage usage);
void TrackAllUsageAndTransitionNow(CommandRecordingContext* commandContext,
D3D12_RESOURCE_STATES newState);
private:
Texture(Device* device, const TextureDescriptor* descriptor, TextureState state);
~Texture() override;
using TextureBase::TextureBase;
@ -89,18 +103,28 @@ namespace dawn_native { namespace d3d12 {
UINT16 GetDepthOrArraySize();
bool TrackUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState);
bool TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
D3D12_RESOURCE_BARRIER* barrier,
D3D12_RESOURCE_STATES newState);
void TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
std::vector<D3D12_RESOURCE_BARRIER>* barrier,
D3D12_RESOURCE_STATES newState,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount);
void TransitionSingleSubresource(std::vector<D3D12_RESOURCE_BARRIER>* barriers,
D3D12_RESOURCE_STATES subresourceNewState,
uint32_t index,
const Serial pendingCommandSerial);
void HandleTransitionSpecialCases(CommandRecordingContext* commandContext);
struct StateAndDecay {
D3D12_RESOURCE_STATES lastState;
Serial lastDecaySerial;
bool isValidToDecay;
};
std::vector<StateAndDecay> mSubresourceStateAndDecay;
ResourceHeapAllocation mResourceAllocation;
D3D12_RESOURCE_STATES mLastState = D3D12_RESOURCE_STATES::D3D12_RESOURCE_STATE_COMMON;
Serial mLastUsedSerial = UINT64_MAX;
bool mValidToDecay = false;
bool mSwapChainTexture = false;
Serial mAcquireMutexKey = 0;

View File

@ -196,4 +196,8 @@ TEST_P(TextureSubresourceTest, ArrayLayersTest) {
//
// * add tests for clear operation upon texture subresource if needed
DAWN_INSTANTIATE_TEST(TextureSubresourceTest, MetalBackend(), OpenGLBackend(), VulkanBackend());
DAWN_INSTANTIATE_TEST(TextureSubresourceTest,
D3D12Backend(),
MetalBackend(),
OpenGLBackend(),
VulkanBackend());