From be65a3c3313862aa91b36c140482680b78e84df0 Mon Sep 17 00:00:00 2001 From: Eugene Golushkov Date: Sat, 16 Nov 2024 01:40:55 +0100 Subject: [PATCH] RSC_TILER + TextureFlags::Tiler[Depth]Memoryless => MTLStorageModeMemoryless and VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT --- OgreMain/include/OgreTextureGpu.h | 17 +++++++- OgreMain/src/OgreRenderSystem.cpp | 3 ++ OgreMain/src/OgreTextureGpu.cpp | 1 + .../src/OgreMetalRenderPassDescriptor.mm | 2 +- .../Metal/src/OgreMetalTextureGpu.mm | 27 +++++++++++++ .../Metal/src/OgreMetalTextureGpuManager.mm | 7 ++++ RenderSystems/Metal/src/OgreMetalWindow.mm | 17 ++++++++ .../Vulkan/src/OgreVulkanTextureGpu.cpp | 40 +++++++++++++++++++ 8 files changed, 112 insertions(+), 2 deletions(-) diff --git a/OgreMain/include/OgreTextureGpu.h b/OgreMain/include/OgreTextureGpu.h index c66732bcfbb..b64fd297e47 100644 --- a/OgreMain/include/OgreTextureGpu.h +++ b/OgreMain/include/OgreTextureGpu.h @@ -167,7 +167,17 @@ namespace Ogre /// frames (e.g. HDR luminance change over time) /// /// If this flag is present, either RenderToTexture or Uav must be present - DiscardableContent = 1u << 14u + DiscardableContent = 1u << 14u, + /// When this flag is present, we can save VRAM by using memoryless storage mode (Metal on + /// iOS and Apple Silicon macOS). Choose the memoryless mode if your texture is a memoryless + /// render target that’s temporarily populated and accessed by the GPU. Memoryless render + /// targets are render targets that exist only in tile memory and are not backed by system + /// memory. An example is a depth or stencil texture thatʼs used only within a render pass + /// and isnʼt needed before or after GPU execution. This flag requires RenderToTexture + TilerMemoryless = 1u << 15u, + /// When this flag is present together with RenderToTexture it will use DepthBuffer with + /// TilerMemoryless option + TilerDepthMemoryless = 1u << 16u // clang-format on }; } @@ -649,6 +659,11 @@ namespace Ogre bool isManualTexture() const; bool isPoolOwner() const; bool isDiscardableContent() const; + bool isTilerMemoryless() const { return ( mTextureFlags & TextureFlags::TilerMemoryless ) != 0; } + bool isTilerDepthMemoryless() const + { + return ( mTextureFlags & TextureFlags::TilerDepthMemoryless ) != 0; + } /// OpenGL RenderWindows are a bit specific: /// * Their origins are upside down. Which means we need to flip Y. diff --git a/OgreMain/src/OgreRenderSystem.cpp b/OgreMain/src/OgreRenderSystem.cpp index 65462105615..9c186e9e497 100644 --- a/OgreMain/src/OgreRenderSystem.cpp +++ b/OgreMain/src/OgreRenderSystem.cpp @@ -675,6 +675,9 @@ namespace Ogre if( !preferDepthTexture ) textureFlags |= TextureFlags::NotTexture | TextureFlags::DiscardableContent; + if( colourTexture->isTilerMemoryless() || colourTexture->isTilerDepthMemoryless() ) + textureFlags |= TextureFlags::TilerMemoryless; + char tmpBuffer[64]; LwString depthBufferName( LwString::FromEmptyPointer( tmpBuffer, sizeof( tmpBuffer ) ) ); depthBufferName.a( "DepthBuffer_", Id::generateNewId() ); diff --git a/OgreMain/src/OgreTextureGpu.cpp b/OgreMain/src/OgreTextureGpu.cpp index 5f7fefc72c6..638448830d8 100644 --- a/OgreMain/src/OgreTextureGpu.cpp +++ b/OgreMain/src/OgreTextureGpu.cpp @@ -912,6 +912,7 @@ namespace Ogre if( this->getInternalWidth() == colourTarget->getInternalWidth() && this->getInternalHeight() == colourTarget->getInternalHeight() && this->getSampleDescription() == colourTarget->getSampleDescription() && + this->isTilerMemoryless() == (colourTarget->isTilerMemoryless() || colourTarget->isTilerDepthMemoryless()) && this->isRenderWindowSpecific() == colourTarget->isRenderWindowSpecific() ) { return true; diff --git a/RenderSystems/Metal/src/OgreMetalRenderPassDescriptor.mm b/RenderSystems/Metal/src/OgreMetalRenderPassDescriptor.mm index d505bd2e056..462aba095ca 100644 --- a/RenderSystems/Metal/src/OgreMetalRenderPassDescriptor.mm +++ b/RenderSystems/Metal/src/OgreMetalRenderPassDescriptor.mm @@ -138,7 +138,7 @@ of this software and associated documentation files (the "Software"), to deal return MTLLoadActionDontCare; case LoadAction::Clear: return MTLLoadActionClear; -#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS +#if OGRE_PLATFORM == OGRE_PLATFORM_APPLE_IOS || ( OGRE_PLATFORM == OGRE_PLATFORM_APPLE && OGRE_CPU == OGRE_CPU_ARM && OGRE_ARCH_TYPE == OGRE_ARCHITECTURE_64 ) case LoadAction::ClearOnTilers: return MTLLoadActionClear; #else diff --git a/RenderSystems/Metal/src/OgreMetalTextureGpu.mm b/RenderSystems/Metal/src/OgreMetalTextureGpu.mm index 0f537d7cb55..6f8ad4f1560 100644 --- a/RenderSystems/Metal/src/OgreMetalTextureGpu.mm +++ b/RenderSystems/Metal/src/OgreMetalTextureGpu.mm @@ -38,6 +38,7 @@ of this software and associated documentation files (the "Software"), to deal #include "OgreVector2.h" #include "Vao/OgreVaoManager.h" +#include "OgreRoot.h" #import "Metal/MTLBlitCommandEncoder.h" namespace Ogre @@ -79,6 +80,24 @@ of this software and associated documentation files (the "Software"), to deal if( mTextureType == TextureTypes::TypeCube || mTextureType == TextureTypes::TypeCubeArray ) desc.arrayLength /= 6u; + RenderSystem* rs = Root::getSingleton().getRenderSystem(); + const RenderSystemCapabilities *capabilities = rs->getCapabilities(); + bool isTiler = capabilities->hasCapability( RSC_IS_TILER ); + if(isTiler && isRenderWindowSpecific() && isRenderToTexture()) + { + ConfigOptionMap& options = rs->getConfigOptions(); + Ogre::ConfigOptionMap::iterator opt = options.find("WindowMemoryless"); + if(opt!=options.end()) + isTiler = opt->second.currentValue=="Yes"; + } + if(isTiler) + { + if(@available(iOS 10, macOS 11, *)) + { + if( (isTilerMemoryless() && isRenderToTexture()) || (isMultisample() && hasMsaaExplicitResolves() && !isTexture() && isRenderToTexture() && isDiscardableContent()) ) + desc.storageMode = MTLStorageModeMemoryless; + } + } if( isMultisample() && hasMsaaExplicitResolves() ) { desc.textureType = MTLTextureType2DMultisample; @@ -112,6 +131,14 @@ of this software and associated documentation files (the "Software"), to deal if( isMultisample() && !hasMsaaExplicitResolves() ) { + if(isTiler) + { + if(@available(iOS 10, macOS 11, *)) + { + if(((isTilerMemoryless() || isTilerDepthMemoryless()) && isRenderToTexture()) || (!isTexture() && isRenderToTexture() && isDiscardableContent()) ) + desc.storageMode = MTLStorageModeMemoryless; + } + } desc.textureType = MTLTextureType2DMultisample; desc.depth = 1u; desc.arrayLength = 1u; diff --git a/RenderSystems/Metal/src/OgreMetalTextureGpuManager.mm b/RenderSystems/Metal/src/OgreMetalTextureGpuManager.mm index 2f2030f17c6..11faed9ab30 100644 --- a/RenderSystems/Metal/src/OgreMetalTextureGpuManager.mm +++ b/RenderSystems/Metal/src/OgreMetalTextureGpuManager.mm @@ -40,6 +40,7 @@ of this software and associated documentation files (the "Software"), to deal #include "Vao/OgreMetalVaoManager.h" #include "OgreException.h" +#include "OgreRoot.h" namespace Ogre { @@ -150,8 +151,11 @@ of this software and associated documentation files (the "Software"), to deal //----------------------------------------------------------------------------------- TextureGpu *MetalTextureGpuManager::createTextureGpuWindow( MetalWindow *window ) { + const RenderSystemCapabilities *capabilities = Root::getSingleton().getRenderSystem()->getCapabilities(); + const bool isTiler = capabilities->hasCapability( RSC_IS_TILER ); return OGRE_NEW MetalTextureGpuWindow( GpuPageOutStrategy::Discard, mVaoManager, "RenderWindow", TextureFlags::NotTexture | TextureFlags::RenderToTexture | + (isTiler ? TextureFlags::TilerDepthMemoryless : 0) | TextureFlags::RenderWindowSpecific | TextureFlags::DiscardableContent, TextureTypes::Type2D, this, window ); @@ -159,9 +163,12 @@ of this software and associated documentation files (the "Software"), to deal //----------------------------------------------------------------------------------- TextureGpu *MetalTextureGpuManager::createWindowDepthBuffer() { + const RenderSystemCapabilities *capabilities = Root::getSingleton().getRenderSystem()->getCapabilities(); + const bool isTiler = capabilities->hasCapability( RSC_IS_TILER ); return OGRE_NEW MetalTextureGpuRenderTarget( GpuPageOutStrategy::Discard, mVaoManager, "RenderWindow DepthBuffer", TextureFlags::NotTexture | TextureFlags::RenderToTexture | + (isTiler ? TextureFlags::TilerMemoryless : 0) | TextureFlags::RenderWindowSpecific | TextureFlags::DiscardableContent, TextureTypes::Type2D, this ); } diff --git a/RenderSystems/Metal/src/OgreMetalWindow.mm b/RenderSystems/Metal/src/OgreMetalWindow.mm index cfe29f57aa0..b017462edec 100644 --- a/RenderSystems/Metal/src/OgreMetalWindow.mm +++ b/RenderSystems/Metal/src/OgreMetalWindow.mm @@ -38,6 +38,7 @@ of this software and associated documentation files (the "Software"), to deal #include "OgreStringConverter.h" #include "OgreViewport.h" #include "OgreWindowEventUtilities.h" +#include "OgreRoot.h" #if OGRE_PLATFORM != OGRE_PLATFORM_APPLE_IOS @@ -197,6 +198,22 @@ static void SetupMetalWindowListeners( Ogre::MetalWindow *metalWindow, NSWindow desc.sampleCount = mSampleDescription.getColourSamples(); desc.usage = MTLTextureUsageRenderTarget; desc.storageMode = MTLStorageModePrivate; + RenderSystem* rs = Root::getSingleton().getRenderSystem(); + assert(rs); + const RenderSystemCapabilities *capabilities = rs->getCapabilities(); + bool isTiler = capabilities->hasCapability( RSC_IS_TILER ); + if(isTiler) + { + ConfigOptionMap& options = rs->getConfigOptions(); + Ogre::ConfigOptionMap::iterator opt = options.find("WindowMemoryless"); + if(opt!=options.end()) + isTiler = opt->second.currentValue=="Yes"; + } + if(isTiler) + { + if(@available(iOS 10, macOS 11, *)) + desc.storageMode = MTLStorageModeMemoryless; + } id msaaTex = [mDevice->mDevice newTextureWithDescriptor:desc]; if( !msaaTex ) diff --git a/RenderSystems/Vulkan/src/OgreVulkanTextureGpu.cpp b/RenderSystems/Vulkan/src/OgreVulkanTextureGpu.cpp index cc4626c7bbb..3556f5fae9f 100644 --- a/RenderSystems/Vulkan/src/OgreVulkanTextureGpu.cpp +++ b/RenderSystems/Vulkan/src/OgreVulkanTextureGpu.cpp @@ -39,6 +39,8 @@ THE SOFTWARE. #include "OgreVulkanMappings.h" #include "OgreVulkanTextureGpuManager.h" #include "OgreVulkanUtils.h" +#include "OgreRoot.h" +#include "OgreRenderSystem.h" #define TODO_add_resource_transitions @@ -144,6 +146,25 @@ namespace Ogre if( isUav() ) imageInfo.usage |= VK_IMAGE_USAGE_STORAGE_BIT; + RenderSystem* rs = Root::getSingleton().getRenderSystem(); + const RenderSystemCapabilities *capabilities = rs->getCapabilities(); + bool isTiler = capabilities->hasCapability( RSC_IS_TILER ); + if(isTiler && isRenderWindowSpecific() && isRenderToTexture()) + { + ConfigOptionMap& options = rs->getConfigOptions(); + Ogre::ConfigOptionMap::iterator opt = options.find("WindowMemoryless"); + if(opt!=options.end()) + isTiler = opt->second.currentValue=="Yes"; + } + if(isTiler && !isUav() && !isPoolOwner() && isRenderToTexture()) + { + if( isTilerMemoryless() || (isMultisample() && hasMsaaExplicitResolves() && !isTexture() && isDiscardableContent()) ) + { + imageInfo.usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; + imageInfo.usage &= (VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + } + } + String textureName = getNameStr(); VulkanTextureGpuManager *textureManager = @@ -979,6 +1000,25 @@ namespace Ogre ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + RenderSystem* rs = Root::getSingleton().getRenderSystem(); + const RenderSystemCapabilities *capabilities = rs->getCapabilities(); + bool isTiler = capabilities->hasCapability( RSC_IS_TILER ); + if(isTiler && isRenderWindowSpecific() && isRenderToTexture()) + { + ConfigOptionMap& options = rs->getConfigOptions(); + Ogre::ConfigOptionMap::iterator opt = options.find("WindowMemoryless"); + if(opt!=options.end()) + isTiler = opt->second.currentValue=="Yes"; + } + if(isTiler && isRenderToTexture()) + { + if((isTilerMemoryless() || isTilerDepthMemoryless()) || (!isTexture() && isDiscardableContent()) ) + { + imageInfo.usage |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; + imageInfo.usage &= (VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT); + } + } + String textureName = getNameStr() + "/MsaaImplicit"; VulkanTextureGpuManager *textureManager =