From 4d10e4566cfad92ba24a0d14011da52cbf7ee897 Mon Sep 17 00:00:00 2001 From: Jim Van Verth Date: Tue, 13 Apr 2021 14:03:28 -0400 Subject: [PATCH] Add more support for UAVs and SRV miplevel access Change-Id: Iefb44f59041c31d45db5c89131f70d6c76376622 Bug: skia:10446 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/396158 Reviewed-by: Greg Daniel Commit-Queue: Jim Van Verth --- src/gpu/d3d/GrD3DCaps.cpp | 9 ++++++++ src/gpu/d3d/GrD3DCaps.h | 3 +++ src/gpu/d3d/GrD3DCommandList.cpp | 15 ++++++++++++++ src/gpu/d3d/GrD3DCommandList.h | 4 +++- src/gpu/d3d/GrD3DCpuDescriptorManager.cpp | 25 ++++++++++++++++++----- src/gpu/d3d/GrD3DCpuDescriptorManager.h | 7 +++++-- src/gpu/d3d/GrD3DResourceProvider.cpp | 8 ++++---- src/gpu/d3d/GrD3DResourceProvider.h | 7 +++++-- 8 files changed, 64 insertions(+), 14 deletions(-) diff --git a/src/gpu/d3d/GrD3DCaps.cpp b/src/gpu/d3d/GrD3DCaps.cpp index 99977cb697..b6f82ff918 100644 --- a/src/gpu/d3d/GrD3DCaps.cpp +++ b/src/gpu/d3d/GrD3DCaps.cpp @@ -701,6 +701,10 @@ void GrD3DCaps::FormatInfo::InitFormatFlags(const D3D12_FEATURE_DATA_FORMAT_SUPP if (SkToBool(D3D12_FORMAT_SUPPORT1_MULTISAMPLE_RESOLVE & formatSupport.Support1)) { *flags = *flags | kResolve_Flag; } + + if (SkToBool(D3D12_FORMAT_SUPPORT1_TYPED_UNORDERED_ACCESS_VIEW & formatSupport.Support1)) { + *flags = *flags | kUnorderedAccess_Flag; + } } static bool multisample_count_supported(ID3D12Device* device, DXGI_FORMAT format, int sampleCount) { @@ -814,6 +818,11 @@ bool GrD3DCaps::isFormatRenderable(DXGI_FORMAT format, int sampleCount) const { return sampleCount <= this->maxRenderTargetSampleCount(format); } +bool GrD3DCaps::isFormatUnorderedAccessible(DXGI_FORMAT format) const { + const FormatInfo& info = this->getFormatInfo(format); + return SkToBool(FormatInfo::kUnorderedAccess_Flag & info.fFlags); +} + int GrD3DCaps::getRenderTargetSampleCount(int requestedCount, const GrBackendFormat& format) const { DXGI_FORMAT dxgiFormat; diff --git a/src/gpu/d3d/GrD3DCaps.h b/src/gpu/d3d/GrD3DCaps.h index 170f1c4b70..a5c7eef8a2 100644 --- a/src/gpu/d3d/GrD3DCaps.h +++ b/src/gpu/d3d/GrD3DCaps.h @@ -38,6 +38,8 @@ public: bool isFormatRenderable(const GrBackendFormat& format, int sampleCount) const override; bool isFormatRenderable(DXGI_FORMAT, int sampleCount) const; + bool isFormatUnorderedAccessible(DXGI_FORMAT) const; + int getRenderTargetSampleCount(int requestedCount, const GrBackendFormat&) const override; int getRenderTargetSampleCount(int requestedCount, DXGI_FORMAT) const; @@ -175,6 +177,7 @@ private: kRenderable_Flag = 0x2, // Rendertarget and blendable kMSAA_Flag = 0x4, kResolve_Flag = 0x8, + kUnorderedAccess_Flag = 0x10, }; uint16_t fFlags = 0; diff --git a/src/gpu/d3d/GrD3DCommandList.cpp b/src/gpu/d3d/GrD3DCommandList.cpp index 6f7ca26686..aa3279eb90 100644 --- a/src/gpu/d3d/GrD3DCommandList.cpp +++ b/src/gpu/d3d/GrD3DCommandList.cpp @@ -110,6 +110,21 @@ void GrD3DCommandList::resourceBarrier(sk_sp resource, } } +void GrD3DCommandList::uavBarrier(sk_sp resource, + ID3D12Resource* uavResource) { + SkASSERT(fIsActive); + // D3D will apply barriers in order so we can just add onto the end + D3D12_RESOURCE_BARRIER& newBarrier = fResourceBarriers.push_back(); + newBarrier.Type = D3D12_RESOURCE_BARRIER_TYPE_UAV; + newBarrier.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE; + newBarrier.UAV.pResource = uavResource; + + fHasWork = true; + if (resource) { + this->addResource(std::move(resource)); + } +} + void GrD3DCommandList::submitResourceBarriers() { SkASSERT(fIsActive); diff --git a/src/gpu/d3d/GrD3DCommandList.h b/src/gpu/d3d/GrD3DCommandList.h index 47aea2141c..1bd23b4efc 100644 --- a/src/gpu/d3d/GrD3DCommandList.h +++ b/src/gpu/d3d/GrD3DCommandList.h @@ -49,12 +49,14 @@ public: // GraphicsCommandList commands //////////////////////////////////////////////////////////////////////////// - // For the moment we only support Transition barriers // All barriers should reference subresources of managedResource void resourceBarrier(sk_sp managedResource, int numBarriers, const D3D12_RESOURCE_TRANSITION_BARRIER* barriers); + void uavBarrier(sk_sp managedResource, + ID3D12Resource* uavResource); + // Helper method that calls copyTextureRegion multiple times, once for each subresource // The srcBuffer comes from a staging buffer so we don't need to take any refs to it. Instead, // we ref the whole buffer during sumbit. diff --git a/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp b/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp index 891362c8cf..7c6d296894 100644 --- a/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp +++ b/src/gpu/d3d/GrD3DCpuDescriptorManager.cpp @@ -51,21 +51,36 @@ GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createConstantBufferVi } GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createShaderResourceView( - GrD3DGpu* gpu, ID3D12Resource* resource) { + GrD3DGpu* gpu, ID3D12Resource* resource, + unsigned int mostDetailedMip, unsigned int mipLevels) { const GrD3DDescriptorHeap::CPUHandle& descriptor = fShaderViewDescriptorPool.allocateHandle(gpu); // TODO: for 4:2:0 YUV formats we'll need to map two different views, one for Y and one for UV. // For now map the entire resource. - gpu->device()->CreateShaderResourceView(resource, nullptr, descriptor.fHandle); + D3D12_SHADER_RESOURCE_VIEW_DESC desc = {}; + desc.Format = resource->GetDesc().Format; + desc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + desc.Texture2D.MostDetailedMip = mostDetailedMip; + desc.Texture2D.MipLevels = mipLevels; + desc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + gpu->device()->CreateShaderResourceView(resource, &desc, descriptor.fHandle); return descriptor; } GrD3DDescriptorHeap::CPUHandle GrD3DCpuDescriptorManager::createUnorderedAccessView( - GrD3DGpu* gpu, ID3D12Resource* resource) { + GrD3DGpu* gpu, ID3D12Resource* resource, unsigned int mipSlice) { const GrD3DDescriptorHeap::CPUHandle& descriptor = fShaderViewDescriptorPool.allocateHandle(gpu); - // TODO: might need more granularity here for textures (specify miplevels, etc.) - gpu->device()->CreateUnorderedAccessView(resource, nullptr, nullptr, descriptor.fHandle); + if (resource->GetDesc().Dimension == D3D12_RESOURCE_DIMENSION_BUFFER) { + // TODO: figure out buffer setup + gpu->device()->CreateUnorderedAccessView(resource, nullptr, nullptr, descriptor.fHandle); + } else { + D3D12_UNORDERED_ACCESS_VIEW_DESC desc = {}; + desc.Format = resource->GetDesc().Format; + desc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D; + desc.Texture2D.MipSlice = mipSlice; + gpu->device()->CreateUnorderedAccessView(resource, nullptr, &desc, descriptor.fHandle); + } return descriptor; } diff --git a/src/gpu/d3d/GrD3DCpuDescriptorManager.h b/src/gpu/d3d/GrD3DCpuDescriptorManager.h index 225af9ea72..bb14f9b29e 100644 --- a/src/gpu/d3d/GrD3DCpuDescriptorManager.h +++ b/src/gpu/d3d/GrD3DCpuDescriptorManager.h @@ -29,9 +29,12 @@ public: size_t offset, size_t size); GrD3DDescriptorHeap::CPUHandle createShaderResourceView(GrD3DGpu*, - ID3D12Resource* resource); + ID3D12Resource* resource, + unsigned int mostDetailedMip, + unsigned int mipLevels); GrD3DDescriptorHeap::CPUHandle createUnorderedAccessView(GrD3DGpu*, - ID3D12Resource* resource); + ID3D12Resource* resource, + unsigned int mipSlice); void recycleShaderView(const GrD3DDescriptorHeap::CPUHandle&); GrD3DDescriptorHeap::CPUHandle createSampler(GrD3DGpu*, diff --git a/src/gpu/d3d/GrD3DResourceProvider.cpp b/src/gpu/d3d/GrD3DResourceProvider.cpp index 566655e071..cd0eb03ee9 100644 --- a/src/gpu/d3d/GrD3DResourceProvider.cpp +++ b/src/gpu/d3d/GrD3DResourceProvider.cpp @@ -105,13 +105,13 @@ GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createConstantBufferView( } GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createShaderResourceView( - ID3D12Resource* resource) { - return fCpuDescriptorManager.createShaderResourceView(fGpu, resource); + ID3D12Resource* resource, unsigned int highestMip, unsigned int mipLevels) { + return fCpuDescriptorManager.createShaderResourceView(fGpu, resource, highestMip, mipLevels); } GrD3DDescriptorHeap::CPUHandle GrD3DResourceProvider::createUnorderedAccessView( - ID3D12Resource* resource) { - return fCpuDescriptorManager.createUnorderedAccessView(fGpu, resource); + ID3D12Resource* resource, unsigned int mipSlice) { + return fCpuDescriptorManager.createUnorderedAccessView(fGpu, resource, mipSlice); } void GrD3DResourceProvider::recycleShaderView( diff --git a/src/gpu/d3d/GrD3DResourceProvider.h b/src/gpu/d3d/GrD3DResourceProvider.h index 3b4888e2a3..9b3fe45031 100644 --- a/src/gpu/d3d/GrD3DResourceProvider.h +++ b/src/gpu/d3d/GrD3DResourceProvider.h @@ -53,8 +53,11 @@ public: GrD3DDescriptorHeap::CPUHandle createConstantBufferView(ID3D12Resource* bufferResource, size_t offset, size_t size); - GrD3DDescriptorHeap::CPUHandle createShaderResourceView(ID3D12Resource* resource); - GrD3DDescriptorHeap::CPUHandle createUnorderedAccessView(ID3D12Resource* resource); + GrD3DDescriptorHeap::CPUHandle createShaderResourceView(ID3D12Resource* resource, + unsigned int mostDetailedMip = 0, + unsigned int mipLevels = -1); + GrD3DDescriptorHeap::CPUHandle createUnorderedAccessView(ID3D12Resource* resource, + unsigned int mipSlice); void recycleShaderView(const GrD3DDescriptorHeap::CPUHandle&); D3D12_CPU_DESCRIPTOR_HANDLE findOrCreateCompatibleSampler(const GrSamplerState& params);