From: David Steele Date: Tue, 2 Mar 2021 12:25:54 +0000 (+0000) Subject: Updating Program to remove shader compilation X-Git-Tag: graphics-backend-pre-release-3~12 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=refs%2Fchanges%2F16%2F254416%2F5;p=platform%2Fcore%2Fuifw%2Fdali-core.git Updating Program to remove shader compilation New Graphics API manages it's own shader compilation. Change-Id: I86b08673e64e2cd3b2c70a082c9c0823337a90ec --- diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h index 5679a01..7aacf76 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-gl-abstraction.h @@ -2496,7 +2496,7 @@ private: // Shaders & Uniforms GLuint mLastShaderIdUsed; - GLuint mLastProgramIdUsed; + GLuint mLastProgramIdUsed{0u}; GLuint mLastUniformIdUsed; typedef std::map UniformIDMap; typedef std::map ProgramUniformMap; diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp index adacc11..fe9c329 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.cpp @@ -54,6 +54,12 @@ T* Uncast(const Graphics::Buffer* object) return const_cast(static_cast(object)); } +template +T* Uncast(const Graphics::Shader* object) +{ + return const_cast(static_cast(object)); +} + std::ostream& operator<<(std::ostream& o, const Graphics::BufferCreateInfo& bufferCreateInfo) { return o << "usage:" << std::hex << bufferCreateInfo.usage << ", size:" << std::dec << bufferCreateInfo.size; @@ -711,7 +717,33 @@ Graphics::UniquePtr TestGraphicsController::CreatePipeline(c Graphics::UniquePtr TestGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, Graphics::UniquePtr&& oldProgram) { mCallStack.PushCall("CreateProgram", ""); - return Graphics::MakeUnique(mGl, programCreateInfo, mVertexFormats); + + for(auto cacheEntry : mProgramCache) + { + bool found = true; + for(auto& shader : *(programCreateInfo.shaderState)) + { + auto graphicsShader = Uncast(shader.shader); + if(memcmp(cacheEntry.shaders[shader.pipelineStage], graphicsShader->mCreateInfo.sourceData, graphicsShader->mCreateInfo.sourceSize)) + { + found = false; + break; + } + } + if(found) + { + return Graphics::MakeUnique(cacheEntry.programImpl); + } + } + + mProgramCache.emplace_back(); + mProgramCache.back().programImpl = new TestGraphicsProgramImpl(mGl, programCreateInfo, mVertexFormats); + for(auto& shader : *(programCreateInfo.shaderState)) + { + auto graphicsShader = Uncast(shader.shader); + mProgramCache.back().shaders[shader.pipelineStage] = graphicsShader->mCreateInfo.sourceData; + } + return Graphics::MakeUnique(mProgramCache.back().programImpl); } Graphics::UniquePtr TestGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr&& oldShader) @@ -789,7 +821,7 @@ bool TestGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, return false; } -bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData ) +bool TestGraphicsController::GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) { mCallStack.PushCall("GetProgramParameter", ""); auto graphicsProgram = Uncast(&program); diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h index 9179a39..fa2fd63 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-controller.h @@ -21,6 +21,7 @@ #include "test-gl-abstraction.h" #include "test-gl-context-helper-abstraction.h" #include "test-gl-sync-abstraction.h" +#include "test-graphics-program.h" #include "test-graphics-reflection.h" namespace Dali @@ -313,7 +314,7 @@ public: // Test Functions * @param[out] outData Pointer to output memory * @return True on success */ - bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData ) override; + bool GetProgramParameter(Graphics::Program& program, uint32_t parameterId, void* outData) override; public: mutable TraceCallStack mCallStack; @@ -328,6 +329,13 @@ public: bool isDrawOnResumeRequiredResult{true}; Property::Array mVertexFormats; + + struct ProgramCache + { + std::map shaders; + TestGraphicsProgramImpl* programImpl; + }; + std::vector mProgramCache; }; } // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp index 1b23380..9a0afa6 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.cpp @@ -18,20 +18,29 @@ namespace Dali { -TestGraphicsProgram::TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats) +TestGraphicsProgramImpl::TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats) : mGl(gl), mCreateInfo(createInfo), mReflection(gl, vertexFormats) { - mId = 0;//mGl.CreateProgram(); + mId = mGl.CreateProgram(); + mGl.LinkProgram(1); // Ensure active sampler uniforms are set } -bool TestGraphicsProgram::GetParameter(uint32_t parameterId, void* outData ) +bool TestGraphicsProgramImpl::GetParameter(uint32_t parameterId, void* outData) { reinterpret_cast(outData)[0] = mId; return true; } +TestGraphicsProgram::TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats) +{ + mImpl = new TestGraphicsProgramImpl(gl, createInfo, vertexFormats); +} +TestGraphicsProgram::TestGraphicsProgram(TestGraphicsProgramImpl* impl) +{ + mImpl = impl; +} } // namespace Dali diff --git a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.h b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.h index d5f5b85..c098718 100644 --- a/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.h +++ b/automated-tests/src/dali/dali-test-suite-utils/test-graphics-program.h @@ -24,10 +24,10 @@ namespace Dali { -class TestGraphicsProgram : public Graphics::Program +class TestGraphicsProgramImpl { public: - TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats); + TestGraphicsProgramImpl(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats); // For API const TestGraphicsReflection& GetReflection() const @@ -37,12 +37,12 @@ public: } // For tests - TestGraphicsReflection& GetProgamReflection() + TestGraphicsReflection& GetProgramReflection() { return mReflection; } - bool GetParameter(uint32_t parameterId, void* outData ); + bool GetParameter(uint32_t parameterId, void* outData); public: TestGlAbstraction& mGl; @@ -51,6 +51,30 @@ public: TestGraphicsReflection mReflection; }; +class TestGraphicsProgram : public Graphics::Program +{ +public: + TestGraphicsProgram(TestGlAbstraction& gl, const Graphics::ProgramCreateInfo& createInfo, Property::Array& vertexFormats); + TestGraphicsProgram(TestGraphicsProgramImpl* impl); + + const TestGraphicsReflection& GetReflection() const + { + return mImpl->GetReflection(); + } + bool GetParameter(uint32_t parameterId, void* outData) + { + return mImpl->GetParameter(parameterId, outData); + } + + TestGraphicsReflection& GetProgamReflection() + { + return mImpl->GetProgramReflection(); + } + +public: + TestGraphicsProgramImpl* mImpl; +}; + } // namespace Dali #endif //DALI_TEST_GRAPHICS_PROGRAM_H diff --git a/dali/internal/render/shaders/program.cpp b/dali/internal/render/shaders/program.cpp index 6d42581..a6f6883 100644 --- a/dali/internal/render/shaders/program.cpp +++ b/dali/internal/render/shaders/program.cpp @@ -23,6 +23,8 @@ #include // INTERNAL INCLUDES +#include +#include #include #include #include @@ -32,41 +34,6 @@ #include #include #include -#include -#include -namespace -{ -void LogWithLineNumbers(const char* source) -{ - uint32_t lineNumber = 0u; - const char* prev = source; - const char* ptr = prev; - - while(true) - { - if(lineNumber > 200u) - { - break; - } - // seek the next end of line or end of text - while(*ptr != '\n' && *ptr != '\0') - { - ++ptr; - } - - std::string line(prev, ptr - prev); - Dali::Integration::Log::LogMessage(Dali::Integration::Log::DebugError, "%4d %s\n", lineNumber, line.c_str()); - - if(*ptr == '\0') - { - break; - } - prev = ++ptr; - ++lineNumber; - } -} - -} //namespace namespace Dali { @@ -106,35 +73,26 @@ Program* Program::New(ProgramCache& cache, Internal::ShaderDataPtr shaderData, G // Get program id and use it as hash for the cache // in order to maintain current functionality as long as needed - gfxController.GetProgramParameter( *gfxProgram, 1, &programId ); + gfxController.GetProgramParameter(*gfxProgram, 1, &programId); size_t shaderHash = programId; - Program* program = cache.GetProgram(shaderHash); if(nullptr == program) { // program not found so create it program = new Program(cache, shaderData, gfxController, std::move(gfxProgram), modifiesGeometry); - program->Load(); + program->GetActiveSamplerUniforms(); cache.AddProgram(shaderHash, program); } return program; } - void Program::Use() { - if(mLinked) - { - if(this != mCache.GetCurrentProgram()) - { - LOG_GL("UseProgram(%d)\n", mProgramId); - CHECK_GL(mGlAbstraction, mGlAbstraction.UseProgram(mProgramId)); - - mCache.SetCurrentProgram(this); - } - } + LOG_GL("UseProgram(%d)\n", mProgramId); + CHECK_GL(mGlAbstraction, mGlAbstraction.UseProgram(mProgramId)); + mCache.SetCurrentProgram(this); } bool Program::IsUsed() @@ -619,11 +577,6 @@ void Program::GlContextCreated() void Program::GlContextDestroyed() { - mLinked = false; - mVertexShaderId = 0; - mFragmentShaderId = 0; - mProgramId = 0; - ResetAttribsUniformCache(); } @@ -637,12 +590,9 @@ Program::Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphi mGlAbstraction(mCache.GetGlAbstraction()), mProjectionMatrix(nullptr), mViewMatrix(nullptr), - mLinked(false), - mVertexShaderId(0), - mFragmentShaderId(0), mProgramId(0), - mGfxProgram( std::move(gfxProgram)), - mGfxController( controller ), + mGfxProgram(std::move(gfxProgram)), + mGfxController(controller), mProgramData(shaderData), mModifiesGeometry(modifiesGeometry) { @@ -666,237 +616,11 @@ Program::Program(ProgramCache& cache, Internal::ShaderDataPtr shaderData, Graphi // Get program id and use it as hash for the cache // in order to maintain current functionality as long as needed - mGfxController.GetProgramParameter( *mGfxProgram, 1, &mProgramId ); - mLinked = true; + mGfxController.GetProgramParameter(*mGfxProgram, 1, &mProgramId); } Program::~Program() { - Unload(); -} - -void Program::Load() -{ - // Temporary, exist if program id is already set - if(mProgramId) - { - GetActiveSamplerUniforms(); - return; - } - - DALI_ASSERT_ALWAYS(nullptr != 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()); - - GLint linked = GL_FALSE; - - const bool binariesSupported = mCache.IsBinarySupported(); - - // if shader binaries are supported and ShaderData contains compiled bytecode? - if(binariesSupported && mProgramData->HasBinary()) - { - DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Program::Load() - Using Compiled Shader, Size = %d\n", mProgramData->GetBufferSize()); - - CHECK_GL(mGlAbstraction, mGlAbstraction.ProgramBinary(mProgramId, mCache.ProgramBinaryFormat(), mProgramData->GetBufferData(), static_cast(mProgramData->GetBufferSize()))); // truncated - - CHECK_GL(mGlAbstraction, mGlAbstraction.ValidateProgram(mProgramId)); - - GLint success; - CHECK_GL(mGlAbstraction, mGlAbstraction.GetProgramiv(mProgramId, GL_VALIDATE_STATUS, &success)); - - DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "ValidateProgram Status = %d\n", success); - - CHECK_GL(mGlAbstraction, mGlAbstraction.GetProgramiv(mProgramId, GL_LINK_STATUS, &linked)); - - if(GL_FALSE == linked) - { - DALI_LOG_ERROR("Failed to load program binary \n"); - - GLint nLength; - CHECK_GL(mGlAbstraction, mGlAbstraction.GetProgramiv(mProgramId, GL_INFO_LOG_LENGTH, &nLength)); - if(nLength > 0) - { - Dali::Vector szLog; - szLog.Reserve(nLength); // Don't call Resize as we don't want to initialise the data, just reserve a buffer - CHECK_GL(mGlAbstraction, mGlAbstraction.GetProgramInfoLog(mProgramId, nLength, &nLength, szLog.Begin())); - DALI_LOG_ERROR("Program Link Error: %s\n", szLog.Begin()); - } - } - else - { - mLinked = true; - DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Reused binary.\n"); - } - } - - // Fall back to compiling and linking the vertex and fragment sources - if(GL_FALSE == linked) - { - DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Program::Load() - Runtime compilation\n"); - if(CompileShader(GL_VERTEX_SHADER, mVertexShaderId, mProgramData->GetVertexShader())) - { - if(CompileShader(GL_FRAGMENT_SHADER, mFragmentShaderId, mProgramData->GetFragmentShader())) - { - Link(); - - if(binariesSupported && mLinked) - { - 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); - if(binaryLength > 0) - { - // Allocate space for the bytecode in ShaderData - mProgramData->AllocateBuffer(binaryLength); - // Copy the bytecode to ShaderData - CHECK_GL(mGlAbstraction, mGlAbstraction.GetProgramBinary(mProgramId, binaryLength, nullptr, &binaryFormat, mProgramData->GetBufferData())); - mCache.StoreBinary(mProgramData); - DALI_LOG_INFO(Debug::Filter::gShader, Debug::General, "Saved binary.\n"); - } - } - } - } - } - - GetActiveSamplerUniforms(); - - // No longer needed - FreeShaders(); -} - -void Program::Unload() -{ - // Bypass when using gfx program - if(!mProgramData && mProgramId) - { - return; - } - FreeShaders(); - - if(this == mCache.GetCurrentProgram()) - { - CHECK_GL(mGlAbstraction, mGlAbstraction.UseProgram(0)); - - mCache.SetCurrentProgram(nullptr); - } - - if(mProgramId) - { - LOG_GL("DeleteProgram(%d)\n", mProgramId); - CHECK_GL(mGlAbstraction, mGlAbstraction.DeleteProgram(mProgramId)); - mProgramId = 0; - } - - mLinked = false; -} - -bool Program::CompileShader(GLenum shaderType, GLuint& shaderId, const char* src) -{ - // Bypass when using gfx program - if(!mProgramData && mProgramId) - { - return true; - } - if(!shaderId) - { - LOG_GL("CreateShader(%d)\n", shaderType); - shaderId = CHECK_GL(mGlAbstraction, mGlAbstraction.CreateShader(shaderType)); - LOG_GL("AttachShader(%d,%d)\n", mProgramId, shaderId); - CHECK_GL(mGlAbstraction, mGlAbstraction.AttachShader(mProgramId, shaderId)); - } - - LOG_GL("ShaderSource(%d)\n", shaderId); - CHECK_GL(mGlAbstraction, mGlAbstraction.ShaderSource(shaderId, 1, &src, nullptr)); - - LOG_GL("CompileShader(%d)\n", shaderId); - CHECK_GL(mGlAbstraction, mGlAbstraction.CompileShader(shaderId)); - - GLint compiled; - LOG_GL("GetShaderiv(%d)\n", shaderId); - CHECK_GL(mGlAbstraction, mGlAbstraction.GetShaderiv(shaderId, GL_COMPILE_STATUS, &compiled)); - - if(compiled == GL_FALSE) - { - DALI_LOG_ERROR("Failed to compile shader\n"); - LogWithLineNumbers(src); - - GLint nLength; - mGlAbstraction.GetShaderiv(shaderId, GL_INFO_LOG_LENGTH, &nLength); - if(nLength > 0) - { - Dali::Vector szLog; - szLog.Reserve(nLength); // Don't call Resize as we don't want to initialise the data, just reserve a buffer - mGlAbstraction.GetShaderInfoLog(shaderId, nLength, &nLength, szLog.Begin()); - DALI_LOG_ERROR("Shader Compiler Error: %s\n", szLog.Begin()); - } - - DALI_ASSERT_ALWAYS(0 && "Shader compilation failure"); - } - - return compiled != 0; -} - -void Program::Link() -{ - // Bypass when using gfx program - if(!mProgramData && mProgramId) - { - return; - } - LOG_GL("LinkProgram(%d)\n", mProgramId); - CHECK_GL(mGlAbstraction, mGlAbstraction.LinkProgram(mProgramId)); - - GLint linked; - LOG_GL("GetProgramiv(%d)\n", mProgramId); - CHECK_GL(mGlAbstraction, mGlAbstraction.GetProgramiv(mProgramId, GL_LINK_STATUS, &linked)); - - if(linked == GL_FALSE) - { - DALI_LOG_ERROR("Shader failed to link \n"); - - GLint nLength; - mGlAbstraction.GetProgramiv(mProgramId, GL_INFO_LOG_LENGTH, &nLength); - if(nLength > 0) - { - Dali::Vector szLog; - szLog.Reserve(nLength); // Don't call Resize as we don't want to initialise the data, just reserve a buffer - mGlAbstraction.GetProgramInfoLog(mProgramId, nLength, &nLength, szLog.Begin()); - DALI_LOG_ERROR("Shader Link Error: %s\n", szLog.Begin()); - } - - DALI_ASSERT_ALWAYS(0 && "Shader linking failure"); - } - - mLinked = linked != GL_FALSE; -} - -void Program::FreeShaders() -{ - // Bypass when using gfx program - if(!mProgramData && mProgramId) - { - return; - } - if(mVertexShaderId) - { - LOG_GL("DeleteShader(%d)\n", mVertexShaderId); - CHECK_GL(mGlAbstraction, mGlAbstraction.DetachShader(mProgramId, mVertexShaderId)); - CHECK_GL(mGlAbstraction, mGlAbstraction.DeleteShader(mVertexShaderId)); - mVertexShaderId = 0; - } - - if(mFragmentShaderId) - { - LOG_GL("DeleteShader(%d)\n", mFragmentShaderId); - CHECK_GL(mGlAbstraction, mGlAbstraction.DetachShader(mProgramId, mFragmentShaderId)); - CHECK_GL(mGlAbstraction, mGlAbstraction.DeleteShader(mFragmentShaderId)); - mFragmentShaderId = 0; - } } void Program::ResetAttribsUniformCache() diff --git a/dali/internal/render/shaders/program.h b/dali/internal/render/shaders/program.h index d1047b5..d26fcc5 100644 --- a/dali/internal/render/shaders/program.h +++ b/dali/internal/render/shaders/program.h @@ -35,7 +35,7 @@ namespace Graphics { class Controller; class Program; -} +} // namespace Graphics class Matrix; namespace Integration @@ -341,51 +341,19 @@ private: Program& operator=(const Program&); ///< assignment operator, not defined /** - * Load the shader, from a precompiled binary if available, else from source code - */ - void Load(); - - /** - * Unload the shader - */ - void Unload(); - - /** - * Compile the shader - * @param shaderType vertex or fragment shader - * @param shaderId of the shader, returned - * @param src of the shader - * @return true if the compilation succeeded - */ - bool CompileShader(GLenum shaderType, GLuint& shaderId, const char* src); - - /** - * Links the shaders together to create program - */ - void Link(); - - /** - * Frees the shader programs - */ - void FreeShaders(); - - /** * Resets caches */ void ResetAttribsUniformCache(); -private: // Data - ProgramCache& mCache; ///< The program cache - Integration::GlAbstraction& mGlAbstraction; ///< The OpenGL Abstraction layer - const Matrix* mProjectionMatrix; ///< currently set projection matrix - const Matrix* mViewMatrix; ///< currently set view matrix - bool mLinked; ///< whether the program is linked - GLuint mVertexShaderId; ///< GL identifier for vertex shader - GLuint mFragmentShaderId; ///< GL identifier for fragment shader - GLuint mProgramId; ///< GL identifier for program - Graphics::UniquePtr mGfxProgram; ///< Gfx program - Graphics::Controller& mGfxController; /// < Gfx controller - Internal::ShaderDataPtr mProgramData; ///< Shader program source and binary (when compiled & linked or loaded) +private: // Data + ProgramCache& mCache; ///< The program cache + Integration::GlAbstraction& mGlAbstraction; ///< The OpenGL Abstraction layer + const Matrix* mProjectionMatrix; ///< currently set projection matrix + const Matrix* mViewMatrix; ///< currently set view matrix + GLuint mProgramId; ///< GL identifier for program + Graphics::UniquePtr mGfxProgram; ///< Gfx program + Graphics::Controller& mGfxController; /// < Gfx controller + Internal::ShaderDataPtr mProgramData; ///< Shader program source and binary (when compiled & linked or loaded) // location caches using NameLocationPair = std::pair;