From 4de58520987882e1daa162e31cabca3f334c20a8 Mon Sep 17 00:00:00 2001 From: assiduous Date: Thu, 5 Nov 2020 22:46:17 -0800 Subject: Refactored TextureBase --- Graphics/GraphicsEngine/include/BufferBase.hpp | 52 ++- Graphics/GraphicsEngine/include/TextureBase.hpp | 389 +++++----------------- Graphics/GraphicsEngine/interface/DeviceContext.h | 4 +- Graphics/GraphicsEngine/src/TextureBase.cpp | 228 ++++++++++++- 4 files changed, 350 insertions(+), 323 deletions(-) (limited to 'Graphics/GraphicsEngine') diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp index 0ccbc0aa..f09e8fc5 100644 --- a/Graphics/GraphicsEngine/include/BufferBase.hpp +++ b/Graphics/GraphicsEngine/include/BufferBase.hpp @@ -138,30 +138,46 @@ public: // Create default views for structured and raw buffers. For formatted buffers we do not know the view format, so // cannot create views. - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + auto CreateDefaultView = [&](BUFFER_VIEW_TYPE ViewType) // { BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS; - auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = UAVName.c_str(); - - IBufferView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == BUFFER_VIEW_UNORDERED_ACCESS, "Unexpected view type"); + ViewDesc.ViewType = ViewType; + + std::string ViewName; + switch (ViewType) + { + case BUFFER_VIEW_UNORDERED_ACCESS: + ViewName = "Default UAV of buffer '"; + break; + + case BUFFER_VIEW_SHADER_RESOURCE: + ViewName = "Default SRV of buffer '"; + break; + + default: + UNEXPECTED("Unexpected buffer view type"); + } + + ViewName += this->m_Desc.Name; + ViewName += '\''; + ViewDesc.Name = ViewName.c_str(); + + IBufferView* pView = nullptr; + CreateViewInternal(ViewDesc, &pView, true); + VERIFY(pView != nullptr, "Failed to create default view for buffer '", this->m_Desc.Name, "'"); + VERIFY(pView->GetDesc().ViewType == ViewType, "Unexpected view type"); + + return static_cast(pView); + }; + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) + { + m_pDefaultUAV.reset(CreateDefaultView(BUFFER_VIEW_UNORDERED_ACCESS)); } if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE && (this->m_Desc.Mode == BUFFER_MODE_STRUCTURED || this->m_Desc.Mode == BUFFER_MODE_RAW)) { - BufferViewDesc ViewDesc; - ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE; - auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\''); - ViewDesc.Name = SRVName.c_str(); - - IBufferView* pSRV = nullptr; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == BUFFER_VIEW_SHADER_RESOURCE, "Unexpected view type"); + m_pDefaultSRV.reset(CreateDefaultView(BUFFER_VIEW_SHADER_RESOURCE)); } } diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp index 559df1ea..ddd1a378 100644 --- a/Graphics/GraphicsEngine/include/TextureBase.hpp +++ b/Graphics/GraphicsEngine/include/TextureBase.hpp @@ -44,9 +44,19 @@ namespace Diligent struct CopyTextureAttribs; -void ValidateTextureDesc(const TextureDesc& TexDesc); +/// Validates texture description and throws an exception in case of an error. +void ValidateTextureDesc(const TextureDesc& TexDesc) noexcept(false); + +/// Validates and corrects texture view description; throws an exception in case of an error. +void ValidatedAndCorrectTextureViewDesc(const TextureDesc& TexDesc, TextureViewDesc& ViewDesc) noexcept(false); + +/// Validates update texture command paramters. void ValidateUpdateTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 Slice, const Box& DstBox, const TextureSubResData& SubresData); + +/// Validates copy texture command paramters. void ValidateCopyTextureParams(const CopyTextureAttribs& CopyAttribs); + +/// Validates map texture command paramters. void ValidateMapTextureParams(const TextureDesc& TexDesc, Uint32 MipLevel, Uint32 ArraySlice, @@ -88,10 +98,10 @@ public: #ifdef DILIGENT_DEBUG m_dbgTexViewObjAllocator(TexViewObjAllocator), #endif - m_pDefaultSRV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultRTV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultDSV(nullptr, STDDeleter(TexViewObjAllocator)), - m_pDefaultUAV(nullptr, STDDeleter(TexViewObjAllocator)) + m_pDefaultSRV{nullptr, STDDeleter(TexViewObjAllocator)}, + m_pDefaultRTV{nullptr, STDDeleter(TexViewObjAllocator)}, + m_pDefaultDSV{nullptr, STDDeleter(TexViewObjAllocator)}, + m_pDefaultUAV{nullptr, STDDeleter(TexViewObjAllocator)} { if (this->m_Desc.MipLevels == 0) { @@ -161,7 +171,78 @@ public: /// - Creates default unordered access view addressing the entire texture if Diligent::BIND_UNORDERED_ACCESS flag is set. /// /// The function calls CreateViewInternal(). - void CreateDefaultViews(); + void CreateDefaultViews() + { + const auto& TexFmtAttribs = GetTextureFormatAttribs(this->m_Desc.Format); + if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_UNDEFINED) + { + // Cannot create default view for TYPELESS formats + return; + } + + auto CreateDefaultView = [&](TEXTURE_VIEW_TYPE ViewType) // + { + TextureViewDesc ViewDesc; + ViewDesc.ViewType = ViewType; + + std::string ViewName; + switch (ViewType) + { + case TEXTURE_VIEW_SHADER_RESOURCE: + if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0) + ViewDesc.Flags |= TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION; + ViewName = "Default SRV of texture '"; + break; + + case TEXTURE_VIEW_RENDER_TARGET: + ViewName = "Default RTV of texture '"; + break; + + case TEXTURE_VIEW_DEPTH_STENCIL: + ViewName = "Default DSV of texture '"; + break; + + case TEXTURE_VIEW_UNORDERED_ACCESS: + ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ_WRITE; + + ViewName = "Default UAV of texture '"; + break; + + default: + UNEXPECTED("Unexpected texture type"); + } + ViewName += this->m_Desc.Name; + ViewName += '\''; + ViewDesc.Name = ViewName.c_str(); + + ITextureView* pView = nullptr; + CreateViewInternal(ViewDesc, &pView, true); + VERIFY(pView != nullptr, "Failed to create default view for texture '", this->m_Desc.Name, "'"); + VERIFY(pView->GetDesc().ViewType == ViewType, "Unexpected view type"); + + return static_cast(pView); + }; + + if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE) + { + m_pDefaultSRV.reset(CreateDefaultView(TEXTURE_VIEW_SHADER_RESOURCE)); + } + + if (this->m_Desc.BindFlags & BIND_RENDER_TARGET) + { + m_pDefaultRTV.reset(CreateDefaultView(TEXTURE_VIEW_RENDER_TARGET)); + } + + if (this->m_Desc.BindFlags & BIND_DEPTH_STENCIL) + { + m_pDefaultDSV.reset(CreateDefaultView(TEXTURE_VIEW_DEPTH_STENCIL)); + } + + if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) + { + m_pDefaultUAV.reset(CreateDefaultView(TEXTURE_VIEW_UNORDERED_ACCESS)); + } + } virtual void DILIGENT_CALL_TYPE SetState(RESOURCE_STATE State) override final { @@ -223,303 +304,7 @@ protected: /// Default UAV addressing the entire texture std::unique_ptr> m_pDefaultUAV; - void CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc); - RESOURCE_STATE m_State = RESOURCE_STATE_UNKNOWN; }; - -template -void TextureBase::CorrectTextureViewDesc(struct TextureViewDesc& ViewDesc) -{ -#define TEX_VIEW_VALIDATION_ERROR(...) LOG_ERROR_AND_THROW("\n Failed to create texture view '", (ViewDesc.Name ? ViewDesc.Name : ""), "' for texture '", this->m_Desc.Name, "': ", ##__VA_ARGS__) - - if (!(ViewDesc.ViewType > TEXTURE_VIEW_UNDEFINED && ViewDesc.ViewType < TEXTURE_VIEW_NUM_VIEWS)) - TEX_VIEW_VALIDATION_ERROR("Texture view type is not specified"); - - if (ViewDesc.MostDetailedMip >= this->m_Desc.MipLevels) - TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); - - if (ViewDesc.NumMipLevels != REMAINING_MIP_LEVELS && ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels > this->m_Desc.MipLevels) - TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") and number of mip levels in the view (", ViewDesc.NumMipLevels, ") is out of range. The texture has only ", this->m_Desc.MipLevels, " mip ", (this->m_Desc.MipLevels > 1 ? "levels." : "level.")); - - if (ViewDesc.Format == TEX_FORMAT_UNKNOWN) - ViewDesc.Format = GetDefaultTextureViewFormat(this->m_Desc.Format, ViewDesc.ViewType, this->m_Desc.BindFlags); - - if (ViewDesc.TextureDim == RESOURCE_DIM_UNDEFINED) - { - if (this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE || this->m_Desc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - switch (ViewDesc.ViewType) - { - case TEXTURE_VIEW_SHADER_RESOURCE: - ViewDesc.TextureDim = this->m_Desc.Type; - break; - - case TEXTURE_VIEW_RENDER_TARGET: - case TEXTURE_VIEW_DEPTH_STENCIL: - case TEXTURE_VIEW_UNORDERED_ACCESS: - ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY; - break; - - default: UNEXPECTED("Unexpected view type"); - } - } - else - { - ViewDesc.TextureDim = this->m_Desc.Type; - } - } - - switch (this->m_Desc.Type) - { - case RESOURCE_DIM_TEX_1D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 1D view: only Texture 1D is allowed"); - } - break; - - case RESOURCE_DIM_TEX_1D_ARRAY: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect view type for Texture 1D Array: only Texture 1D or Texture 1D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_2D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D view: only Texture 2D or Texture 2D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_2D_ARRAY: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D Array view: only Texture 2D or Texture 2D Array are allowed"); - } - break; - - case RESOURCE_DIM_TEX_3D: - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 3D view: only Texture 3D is allowed"); - } - break; - - case RESOURCE_DIM_TEX_CUBE: - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube SRV: Texture 2D, Texture 2D array or Texture Cube is allowed"); - } - } - else - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube non-shader resource view: Texture 2D or Texture 2D array is allowed"); - } - } - break; - - case RESOURCE_DIM_TEX_CUBE_ARRAY: - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array SRV: Texture 2D, Texture 2D array, Texture Cube or Texture Cube Array is allowed"); - } - } - else - { - if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && - ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) - { - TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array non-shader resource view: Texture 2D or Texture 2D array is allowed"); - } - } - break; - - default: - UNEXPECTED("Unexpected texture type"); - break; - } - - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE) - { - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); - if (ViewDesc.NumArraySlices != 6 && ViewDesc.NumArraySlices != 0 && ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES) - TEX_VIEW_VALIDATION_ERROR("Texture cube SRV is expected to have 6 array slices, while ", ViewDesc.NumArraySlices, " is provided"); - if (ViewDesc.FirstArraySlice != 0) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture cube SRV"); - } - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && (ViewDesc.NumArraySlices % 6) != 0) - TEX_VIEW_VALIDATION_ERROR("Number of slices in texture cube array SRV is expected to be multiple of 6. ", ViewDesc.NumArraySlices, " slices is provided."); - } - - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D) - { - if (ViewDesc.FirstArraySlice != 0) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture 1D/2D views"); - - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.NumArraySlices > 1) - TEX_VIEW_VALIDATION_ERROR("Number of slices in the view (", ViewDesc.NumArraySlices, ") must be 1 (or 0) for non-array texture 1D/2D views"); - } - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - { - if (ViewDesc.FirstArraySlice >= this->m_Desc.ArraySize) - TEX_VIEW_VALIDATION_ERROR("First array slice (", ViewDesc.FirstArraySlice, ") exceeds the number of slices in the texture array (", this->m_Desc.ArraySize, ")"); - - if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.FirstArraySlice + ViewDesc.NumArraySlices > this->m_Desc.ArraySize) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") and number of slices in the view (", ViewDesc.NumArraySlices, ") specify more slices than target texture has (", this->m_Desc.ArraySize, ")"); - } - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) - { - auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; - if (ViewDesc.FirstDepthSlice + ViewDesc.NumDepthSlices > MipDepth) - TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstDepthSlice, ") and number of slices in the view (", ViewDesc.NumDepthSlices, ") specify more slices than target 3D texture mip level has (", MipDepth, ")"); - } - else - { - UNEXPECTED("Unexpected texture dimension"); - } - - if (GetTextureFormatAttribs(ViewDesc.Format).IsTypeless) - { - TEX_VIEW_VALIDATION_ERROR("Texture view format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") cannot be typeless"); - } - - if ((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0) - { - if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) == 0) - TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only set if the texture was created with MISC_TEXTURE_FLAG_GENERATE_MIPS flag"); - - if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) - TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only be used with TEXTURE_VIEW_SHADER_RESOURCE view type"); - } - -#undef TEX_VIEW_VALIDATION_ERROR - - if (ViewDesc.NumMipLevels == 0 || ViewDesc.NumMipLevels == REMAINING_MIP_LEVELS) - { - if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) - ViewDesc.NumMipLevels = this->m_Desc.MipLevels - ViewDesc.MostDetailedMip; - else - ViewDesc.NumMipLevels = 1; - } - - if (ViewDesc.NumArraySlices == 0 || ViewDesc.NumArraySlices == REMAINING_ARRAY_SLICES) - { - if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || - ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) - ViewDesc.NumArraySlices = this->m_Desc.ArraySize - ViewDesc.FirstArraySlice; - else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) - { - auto MipDepth = this->m_Desc.Depth >> ViewDesc.MostDetailedMip; - ViewDesc.NumDepthSlices = MipDepth - ViewDesc.FirstDepthSlice; - } - else - ViewDesc.NumArraySlices = 1; - } - - if ((ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) && - (ViewDesc.Format == TEX_FORMAT_R8_SNORM || ViewDesc.Format == TEX_FORMAT_RG8_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA8_SNORM || - ViewDesc.Format == TEX_FORMAT_R16_SNORM || ViewDesc.Format == TEX_FORMAT_RG16_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA16_SNORM)) - { - const auto* FmtName = GetTextureFormatAttribs(ViewDesc.Format).Name; - LOG_WARNING_MESSAGE(FmtName, " render target view is created.\n" - "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero.\n" - "Use UNORM format instead."); - } -} - -template -void TextureBase::CreateDefaultViews() -{ - const auto& TexFmtAttribs = GetTextureFormatAttribs(this->m_Desc.Format); - if (TexFmtAttribs.ComponentType == COMPONENT_TYPE_UNDEFINED) - { - // Cannot create default view for TYPELESS formats - return; - } - - if (this->m_Desc.BindFlags & BIND_SHADER_RESOURCE) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_SHADER_RESOURCE; - auto ViewName = FormatString("Default SRV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pSRV = nullptr; - if ((this->m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0) - ViewDesc.Flags |= TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION; - CreateViewInternal(ViewDesc, &pSRV, true); - m_pDefaultSRV.reset(static_cast(pSRV)); - VERIFY(m_pDefaultSRV->GetDesc().ViewType == TEXTURE_VIEW_SHADER_RESOURCE, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_RENDER_TARGET) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_RENDER_TARGET; - auto ViewName = FormatString("Default RTV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pRTV = nullptr; - CreateViewInternal(ViewDesc, &pRTV, true); - m_pDefaultRTV.reset(static_cast(pRTV)); - VERIFY(m_pDefaultRTV->GetDesc().ViewType == TEXTURE_VIEW_RENDER_TARGET, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_DEPTH_STENCIL) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_DEPTH_STENCIL; - auto ViewName = FormatString("Default DSV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ITextureView* pDSV = nullptr; - CreateViewInternal(ViewDesc, &pDSV, true); - m_pDefaultDSV.reset(static_cast(pDSV)); - VERIFY(m_pDefaultDSV->GetDesc().ViewType == TEXTURE_VIEW_DEPTH_STENCIL, "Unexpected view type"); - } - - if (this->m_Desc.BindFlags & BIND_UNORDERED_ACCESS) - { - TextureViewDesc ViewDesc; - ViewDesc.ViewType = TEXTURE_VIEW_UNORDERED_ACCESS; - auto ViewName = FormatString("Default UAV of texture '", this->m_Desc.Name, "'"); - ViewDesc.Name = ViewName.c_str(); - - ViewDesc.AccessFlags = UAV_ACCESS_FLAG_READ_WRITE; - ITextureView* pUAV = nullptr; - CreateViewInternal(ViewDesc, &pUAV, true); - m_pDefaultUAV.reset(static_cast(pUAV)); - VERIFY(m_pDefaultUAV->GetDesc().ViewType == TEXTURE_VIEW_UNORDERED_ACCESS, "Unexpected view type"); - } -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/DeviceContext.h b/Graphics/GraphicsEngine/interface/DeviceContext.h index d19021f1..de0ce74f 100644 --- a/Graphics/GraphicsEngine/interface/DeviceContext.h +++ b/Graphics/GraphicsEngine/interface/DeviceContext.h @@ -1190,8 +1190,8 @@ struct TraceRaysAttribs typedef struct TraceRaysAttribs TraceRaysAttribs; -static const Uint32 REMAINING_MIP_LEVELS = 0xFFFFFFFFU; -static const Uint32 REMAINING_ARRAY_SLICES = 0xFFFFFFFFU; +static const Uint32 REMAINING_MIP_LEVELS = ~0u; +static const Uint32 REMAINING_ARRAY_SLICES = ~0u; /// Resource state transition barrier description struct StateTransitionDesc diff --git a/Graphics/GraphicsEngine/src/TextureBase.cpp b/Graphics/GraphicsEngine/src/TextureBase.cpp index cd31242f..0ecfc538 100644 --- a/Graphics/GraphicsEngine/src/TextureBase.cpp +++ b/Graphics/GraphicsEngine/src/TextureBase.cpp @@ -32,7 +32,7 @@ namespace Diligent { -void ValidateTextureDesc(const TextureDesc& Desc) +void ValidateTextureDesc(const TextureDesc& Desc) noexcept(false) { #define LOG_TEXTURE_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Texture '", (Desc.Name ? Desc.Name : ""), "': ", ##__VA_ARGS__) @@ -311,4 +311,230 @@ void ValidateMapTextureParams(const TextureDesc& TexDesc, } } +void ValidatedAndCorrectTextureViewDesc(const TextureDesc& TexDesc, TextureViewDesc& ViewDesc) noexcept(false) +{ +#define TEX_VIEW_VALIDATION_ERROR(...) LOG_ERROR_AND_THROW("\n Failed to create texture view '", (ViewDesc.Name ? ViewDesc.Name : ""), "' for texture '", TexDesc.Name, "': ", ##__VA_ARGS__) + + if (!(ViewDesc.ViewType > TEXTURE_VIEW_UNDEFINED && ViewDesc.ViewType < TEXTURE_VIEW_NUM_VIEWS)) + TEX_VIEW_VALIDATION_ERROR("Texture view type is not specified"); + + if (ViewDesc.MostDetailedMip >= TexDesc.MipLevels) + TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") is out of range. The texture has only ", TexDesc.MipLevels, " mip ", (TexDesc.MipLevels > 1 ? "levels." : "level.")); + + if (ViewDesc.NumMipLevels != REMAINING_MIP_LEVELS && ViewDesc.MostDetailedMip + ViewDesc.NumMipLevels > TexDesc.MipLevels) + TEX_VIEW_VALIDATION_ERROR("Most detailed mip (", ViewDesc.MostDetailedMip, ") and number of mip levels in the view (", ViewDesc.NumMipLevels, ") is out of range. The texture has only ", TexDesc.MipLevels, " mip ", (TexDesc.MipLevels > 1 ? "levels." : "level.")); + + if (ViewDesc.Format == TEX_FORMAT_UNKNOWN) + ViewDesc.Format = GetDefaultTextureViewFormat(TexDesc.Format, ViewDesc.ViewType, TexDesc.BindFlags); + + if (ViewDesc.TextureDim == RESOURCE_DIM_UNDEFINED) + { + if (TexDesc.Type == RESOURCE_DIM_TEX_CUBE || TexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + switch (ViewDesc.ViewType) + { + case TEXTURE_VIEW_SHADER_RESOURCE: + ViewDesc.TextureDim = TexDesc.Type; + break; + + case TEXTURE_VIEW_RENDER_TARGET: + case TEXTURE_VIEW_DEPTH_STENCIL: + case TEXTURE_VIEW_UNORDERED_ACCESS: + ViewDesc.TextureDim = RESOURCE_DIM_TEX_2D_ARRAY; + break; + + default: UNEXPECTED("Unexpected view type"); + } + } + else + { + ViewDesc.TextureDim = TexDesc.Type; + } + } + + switch (TexDesc.Type) + { + case RESOURCE_DIM_TEX_1D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 1D view: only Texture 1D is allowed"); + } + break; + + case RESOURCE_DIM_TEX_1D_ARRAY: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_1D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect view type for Texture 1D Array: only Texture 1D or Texture 1D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_2D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D view: only Texture 2D or Texture 2D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_2D_ARRAY: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 2D Array view: only Texture 2D or Texture 2D Array are allowed"); + } + break; + + case RESOURCE_DIM_TEX_3D: + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_3D) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture 3D view: only Texture 3D is allowed"); + } + break; + + case RESOURCE_DIM_TEX_CUBE: + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube SRV: Texture 2D, Texture 2D array or Texture Cube is allowed"); + } + } + else + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube non-shader resource view: Texture 2D or Texture 2D array is allowed"); + } + } + break; + + case RESOURCE_DIM_TEX_CUBE_ARRAY: + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_CUBE_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array SRV: Texture 2D, Texture 2D array, Texture Cube or Texture Cube Array is allowed"); + } + } + else + { + if (ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D && + ViewDesc.TextureDim != RESOURCE_DIM_TEX_2D_ARRAY) + { + TEX_VIEW_VALIDATION_ERROR("Incorrect texture type for Texture cube array non-shader resource view: Texture 2D or Texture 2D array is allowed"); + } + } + break; + + default: + UNEXPECTED("Unexpected texture type"); + break; + } + + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE) + { + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); + if (ViewDesc.NumArraySlices != 6 && ViewDesc.NumArraySlices != 0 && ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES) + TEX_VIEW_VALIDATION_ERROR("Texture cube SRV is expected to have 6 array slices, while ", ViewDesc.NumArraySlices, " is provided"); + if (ViewDesc.FirstArraySlice != 0) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture cube SRV"); + } + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("Unexpected view type: SRV is expected"); + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && (ViewDesc.NumArraySlices % 6) != 0) + TEX_VIEW_VALIDATION_ERROR("Number of slices in texture cube array SRV is expected to be multiple of 6. ", ViewDesc.NumArraySlices, " slices is provided."); + } + + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D) + { + if (ViewDesc.FirstArraySlice != 0) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") must be 0 for non-array texture 1D/2D views"); + + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.NumArraySlices > 1) + TEX_VIEW_VALIDATION_ERROR("Number of slices in the view (", ViewDesc.NumArraySlices, ") must be 1 (or 0) for non-array texture 1D/2D views"); + } + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + { + if (ViewDesc.FirstArraySlice >= TexDesc.ArraySize) + TEX_VIEW_VALIDATION_ERROR("First array slice (", ViewDesc.FirstArraySlice, ") exceeds the number of slices in the texture array (", TexDesc.ArraySize, ")"); + + if (ViewDesc.NumArraySlices != REMAINING_ARRAY_SLICES && ViewDesc.FirstArraySlice + ViewDesc.NumArraySlices > TexDesc.ArraySize) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstArraySlice, ") and number of slices in the view (", ViewDesc.NumArraySlices, ") specify more slices than target texture has (", TexDesc.ArraySize, ")"); + } + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) + { + auto MipDepth = TexDesc.Depth >> ViewDesc.MostDetailedMip; + if (ViewDesc.FirstDepthSlice + ViewDesc.NumDepthSlices > MipDepth) + TEX_VIEW_VALIDATION_ERROR("First slice (", ViewDesc.FirstDepthSlice, ") and number of slices in the view (", ViewDesc.NumDepthSlices, ") specify more slices than target 3D texture mip level has (", MipDepth, ")"); + } + else + { + UNEXPECTED("Unexpected texture dimension"); + } + + if (GetTextureFormatAttribs(ViewDesc.Format).IsTypeless) + { + TEX_VIEW_VALIDATION_ERROR("Texture view format (", GetTextureFormatAttribs(ViewDesc.Format).Name, ") cannot be typeless"); + } + + if ((ViewDesc.Flags & TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION) != 0) + { + if ((TexDesc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) == 0) + TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only set if the texture was created with MISC_TEXTURE_FLAG_GENERATE_MIPS flag"); + + if (ViewDesc.ViewType != TEXTURE_VIEW_SHADER_RESOURCE) + TEX_VIEW_VALIDATION_ERROR("TEXTURE_VIEW_FLAG_ALLOW_MIP_MAP_GENERATION flag can only be used with TEXTURE_VIEW_SHADER_RESOURCE view type"); + } + +#undef TEX_VIEW_VALIDATION_ERROR + + if (ViewDesc.NumMipLevels == 0 || ViewDesc.NumMipLevels == REMAINING_MIP_LEVELS) + { + if (ViewDesc.ViewType == TEXTURE_VIEW_SHADER_RESOURCE) + ViewDesc.NumMipLevels = TexDesc.MipLevels - ViewDesc.MostDetailedMip; + else + ViewDesc.NumMipLevels = 1; + } + + if (ViewDesc.NumArraySlices == 0 || ViewDesc.NumArraySlices == REMAINING_ARRAY_SLICES) + { + if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_1D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_2D_ARRAY || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE || + ViewDesc.TextureDim == RESOURCE_DIM_TEX_CUBE_ARRAY) + ViewDesc.NumArraySlices = TexDesc.ArraySize - ViewDesc.FirstArraySlice; + else if (ViewDesc.TextureDim == RESOURCE_DIM_TEX_3D) + { + auto MipDepth = TexDesc.Depth >> ViewDesc.MostDetailedMip; + ViewDesc.NumDepthSlices = MipDepth - ViewDesc.FirstDepthSlice; + } + else + ViewDesc.NumArraySlices = 1; + } + + if ((ViewDesc.ViewType == TEXTURE_VIEW_RENDER_TARGET) && + (ViewDesc.Format == TEX_FORMAT_R8_SNORM || ViewDesc.Format == TEX_FORMAT_RG8_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA8_SNORM || + ViewDesc.Format == TEX_FORMAT_R16_SNORM || ViewDesc.Format == TEX_FORMAT_RG16_SNORM || ViewDesc.Format == TEX_FORMAT_RGBA16_SNORM)) + { + const auto* FmtName = GetTextureFormatAttribs(ViewDesc.Format).Name; + LOG_WARNING_MESSAGE(FmtName, " render target view is created.\n" + "There might be an issue in OpenGL driver on NVidia hardware: when rendering to SNORM textures, all negative values are clamped to zero.\n" + "Use UNORM format instead."); + } +} + } // namespace Diligent -- cgit v1.2.3