D3D12: clear nonrenderable texture formats

Clears nonrenderable color formats and merges zero vs nonzero clears
to use the same code path.

Bug: dawn:145
Change-Id: Ibe0745907688e149e6d017ff088a05f4b613b4a8
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/10140
Commit-Queue: Natasha Lee <natlee@microsoft.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
Natasha Lee 2019-08-30 18:19:56 +00:00 committed by Commit Bot service account
parent 864bae4cc6
commit adbecedad5
7 changed files with 186 additions and 146 deletions

View File

@ -31,6 +31,7 @@
#include "dawn_native/d3d12/SamplerD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h"
#include "dawn_native/d3d12/TextureD3D12.h"
#include "dawn_native/d3d12/UtilsD3D12.h"
#include <deque>
@ -48,17 +49,6 @@ namespace dawn_native { namespace d3d12 {
}
}
D3D12_TEXTURE_COPY_LOCATION CreateTextureCopyLocationForTexture(const Texture& texture,
uint32_t level,
uint32_t slice) {
D3D12_TEXTURE_COPY_LOCATION copyLocation;
copyLocation.pResource = texture.GetD3D12Resource();
copyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
copyLocation.SubresourceIndex = texture.GetSubresourceIndex(level, slice);
return copyLocation;
}
bool CanUseCopyResource(const uint32_t sourceNumMipLevels,
const Extent3D& srcSize,
const Extent3D& dstSize,
@ -622,29 +612,18 @@ namespace dawn_native { namespace d3d12 {
copy->source.offset, copy->source.rowPitch, copy->source.imageHeight);
D3D12_TEXTURE_COPY_LOCATION textureLocation =
CreateTextureCopyLocationForTexture(*texture, copy->destination.mipLevel,
ComputeTextureCopyLocationForTexture(texture, copy->destination.mipLevel,
copy->destination.arrayLayer);
for (uint32_t i = 0; i < copySplit.count; ++i) {
auto& info = copySplit.copies[i];
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
D3D12_TEXTURE_COPY_LOCATION bufferLocation;
bufferLocation.pResource = buffer->GetD3D12Resource().Get();
bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
bufferLocation.PlacedFootprint.Offset = copySplit.offset;
bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
bufferLocation.PlacedFootprint.Footprint.RowPitch = copy->source.rowPitch;
D3D12_BOX sourceRegion;
sourceRegion.left = info.bufferOffset.x;
sourceRegion.top = info.bufferOffset.y;
sourceRegion.front = info.bufferOffset.z;
sourceRegion.right = info.bufferOffset.x + info.copySize.width;
sourceRegion.bottom = info.bufferOffset.y + info.copySize.height;
sourceRegion.back = info.bufferOffset.z + info.copySize.depth;
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(
texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
copySplit.offset, copy->source.rowPitch);
D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
info.textureOffset.y, info.textureOffset.z,
@ -663,36 +642,25 @@ namespace dawn_native { namespace d3d12 {
texture->TransitionUsageNow(commandList, dawn::TextureUsage::CopySrc);
buffer->TransitionUsageNow(commandList, dawn::BufferUsage::CopyDst);
auto copySplit = ComputeTextureCopySplit(
TextureCopySplit copySplit = ComputeTextureCopySplit(
copy->source.origin, copy->copySize, texture->GetFormat(),
copy->destination.offset, copy->destination.rowPitch,
copy->destination.imageHeight);
D3D12_TEXTURE_COPY_LOCATION textureLocation =
CreateTextureCopyLocationForTexture(*texture, copy->source.mipLevel,
ComputeTextureCopyLocationForTexture(texture, copy->source.mipLevel,
copy->source.arrayLayer);
for (uint32_t i = 0; i < copySplit.count; ++i) {
auto& info = copySplit.copies[i];
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
D3D12_TEXTURE_COPY_LOCATION bufferLocation;
bufferLocation.pResource = buffer->GetD3D12Resource().Get();
bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
bufferLocation.PlacedFootprint.Offset = copySplit.offset;
bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
bufferLocation.PlacedFootprint.Footprint.Width = info.bufferSize.width;
bufferLocation.PlacedFootprint.Footprint.Height = info.bufferSize.height;
bufferLocation.PlacedFootprint.Footprint.Depth = info.bufferSize.depth;
bufferLocation.PlacedFootprint.Footprint.RowPitch =
copy->destination.rowPitch;
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(
texture, buffer->GetD3D12Resource().Get(), info.bufferSize,
copySplit.offset, copy->destination.rowPitch);
D3D12_BOX sourceRegion;
sourceRegion.left = info.textureOffset.x;
sourceRegion.top = info.textureOffset.y;
sourceRegion.front = info.textureOffset.z;
sourceRegion.right = info.textureOffset.x + info.copySize.width;
sourceRegion.bottom = info.textureOffset.y + info.copySize.height;
sourceRegion.back = info.textureOffset.z + info.copySize.depth;
D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
info.bufferOffset.y, info.bufferOffset.z,
@ -727,21 +695,16 @@ namespace dawn_native { namespace d3d12 {
source->GetD3D12Resource());
} else {
D3D12_TEXTURE_COPY_LOCATION srcLocation =
CreateTextureCopyLocationForTexture(*source, copy->source.mipLevel,
ComputeTextureCopyLocationForTexture(source, copy->source.mipLevel,
copy->source.arrayLayer);
D3D12_TEXTURE_COPY_LOCATION dstLocation =
CreateTextureCopyLocationForTexture(*destination,
ComputeTextureCopyLocationForTexture(destination,
copy->destination.mipLevel,
copy->destination.arrayLayer);
D3D12_BOX sourceRegion;
sourceRegion.left = copy->source.origin.x;
sourceRegion.top = copy->source.origin.y;
sourceRegion.front = copy->source.origin.z;
sourceRegion.right = copy->source.origin.x + copy->copySize.width;
sourceRegion.bottom = copy->source.origin.y + copy->copySize.height;
sourceRegion.back = copy->source.origin.z + copy->copySize.depth;
D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(copy->source.origin, copy->copySize);
commandList->CopyTextureRegion(
&dstLocation, copy->destination.origin.x, copy->destination.origin.y,

View File

@ -14,9 +14,17 @@
#include "dawn_native/d3d12/TextureD3D12.h"
#include "common/Constants.h"
#include "common/Math.h"
#include "dawn_native/DynamicUploader.h"
#include "dawn_native/Error.h"
#include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/DescriptorHeapAllocator.h"
#include "dawn_native/d3d12/DeviceD3D12.h"
#include "dawn_native/d3d12/ResourceAllocator.h"
#include "dawn_native/d3d12/StagingBufferD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h"
#include "dawn_native/d3d12/UtilsD3D12.h"
namespace dawn_native { namespace d3d12 {
@ -239,45 +247,9 @@ namespace dawn_native { namespace d3d12 {
D3D12_RESOURCE_STATE_COMMON);
if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator();
if (GetFormat().HasDepthOrStencil()) {
TransitionUsageNow(device->GetPendingCommandList(),
D3D12_RESOURCE_STATE_DEPTH_WRITE);
DescriptorHeapHandle dsvHeap =
descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1);
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(0);
device->GetD3D12Device()->CreateDepthStencilView(mResource.Get(), &dsvDesc,
dsvHandle);
D3D12_CLEAR_FLAGS clearFlags = {};
if (GetFormat().HasDepth()) {
clearFlags |= D3D12_CLEAR_FLAG_DEPTH;
}
if (GetFormat().HasStencil()) {
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
}
device->GetPendingCommandList()->ClearDepthStencilView(dsvHandle, clearFlags, 1.0f,
1u, 0, nullptr);
} else {
TransitionUsageNow(device->GetPendingCommandList(),
D3D12_RESOURCE_STATE_RENDER_TARGET);
DescriptorHeapHandle rtvHeap =
descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(0);
const float clearColor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
// TODO(natlee@microsoft.com): clear all array layers for 2D array textures
for (int i = 0; i < resourceDescriptor.MipLevels; i++) {
D3D12_RENDER_TARGET_VIEW_DESC rtvDesc =
GetRTVDescriptor(i, 0, GetArrayLayers());
device->GetD3D12Device()->CreateRenderTargetView(mResource.Get(), &rtvDesc,
rtvHandle);
device->GetPendingCommandList()->ClearRenderTargetView(rtvHandle, clearColor, 0,
nullptr);
}
}
device->ConsumedError(ClearTexture(device->GetPendingCommandList(), 0,
GetNumMipLevels(), 0, GetArrayLayers(),
TextureBase::ClearValue::NonZero));
}
}
@ -452,28 +424,31 @@ namespace dawn_native { namespace d3d12 {
return dsvDesc;
}
void Texture::ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
MaybeError Texture::ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount) {
uint32_t layerCount,
TextureBase::ClearValue clearValue) {
// TODO(jiawei.shao@intel.com): initialize the textures in compressed formats with copies.
if (GetFormat().isCompressed) {
SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
layerCount);
return;
return {};
}
Device* device = ToBackend(GetDevice());
DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator();
uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
if (GetFormat().isRenderable) {
if (GetFormat().HasDepthOrStencil()) {
TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_DEPTH_WRITE);
DescriptorHeapHandle dsvHeap =
descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, 1);
D3D12_CPU_DESCRIPTOR_HANDLE dsvHandle = dsvHeap.GetCPUHandle(0);
D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc = GetDSVDescriptor(baseMipLevel);
device->GetD3D12Device()->CreateDepthStencilView(mResource.Get(), &dsvDesc, dsvHandle);
device->GetD3D12Device()->CreateDepthStencilView(mResource.Get(), &dsvDesc,
dsvHandle);
D3D12_CLEAR_FLAGS clearFlags = {};
if (GetFormat().HasDepth()) {
@ -483,13 +458,14 @@ namespace dawn_native { namespace d3d12 {
clearFlags |= D3D12_CLEAR_FLAG_STENCIL;
}
commandList->ClearDepthStencilView(dsvHandle, clearFlags, 0.0f, 0u, 0, nullptr);
commandList->ClearDepthStencilView(dsvHandle, clearFlags, clearColor, clearColor, 0,
nullptr);
} else {
TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_RENDER_TARGET);
DescriptorHeapHandle rtvHeap =
descriptorHeapAllocator->AllocateCPUHeap(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1);
D3D12_CPU_DESCRIPTOR_HANDLE rtvHandle = rtvHeap.GetCPUHandle(0);
const float clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
const float clearColorRGBA[4] = {clearColor, clearColor, clearColor, clearColor};
// TODO(natlee@microsoft.com): clear all array layers for 2D array textures
for (uint32_t i = baseMipLevel; i < baseMipLevel + levelCount; i++) {
@ -497,12 +473,55 @@ namespace dawn_native { namespace d3d12 {
GetRTVDescriptor(i, baseArrayLayer, layerCount);
device->GetD3D12Device()->CreateRenderTargetView(mResource.Get(), &rtvDesc,
rtvHandle);
commandList->ClearRenderTargetView(rtvHandle, clearColor, 0, nullptr);
commandList->ClearRenderTargetView(rtvHandle, clearColorRGBA, 0, nullptr);
}
}
SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, layerCount);
} else {
// TODO(natlee@microsoft.com): test compressed textures are cleared
// create temp buffer with clear color to copy to the texture image
uint32_t rowPitch =
Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
kTextureRowPitchAlignment);
uint32_t bufferSize = rowPitch * (GetSize().height / GetFormat().blockHeight);
DynamicUploader* uploader = nullptr;
DAWN_TRY_ASSIGN(uploader, device->GetDynamicUploader());
UploadHandle uploadHandle;
DAWN_TRY_ASSIGN(uploadHandle, uploader->Allocate(bufferSize));
std::fill(reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer),
reinterpret_cast<uint32_t*>(uploadHandle.mappedBuffer + bufferSize),
clearColor);
TransitionUsageNow(commandList, D3D12_RESOURCE_STATE_COPY_DEST);
// compute d3d12 texture copy locations for texture and buffer
Extent3D copySize = {GetSize().width, GetSize().height, 1};
TextureCopySplit copySplit = ComputeTextureCopySplit(
{0, 0, 0}, copySize, GetFormat(), uploadHandle.startOffset, rowPitch, 0);
D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(this, baseMipLevel, baseArrayLayer);
for (uint32_t i = 0; i < copySplit.count; ++i) {
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(
this, ToBackend(uploadHandle.stagingBuffer)->GetResource(), info.bufferSize,
copySplit.offset, rowPitch);
D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
// copy the buffer filled with clear color to the texture
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
info.textureOffset.y, info.textureOffset.z,
&bufferLocation, &sourceRegion);
}
}
if (clearValue == TextureBase::ClearValue::Zero) {
SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer,
layerCount);
GetDevice()->IncrementLazyClearCountForTesting();
}
return {};
}
void Texture::EnsureSubresourceContentInitialized(ComPtr<ID3D12GraphicsCommandList> commandList,
uint32_t baseMipLevel,
@ -516,7 +535,9 @@ namespace dawn_native { namespace d3d12 {
layerCount)) {
// If subresource has not been initialized, clear it to black as it could contain
// dirty bits from recycled memory
ClearTexture(commandList, baseMipLevel, levelCount, baseArrayLayer, layerCount);
GetDevice()->ConsumedError(ClearTexture(commandList, baseMipLevel, levelCount,
baseArrayLayer, layerCount,
TextureBase::ClearValue::Zero));
}
}

View File

@ -54,11 +54,12 @@ namespace dawn_native { namespace d3d12 {
private:
// Dawn API
void DestroyImpl() override;
void ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
MaybeError ClearTexture(ComPtr<ID3D12GraphicsCommandList> commandList,
uint32_t baseMipLevel,
uint32_t levelCount,
uint32_t baseArrayLayer,
uint32_t layerCount);
uint32_t layerCount,
TextureBase::ClearValue clearValue);
UINT16 GetDepthOrArraySize();

View File

@ -41,4 +41,44 @@ namespace dawn_native { namespace d3d12 {
}
}
D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
uint32_t level,
uint32_t slice) {
D3D12_TEXTURE_COPY_LOCATION copyLocation;
copyLocation.pResource = texture->GetD3D12Resource();
copyLocation.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
copyLocation.SubresourceIndex = texture->GetSubresourceIndex(level, slice);
return copyLocation;
}
D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
const Texture* texture,
ID3D12Resource* bufferResource,
const Extent3D& bufferSize,
const uint64_t offset,
const uint32_t rowPitch) {
D3D12_TEXTURE_COPY_LOCATION bufferLocation;
bufferLocation.pResource = bufferResource;
bufferLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
bufferLocation.PlacedFootprint.Offset = offset;
bufferLocation.PlacedFootprint.Footprint.Format = texture->GetD3D12Format();
bufferLocation.PlacedFootprint.Footprint.Width = bufferSize.width;
bufferLocation.PlacedFootprint.Footprint.Height = bufferSize.height;
bufferLocation.PlacedFootprint.Footprint.Depth = bufferSize.depth;
bufferLocation.PlacedFootprint.Footprint.RowPitch = rowPitch;
return bufferLocation;
}
D3D12_BOX ComputeD3D12BoxFromOffsetAndSize(const Origin3D& offset, const Extent3D& copySize) {
D3D12_BOX sourceRegion;
sourceRegion.left = offset.x;
sourceRegion.top = offset.y;
sourceRegion.front = offset.z;
sourceRegion.right = offset.x + copySize.width;
sourceRegion.bottom = offset.y + copySize.height;
sourceRegion.back = offset.z + copySize.depth;
return sourceRegion;
}
}} // namespace dawn_native::d3d12

View File

@ -15,6 +15,9 @@
#ifndef DAWNNATIVE_D3D12_UTILSD3D12_H_
#define DAWNNATIVE_D3D12_UTILSD3D12_H_
#include "dawn_native/d3d12/BufferD3D12.h"
#include "dawn_native/d3d12/TextureCopySplitter.h"
#include "dawn_native/d3d12/TextureD3D12.h"
#include "dawn_native/d3d12/d3d12_platform.h"
#include "dawn_native/dawn_platform.h"
@ -22,6 +25,18 @@ namespace dawn_native { namespace d3d12 {
D3D12_COMPARISON_FUNC ToD3D12ComparisonFunc(dawn::CompareFunction func);
D3D12_TEXTURE_COPY_LOCATION ComputeTextureCopyLocationForTexture(const Texture* texture,
uint32_t level,
uint32_t slice);
D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
const Texture* texture,
ID3D12Resource* bufferResource,
const Extent3D& bufferSize,
const uint64_t offset,
const uint32_t rowPitch);
D3D12_BOX ComputeD3D12BoxFromOffsetAndSize(const Origin3D& offset, const Extent3D& copySize);
}} // namespace dawn_native::d3d12
#endif // DAWNNATIVE_D3D12_UTILSD3D12_H_

View File

@ -97,7 +97,7 @@ TEST_P(NonzeroTextureCreationTests, ArrayLayerClears) {
// Test that nonrenderable texture formats clear to 1's because toggle is enabled
TEST_P(NonzeroTextureCreationTests, NonrenderableTextureFormat) {
// skip test for other backends since they are not implemented yet
DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
DAWN_SKIP_TEST_IF(IsOpenGL());
dawn::TextureDescriptor descriptor;
descriptor.dimension = dawn::TextureDimension::e2D;
descriptor.size.width = kSize;

View File

@ -560,7 +560,7 @@ TEST_P(TextureZeroInitTest, ComputePassSampledTextureClear) {
// This tests that the code path of CopyTextureToBuffer clears correctly for non-renderable textures
TEST_P(TextureZeroInitTest, NonRenderableTextureClear) {
// skip test for other backends since they are not implemented yet
DAWN_SKIP_TEST_IF(IsOpenGL() || IsD3D12());
DAWN_SKIP_TEST_IF(IsOpenGL());
dawn::TextureDescriptor descriptor =
CreateTextureDescriptor(1, 1, dawn::TextureUsage::CopySrc, kNonrenderableColorFormat);