From e8d12b44b6a2a2bf0b0a27417b4dfd76f65e583f Mon Sep 17 00:00:00 2001 From: Jiawei Shao Date: Fri, 26 Oct 2018 06:29:38 +0000 Subject: [PATCH] Create texture view with descriptor on D3D12 and Metal - Part I This patch is the first part to implement creating a texture view with a texture view descriptor on D3D12 and Metal back-ends. With this patch the texture views created with descriptor can be bound as sampledTextures on D3D12 and Metal back-ends. Note that the support of rendering into a layer or a mipmap level of a texture on D3D12 and Metal back-ends is not included in this patch. BUG=dawn:16 TEST=dawn_end2end_tests Change-Id: I62473ec5a4bb6b84d797ef7fd9cb98689ff763f4 Reviewed-on: https://dawn-review.googlesource.com/c/1940 Commit-Queue: Corentin Wallez Reviewed-by: Corentin Wallez --- src/dawn_native/d3d12/TextureD3D12.cpp | 40 ++++++++++++----------- src/dawn_native/metal/CommandBufferMTL.mm | 13 +++++--- src/dawn_native/metal/TextureMTL.h | 6 ++++ src/dawn_native/metal/TextureMTL.mm | 36 +++++++++++++++++++- src/tests/end2end/TextureViewTests.cpp | 8 ++--- 5 files changed, 74 insertions(+), 29 deletions(-) diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index 0a52364e8e..f200a4683c 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -187,28 +187,28 @@ namespace dawn_native { namespace d3d12 { mLastUsage = usage; } - // TODO(jiawei.shao@intel.com): create texture view by TextureViewDescriptor TextureView::TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor) : TextureViewBase(texture, descriptor) { - mSrvDesc.Format = D3D12TextureFormat(GetTexture()->GetFormat()); + mSrvDesc.Format = D3D12TextureFormat(descriptor->format); mSrvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; - switch (GetTexture()->GetDimension()) { - case dawn::TextureDimension::e2D: - if (GetTexture()->GetArrayLayers() == 1) { - mSrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; - mSrvDesc.Texture2D.MostDetailedMip = 0; - mSrvDesc.Texture2D.MipLevels = GetTexture()->GetNumMipLevels(); - mSrvDesc.Texture2D.PlaneSlice = 0; - mSrvDesc.Texture2D.ResourceMinLODClamp = 0; - } else { - mSrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; - mSrvDesc.Texture2DArray.ArraySize = GetTexture()->GetArrayLayers(); - mSrvDesc.Texture2DArray.FirstArraySlice = 0; - mSrvDesc.Texture2DArray.MipLevels = GetTexture()->GetNumMipLevels(); - mSrvDesc.Texture2DArray.MostDetailedMip = 0; - mSrvDesc.Texture2DArray.PlaneSlice = 0; - mSrvDesc.Texture2DArray.ResourceMinLODClamp = 0; - } + + // Currently we always use D3D12_TEX2D_ARRAY_SRV because we cannot specify base array layer + // and layer count in D3D12_TEX2D_SRV. For 2D texture views, we treat them as 1-layer 2D + // array textures. + // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_tex2d_srv + // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_tex2d_array_srv + // TODO(jiawei.shao@intel.com): support more texture view dimensions. + switch (descriptor->dimension) { + case dawn::TextureViewDimension::e2D: + case dawn::TextureViewDimension::e2DArray: + ASSERT(texture->GetDimension() == dawn::TextureDimension::e2D); + mSrvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + mSrvDesc.Texture2DArray.ArraySize = descriptor->layerCount; + mSrvDesc.Texture2DArray.FirstArraySlice = descriptor->baseArrayLayer; + mSrvDesc.Texture2DArray.MipLevels = descriptor->levelCount; + mSrvDesc.Texture2DArray.MostDetailedMip = descriptor->baseMipLevel; + mSrvDesc.Texture2DArray.PlaneSlice = 0; + mSrvDesc.Texture2DArray.ResourceMinLODClamp = 0; break; default: @@ -220,6 +220,7 @@ namespace dawn_native { namespace d3d12 { return mSrvDesc; } + // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture. D3D12_RENDER_TARGET_VIEW_DESC TextureView::GetRTVDescriptor() { D3D12_RENDER_TARGET_VIEW_DESC rtvDesc; rtvDesc.Format = ToBackend(GetTexture())->GetD3D12Format(); @@ -229,6 +230,7 @@ namespace dawn_native { namespace d3d12 { return rtvDesc; } + // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture. D3D12_DEPTH_STENCIL_VIEW_DESC TextureView::GetDSVDescriptor() { D3D12_DEPTH_STENCIL_VIEW_DESC dsvDesc; dsvDesc.Format = ToBackend(GetTexture())->GetD3D12Format(); diff --git a/src/dawn_native/metal/CommandBufferMTL.mm b/src/dawn_native/metal/CommandBufferMTL.mm index 746f298d64..3aff378410 100644 --- a/src/dawn_native/metal/CommandBufferMTL.mm +++ b/src/dawn_native/metal/CommandBufferMTL.mm @@ -63,6 +63,7 @@ namespace dawn_native { namespace metal { descriptor.colorAttachments[i].loadAction = MTLLoadActionLoad; } + // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture. descriptor.colorAttachments[i].texture = ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture(); descriptor.colorAttachments[i].storeAction = MTLStoreActionStore; @@ -71,6 +72,7 @@ namespace dawn_native { namespace metal { if (desc->HasDepthStencilAttachment()) { auto& attachmentInfo = desc->GetDepthStencilAttachment(); + // TODO(jiawei.shao@intel.com): support rendering into a layer of a texture. id texture = ToBackend(attachmentInfo.view->GetTexture())->GetMTLTexture(); dawn::TextureFormat format = attachmentInfo.view->GetTexture()->GetFormat(); @@ -187,16 +189,17 @@ namespace dawn_native { namespace metal { } break; case dawn::BindingType::SampledTexture: { - auto texture = - ToBackend(group->GetBindingAsTextureView(binding)->GetTexture()); + auto textureView = ToBackend(group->GetBindingAsTextureView(binding)); if (hasVertStage) { - [render setVertexTexture:texture->GetMTLTexture() atIndex:vertIndex]; + [render setVertexTexture:textureView->GetMTLTexture() + atIndex:vertIndex]; } if (hasFragStage) { - [render setFragmentTexture:texture->GetMTLTexture() atIndex:fragIndex]; + [render setFragmentTexture:textureView->GetMTLTexture() + atIndex:fragIndex]; } if (hasComputeStage) { - [compute setTexture:texture->GetMTLTexture() atIndex:computeIndex]; + [compute setTexture:textureView->GetMTLTexture() atIndex:computeIndex]; } } break; } diff --git a/src/dawn_native/metal/TextureMTL.h b/src/dawn_native/metal/TextureMTL.h index 01efb210ed..c002f569db 100644 --- a/src/dawn_native/metal/TextureMTL.h +++ b/src/dawn_native/metal/TextureMTL.h @@ -40,6 +40,12 @@ namespace dawn_native { namespace metal { class TextureView : public TextureViewBase { public: TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor); + ~TextureView(); + + id GetMTLTexture(); + + private: + id mMtlTextureView = nil; }; }} // namespace dawn_native::metal diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm index 7d6d0243b8..5102055846 100644 --- a/src/dawn_native/metal/TextureMTL.mm +++ b/src/dawn_native/metal/TextureMTL.mm @@ -55,6 +55,10 @@ namespace dawn_native { namespace metal { result |= MTLTextureUsageRenderTarget; } + // TODO(jiawei.shao@intel.com): investigate if we should skip setting this flag when the + // texture is only used as a render target. + result |= MTLTextureUsagePixelFormatView; + return result; } @@ -65,6 +69,18 @@ namespace dawn_native { namespace metal { return (arrayLayers > 1) ? MTLTextureType2DArray : MTLTextureType2D; } } + + MTLTextureType MetalTextureViewType(dawn::TextureViewDimension dimension) { + switch (dimension) { + case dawn::TextureViewDimension::e2D: + return MTLTextureType2D; + case dawn::TextureViewDimension::e2DArray: + return MTLTextureType2DArray; + default: + UNREACHABLE(); + return MTLTextureType2D; + } + } } Texture::Texture(Device* device, const TextureDescriptor* descriptor) @@ -101,9 +117,27 @@ namespace dawn_native { namespace metal { return mMtlTexture; } - // TODO(jiawei.shao@intel.com): create texture view by texture view descriptor + // TODO(jiawei.shao@intel.com): use the original texture directly when the descriptor covers the + // whole texture in the same format (for example, when CreateDefaultTextureView() is called). TextureView::TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor) : TextureViewBase(texture, descriptor) { + MTLPixelFormat format = MetalPixelFormat(descriptor->format); + MTLTextureType textureViewType = MetalTextureViewType(descriptor->dimension); + auto mipLevelRange = NSMakeRange(descriptor->baseMipLevel, descriptor->levelCount); + auto arrayLayerRange = NSMakeRange(descriptor->baseArrayLayer, descriptor->layerCount); + + id mtlTexture = ToBackend(texture)->GetMTLTexture(); + mMtlTextureView = [mtlTexture newTextureViewWithPixelFormat:format + textureType:textureViewType + levels:mipLevelRange + slices:arrayLayerRange]; } + TextureView::~TextureView() { + [mMtlTextureView release]; + } + + id TextureView::GetMTLTexture() { + return mMtlTextureView; + } }} // namespace dawn_native::metal diff --git a/src/tests/end2end/TextureViewTests.cpp b/src/tests/end2end/TextureViewTests.cpp index 8e3abd80ad..1877cf4332 100644 --- a/src/tests/end2end/TextureViewTests.cpp +++ b/src/tests/end2end/TextureViewTests.cpp @@ -164,8 +164,8 @@ protected: uint32_t textureViewBaseLayer, uint32_t textureViewBaseMipLevel) { // TODO(jiawei.shao@intel.com): support creating texture view with a texture view descriptor - // on D3D12, Metal and OpenGL. - DAWN_SKIP_TEST_IF(IsD3D12() || IsMetal() || IsOpenGL()); + // on OpenGL. + DAWN_SKIP_TEST_IF(IsOpenGL()); ASSERT(textureViewBaseLayer < textureArrayLayers); ASSERT(textureViewBaseMipLevel < textureMipLevels); @@ -201,8 +201,8 @@ protected: uint32_t textureViewBaseLayer, uint32_t textureViewBaseMipLevel) { // TODO(jiawei.shao@intel.com): support creating texture view with a texture view descriptor - // on D3D12, Metal and OpenGL. - DAWN_SKIP_TEST_IF(IsD3D12() || IsMetal() || IsOpenGL()); + // on OpenGL. + DAWN_SKIP_TEST_IF(IsOpenGL()); ASSERT(textureViewBaseLayer < textureArrayLayers); ASSERT(textureViewBaseMipLevel < textureMipLevels);