diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 2321a4c838..86254d781f 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -169,20 +169,26 @@ namespace dawn_native { namespace d3d12 { wgpu::BufferUsage::Storage); break; - case wgpu::BindingType::ReadonlyStorageTexture: - ToBackend(static_cast(mBindings[index][binding]) - ->GetTexture()) - ->TrackUsageAndTransitionNow(commandContext, - kReadonlyStorageTexture); + case wgpu::BindingType::ReadonlyStorageTexture: { + TextureViewBase* view = + static_cast(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(mBindings[index][binding]) - ->GetTexture()) - ->TrackUsageAndTransitionNow(commandContext, - wgpu::TextureUsage::Storage); + } + case wgpu::BindingType::WriteonlyStorageTexture: { + TextureViewBase* view = + static_cast(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); diff --git a/src/dawn_native/d3d12/CommandRecordingContext.cpp b/src/dawn_native/d3d12/CommandRecordingContext.cpp index 81dad3c138..d652d878e6 100644 --- a/src/dawn_native/d3d12/CommandRecordingContext.cpp +++ b/src/dawn_native/d3d12/CommandRecordingContext.cpp @@ -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 = diff --git a/src/dawn_native/d3d12/SwapChainD3D12.cpp b/src/dawn_native/d3d12/SwapChainD3D12.cpp index 45ec25bb97..ee5e9cc371 100644 --- a/src/dawn_native/d3d12/SwapChainD3D12.cpp +++ b/src/dawn_native/d3d12/SwapChainD3D12.cpp @@ -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()); diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index 77966b48d7..78bf027ae3 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -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 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 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* 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* 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* barriers, + const std::vector& 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 diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h index 45443c11de..c8c7f5a067 100644 --- a/src/dawn_native/d3d12/TextureD3D12.h +++ b/src/dawn_native/d3d12/TextureD3D12.h @@ -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* barrier, + const std::vector& 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* barrier, + D3D12_RESOURCE_STATES newState, + uint32_t baseMipLevel, + uint32_t levelCount, + uint32_t baseArrayLayer, + uint32_t layerCount); + + void TransitionSingleSubresource(std::vector* 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 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; diff --git a/src/tests/end2end/TextureSubresourceTests.cpp b/src/tests/end2end/TextureSubresourceTests.cpp index 03dd486566..29411de252 100644 --- a/src/tests/end2end/TextureSubresourceTests.cpp +++ b/src/tests/end2end/TextureSubresourceTests.cpp @@ -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());