Skip to content

Commit

Permalink
Changes to Memoryless texture setting
Browse files Browse the repository at this point in the history
- Added extensive validation:
  - Load & Store actions are validated
  - TextureGpu::copyTo validates
  - AsyncTextureTicket validates
  - StagingTexture validates
- Validation is used on non-tilers too, to ease development and
cross-platform compatibility & testing.
- Replaced TextureFlags::TilerDepthMemoryless with
DepthBuffer::POOL_MEMORYLESS
- Eugene's code was more aggressive in deducing if memoryless could be
used, but this would break advanced user cases (i.e. where UAV / Compute
Shaders are involved). While it might be possible to deduce a that a
NotTexture + RenderTexture + not UAV should be memoryless, such specific
flag combination implies the user knows what they're doing and can
request the memoryless explicitly. Discardable does not mean it's safe
for the texture to be memoryless, since Discardable is for content that
can be discarded for the next frame, but it may still be accessed during
the same frame. Explicit MSAA are almost never intended to be
memoryless.
- Make implicit MSAA textures always memoryless
- "WindowMemoryless" replaced with per-window setting
memoryless_depth_buffer
  • Loading branch information
darksylinc committed Nov 16, 2024
1 parent c41413e commit bf991d0
Show file tree
Hide file tree
Showing 39 changed files with 234 additions and 148 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
24 changes: 12 additions & 12 deletions OgreMain/include/OgreTextureGpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,15 +169,19 @@ namespace Ogre
/// If this flag is present, either RenderToTexture or Uav must be present
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
/// 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,
/// When this flag is present together with RenderToTexture it will use DepthBuffer with
/// TilerMemoryless option
TilerDepthMemoryless = 1u << 16u
// clang-format on
};
}
Expand Down Expand Up @@ -660,10 +664,6 @@ namespace Ogre
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.
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: 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
2 changes: 1 addition & 1 deletion OgreMain/src/OgreRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,7 +675,7 @@ namespace Ogre
if( !preferDepthTexture )
textureFlags |= TextureFlags::NotTexture | TextureFlags::DiscardableContent;

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

char tmpBuffer[64];
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: 4 additions & 1 deletion 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 @@ -913,7 +916,7 @@ namespace Ogre
this->getInternalHeight() == colourTarget->getInternalHeight() &&
this->getSampleDescription() == colourTarget->getSampleDescription() &&
this->isTilerMemoryless() ==
( colourTarget->isTilerMemoryless() || colourTarget->isTilerDepthMemoryless() ) &&
( colourTarget->getDepthBufferPoolId() == DepthBuffer::POOL_MEMORYLESS ) &&
this->isRenderWindowSpecific() == colourTarget->isRenderWindowSpecific() )
{
return true;
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
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ namespace Ogre
Win32GLSupport &glsupport );
virtual ~Win32Window();

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

virtual void reposition( int32 left, int32 top );
Expand Down
2 changes: 1 addition & 1 deletion RenderSystems/GL3Plus/src/OgreGL3PlusRenderSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -889,7 +889,7 @@ namespace Ogre
mTextureGpuManager->_update( true );
}

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

return win;
}
Expand Down
2 changes: 1 addition & 1 deletion RenderSystems/GL3Plus/src/windowing/GLX/OgreGLXWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ namespace Ogre
mClosed = false;
}
//-----------------------------------------------------------------------------------
void GLXWindow::_initialize( TextureGpuManager *_textureManager )
void GLXWindow::_initialize( TextureGpuManager *_textureManager, const NameValuePairList * )
{
GL3PlusTextureGpuManager *textureManager =
static_cast<GL3PlusTextureGpuManager *>( _textureManager );
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -642,7 +642,7 @@ namespace Ogre
mFullscreenMode = mRequestedFullscreenMode;
}
//-----------------------------------------------------------------------------------
void Win32Window::_initialize( TextureGpuManager *textureGpuManager )
void Win32Window::_initialize( TextureGpuManager *textureGpuManager, const NameValuePairList * )
{
GL3PlusTextureGpuManager *textureManager =
static_cast<GL3PlusTextureGpuManager *>( textureGpuManager );
Expand Down
2 changes: 1 addition & 1 deletion RenderSystems/Metal/include/OgreMetalTextureGpuManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace Ogre
If caller doesn't delete it, it will leak.
*/
TextureGpu *createTextureGpuWindow( MetalWindow *window );
TextureGpu *createWindowDepthBuffer();
TextureGpu *createWindowDepthBuffer( const bool bMemoryLess );

id<MTLTexture> getBlankTextureMetalName( TextureTypes::TextureTypes textureType ) const;

Expand Down
3 changes: 2 additions & 1 deletion RenderSystems/Metal/include/OgreMetalWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ namespace Ogre
virtual void create( bool fullScreen, const NameValuePairList *miscParams );
void destroy() override;

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

void reposition( int32 left, int32 top ) override;
void requestResolution( uint32 width, uint32 height ) override;
Expand Down
Loading

0 comments on commit bf991d0

Please sign in to comment.