Skip to content

Commit

Permalink
Merge pull request #477 from OGRECave/memoryless_tiler
Browse files Browse the repository at this point in the history
Memoryless tiler
  • Loading branch information
eugenegff authored Nov 21, 2024
2 parents 6d6f8b1 + d0393ac commit b718ca1
Show file tree
Hide file tree
Showing 46 changed files with 350 additions and 61 deletions.
5 changes: 5 additions & 0 deletions OgreMain/include/OgreDepthBuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ namespace Ogre
POOL_NO_DEPTH = 0,
POOL_MANUAL_USAGE OGRE_DEPRECATED_ENUM_VER( 3 ) = 0,
POOL_DEFAULT = 1,

/// The depth buffer doesn't does not have memory backing it.
/// It will be created with TextureFlags::TilerMemoryless.
POOL_MEMORYLESS = 65533,

/// Deprecated.
///
/// Do NOT use this flag directly. It made sense in Ogre 2.1
Expand Down
4 changes: 4 additions & 0 deletions OgreMain/include/OgreRenderPassDescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,10 @@ namespace Ogre

protected:
void checkRequiresTextureFlipping();
void validateMemorylessTexture( const TextureGpu *texture,
const LoadAction::LoadAction loadAction,
const StoreAction::StoreAction storeAction,
const bool bIsDepthStencil );
virtual void colourEntriesModified();

public:
Expand Down
17 changes: 16 additions & 1 deletion OgreMain/include/OgreTextureGpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,21 @@ 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) aka TRANSIENT memory (Vulkan).
///
/// With this flag set, the texture will not be backed by memory, it will only ever live in
/// cache. Only TBDR GPUs support this. It will be ignored if unsupported.
///
/// Many operations are unsupported with TilerMemoryless textures (e.g. copy operations)
/// because there is no memory behind them.
///
/// 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,
// clang-format on
};
}
Expand Down Expand Up @@ -649,6 +663,7 @@ namespace Ogre
bool isManualTexture() const;
bool isPoolOwner() const;
bool isDiscardableContent() const;
bool isTilerMemoryless() const { return ( mTextureFlags & TextureFlags::TilerMemoryless ) != 0; }

/// OpenGL RenderWindows are a bit specific:
/// * Their origins are upside down. Which means we need to flip Y.
Expand Down
10 changes: 10 additions & 0 deletions OgreMain/include/OgreTextureGpuManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,7 @@ namespace Ogre

DefaultMipmapGen::DefaultMipmapGen mDefaultMipmapGen;
DefaultMipmapGen::DefaultMipmapGen mDefaultMipmapGenCubemaps;
bool mAllowMemoryLess;
bool mShuttingDown;
std::atomic<bool> mUseMultiload;
ThreadHandlePtr mWorkerThread;
Expand Down Expand Up @@ -754,6 +755,15 @@ namespace Ogre
DefaultMipmapGen::DefaultMipmapGen getDefaultMipmapGeneration() const;
DefaultMipmapGen::DefaultMipmapGen getDefaultMipmapGenerationCubemaps() const;

/** When false, TextureFlags::TilerMemoryless will be ignored (including implicit MSAA surfaces).
Useful if you're rendering a heavy scene and run out of tile memory on mobile / TBDR.
@param bAllowMemoryLess
True to allow TilerMemoryless. False otherwise.
If HW does not support TilerMemoryless, this value will be forced to false.
*/
void setAllowMemoryless( const bool bAllowMemoryLess );
bool allowMemoryless() const { return mAllowMemoryLess; }

const ResourceEntryMap &getEntries() const { return mEntries; }

/// Must be called from main thread.
Expand Down
5 changes: 4 additions & 1 deletion OgreMain/include/OgreWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ namespace Ogre

void setFinalResolution( uint32 widthPx, uint32 heightPx );

static bool requestedMemoryless( const NameValuePairList *ogre_nullable miscParams );

public:
Window( const String &title, uint32 widthPt, uint32 heightPt, bool fullscreenMode );
virtual ~Window();
Expand Down Expand Up @@ -288,7 +290,8 @@ namespace Ogre
void _setPrimary();
bool isPrimary() const;

virtual void _initialize( TextureGpuManager *textureGpuManager ) = 0;
virtual void _initialize( TextureGpuManager *textureGpuManager,
const NameValuePairList *ogre_nullable miscParams ) = 0;

/// Overloaded version of getMetrics from RenderTarget, including extra details
/// specific to windowing systems. Result is in pixels.
Expand Down
2 changes: 1 addition & 1 deletion OgreMain/src/GLX/OgreConfigDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ namespace Ogre
{
/* GUI constants */
static const int wWidth = 600; // Width of window
static const int wHeight = 380; // Height of window
static const int wHeight = 420; // Height of window
static const int col1x = 20; // Starting x of column 1 (labels)
static const int col2x = 220; // Starting x of column 2 (options)
static const int col1w = 180; // Width of column 1 (labels)
Expand Down
2 changes: 2 additions & 0 deletions OgreMain/src/OgreAsyncTextureTicket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@ namespace Ogre
assert( ( !textureSrc->isMultisample() || !textureSrc->hasMsaaExplicitResolves() ||
textureSrc->isOpenGLRenderWindow() ) &&
"Cannot download from an explicitly resolved MSAA texture!" );
OGRE_ASSERT_LOW( !textureSrc->isTilerMemoryless() &&
"Cannot download from a memoryless texture!" );
}
//-----------------------------------------------------------------------------------
void AsyncTextureTicket::notifyTextureChanged( TextureGpu *texture,
Expand Down
57 changes: 57 additions & 0 deletions OgreMain/src/OgreRenderPassDescriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,47 @@ namespace Ogre
mRequiresTextureFlipping = mColour[0].resolveTexture->requiresTextureFlipping();
}
//-----------------------------------------------------------------------------------
void RenderPassDescriptor::validateMemorylessTexture( const TextureGpu *texture,
const LoadAction::LoadAction loadAction,
const StoreAction::StoreAction storeAction,
const bool bIsDepthStencil )
{
if( !texture->isTilerMemoryless() )
return;

if( loadAction != LoadAction::Clear && loadAction != LoadAction::DontCare &&
loadAction != LoadAction::ClearOnTilers )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"Texture '" + texture->getNameStr() +
"' is TilerMemoryless. For load actions it can only use clear, "
"dont_care or clear_on_tilers.",
"RenderPassDescriptor::validateMemorylessTexture" );
}

if( !texture->isMultisample() || bIsDepthStencil )
{
if( storeAction != StoreAction::DontCare )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"Texture '" + texture->getNameStr() +
"' is TilerMemoryless. For store actions it can only use dont_care.",
"RenderPassDescriptor::validateMemorylessTexture" );
}
}
else
{
if( storeAction != StoreAction::DontCare && storeAction != StoreAction::MultisampleResolve )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"MSAA Texture '" + texture->getNameStr() +
"' is TilerMemoryless. For store actions it can only use dont_care "
"or resolve.",
"RenderPassDescriptor::validateMemorylessTexture" );
}
}
}
//-----------------------------------------------------------------------------------
void RenderPassDescriptor::colourEntriesModified()
{
mNumColourEntries = 0;
Expand All @@ -176,6 +217,9 @@ namespace Ogre
{
const RenderPassColourTarget &colourEntry = mColour[mNumColourEntries];

validateMemorylessTexture( colourEntry.texture, colourEntry.loadAction,
colourEntry.storeAction, false );

if( colourEntry.texture->isRenderWindowSpecific() )
{
RenderPassColourTarget &colourEntryRW = mColour[mNumColourEntries];
Expand Down Expand Up @@ -208,6 +252,14 @@ namespace Ogre
"RenderPassDescriptor::colourEntriesModified" );
}

if( colourEntry.resolveTexture->isTilerMemoryless() )
{
OGRE_EXCEPT( Exception::ERR_INVALIDPARAMS,
"Resolving to Texture '" + colourEntry.resolveTexture->getNameStr() +
"' which is memoryless!",
"RenderPassDescriptor::colourEntriesModified" );
}

if( colourEntry.texture != colourEntry.resolveTexture &&
!colourEntry.texture->hasMsaaExplicitResolves() )
{
Expand Down Expand Up @@ -305,6 +357,8 @@ namespace Ogre
"RenderPassDescriptor::entriesModified" );
}
}

validateMemorylessTexture( mDepth.texture, mDepth.loadAction, mDepth.storeAction, true );
}

if( mStencil.texture && mStencil.texture != mDepth.texture )
Expand All @@ -323,6 +377,9 @@ namespace Ogre
"RenderPassDescriptor::entriesModified" );
}
}

validateMemorylessTexture( mStencil.texture, mStencil.loadAction, mStencil.storeAction,
true );
}

checkRequiresTextureFlipping();
Expand Down
3 changes: 3 additions & 0 deletions OgreMain/src/OgreRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,9 @@ namespace Ogre
if( !preferDepthTexture )
textureFlags |= TextureFlags::NotTexture | TextureFlags::DiscardableContent;

if( colourTexture->getDepthBufferPoolId() == DepthBuffer::POOL_MEMORYLESS )
textureFlags |= TextureFlags::TilerMemoryless;

char tmpBuffer[64];
LwString depthBufferName( LwString::FromEmptyPointer( tmpBuffer, sizeof( tmpBuffer ) ) );
depthBufferName.a( "DepthBuffer_", Id::generateNewId<TextureGpu>() );
Expand Down
8 changes: 8 additions & 0 deletions OgreMain/src/OgreStagingTexture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ namespace Ogre
"Did you modify it? Did it get corrupted?" );
assert( ( !cpuSrcBox || srcBox.equalSize( *cpuSrcBox ) ) && "Src & cpuSrcBox must be equal" );

if( dstTexture->isTilerMemoryless() )
{
OGRE_EXCEPT(
Exception::ERR_INVALIDPARAMS,
"Cannot upload to texture '" + dstTexture->getNameStr() + "' because it's memoryless.",
"StagingTexture::upload" );
}

if( dstTexture->isMultisample() )
{
OGRE_EXCEPT(
Expand Down
5 changes: 5 additions & 0 deletions OgreMain/src/OgreTextureGpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ THE SOFTWARE.

#include "OgreTextureGpu.h"

#include "OgreDepthBuffer.h"
#include "OgreException.h"
#include "OgreLogManager.h"
#include "OgreLwString.h"
Expand Down Expand Up @@ -668,6 +669,8 @@ namespace Ogre
assert( this != dst || !srcBox.overlaps( dstBox ) );
assert( srcMipLevel < this->getNumMipmaps() && dstMipLevel < dst->getNumMipmaps() );
OGRE_ASSERT_LOW( ( this->getOrientationMode() & 0x01 ) == ( dst->getOrientationMode() & 0x01 ) );
OGRE_ASSERT_LOW( !this->isTilerMemoryless() );
OGRE_ASSERT_LOW( !dst->isTilerMemoryless() );
}
//-----------------------------------------------------------------------------------
void TextureGpu::_setDepthBufferDefaults( uint16 depthBufferPoolId, bool preferDepthTexture,
Expand Down Expand Up @@ -912,6 +915,8 @@ namespace Ogre
if( this->getInternalWidth() == colourTarget->getInternalWidth() &&
this->getInternalHeight() == colourTarget->getInternalHeight() &&
this->getSampleDescription() == colourTarget->getSampleDescription() &&
this->isTilerMemoryless() ==
( colourTarget->getDepthBufferPoolId() == DepthBuffer::POOL_MEMORYLESS ) &&
this->isRenderWindowSpecific() == colourTarget->isRenderWindowSpecific() )
{
return true;
Expand Down
18 changes: 18 additions & 0 deletions OgreMain/src/OgreTextureGpuManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ namespace Ogre
TextureGpuManager::TextureGpuManager( VaoManager *vaoManager, RenderSystem *renderSystem ) :
mDefaultMipmapGen( DefaultMipmapGen::HwMode ),
mDefaultMipmapGenCubemaps( DefaultMipmapGen::SwMode ),
mAllowMemoryLess( false ),
mShuttingDown( false ),
mUseMultiload( false ),
mTryLockMutexFailureCount( 0u ),
Expand Down Expand Up @@ -2093,6 +2094,23 @@ namespace Ogre
return mDefaultMipmapGenCubemaps;
}
//-----------------------------------------------------------------------------------
void TextureGpuManager::setAllowMemoryless( const bool bAllowMemoryLess )
{
if( !mRenderSystem->getCapabilities()->hasCapability( RSC_IS_TILER ) )
{
mAllowMemoryLess = false;
LogManager::getSingleton().logMessage(
"Device is NOT tiler. TilerMemoryless flag will be ignored." );
}
else
{
mAllowMemoryLess = bAllowMemoryLess;
LogManager::getSingleton().logMessage(
String( "Device IS tiler. TilerMemoryless flag will be: " ) +
( bAllowMemoryLess ? "allowed." : "ignored" ) );
}
}
//-----------------------------------------------------------------------------------
void TextureGpuManager::_reserveSlotForTexture( TextureGpu *texture )
{
bool matchFound = false;
Expand Down
15 changes: 15 additions & 0 deletions OgreMain/src/OgreWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ THE SOFTWARE.
#include "OgreWindow.h"

#include "OgreException.h"
#include "OgreStringConverter.h"

namespace Ogre
{
Expand Down Expand Up @@ -71,6 +72,20 @@ namespace Ogre
if( mStencilBuffer )
mStencilBuffer->setResolution( widthPx, heightPx, 1u );
}
//-------------------------------------------------------------------------
bool Window::requestedMemoryless( const NameValuePairList *ogre_nullable miscParams )
{
if( !miscParams )
return false;

NameValuePairList::const_iterator opt;
NameValuePairList::const_iterator end = miscParams->end();

opt = miscParams->find( "memoryless_depth_buffer" );
if( opt != end )
return StringConverter::parseBool( opt->second );
return false;
}
//-----------------------------------------------------------------------------------
void Window::setTitle( const String &title ) { mTitle = title; }
//-----------------------------------------------------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion RenderSystems/Direct3D11/include/OgreD3D11Window.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,8 @@ namespace Ogre
D3D11RenderSystem *renderSystem );
~D3D11WindowSwapChainBased() override;

void _initialize( TextureGpuManager *textureGpuManager ) override;
void _initialize( TextureGpuManager *textureGpuManager,
const NameValuePairList *ogre_nullable miscParams ) override;
void destroy() override;

/// @copydoc Window::setFsaa
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ namespace Ogre
D3D11Device &device, D3D11RenderSystem *renderSystem );
~D3D11WindowHwnd() override;

void _initialize( TextureGpuManager *textureGpuManager ) override;
void _initialize( TextureGpuManager *textureGpuManager,
const NameValuePairList *ogre_nullable miscParams ) override;
void destroy() override;

void reposition( int32 left, int32 top ) override;
Expand Down
2 changes: 1 addition & 1 deletion RenderSystems/Direct3D11/src/OgreD3D11RenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,7 @@ namespace Ogre
mSecondaryWindows.push_back( win );
}

win->_initialize( mTextureGpuManager );
win->_initialize( mTextureGpuManager, miscParams );

return win;
}
Expand Down
3 changes: 2 additions & 1 deletion RenderSystems/Direct3D11/src/OgreD3D11Window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ namespace Ogre
return mUseFlipMode ? 2 : mRenderSystem->getVaoManager()->getDynamicBufferMultiplier() - 1u;
}
//-----------------------------------------------------------------------------------
void D3D11WindowSwapChainBased::_initialize( TextureGpuManager *textureGpuManager )
void D3D11WindowSwapChainBased::_initialize( TextureGpuManager *textureGpuManager,
const NameValuePairList * )
{
_createSwapChain();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -470,9 +470,10 @@ namespace Ogre
setHidden( mHidden );
}
//-----------------------------------------------------------------------------------
void D3D11WindowHwnd::_initialize( TextureGpuManager *textureGpuManager )
void D3D11WindowHwnd::_initialize( TextureGpuManager *textureGpuManager,
const NameValuePairList *miscParams )
{
D3D11WindowSwapChainBased::_initialize( textureGpuManager );
D3D11WindowSwapChainBased::_initialize( textureGpuManager, miscParams );

IDXGIFactory1 *dxgiFactory1 = mDevice.GetDXGIFactory();
dxgiFactory1->MakeWindowAssociation( mHwnd,
Expand Down
7 changes: 6 additions & 1 deletion RenderSystems/GL3Plus/include/windowing/GLX/OgreGLXWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ THE SOFTWARE.

namespace Ogre
{
OGRE_ASSUME_NONNULL_BEGIN

class _OgrePrivate GLXWindow final : public Window
{
protected:
Expand All @@ -60,7 +62,8 @@ namespace Ogre
GLXGLSupport *glsupport );
~GLXWindow() override;

void _initialize( TextureGpuManager *textureManager ) override;
void _initialize( TextureGpuManager *textureManager,
const NameValuePairList *ogre_nullable miscParams ) override;

void setVSync( bool vSync, uint32 vSyncInterval ) override;
void reposition( int32 left, int32 top ) override;
Expand Down Expand Up @@ -108,6 +111,8 @@ namespace Ogre

bool requiresTextureFlipping() const { return false; }
};

OGRE_ASSUME_NONNULL_END
} // namespace Ogre

#endif
Loading

0 comments on commit b718ca1

Please sign in to comment.