Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memoryless tiler #477

Merged
merged 4 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading