//PMDTODO: Implement this /// @copydoc Resource::SerializePersistentResourceData() void Texture2d::SerializePersistentResourceData( Serializer& s ) { uint32_t baseLevelWidth = 0; uint32_t baseLevelHeight = 0; uint32_t mipCount = 0; int32_t pixelFormatIndex = RENDERER_PIXEL_FORMAT_INVALID; RTexture2d* pTexture2d = static_cast< RTexture2d* >( m_spTexture.Get() ); if( pTexture2d ) { baseLevelWidth = pTexture2d->GetWidth(); baseLevelHeight = pTexture2d->GetHeight(); mipCount = pTexture2d->GetMipCount(); pixelFormatIndex = pTexture2d->GetPixelFormat(); } s << baseLevelWidth; s << baseLevelHeight; s << mipCount; s << pixelFormatIndex; if( s.GetMode() == Serializer::MODE_LOAD ) { m_spTexture.Release(); Renderer* pRenderer = Renderer::GetStaticInstance(); if( pRenderer && baseLevelWidth != 0 && baseLevelHeight != 0 && mipCount != 0 && static_cast< uint32_t >( pixelFormatIndex ) < static_cast< uint32_t >( RENDERER_PIXEL_FORMAT_MAX ) ) { m_spTexture = pRenderer->CreateTexture2d( baseLevelWidth, baseLevelHeight, mipCount, static_cast< ERendererPixelFormat >( pixelFormatIndex ), RENDERER_BUFFER_USAGE_STATIC ); if( !m_spTexture ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Texture2d::SerializePersistentResourceData(): Failed to create texture render " ) TXT( "resource (width: %" ) TPRIu32 TXT( "; height: %" ) TPRIu32 TXT( "; mip count: %" ) TPRIu32 TXT( "; pixel format index: %" ) TPRId32 TXT( ").\n" ) ), baseLevelWidth, baseLevelHeight, mipCount, pixelFormatIndex ); } } } }
/// Reinitialize any resources dependent on graphics configuration settings. /// /// This can be called during runtime when the graphics configuration settings change to reconstruct states and /// other resources that are dependent on certain graphics configuration settings (i.e. default texture filtering /// mode). Existing resources that are reinitialized will have their reference counts decremented and will be /// cleared out of this manager. If no renderer is initialized, resources will remain null. /// /// @see Initialize(), Shutdown() void RenderResourceManager::PostConfigUpdate() { // Release resources that are dependent on configuration settings. RSamplerStatePtr* pLinearSamplerStates = m_samplerStates[ TEXTURE_FILTER_LINEAR ]; for( size_t addressModeIndex = 0; addressModeIndex < RENDERER_TEXTURE_ADDRESS_MODE_MAX; ++addressModeIndex ) { pLinearSamplerStates[ addressModeIndex ].Release(); } m_spShadowDepthTexture.Release(); m_spSceneTexture.Release(); // Get the renderer and graphics configuration. Renderer* pRenderer = Renderer::GetStaticInstance(); if( !pRenderer ) { return; } Config& rConfig = Config::GetStaticInstance(); StrongPtr< GraphicsConfig > spGraphicsConfig( rConfig.GetConfigObject< GraphicsConfig >( Name( TXT( "GraphicsConfig" ) ) ) ); if( !spGraphicsConfig ) { HELIUM_TRACE( TRACE_ERROR, TXT( "RenderResourceManager::PostConfigUpdate(): Initialization failed; missing GraphicsConfig.\n" ) ); return; } // Create the standard linear-filtering sampler states. RSamplerState::Description samplerStateDesc; samplerStateDesc.addressModeW = RENDERER_TEXTURE_ADDRESS_MODE_CLAMP; samplerStateDesc.mipLodBias = 0; samplerStateDesc.maxAnisotropy = spGraphicsConfig->GetMaxAnisotropy(); GraphicsConfig::ETextureFilter textureFiltering = spGraphicsConfig->GetTextureFiltering(); switch( textureFiltering ) { case GraphicsConfig::ETextureFilter::TRILINEAR: { samplerStateDesc.filter = RENDERER_TEXTURE_FILTER_MIN_LINEAR_MAG_LINEAR_MIP_LINEAR; break; } case GraphicsConfig::ETextureFilter::ANISOTROPIC: { samplerStateDesc.filter = RENDERER_TEXTURE_FILTER_ANISOTROPIC; break; } case GraphicsConfig::ETextureFilter::BILINEAR: default: { samplerStateDesc.filter = RENDERER_TEXTURE_FILTER_MIN_LINEAR_MAG_LINEAR_MIP_POINT; break; } } for( size_t addressModeIndex = 0; addressModeIndex < RENDERER_TEXTURE_ADDRESS_MODE_MAX; ++addressModeIndex ) { ERendererTextureAddressMode addressMode = static_cast< ERendererTextureAddressMode >( addressModeIndex ); samplerStateDesc.addressModeU = addressMode; samplerStateDesc.addressModeV = addressMode; samplerStateDesc.addressModeW = addressMode; pLinearSamplerStates[ addressModeIndex ] = pRenderer->CreateSamplerState( samplerStateDesc ); HELIUM_ASSERT( pLinearSamplerStates[ addressModeIndex ] ); } // Create the scene color target and shadow buffer depth textures. Due to restrictions with render target // settings on certain platforms (namely when using Direct3D), these must be the same size. // XXX WDI: Implement support for the NULL FOURCC format for Direct3D to avoid this restriction when possible. uint32_t bufferWidth = pRenderer->GetMainContextWidth(); uint32_t bufferHeight = pRenderer->GetMainContextHeight(); GraphicsConfig::EShadowMode shadowMode = GraphicsConfig::EShadowMode::NONE; uint32_t shadowBufferUsableSize = 0; if( pRenderer->SupportsAnyFeature( RENDERER_FEATURE_FLAG_DEPTH_TEXTURE ) ) { shadowMode = spGraphicsConfig->GetShadowMode(); if( shadowMode != GraphicsConfig::EShadowMode::INVALID && shadowMode != GraphicsConfig::EShadowMode::NONE ) { shadowBufferUsableSize = spGraphicsConfig->GetShadowBufferSize(); if( shadowBufferUsableSize != 0 ) { if( bufferWidth < shadowBufferUsableSize ) { bufferWidth = shadowBufferUsableSize; } if( bufferHeight < shadowBufferUsableSize ) { bufferHeight = shadowBufferUsableSize; } m_spShadowDepthTexture = pRenderer->CreateTexture2d( bufferWidth, bufferHeight, 1, RENDERER_PIXEL_FORMAT_DEPTH, RENDERER_BUFFER_USAGE_DEPTH_STENCIL ); if( !m_spShadowDepthTexture ) { HELIUM_TRACE( TRACE_ERROR, ( TXT( "Failed to create shadow depth texture of size %" ) TPRIu32 TXT( "x%" ) TPRIu32 TXT( ".\n" ) ), bufferWidth, bufferHeight ); shadowMode = GraphicsConfig::EShadowMode::NONE; shadowBufferUsableSize = 0; } } } } m_shadowMode = shadowMode; m_shadowDepthTextureUsableSize = shadowBufferUsableSize; m_spSceneTexture = pRenderer->CreateTexture2d( bufferWidth, bufferHeight, 1, RENDERER_PIXEL_FORMAT_R16G16B16A16_FLOAT, RENDERER_BUFFER_USAGE_RENDER_TARGET ); if( !m_spSceneTexture ) { HELIUM_TRACE( TRACE_ERROR, TXT( "Failed to create scene render texture of size %" ) TPRIu32 TXT( "x%" ) TPRIu32 TXT( ".\n" ), bufferWidth, bufferHeight ); } }
/// Reconstruct render resources based on the maximum render viewport size. /// /// @param[in] width Maximum viewport width, in pixels. /// @param[in] height Maximum viewport height, in pixels. void RenderResourceManager::UpdateMaxViewportSize( uint32_t width, uint32_t height ) { if ( width == m_viewportWidthMax && height == m_viewportHeightMax ) { return; } m_spDepthStencilSurface.Release(); m_spShadowDepthTexture.Release(); m_spSceneTexture.Release(); Renderer* pRenderer = Renderer::GetInstance(); if ( !pRenderer ) { m_viewportWidthMax = 0; m_viewportHeightMax = 0; m_shadowMode = GraphicsConfig::EShadowMode::NONE; m_shadowDepthTextureUsableSize = 0; return; } // Don't create any surfaces for zero-sized viewports. if ( width == 0 || height == 0 ) { m_viewportWidthMax = 0; m_viewportHeightMax = 0; return; } // Due to restrictions with render target settings on certain platforms (namely when using Direct3D), the scene // texture, depth-stencil surface, and shadow depth texture must all be the same size. // XXX WDI: Implement support for the NULL FOURCC format for Direct3D to avoid this restriction when possible. uint32_t bufferWidth = Max( width, m_shadowDepthTextureUsableSize ); uint32_t bufferHeight = Max( height, m_shadowDepthTextureUsableSize ); m_spSceneTexture = pRenderer->CreateTexture2d( bufferWidth, bufferHeight, 1, RENDERER_PIXEL_FORMAT_R16G16B16A16_FLOAT, RENDERER_BUFFER_USAGE_RENDER_TARGET ); if ( !m_spSceneTexture ) { HELIUM_TRACE( TraceLevels::Error, "Failed to create scene render texture of size %" PRIu32 "x%" PRIu32 ".\n", bufferWidth, bufferHeight ); } m_spDepthStencilSurface = pRenderer->CreateDepthStencilSurface( bufferWidth, bufferHeight, RENDERER_SURFACE_FORMAT_DEPTH_STENCIL, 0 ); if ( !m_spDepthStencilSurface ) { HELIUM_TRACE( TraceLevels::Error, "Failed to create scene depth-stencil surface of size %" PRIu32 "x%" PRIu32 ".\n", bufferWidth, bufferHeight ); } if ( m_shadowMode != GraphicsConfig::EShadowMode::NONE && m_shadowMode != GraphicsConfig::EShadowMode::INVALID && m_shadowDepthTextureUsableSize != 0 ) { m_spShadowDepthTexture = pRenderer->CreateTexture2d( bufferWidth, bufferHeight, 1, RENDERER_PIXEL_FORMAT_DEPTH, RENDERER_BUFFER_USAGE_DEPTH_STENCIL ); if ( !m_spShadowDepthTexture ) { HELIUM_TRACE( TraceLevels::Error, "Failed to create shadow depth texture of size %" PRIu32 "x%" PRIu32 ".\n", bufferWidth, bufferHeight ); } } }
/// @copydoc Asset::BeginPrecacheResourceData() bool Font::BeginPrecacheResourceData() { uint_fast8_t textureCount = m_persistentResourceData.m_textureCount; HELIUM_ASSERT( m_persistentResourceData.m_pspTextures || textureCount == 0 ); // If we have don't have a renderer, we don't need to load the texture sheets. Renderer* pRenderer = Renderer::GetStaticInstance(); if( !pRenderer ) { for( uint_fast8_t textureIndex = 0; textureIndex < textureCount; ++textureIndex ) { m_persistentResourceData.m_pspTextures[ textureIndex ].Release(); SetInvalid( m_persistentResourceData.m_pTextureLoadIds[ textureIndex ] ); } return true; } // Allocate and begin loading texture resources. ERendererPixelFormat format = ( m_textureCompression == ECompression::COLOR_COMPRESSED ? RENDERER_PIXEL_FORMAT_BC1 : RENDERER_PIXEL_FORMAT_R8 ); size_t blockRowCount = RendererUtil::PixelToBlockRowCount( m_textureSheetHeight, format ); uint16_t textureSheetWidth = Max< uint16_t >( m_textureSheetWidth, 1 ); uint16_t textureSheetHeight = Max< uint16_t >( m_textureSheetHeight, 1 ); for( uint_fast8_t textureIndex = 0; textureIndex < textureCount; ++textureIndex ) { RTexture2d* pTexture = NULL; size_t loadId; SetInvalid( loadId ); size_t textureSize = GetSubDataSize( textureIndex ); if( IsInvalid( textureSize ) ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Font::BeginPrecacheResourceData(): Unable to locate cached texture data for texture sheet %" ) PRIuFAST8 TXT( " of font \"%s\".\n" ) ), textureIndex, *GetPath().ToString() ); } else { pTexture = pRenderer->CreateTexture2d( textureSheetWidth, textureSheetHeight, 1, format, RENDERER_BUFFER_USAGE_STATIC ); if( !pTexture ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Font::BeginPrecacheResourceData(): Failed to allocate %" ) PRIu16 TXT( "x%") PRIu16 TXT( " texture for texture sheet %" ) PRIuFAST8 TXT( " of font \"%s\".\n" ) ), textureSheetWidth, textureSheetHeight, textureIndex, *GetPath().ToString() ); } else { size_t pitch = 0; void* pMappedData = pTexture->Map( 0, pitch ); HELIUM_ASSERT( pMappedData ); textureSize = Min( textureSize, pitch * blockRowCount ); loadId = BeginLoadSubData( pMappedData, textureIndex, textureSize ); if( IsInvalid( loadId ) ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Font::BeginPrecacheResourceData(): Failed to begin loading texture sheet %" ) PRIuFAST8 TXT( " of font \"%s\".\n" ) ), textureIndex, *GetPath().ToString() ); pTexture->Unmap( 0 ); } } } m_persistentResourceData.m_pspTextures[ textureIndex ] = pTexture; m_persistentResourceData.m_pTextureLoadIds[ textureIndex ] = loadId; } return true; }