/// @copydoc GameObject::BeginPrecacheResourceData() bool Material::BeginPrecacheResourceData() { #if HELIUM_TOOLS // Convert shader options to variant indices if we just loaded a set of options. if( m_bLoadedOptions ) { MemoryZero( m_persistentResourceData.m_shaderVariantIndices, sizeof( m_persistentResourceData.m_shaderVariantIndices ) ); Shader* pShader = m_spShader; if( pShader ) { const Shader::Options& rUserOptions = pShader->GetUserOptions(); for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_persistentResourceData.m_shaderVariantIndices ); ++shaderTypeIndex ) { m_persistentResourceData.m_shaderVariantIndices[ shaderTypeIndex ] = static_cast< uint32_t >( rUserOptions.GetOptionSetIndex( static_cast< RShader::EType >( shaderTypeIndex ), m_userOptions.GetData(), m_userOptions.GetSize() ) ); } } m_userOptions.Clear(); m_bLoadedOptions = false; } #endif // Preload shader variant resources. Shader* pShader = m_spShader; if( !pShader ) { for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_shaderVariants ); ++shaderTypeIndex ) { HELIUM_ASSERT( IsInvalid( m_shaderVariantLoadIds[ shaderTypeIndex ] ) ); m_shaderVariants[ shaderTypeIndex ].Release(); } } else { for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_shaderVariants ); ++shaderTypeIndex ) { HELIUM_ASSERT( IsInvalid( m_shaderVariantLoadIds[ shaderTypeIndex ] ) ); m_shaderVariantLoadIds[ shaderTypeIndex ] = pShader->BeginLoadVariant( static_cast< RShader::EType >( shaderTypeIndex ), m_persistentResourceData.m_shaderVariantIndices[ shaderTypeIndex ] ); } } // Preload the constant buffers for shader parameters. Renderer* pRenderer = Renderer::GetStaticInstance(); if( pRenderer ) { for( size_t shaderTypeIndex = 0; shaderTypeIndex < HELIUM_ARRAY_COUNT( m_constantBuffers ); ++shaderTypeIndex ) { HELIUM_ASSERT( !m_constantBuffers[ shaderTypeIndex ] ); HELIUM_ASSERT( IsInvalid( m_constantBufferLoadIds[ shaderTypeIndex ] ) ); size_t bufferSize = GetSubDataSize( static_cast< uint32_t >( shaderTypeIndex ) ); if( bufferSize == 0 ) { continue; } RConstantBufferPtr spBuffer = pRenderer->CreateConstantBuffer( bufferSize, RENDERER_BUFFER_USAGE_STATIC ); if( !spBuffer ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Material::BeginPrecacheResourceData(): Failed to allocate constant buffer of %" ) TPRIuSZ TXT( " bytes for parameter usage for material \"%s\".\n" ) ), bufferSize, *GetPath().ToString() ); continue; } void* pBufferData = spBuffer->Map(); if( !pBufferData ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Material::BeginPrecacheResourceData(): Failed to map constant buffer data for " ) TXT( "material \"%s\".\n" ) ), *GetPath().ToString() ); continue; } size_t loadId = BeginLoadSubData( pBufferData, static_cast< uint32_t >( shaderTypeIndex ) ); if( IsInvalid( loadId ) ) { HELIUM_TRACE( TraceLevels::Error, ( TXT( "Material::BeginPrecacheResourceData(): Failed to begin loading resource sub-data %" ) TPRIuSZ TXT( " for material \"%s\".\n" ) ), shaderTypeIndex, *GetPath().ToString() ); spBuffer->Unmap(); continue; } m_constantBuffers[ shaderTypeIndex ] = spBuffer; m_constantBufferLoadIds[ shaderTypeIndex ] = loadId; } } return true; }
/// @copydoc ResourceHandler::CacheResource() bool MaterialResourceHandler::CacheResource( AssetPreprocessor* pAssetPreprocessor, Resource* pResource, const String& /*rSourceFilePath*/ ) { HELIUM_ASSERT( pAssetPreprocessor ); HELIUM_ASSERT( pResource ); Material* pMaterial = Reflect::AssertCast< Material >( pResource ); Shader* pShader = pMaterial->GetShader(); bool failedToWriteASubdata = false; StrongPtr< Material::PersistentResourceData > resource_data( new Material::PersistentResourceData() ); // Compute the shader variant indices from the user options selected in the material, as the array of indices in // the material is not yet initialized. //uint32_t shaderVariantIndices[ RShader::TYPE_MAX ]; if( pShader ) { const Shader::Options& rShaderUserOptions = pShader->GetUserOptions(); const DynamicArray< Shader::SelectPair >& rMaterialUserOptions = pMaterial->GetUserOptions(); for( size_t shaderTypeIndex = 0; shaderTypeIndex < RShader::TYPE_MAX; ++shaderTypeIndex ) { size_t optionSetIndex = rShaderUserOptions.GetOptionSetIndex( static_cast< RShader::EType >( shaderTypeIndex ), rMaterialUserOptions.GetData(), rMaterialUserOptions.GetSize() ); resource_data->m_shaderVariantIndices[ shaderTypeIndex ] = static_cast< uint32_t >( optionSetIndex ); } } else { MemoryZero( resource_data->m_shaderVariantIndices, sizeof( resource_data->m_shaderVariantIndices ) ); } size_t float1ParameterCount = pMaterial->GetFloat1ParameterCount(); size_t float2ParameterCount = pMaterial->GetFloat2ParameterCount(); size_t float3ParameterCount = pMaterial->GetFloat3ParameterCount(); size_t float4ParameterCount = pMaterial->GetFloat4ParameterCount(); Name parameterConstantBufferName = Material::GetParameterConstantBufferName(); for( size_t platformIndex = 0; platformIndex < static_cast< size_t >( Cache::PLATFORM_MAX ); ++platformIndex ) { PlatformPreprocessor* pPreprocessor = pAssetPreprocessor->GetPlatformPreprocessor( static_cast< Cache::EPlatform >( platformIndex ) ); if( !pPreprocessor ) { continue; } Resource::PreprocessedData& rPreprocessedData = pResource->GetPreprocessedData( static_cast< Cache::EPlatform >( platformIndex ) ); SaveObjectToPersistentDataBuffer(resource_data.Get(), rPreprocessedData.persistentDataBuffer); rPreprocessedData.bLoaded = true; // Write out the parameter constant buffer data as the resource sub-data. size_t shaderProfileCount = pPreprocessor->GetShaderProfileCount(); DynamicArray< DynamicArray< uint8_t > >& rSubDataBuffers = rPreprocessedData.subDataBuffers; rSubDataBuffers.Clear(); rSubDataBuffers.Reserve( shaderProfileCount * RShader::TYPE_MAX ); rSubDataBuffers.Resize( shaderProfileCount * RShader::TYPE_MAX ); if( pShader ) { // deserializer.SetByteSwapping( bSwapBytes ); for( size_t shaderTypeIndex = 0; shaderTypeIndex < RShader::TYPE_MAX; ++shaderTypeIndex ) { RShader::EType shaderType = static_cast< RShader::EType >( shaderTypeIndex ); size_t variantLoadId = pShader->BeginLoadVariant( shaderType, resource_data->m_shaderVariantIndices[ shaderTypeIndex ] ); if( IsInvalid( variantLoadId ) ) { continue; } ShaderVariantPtr spVariant; while( !pShader->TryFinishLoadVariant( variantLoadId, spVariant ) ) { } ShaderVariant* pVariant = spVariant; if( !pVariant ) { continue; } const Resource::PreprocessedData& rVariantData = pVariant->GetPreprocessedData( static_cast< Cache::EPlatform >( platformIndex ) ); HELIUM_ASSERT( rVariantData.bLoaded ); const DynamicArray< DynamicArray< uint8_t > >& rVariantSubDataBuffers = rVariantData.subDataBuffers; size_t variantSubDataCount = rVariantSubDataBuffers.GetSize(); HELIUM_ASSERT( variantSubDataCount != 0 ); HELIUM_ASSERT( variantSubDataCount % shaderProfileCount == 0 ); size_t systemOptionSetCount = variantSubDataCount / shaderProfileCount; for( size_t profileIndex = 0; profileIndex < shaderProfileCount; ++profileIndex ) { // Get the first option set of each profile const DynamicArray< uint8_t >& rVariantSubData = rVariantSubDataBuffers[ profileIndex * systemOptionSetCount ]; Reflect::ObjectPtr variantSubDataObjectPtr = Cache::ReadCacheObjectFromBuffer(rVariantSubData); if (!variantSubDataObjectPtr.ReferencesObject()) { HELIUM_TRACE( TraceLevels::Error, "MaterialResourceHandler: A shader variant subdata could not be read. (Option Set: %d Profile: %d)", 0, profileIndex ); failedToWriteASubdata = true; } else if (!variantSubDataObjectPtr->IsA(Reflect::GetMetaClass<CompiledShaderData>())) { HELIUM_TRACE( TraceLevels::Error, "MaterialResourceHandler: A shader variant subdata was of an unexpected type. (Option Set: %d Profile: %d)\n", 0, profileIndex ); failedToWriteASubdata = true; } else { CompiledShaderData &csd = *Reflect::AssertCast<CompiledShaderData>(variantSubDataObjectPtr.Get()); size_t bufferCount = csd.constantBuffers.GetSize(); for( size_t bufferIndex = 0; bufferIndex < bufferCount; ++bufferIndex ) { const ShaderConstantBufferInfo& rBufferInfo = csd.constantBuffers[ bufferIndex ]; if( rBufferInfo.name != parameterConstantBufferName ) { continue; } size_t bufferSize = rBufferInfo.size; DynamicArray< uint8_t >& rMaterialSubData = rSubDataBuffers[ profileIndex * RShader::TYPE_MAX + shaderTypeIndex ]; rMaterialSubData.Clear(); rMaterialSubData.Reserve( bufferSize ); rMaterialSubData.Add( 0, bufferSize ); DynamicMemoryStream memoryStream( &rMaterialSubData ); ByteSwappingStream byteSwapStream( &memoryStream ); Stream& rOutputStream = memoryStream; //Stream& rOutputStream = // ( bSwapBytes // ? static_cast< Stream& >( byteSwapStream ) // : static_cast< Stream& >( memoryStream ) ); const DynamicArray< ShaderConstantInfo >& rConstants = rBufferInfo.constants; size_t constantCount = rConstants.GetSize(); for( size_t constantIndex = 0; constantIndex < constantCount; ++constantIndex ) { const ShaderConstantInfo& rConstantInfo = rConstants[ constantIndex ]; Name constantName = rConstantInfo.name; size_t parameterIndex; for( parameterIndex = 0; parameterIndex < float1ParameterCount; ++parameterIndex ) { const Material::Float1Parameter& rParameter = pMaterial->GetFloat1Parameter( parameterIndex ); if( rParameter.name == constantName ) { rOutputStream.Seek( rConstantInfo.offset, SeekOrigins::Begin ); rOutputStream.Write( &rParameter.value, sizeof( float32_t ), Min< size_t >( 1, rConstantInfo.size / sizeof( float32_t ) ) ); break; } } if( parameterIndex >= float1ParameterCount ) { for( parameterIndex = 0; parameterIndex < float2ParameterCount; ++parameterIndex ) { const Material::Float2Parameter& rParameter = pMaterial->GetFloat2Parameter( parameterIndex ); if( rParameter.name == constantName ) { rOutputStream.Seek( rConstantInfo.offset, SeekOrigins::Begin ); rOutputStream.Write( &rParameter.value, sizeof( float32_t ), Min< size_t >( 2, rConstantInfo.size / sizeof( float32_t ) ) ); break; } } if( parameterIndex >= float2ParameterCount ) { for( parameterIndex = 0; parameterIndex < float3ParameterCount; ++parameterIndex ) { const Material::Float3Parameter& rParameter = pMaterial->GetFloat3Parameter( parameterIndex ); if( rParameter.name == constantName ) { rOutputStream.Seek( rConstantInfo.offset, SeekOrigins::Begin ); rOutputStream.Write( &rParameter.value, sizeof( float32_t ), Min< size_t >( 3, rConstantInfo.size / sizeof( float32_t ) ) ); break; } } if( parameterIndex >= float3ParameterCount ) { for( parameterIndex = 0; parameterIndex < float4ParameterCount; ++parameterIndex ) { const Material::Float4Parameter& rParameter = pMaterial->GetFloat4Parameter( parameterIndex ); if( rParameter.name == constantName ) { rOutputStream.Seek( rConstantInfo.offset, SeekOrigins::Begin ); rOutputStream.Write( &rParameter.value, sizeof( float32_t ), Min< size_t >( 4, rConstantInfo.size / sizeof( float32_t ) ) ); break; } } } } } } break; } } } } } } return !failedToWriteASubdata; }
/// Initialize all resources provided by this manager. /// /// @see Cleanup(), PostConfigUpdate() bool RenderResourceManager::Initialize() { // Release any existing resources. Cleanup(); // Get the renderer and graphics configuration. Renderer* pRenderer = Renderer::GetInstance(); if ( !pRenderer ) { return false; } Config* pConfig = Config::GetInstance(); if ( !HELIUM_VERIFY( pConfig ) ) { return false; } StrongPtr< GraphicsConfig > spGraphicsConfig( pConfig->GetConfigObject< GraphicsConfig >( Name( "GraphicsConfig" ) ) ); if ( !spGraphicsConfig ) { HELIUM_TRACE( TraceLevels::Error, "RenderResourceManager::Initialize(): Initialization failed; missing GraphicsConfig.\n" ); return false; } // Create the standard rasterizer states. RRasterizerState::Description rasterizerStateDesc; rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_SOLID; rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK; rasterizerStateDesc.winding = RENDERER_WINDING_CLOCKWISE; rasterizerStateDesc.depthBias = 0; rasterizerStateDesc.slopeScaledDepthBias = 0.0f; m_rasterizerStates[RASTERIZER_STATE_DEFAULT] = pRenderer->CreateRasterizerState( rasterizerStateDesc ); HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_DEFAULT] ); rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_NONE; m_rasterizerStates[RASTERIZER_STATE_DOUBLE_SIDED] = pRenderer->CreateRasterizerState( rasterizerStateDesc ); HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_DOUBLE_SIDED] ); rasterizerStateDesc.depthBias = 1; rasterizerStateDesc.slopeScaledDepthBias = 2.0f; m_rasterizerStates[RASTERIZER_STATE_SHADOW_DEPTH] = pRenderer->CreateRasterizerState( rasterizerStateDesc ); HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_SHADOW_DEPTH] ); rasterizerStateDesc.depthBias = 0; rasterizerStateDesc.slopeScaledDepthBias = 0.0f; rasterizerStateDesc.fillMode = RENDERER_FILL_MODE_WIREFRAME; m_rasterizerStates[RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED] = pRenderer->CreateRasterizerState( rasterizerStateDesc ); HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_WIREFRAME_DOUBLE_SIDED] ); rasterizerStateDesc.cullMode = RENDERER_CULL_MODE_BACK; m_rasterizerStates[RASTERIZER_STATE_WIREFRAME] = pRenderer->CreateRasterizerState( rasterizerStateDesc ); HELIUM_ASSERT( m_rasterizerStates[RASTERIZER_STATE_WIREFRAME] ); // Create the standard blend states. RBlendState::Description blendStateDesc; blendStateDesc.bBlendEnable = false; m_blendStates[BLEND_STATE_OPAQUE] = pRenderer->CreateBlendState( blendStateDesc ); HELIUM_ASSERT( m_blendStates[BLEND_STATE_OPAQUE] ); blendStateDesc.colorWriteMask = 0; m_blendStates[BLEND_STATE_NO_COLOR] = pRenderer->CreateBlendState( blendStateDesc ); HELIUM_ASSERT( m_blendStates[BLEND_STATE_NO_COLOR] ); blendStateDesc.colorWriteMask = RENDERER_COLOR_WRITE_MASK_FLAG_ALL; blendStateDesc.bBlendEnable = true; blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_SRC_ALPHA; blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_INV_SRC_ALPHA; blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD; m_blendStates[BLEND_STATE_TRANSPARENT] = pRenderer->CreateBlendState( blendStateDesc ); HELIUM_ASSERT( m_blendStates[BLEND_STATE_TRANSPARENT] ); blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_ONE; blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ONE; m_blendStates[BLEND_STATE_ADDITIVE] = pRenderer->CreateBlendState( blendStateDesc ); HELIUM_ASSERT( m_blendStates[BLEND_STATE_ADDITIVE] ); blendStateDesc.function = RENDERER_BLEND_FUNCTION_REVERSE_SUBTRACT; m_blendStates[BLEND_STATE_SUBTRACTIVE] = pRenderer->CreateBlendState( blendStateDesc ); HELIUM_ASSERT( m_blendStates[BLEND_STATE_SUBTRACTIVE] ); blendStateDesc.sourceFactor = RENDERER_BLEND_FACTOR_DEST_COLOR; blendStateDesc.destinationFactor = RENDERER_BLEND_FACTOR_ZERO; blendStateDesc.function = RENDERER_BLEND_FUNCTION_ADD; m_blendStates[BLEND_STATE_MODULATE] = pRenderer->CreateBlendState( blendStateDesc ); HELIUM_ASSERT( m_blendStates[BLEND_STATE_MODULATE] ); // Create the standard depth/stencil states. RDepthStencilState::Description depthStateDesc; depthStateDesc.stencilWriteMask = 0; depthStateDesc.bStencilTestEnable = false; depthStateDesc.depthFunction = RENDERER_COMPARE_FUNCTION_LESS_EQUAL; depthStateDesc.bDepthTestEnable = true; depthStateDesc.bDepthWriteEnable = true; m_depthStencilStates[DEPTH_STENCIL_STATE_DEFAULT] = pRenderer->CreateDepthStencilState( depthStateDesc ); HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_DEFAULT] ); depthStateDesc.bDepthWriteEnable = false; m_depthStencilStates[DEPTH_STENCIL_STATE_TEST_ONLY] = pRenderer->CreateDepthStencilState( depthStateDesc ); HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_TEST_ONLY] ); depthStateDesc.bDepthTestEnable = false; m_depthStencilStates[DEPTH_STENCIL_STATE_NONE] = pRenderer->CreateDepthStencilState( depthStateDesc ); HELIUM_ASSERT( m_depthStencilStates[DEPTH_STENCIL_STATE_NONE] ); // Create the standard sampler states that are not dependent on configuration settings. RSamplerState::Description samplerStateDesc; samplerStateDesc.filter = RENDERER_TEXTURE_FILTER_MIN_POINT_MAG_POINT_MIP_POINT; samplerStateDesc.addressModeW = RENDERER_TEXTURE_ADDRESS_MODE_CLAMP; samplerStateDesc.mipLodBias = 0; samplerStateDesc.maxAnisotropy = spGraphicsConfig->GetMaxAnisotropy(); 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; m_samplerStates[TEXTURE_FILTER_POINT][addressModeIndex] = pRenderer->CreateSamplerState( samplerStateDesc ); HELIUM_ASSERT( m_samplerStates[TEXTURE_FILTER_POINT][addressModeIndex] ); } // Create the standard set of mesh vertex descriptions. RVertexDescription::Element vertexElements[6]; vertexElements[0].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_3; vertexElements[0].semantic = RENDERER_VERTEX_SEMANTIC_POSITION; vertexElements[0].semanticIndex = 0; vertexElements[0].bufferIndex = 0; vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_COLOR; vertexElements[1].semanticIndex = 0; vertexElements[1].bufferIndex = 0; vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2; vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD; vertexElements[2].semanticIndex = 0; vertexElements[2].bufferIndex = 0; vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2; vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD; vertexElements[3].semanticIndex = 1; vertexElements[3].bufferIndex = 0; m_spSimpleVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 2 ); HELIUM_ASSERT( m_spSimpleVertexDescription ); m_spSimpleTexturedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 ); HELIUM_ASSERT( m_spSimpleTexturedVertexDescription ); m_spProjectedVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 4 ); HELIUM_ASSERT( m_spProjectedVertexDescription ); vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL; vertexElements[1].semanticIndex = 0; vertexElements[1].bufferIndex = 0; vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT; vertexElements[2].semanticIndex = 0; vertexElements[2].bufferIndex = 0; vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_COLOR; vertexElements[3].semanticIndex = 0; vertexElements[3].bufferIndex = 0; vertexElements[4].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2; vertexElements[4].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD; vertexElements[4].semanticIndex = 0; vertexElements[4].bufferIndex = 0; vertexElements[5].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2; vertexElements[5].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD; vertexElements[5].semanticIndex = 1; vertexElements[5].bufferIndex = 0; m_staticMeshVertexDescriptions[0] = pRenderer->CreateVertexDescription( vertexElements, 5 ); HELIUM_ASSERT( m_staticMeshVertexDescriptions[0] ); m_staticMeshVertexDescriptions[1] = pRenderer->CreateVertexDescription( vertexElements, 6 ); HELIUM_ASSERT( m_staticMeshVertexDescriptions[1] ); vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_BLENDWEIGHT; vertexElements[1].semanticIndex = 0; vertexElements[1].bufferIndex = 0; vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4; vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_BLENDINDICES; vertexElements[2].semanticIndex = 0; vertexElements[2].bufferIndex = 0; vertexElements[3].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[3].semantic = RENDERER_VERTEX_SEMANTIC_NORMAL; vertexElements[3].semanticIndex = 0; vertexElements[3].bufferIndex = 0; vertexElements[4].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[4].semantic = RENDERER_VERTEX_SEMANTIC_TANGENT; vertexElements[4].semanticIndex = 0; vertexElements[4].bufferIndex = 0; vertexElements[5].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2; vertexElements[5].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD; vertexElements[5].semanticIndex = 0; vertexElements[5].bufferIndex = 0; m_spSkinnedMeshVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 6 ); HELIUM_ASSERT( m_spSkinnedMeshVertexDescription ); vertexElements[0].type = RENDERER_VERTEX_DATA_TYPE_FLOAT32_2; vertexElements[0].semantic = RENDERER_VERTEX_SEMANTIC_POSITION; vertexElements[0].semanticIndex = 0; vertexElements[0].bufferIndex = 0; vertexElements[1].type = RENDERER_VERTEX_DATA_TYPE_UINT8_4_NORM; vertexElements[1].semantic = RENDERER_VERTEX_SEMANTIC_COLOR; vertexElements[1].semanticIndex = 0; vertexElements[1].bufferIndex = 0; vertexElements[2].type = RENDERER_VERTEX_DATA_TYPE_FLOAT16_2; vertexElements[2].semantic = RENDERER_VERTEX_SEMANTIC_TEXCOORD; vertexElements[2].semanticIndex = 0; vertexElements[2].bufferIndex = 0; m_spScreenVertexDescription = pRenderer->CreateVertexDescription( vertexElements, 3 ); HELIUM_ASSERT( m_spScreenVertexDescription ); // Create configuration-dependent render resources. PostConfigUpdate(); // Attempt to load the depth-only pre-pass shader. // TODO: XXX TMC: Migrate to a more data-driven solution. AssetLoader* pAssetLoader = AssetLoader::GetInstance(); HELIUM_ASSERT( pAssetLoader ); #ifdef HELIUM_DIRECT3D AssetPath prePassShaderPath; HELIUM_VERIFY( prePassShaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "PrePass.hlsl" ) ); AssetPtr spPrePassShader; HELIUM_VERIFY( pAssetLoader->LoadObject( prePassShaderPath, spPrePassShader ) ); Shader* pPrePassShader = Reflect::SafeCast< Shader >( spPrePassShader.Get() ); if ( HELIUM_VERIFY( pPrePassShader ) ) { size_t loadId = pPrePassShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if ( IsValid( loadId ) ) { while ( !pPrePassShader->TryFinishLoadVariant( loadId, m_spPrePassVertexShader ) ) { pAssetLoader->Tick(); } } } // Attempt to load the simple world-space, simple screen-space, and screen-space text shaders. // TODO: XXX TMC: Migrate to a more data-driven solution. AssetPath shaderPath; HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "Simple.hlsl" ) ); AssetPtr spShader; HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) ); Shader* pShader = Reflect::SafeCast< Shader >( spShader.Get() ); if ( HELIUM_VERIFY( pShader ) ) { size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if ( IsValid( loadId ) ) { while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpaceVertexShader ) ) { pAssetLoader->Tick(); } } loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if ( IsValid( loadId ) ) { while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleWorldSpacePixelShader ) ) { pAssetLoader->Tick(); } } } HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "ScreenSpaceTexture.hlsl" ) ); HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) ); pShader = Reflect::SafeCast< Shader >( spShader.Get() ); if ( HELIUM_VERIFY( pShader ) ) { size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if ( IsValid( loadId ) ) { while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpaceVertexShader ) ) { pAssetLoader->Tick(); } } loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if ( IsValid( loadId ) ) { while ( !pShader->TryFinishLoadVariant( loadId, m_spSimpleScreenSpacePixelShader ) ) { pAssetLoader->Tick(); } } } HELIUM_VERIFY( shaderPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Shaders" HELIUM_OBJECT_PATH_CHAR_STRING "ScreenText.hlsl" ) ); HELIUM_VERIFY( pAssetLoader->LoadObject( shaderPath, spShader ) ); pShader = Reflect::SafeCast< Shader >( spShader.Get() ); if ( HELIUM_VERIFY( pShader ) ) { size_t loadId = pShader->BeginLoadVariant( RShader::TYPE_VERTEX, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if ( IsValid( loadId ) ) { while ( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextVertexShader ) ) { pAssetLoader->Tick(); } } loadId = pShader->BeginLoadVariant( RShader::TYPE_PIXEL, 0 ); HELIUM_ASSERT( IsValid( loadId ) ); if ( IsValid( loadId ) ) { while ( !pShader->TryFinishLoadVariant( loadId, m_spScreenTextPixelShader ) ) { pAssetLoader->Tick(); } } } // Attempt to load the debug fonts. // TODO: XXX TMC: Migrate to a more data-driven solution. AssetPath fontPath; AssetPtr spFont; HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugSmall" ) ); HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) ); m_debugFonts[DEBUG_FONT_SIZE_SMALL] = Reflect::SafeCast< Font >( spFont.Get() ); spFont.Release(); HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugMedium" ) ); HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) ); m_debugFonts[DEBUG_FONT_SIZE_MEDIUM] = Reflect::SafeCast< Font >( spFont.Get() ); spFont.Release(); HELIUM_VERIFY( fontPath.Set( HELIUM_PACKAGE_PATH_CHAR_STRING "Fonts" HELIUM_OBJECT_PATH_CHAR_STRING "DebugLarge" ) ); HELIUM_VERIFY( pAssetLoader->LoadObject( fontPath, spFont ) ); m_debugFonts[DEBUG_FONT_SIZE_LARGE] = Reflect::SafeCast< Font >( spFont.Get() ); spFont.Release(); #endif return true; }