X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fshaders%2Fprogram.cpp;h=451de0bb6c7083eeccb9bf7e90e73e82b30a29c9;hb=649ec06daecb510fb84fe4642a6af957f127e7ab;hp=e72636d882d76e2654e29e6769455a179c364431;hpb=a86edb3ce9fefcfe5f155e12c598399847ae5273;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/shaders/program.cpp b/dali/internal/render/shaders/program.cpp index e72636d..451de0b 100644 --- a/dali/internal/render/shaders/program.cpp +++ b/dali/internal/render/shaders/program.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * Copyright (c) 2017 Samsung Electronics Co., Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,13 +20,14 @@ // EXTERNAL INCLUDES #include +#include // INTERNAL INCLUDES #include #include #include #include -#include +#include #include #include #include @@ -79,11 +80,7 @@ namespace const char* gStdAttribs[ Program::ATTRIB_TYPE_LAST ] = { "aPosition", // ATTRIB_POSITION - "aNormal", // ATTRIB_NORMAL "aTexCoord", // ATTRIB_TEXCOORD - "aColor", // ATTRIB_COLOR - "aBoneWeights", // ATTRIB_BONE_WEIGHTS - "aBoneIndices" // ATTRIB_BONE_INDICES }; const char* gStdUniforms[ Program::UNIFORM_TYPE_LAST ] = @@ -95,33 +92,17 @@ const char* gStdUniforms[ Program::UNIFORM_TYPE_LAST ] = "uViewMatrix", // UNIFORM_VIEW_MATRIX, "uNormalMatrix", // UNIFORM_NORMAL_MATRIX "uColor", // UNIFORM_COLOR - "uCustomTextureCoords", // UNIFORM_CUSTOM_TEXTURE_COORDS "sTexture", // UNIFORM_SAMPLER "sTextureRect", // UNIFORM_SAMPLER_RECT "sEffect", // UNIFORM_EFFECT_SAMPLER - "sEffectRect", // UNIFORM_EFFECT_SAMPLER_RECT - "uTimeDelta", // UNIFORM_TIME_DELTA - "sOpacityTexture", // UNIFORM_SAMPLER_OPACITY - "sNormalMapTexture", // UNIFORM_SAMPLER_NORMAL_MAP - "uTextColor", // UNIFORM_TEXT_COLOR - "uSmoothing", // UNIFORM_SMOOTHING - "uOutline", // UNIFORM_OUTLINE - "uOutlineColor", // UNIFORM_OUTLINE_COLOR - "uGlow", // UNIFORM_GLOW - "uGlowColor", // UNIFORM_GLOW_COLOR - "uShadow", // UNIFORM_SHADOW - "uShadowColor", // UNIFORM_SHADOW_COLOR - "uShadowSmoothing", // UNIFORM_SHADOW_SMOOTHING - "uGradientColor", // UNIFORM_GRADIENT_COLOR - "uGradientLine", // UNIFORM_GRADIENT_LINE - "uInvTextSize" // UNIFORM_INVERSE_TEXT_SIZE + "uSize" // UNIFORM_SIZE }; } // namespace // IMPLEMENTATION -Program* Program::New( ProgramCache& cache, Integration::ShaderDataPtr shaderData, bool modifiesGeometry ) +Program* Program::New( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool modifiesGeometry ) { size_t shaderHash = shaderData->GetHashValue(); Program* program = cache.GetProgram( shaderHash ); @@ -130,9 +111,7 @@ Program* Program::New( ProgramCache& cache, Integration::ShaderDataPtr shaderDat { // program not found so create it program = new Program( cache, shaderData, modifiesGeometry ); - - // we want to lazy load programs so dont do a Load yet, it gets done in Use() - + program->Load(); cache.AddProgram( shaderHash, program ); } @@ -141,11 +120,6 @@ Program* Program::New( ProgramCache& cache, Integration::ShaderDataPtr shaderDat void Program::Use() { - if ( !mLinked ) - { - Load(); - } - if ( mLinked ) { if ( this != mCache.GetCurrentProgram() ) @@ -167,16 +141,46 @@ GLint Program::GetAttribLocation( AttribType type ) { DALI_ASSERT_DEBUG(type != ATTRIB_UNKNOWN); - if( mAttribLocations[ type ] == ATTRIB_UNKNOWN ) + return GetCustomAttributeLocation( type ); +} + +unsigned int Program::RegisterCustomAttribute( const std::string& name ) +{ + unsigned int index = 0; + // find the value from cache + for( ;index < mAttributeLocations.size(); ++index ) + { + if( mAttributeLocations[ index ].first == name ) + { + // name found so return index + return index; + } + } + // if we get here, index is one past end so push back the new name + mAttributeLocations.push_back( std::make_pair( name, ATTRIB_UNKNOWN ) ); + return index; +} + +GLint Program::GetCustomAttributeLocation( unsigned int attributeIndex ) +{ + // debug check that index is within name cache + DALI_ASSERT_DEBUG( mAttributeLocations.size() > attributeIndex ); + + // check if we have already queried the location of the attribute + GLint location = mAttributeLocations[ attributeIndex ].second; + + if( location == ATTRIB_UNKNOWN ) { - GLint loc = CHECK_GL( mGlAbstraction, mGlAbstraction.GetAttribLocation( mProgramId, gStdAttribs[type] ) ); - mAttribLocations[ type ] = loc; - LOG_GL( "GetAttribLocation(program=%d,%s) = %d\n", mProgramId, gStdAttribs[type], mAttribLocations[type] ); + location = CHECK_GL( mGlAbstraction, mGlAbstraction.GetAttribLocation( mProgramId, mAttributeLocations[ attributeIndex ].first.c_str() ) ); + + mAttributeLocations[ attributeIndex ].second = location; + LOG_GL( "GetAttributeLocation(program=%d,%s) = %d\n", mProgramId, mAttributeLocations[ attributeIndex ].first.c_str(), mAttributeLocations[ attributeIndex ].second ); } - return mAttribLocations[type]; + return location; } + unsigned int Program::RegisterUniform( const std::string& name ) { unsigned int index = 0; @@ -213,6 +217,125 @@ GLint Program::GetUniformLocation( unsigned int uniformIndex ) return location; } +namespace +{ +/** + * This struct is used to record the position of a uniform declaration + * within the fragment shader source code. + */ +struct LocationPosition +{ + GLint uniformLocation; ///< The location of the uniform (used as an identifier) + int position; ///< the position of the uniform declaration + LocationPosition( GLint uniformLocation, int position ) + : uniformLocation(uniformLocation), position(position) + { + } +}; + +bool sortByPosition( LocationPosition a, LocationPosition b ) +{ + return a.position < b.position; +} +} + +void Program::GetActiveSamplerUniforms() +{ + GLint numberOfActiveUniforms = -1; + GLint uniformMaxNameLength=-1; + + mGlAbstraction.GetProgramiv( mProgramId, GL_ACTIVE_UNIFORMS, &numberOfActiveUniforms ); + mGlAbstraction.GetProgramiv( mProgramId, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformMaxNameLength ); + + std::vector samplerNames; + char name[uniformMaxNameLength+1]; // Allow for null terminator + std::vector< LocationPosition > samplerUniformLocations; + + { + int nameLength = -1; + int number = -1; + GLenum type = GL_ZERO; + + for( int i=0; i( i ), uniformMaxNameLength, + &nameLength, &number, &type, name ); + + if( type == GL_SAMPLER_2D || type == GL_SAMPLER_CUBE || type == GL_SAMPLER_EXTERNAL_OES ) + { + GLuint location = mGlAbstraction.GetUniformLocation( mProgramId, name ); + samplerNames.push_back(name); + samplerUniformLocations.push_back(LocationPosition(location, -1)); + } + } + } + + //Determine declaration order of each sampler + char* fragShader = strdup( mProgramData->GetFragmentShader() ); + char* nextPtr = NULL; + const char* token = strtok_r( fragShader, " ;\n", &nextPtr ); + int samplerPosition = 0; + while( token ) + { + if( ( strncmp( token, "sampler2D", 9u ) == 0 ) || + ( strncmp( token, "samplerCube", 11u ) == 0 ) || + ( strncmp( token, "samplerExternalOES", 18u ) == 0 ) ) + { + bool found( false ); + token = strtok_r( NULL, " ;\n", &nextPtr ); + for( size_t i=0; i 1 ) + { + std::sort( samplerUniformLocations.begin(), samplerUniformLocations.end(), sortByPosition); + } + + mSamplerUniformLocations.resize( samplerUniformCount ); + for( size_t i=0; i= MAX_UNIFORM_CACHE_SIZE ) + { + // not cached, make the gl call + LOG_GL( "Uniform2f(%d,%f,%f)\n", location, value0, value1 ); + CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform2f( location, value0, value1 ) ); + } + else + { + // check if the same value has already been set, reset if it is different + if( ( fabsf(value0 - mUniformCacheFloat2[ location ][ 0 ]) >= Math::MACHINE_EPSILON_1 )|| + ( fabsf(value1 - mUniformCacheFloat2[ location ][ 1 ]) >= Math::MACHINE_EPSILON_1 ) ) + { + // make the gl call + LOG_GL( "Uniform2f(%d,%f,%f)\n", location, value0, value1 ); + CHECK_GL( mGlAbstraction, mGlAbstraction.Uniform2f( location, value0, value1 ) ); + + // update cache + mUniformCacheFloat2[ location ][ 0 ] = value0; + mUniformCacheFloat2[ location ][ 1 ] = value1; + } + } +} + +void Program::SetSizeUniform3f( GLint location, GLfloat value0, GLfloat value1, GLfloat value2 ) +{ + if( ( fabsf(value0 - mSizeUniformCache.x) >= Math::MACHINE_EPSILON_1 )|| + ( fabsf(value1 - mSizeUniformCache.y) >= Math::MACHINE_EPSILON_1 )|| + ( fabsf(value2 - mSizeUniformCache.z) >= Math::MACHINE_EPSILON_1 ) ) + { + mSizeUniformCache.x = value0; + mSizeUniformCache.y = value1; + mSizeUniformCache.z = value2; + SetUniform3f( location, value0, value1, value2 ); + } } void Program::SetUniform3f( GLint location, GLfloat value0, GLfloat value1, GLfloat value2 ) @@ -429,7 +584,7 @@ bool Program::ModifiesGeometry() return mModifiesGeometry; } -Program::Program( ProgramCache& cache, Integration::ShaderDataPtr shaderData, bool modifiesGeometry ) +Program::Program( ProgramCache& cache, Internal::ShaderDataPtr shaderData, bool modifiesGeometry ) : mCache( cache ), mGlAbstraction( mCache.GetGlAbstraction() ), mProjectionMatrix( NULL ), @@ -441,6 +596,13 @@ Program::Program( ProgramCache& cache, Integration::ShaderDataPtr shaderData, bo mProgramData(shaderData), mModifiesGeometry( modifiesGeometry ) { + // reserve space for standard attributes + mAttributeLocations.reserve( ATTRIB_TYPE_LAST ); + for( int i=0; iGetVertexShader(), mProgramData->GetFragmentShader() ); CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramiv(mProgramId, GL_PROGRAM_BINARY_LENGTH_OES, &binaryLength) ); DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Program::Load() - GL_PROGRAM_BINARY_LENGTH_OES: %d\n", binaryLength); @@ -528,12 +694,15 @@ void Program::Load() // Copy the bytecode to ShaderData CHECK_GL( mGlAbstraction, mGlAbstraction.GetProgramBinary(mProgramId, binaryLength, NULL, &binaryFormat, mProgramData->GetBufferData()) ); mCache.StoreBinary( mProgramData ); + DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "Saved binary.\n" ); } } } } } + GetActiveSamplerUniforms(); + // No longer needed FreeShaders(); } @@ -652,9 +821,9 @@ void Program::FreeShaders() void Program::ResetAttribsUniformCache() { // reset attribute locations - for( unsigned i = 0; i < ATTRIB_TYPE_LAST; ++i ) + for( unsigned i = 0; i < mAttributeLocations.size() ; ++i ) { - mAttribLocations[ i ] = ATTRIB_UNKNOWN; + mAttributeLocations[ i ].second = ATTRIB_UNKNOWN; } // reset all gl uniform locations @@ -664,12 +833,18 @@ void Program::ResetAttribsUniformCache() mUniformLocations[ i ].second = UNIFORM_NOT_QUERIED; } - // reset uniform cache + mSamplerUniformLocations.clear(); + + // reset uniform caches + mSizeUniformCache.x = mSizeUniformCache.y = mSizeUniformCache.z = 0.f; + for( int i = 0; i < MAX_UNIFORM_CACHE_SIZE; ++i ) { // GL initializes uniforms to 0 mUniformCacheInt[ i ] = 0; mUniformCacheFloat[ i ] = 0.0f; + mUniformCacheFloat2[ i ][ 0 ] = 0.0f; + mUniformCacheFloat2[ i ][ 1 ] = 0.0f; mUniformCacheFloat4[ i ][ 0 ] = 0.0f; mUniformCacheFloat4[ i ][ 1 ] = 0.0f; mUniformCacheFloat4[ i ][ 2 ] = 0.0f;