diff options
| author | assiduous <assiduous@diligentgraphics.com> | 2020-10-01 00:01:15 +0000 |
|---|---|---|
| committer | assiduous <assiduous@diligentgraphics.com> | 2020-10-01 00:01:15 +0000 |
| commit | 3941b472dedd0836b5e4970460fbf0e38a42e4e4 (patch) | |
| tree | fc4d0002e0c17cab1f09f4f1955e80c2b5fa4ce0 | |
| parent | Updated Metal interfaces plus a number of misc fixes (diff) | |
| download | DiligentCore-3941b472dedd0836b5e4970460fbf0e38a42e4e4.tar.gz DiligentCore-3941b472dedd0836b5e4970460fbf0e38a42e4e4.zip | |
A number of updates to support Metal backend
13 files changed, 80 insertions, 48 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 01fe74e4..2caa523f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,9 @@ include(GNUInstallDirs) set_property(GLOBAL PROPERTY USE_FOLDERS ON) +# Generate XCode schema files +set(CMAKE_XCODE_GENERATE_SCHEME TRUE) + if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug CACHE STRING "" FORCE) message(STATUS "CMAKE_BUILD_TYPE is not specified, default to Debug. Note that this is only relevant for single-configuration generators (such as Makefile Generators and Ninja).") diff --git a/Common/interface/RefCntAutoPtr.hpp b/Common/interface/RefCntAutoPtr.hpp index 7cf13e15..140c01d5 100644 --- a/Common/interface/RefCntAutoPtr.hpp +++ b/Common/interface/RefCntAutoPtr.hpp @@ -220,7 +220,7 @@ public: const T* operator->() const noexcept { return m_pObject; } template <typename InterfaceType> - RefCntAutoPtr<InterfaceType> Cast(const INTERFACE_ID& IID) + RefCntAutoPtr<InterfaceType> Cast(const INTERFACE_ID& IID) const { return RefCntAutoPtr<InterfaceType>{m_pObject, IID}; } diff --git a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp index 0e834f0b..47ded2c1 100644 --- a/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp +++ b/Graphics/GraphicsAccessories/interface/GraphicsAccessories.hpp @@ -471,4 +471,9 @@ bool IsConsistentShaderType(SHADER_TYPE ShaderType, PIPELINE_TYPE Pipelin Int32 GetShaderTypePipelineIndex(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineType); SHADER_TYPE GetShaderTypeFromPipelineIndex(Int32 Index, PIPELINE_TYPE PipelineType); +Uint32 GetStagingTextureSubresOffset(const TextureDesc& TexDesc, + Uint32 ArraySlice, + Uint32 MipLevel, + Uint32 Alignment); + } // namespace Diligent diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index 6229ff2b..193a4989 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -1395,4 +1395,40 @@ SHADER_TYPE GetShaderTypeFromPipelineIndex(Int32 Index, PIPELINE_TYPE PipelineTy } } + +Uint32 GetStagingTextureSubresOffset(const TextureDesc& TexDesc, + Uint32 ArraySlice, + Uint32 MipLevel, + Uint32 Alignment) +{ + VERIFY_EXPR(ArraySlice < TexDesc.ArraySize && MipLevel < TexDesc.MipLevels || ArraySlice == TexDesc.ArraySize && MipLevel == 0); + + Uint32 Offset = 0; + if (ArraySlice > 0) + { + Uint32 ArraySliceSize = 0; + for (Uint32 mip = 0; mip < TexDesc.MipLevels; ++mip) + { + auto MipInfo = GetMipLevelProperties(TexDesc, mip); + ArraySliceSize += Align(MipInfo.MipSize, Alignment); + } + + Offset = ArraySliceSize; + if (TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY || + TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY || + TexDesc.Type == RESOURCE_DIM_TEX_CUBE || + TexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) + Offset *= ArraySlice; + } + + for (Uint32 mip = 0; mip < MipLevel; ++mip) + { + auto MipInfo = GetMipLevelProperties(TexDesc, mip); + Offset += Align(MipInfo.MipSize, Alignment); + } + + return Offset; +} + + } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 93295972..e8263232 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1743,6 +1743,10 @@ struct DeviceCaps { return DevType == RENDER_DEVICE_TYPE_VULKAN; } + bool IsMetalDevice()const + { + return DevType == RENDER_DEVICE_TYPE_METAL; + } struct NDCAttribs { diff --git a/Graphics/GraphicsEngineMetal/interface/BufferMtl.h b/Graphics/GraphicsEngineMetal/interface/BufferMtl.h index 1ed88a5c..7f4a0a61 100644 --- a/Graphics/GraphicsEngineMetal/interface/BufferMtl.h +++ b/Graphics/GraphicsEngineMetal/interface/BufferMtl.h @@ -41,8 +41,8 @@ static const INTERFACE_ID IID_BufferMtl = class IBufferMtl : public IBuffer { public: - /// Returns a pointer to Metal buffer (MTLBuffer) - virtual void* GetMtlBuffer() const = 0; + /// Returns a pointer to a Metal buffer (MTLBuffer). + virtual void* GetMtlResource() const = 0; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineMetal/interface/TextureMtl.h b/Graphics/GraphicsEngineMetal/interface/TextureMtl.h index da2db211..bced9bb7 100644 --- a/Graphics/GraphicsEngineMetal/interface/TextureMtl.h +++ b/Graphics/GraphicsEngineMetal/interface/TextureMtl.h @@ -41,6 +41,10 @@ static const INTERFACE_ID IID_TextureMtl = class ITextureMtl : public ITexture { public: + /// Returns a pointer to a Metal resource. + /// For a staging texture, this will be a pointer to a MTLStorageModeShared buffer (MTLBuffer). + /// For all other texture types, this will be a pointer to Metal texture object (MTLTexture). + virtual void* GetMtlResource() const = 0; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp index 39eb7ec1..b04babec 100644 --- a/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/TextureVkImpl.hpp @@ -42,8 +42,6 @@ namespace Diligent class FixedBlockMemoryAllocator; -Uint32 GetStagingDataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint32 MipLevel, Uint32 Alignment = 4); - /// Texture object implementation in Vulkan backend. class TextureVkImpl final : public TextureBase<ITextureVk, RenderDeviceVkImpl, TextureViewVkImpl, FixedBlockMemoryAllocator> { @@ -101,6 +99,12 @@ public: void InvalidateStagingRange(VkDeviceSize Offset, VkDeviceSize Size); + // bufferOffset must be a multiple of 4 (18.4) + // If the calling command's VkImage parameter is a compressed image, bufferOffset + // must be a multiple of the compressed texel block size in bytes (18.4). This + // is automatically guaranteed as MipWidth and MipHeight are rounded to block size. + static constexpr Uint32 StagingDataAlignment = 4; + protected: void CreateViewInternal(const struct TextureViewDesc& ViewDesc, ITextureView** ppView, bool bIsDefaultView) override; //void PrepareVkInitData(const TextureData &InitData, Uint32 NumSubresources, std::vector<Vk_SUBRESOURCE_DATA> &VkInitData); diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index cd5d0901..f14e7f9c 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -1634,7 +1634,7 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs) DEV_CHECK_ERR((SrcTexDesc.CPUAccessFlags & CPU_ACCESS_WRITE), "Attempting to copy from staging texture that was not created with CPU_ACCESS_WRITE flag"); DEV_CHECK_ERR(pSrcTexVk->GetState() == RESOURCE_STATE_COPY_SOURCE, "Source staging texture must permanently be in RESOURCE_STATE_COPY_SOURCE state"); - auto SrcBufferOffset = GetStagingDataOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel); + auto SrcBufferOffset = GetStagingTextureSubresOffset(SrcTexDesc, CopyAttribs.SrcSlice, CopyAttribs.SrcMipLevel, TextureVkImpl::StagingDataAlignment); auto SrcMipLevelAttribs = GetMipLevelProperties(SrcTexDesc, CopyAttribs.SrcMipLevel); // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1) SrcBufferOffset += @@ -1667,8 +1667,10 @@ void DeviceContextVkImpl::CopyTexture(const CopyTextureAttribs& CopyAttribs) DEV_CHECK_ERR((DstTexDesc.CPUAccessFlags & CPU_ACCESS_READ), "Attempting to copy to staging texture that was not created with CPU_ACCESS_READ flag"); DEV_CHECK_ERR(pDstTexVk->GetState() == RESOURCE_STATE_COPY_DEST, "Destination staging texture must permanently be in RESOURCE_STATE_COPY_DEST state"); - auto DstBufferOffset = GetStagingDataOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel); - auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel); + auto DstBufferOffset = + GetStagingTextureSubresOffset(DstTexDesc, CopyAttribs.DstSlice, CopyAttribs.DstMipLevel, + TextureVkImpl::StagingDataAlignment); + const auto DstMipLevelAttribs = GetMipLevelProperties(DstTexDesc, CopyAttribs.DstMipLevel); // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1) DstBufferOffset += // For compressed-block formats, RowSize is the size of one compressed row. @@ -2007,8 +2009,10 @@ void DeviceContextVkImpl::MapTextureSubresource(ITexture* pTextu } else if (TexDesc.Usage == USAGE_STAGING) { - auto SubresourceOffset = GetStagingDataOffset(TexDesc, ArraySlice, MipLevel); - auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel); + auto SubresourceOffset = + GetStagingTextureSubresOffset(TexDesc, ArraySlice, MipLevel, + TextureVkImpl::StagingDataAlignment); + const auto MipLevelAttribs = GetMipLevelProperties(TexDesc, MipLevel); // address of (x,y,z) = region->bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1) auto MapStartOffset = SubresourceOffset + // For compressed-block formats, RowSize is the size of one compressed row. diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp index ca04f900..8a37df0c 100644 --- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp @@ -408,7 +408,7 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, VkStagingBuffCI.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; VkStagingBuffCI.pNext = nullptr; VkStagingBuffCI.flags = 0; - VkStagingBuffCI.size = GetStagingDataOffset(m_Desc, m_Desc.ArraySize, 0); + VkStagingBuffCI.size = GetStagingTextureSubresOffset(m_Desc, m_Desc.ArraySize, 0, StagingDataAlignment); // clang-format off DEV_CHECK_ERR((m_Desc.CPUAccessFlags & (CPU_ACCESS_READ | CPU_ACCESS_WRITE)) == CPU_ACCESS_READ || @@ -470,42 +470,6 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, VERIFY_EXPR(IsInKnownState()); } -Uint32 GetStagingDataOffset(const TextureDesc& TexDesc, Uint32 ArraySlice, Uint32 MipLevel, Uint32 Alignment) -{ - VERIFY_EXPR(ArraySlice < TexDesc.ArraySize && MipLevel < TexDesc.MipLevels || ArraySlice == TexDesc.ArraySize && MipLevel == 0); - - Uint32 Offset = 0; - if (ArraySlice > 0) - { - Uint32 ArraySliceSize = 0; - for (Uint32 mip = 0; mip < TexDesc.MipLevels; ++mip) - { - auto MipInfo = GetMipLevelProperties(TexDesc, mip); - // bufferOffset must be a multiple of 4 (18.4) - // If the calling command's VkImage parameter is a compressed image, bufferOffset - // must be a multiple of the compressed texel block size in bytes (18.4). This - // is automatically guaranteed as MipWidth and MipHeight are rounded to block size - ArraySliceSize += Align(MipInfo.MipSize, Alignment); - } - - Offset = ArraySliceSize; - if (TexDesc.Type == RESOURCE_DIM_TEX_1D_ARRAY || - TexDesc.Type == RESOURCE_DIM_TEX_2D_ARRAY || - TexDesc.Type == RESOURCE_DIM_TEX_CUBE || - TexDesc.Type == RESOURCE_DIM_TEX_CUBE_ARRAY) - Offset *= ArraySlice; - } - - for (Uint32 mip = 0; mip < MipLevel; ++mip) - { - auto MipInfo = GetMipLevelProperties(TexDesc, mip); - // bufferOffset must be a multiple of 4 (18.4) - Offset += Align(MipInfo.MipSize, Alignment); - } - - return Offset; -} - TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, FixedBlockMemoryAllocator& TexViewObjAllocator, RenderDeviceVkImpl* pDeviceVk, diff --git a/Tests/DiligentCoreAPITest/CMakeLists.txt b/Tests/DiligentCoreAPITest/CMakeLists.txt index fb3aeb37..b2a5c2fb 100644 --- a/Tests/DiligentCoreAPITest/CMakeLists.txt +++ b/Tests/DiligentCoreAPITest/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required (VERSION 3.6) +cmake_minimum_required (VERSION 3.17) project(DiligentCoreAPITest) @@ -159,6 +159,7 @@ PRIVATE set_target_properties(DiligentCoreAPITest PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets" + XCODE_SCHEME_WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/assets" ) if(PLATFORM_WIN32) diff --git a/Tests/DiligentCoreAPITest/include/Metal/TestingEnvironmentMtl.hpp b/Tests/DiligentCoreAPITest/include/Metal/TestingEnvironmentMtl.hpp index 3a214c81..80cc7f53 100644 --- a/Tests/DiligentCoreAPITest/include/Metal/TestingEnvironmentMtl.hpp +++ b/Tests/DiligentCoreAPITest/include/Metal/TestingEnvironmentMtl.hpp @@ -48,6 +48,8 @@ public: virtual void Reset() override final; + void* GetMtlDevice() const; + private: }; diff --git a/Tests/DiligentCoreAPITest/src/Metal/TestingEnvironmentMtl.mm b/Tests/DiligentCoreAPITest/src/Metal/TestingEnvironmentMtl.mm index 6b50bee5..90f5ebcc 100644 --- a/Tests/DiligentCoreAPITest/src/Metal/TestingEnvironmentMtl.mm +++ b/Tests/DiligentCoreAPITest/src/Metal/TestingEnvironmentMtl.mm @@ -68,6 +68,11 @@ TestingEnvironment* CreateTestingEnvironmentMtl(RENDER_DEVICE_TYPE deviceType, return new TestingEnvironmentMtl{deviceType, AdapterType, AdapterId, SCDesc}; } +void* TestingEnvironmentMtl::GetMtlDevice() const +{ + return m_pDevice.Cast<IRenderDeviceMtl>(IID_RenderDeviceMtl)->GetMtlDevice(); +} + } // namespace Testing } // namespace Diligent |
