X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=dali%2Finternal%2Frender%2Fshaders%2Fprogram.cpp;h=451de0bb6c7083eeccb9bf7e90e73e82b30a29c9;hb=649ec06daecb510fb84fe4642a6af957f127e7ab;hp=dbfc2983b4d72d5ab8fea87334a09c46dd59d244;hpb=432923e17cb38a99fc012473ef97fa8c4fc36162;p=platform%2Fcore%2Fuifw%2Fdali-core.git diff --git a/dali/internal/render/shaders/program.cpp b/dali/internal/render/shaders/program.cpp index dbfc298..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,14 +92,9 @@ 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 "uSize" // UNIFORM_SIZE }; @@ -110,7 +102,7 @@ const char* gStdUniforms[ Program::UNIFORM_TYPE_LAST ] = // 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 ); @@ -119,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 ); } @@ -130,11 +120,6 @@ Program* Program::New( ProgramCache& cache, Integration::ShaderDataPtr shaderDat void Program::Use() { - if ( !mLinked ) - { - Load(); - } - if ( mLinked ) { if ( this != mCache.GetCurrentProgram() ) @@ -232,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 ) @@ -448,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 ), @@ -474,6 +610,7 @@ Program::Program( ProgramCache& cache, Integration::ShaderDataPtr shaderData, bo { RegisterUniform( gStdUniforms[ i ] ); } + // reset values ResetAttribsUniformCache(); } @@ -486,6 +623,7 @@ Program::~Program() void Program::Load() { DALI_ASSERT_ALWAYS( NULL != mProgramData.Get() && "Program data is not initialized" ); + DALI_ASSERT_DEBUG( mProgramId == 0 && "mProgramId != 0, so about to leak a GL resource by overwriting it." ); LOG_GL( "CreateProgram()\n" ); mProgramId = CHECK_GL( mGlAbstraction, mGlAbstraction.CreateProgram() ); @@ -527,6 +665,7 @@ void Program::Load() else { mLinked = true; + DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "Reused binary.\n" ); } } @@ -544,6 +683,7 @@ void Program::Load() { GLint binaryLength = 0; GLenum binaryFormat; + DALI_LOG_INFO( Debug::Filter::gShader, Debug::General, "Compiled and linked.\n\nVS:\n%s\nFS:\n%s\n", mProgramData->GetVertexShader(), 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); @@ -554,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(); } @@ -690,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;