for(const auto& uniform : mActiveUniforms)
{
- std::string name = uniform.name;
- if(uniform.size <= 1)
- {
- GetUniformLocation(program, name.c_str());
- }
- else
- {
- // Convert single active uniform from "uBlah[0]" or "uStruct[0].element" to N versions of the same
- std::string suffix;
- auto iter = name.find("["); // Search for index operator
- if(iter != std::string::npos)
- {
- name = uniform.name.substr(0, iter); // Strip off index operator
- iter = uniform.name.find("]");
- if(iter != std::string::npos && iter + 1 != uniform.name.length())
- {
- suffix = uniform.name.substr(iter + 1);
- }
- }
- for(int i = 0; i < uniform.size; ++i)
- {
- std::stringstream nss;
- nss << name << "[" << i << "]" << suffix;
- GetUniformLocation(program, nss.str().c_str()); // Generate N uniforms in the uniform map
- }
- }
+ GetUniformLocation(program, uniform.name.c_str());
}
for(const auto& uniform : mCustomUniformData)
TestGraphicsApplication::~TestGraphicsApplication()
{
- mGraphicsController.Shutdown();
Dali::Integration::Log::UninstallLogFunction();
delete mCore;
}
dali2-core
dali2-adaptor
glesv2
+ ecore
+ ecore-x
)
ADD_COMPILE_OPTIONS( -O0 -ggdb --coverage -Wall -Werror )
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
namespace
{
const std::string VERT_SHADER_SOURCE = "myVertShaderSource";
-
-const std::string VERT_SHADER_SOURCE2 =
- "\n"
- "in vec3 aPosition;\n"
- "in vec3 aTexCoord;\n"
- "out vec2 vTexCoord;\n"
- "main()\n"
- "{\n"
- " gl_Position=aPosition;\n"
- " vTexCoord = aTexCoord;\n"
- "}\n";
-
const std::string FRAG_SHADER_SOURCE =
"\n"
"uniform sampler2D sAlbedo;\n"
"{\n"
" gl_fragColor = texture2d(sAlbedo, vTexCoord) + lightDirection*texture2d(sNormals, vTexCoord);\n"
"}\n";
-
-const std::string FRAG_SHADER_SOURCE2 =
- "\n"
- "uniform sampler2D sTextures[4];\n"
- "uniform mediump vec3 lightDirection;\n"
- "in mediump vec2 vTexCoord;\n"
- "main()\n"
- "{\n"
- " gl_fragColor = texture2d(sTextures[0], vTexCoord) + lightDirection*texture2d(sTextures[2], vTexCoord);\n"
- "}\n";
-
} //anonymous namespace
-int UtcDaliGraphicsProgram01(void)
+int UtcDaliGraphicsProgram(void)
{
TestGraphicsApplication app;
tet_infoline("UtcDaliProgram - check that right sampler uniforms are bound for textures");
END_TEST;
}
-
-int UtcDaliGraphicsProgram02(void)
-{
- TestGraphicsApplication app;
- tet_infoline("UtcDaliProgram - check that sampler arrays are handled and bound to textures");
-
- Texture normals = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
- Texture metalroughness = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
- Texture ao = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
- Texture albedo = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
-
- TextureSet textureSet = TextureSet::New();
- textureSet.SetTexture(0, albedo);
- textureSet.SetTexture(1, metalroughness);
- textureSet.SetTexture(2, normals);
- textureSet.SetTexture(3, ao);
-
- Actor actor = CreateRenderableActor2(textureSet, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE2);
- app.GetScene().Add(actor);
-
- auto& gl = app.GetGlAbstraction();
- auto& glUniformTrace = gl.GetSetUniformTrace();
- glUniformTrace.Enable(true);
- glUniformTrace.EnableLogging(true);
- gl.GetShaderTrace().Enable(true);
- gl.GetShaderTrace().EnableLogging(true);
-
- std::vector<ActiveUniform> activeUniforms{
- {"uLightDir", GL_FLOAT_VEC4, 1},
- {"sTextures[0]", GL_SAMPLER_2D, 4}}; // Array of 4 samplers
- gl.SetActiveUniforms(activeUniforms);
-
- app.SendNotification();
- app.Render(16); // The above actor will get rendered and drawn once.
-
- // Check what uniform values were set:
- int value;
- DALI_TEST_CHECK(gl.GetUniformValue("sTextures[0]", value)); // First in frag shader
- DALI_TEST_EQUALS(value, 0, TEST_LOCATION);
- DALI_TEST_CHECK(gl.GetUniformValue("sTextures[3]", value)); // 4th
- DALI_TEST_EQUALS(value, 3, TEST_LOCATION);
- DALI_TEST_CHECK(gl.GetUniformValue("sTextures[2]", value)); // 3rd
- DALI_TEST_EQUALS(value, 2, TEST_LOCATION);
- DALI_TEST_CHECK(gl.GetUniformValue("sTextures[1]", value)); // 2nd
- DALI_TEST_EQUALS(value, 1, TEST_LOCATION);
-
- END_TEST;
-}
-
-int UtcDaliGraphicsShaderNew(void)
-{
- TestGraphicsApplication app;
- tet_infoline("UtcDaliProgram - check that multiple shaders from same source only create 1 program");
-
- Texture diffuse = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
-
- // Creates 3 Dali::Shaders
- Actor actor1 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE);
- Actor actor2 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE);
- Actor actor3 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE);
-
- app.GetScene().Add(actor1);
- app.GetScene().Add(actor2);
- app.GetScene().Add(actor3);
-
- auto& gl = app.GetGlAbstraction();
- auto& glShaderTrace = gl.GetShaderTrace();
- glShaderTrace.Enable(true);
- glShaderTrace.EnableLogging(true);
-
- app.SendNotification();
- app.Render(16); // The above actors will get rendered and drawn once, only 2 shaders should be created
-
- DALI_TEST_EQUALS(glShaderTrace.CountMethod("CreateShader"), 2, TEST_LOCATION);
-
- END_TEST;
-}
-
-int UtcDaliGraphicsShaderNew02(void)
-{
- TestGraphicsApplication app;
- tet_infoline("UtcDaliProgram - check that mixed up multiple shaders from same source don't create dups");
-
- Texture diffuse = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
-
- // Creates 3 Dali::Shaders
- Actor actor1 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE);
- Actor actor2 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE2, FRAG_SHADER_SOURCE2);
- Actor actor3 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE2);
- Actor actor4 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE2, FRAG_SHADER_SOURCE);
-
- app.GetScene().Add(actor1);
- app.GetScene().Add(actor2);
- app.GetScene().Add(actor3);
- app.GetScene().Add(actor4);
-
- auto& gl = app.GetGlAbstraction();
- auto& glShaderTrace = gl.GetShaderTrace();
- glShaderTrace.Enable(true);
- glShaderTrace.EnableLogging(true);
-
- app.SendNotification();
- app.Render(16); // The above actors will get rendered and drawn once, only 2 shaders should be created
-
- // Should only be 4 shaders, not 8.
- DALI_TEST_EQUALS(glShaderTrace.CountMethod("CreateShader"), 4, TEST_LOCATION);
-
- END_TEST;
-}
-
-int UtcDaliGraphicsShaderFlush(void)
-{
- TestGraphicsApplication app;
- tet_infoline("UtcDaliProgram - check that unused shaders are flushed");
-
- Texture diffuse = CreateTexture(TextureType::TEXTURE_2D, Pixel::RGBA8888, 16u, 16u);
- auto& gl = app.GetGlAbstraction();
- auto& glShaderTrace = gl.GetShaderTrace();
- glShaderTrace.Enable(true);
- glShaderTrace.EnableLogging(true);
-
- {
- // Creates 3 Dali::Shaders
- Actor actor1 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE);
- Actor actor2 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE2, FRAG_SHADER_SOURCE2);
- Actor actor3 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE, FRAG_SHADER_SOURCE2);
- Actor actor4 = CreateRenderableActor(diffuse, VERT_SHADER_SOURCE2, FRAG_SHADER_SOURCE);
-
- app.GetScene().Add(actor1);
- app.GetScene().Add(actor2);
- app.GetScene().Add(actor3);
- app.GetScene().Add(actor4);
-
- app.SendNotification();
- app.Render(16); // The above actors will get rendered and drawn once
-
- // Should only be 4 shaders, not 8.
- DALI_TEST_EQUALS(glShaderTrace.CountMethod("CreateShader"), 4, TEST_LOCATION);
-
- UnparentAndReset(actor1);
- UnparentAndReset(actor2);
- UnparentAndReset(actor3);
- UnparentAndReset(actor4);
- }
-
- for(int i = 0; i < 1199; ++i) // 3 flushes per frame
- {
- app.SendNotification();
- app.Render(16);
- DALI_TEST_EQUALS(glShaderTrace.CountMethod("DeleteShader"), 0, TEST_LOCATION);
- }
- app.SendNotification();
- app.Render(16);
- DALI_TEST_EQUALS(glShaderTrace.CountMethod("DeleteShader"), 4, TEST_LOCATION);
-
- END_TEST;
-}
Graphics::UniquePtr<Program> EglGraphicsController::CreateProgram(
const ProgramCreateInfo& programCreateInfo, UniquePtr<Program>&& oldProgram)
{
- // Create pipeline cache if needed
+ // Create program cache if needed
if(!mPipelineCache)
{
mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
Graphics::UniquePtr<Shader> EglGraphicsController::CreateShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Shader>&& oldShader)
{
- // Create pipeline cache if needed
- if(!mPipelineCache)
- {
- mPipelineCache = std::make_unique<GLES::PipelineCache>(*this);
- }
- return mPipelineCache->GetShader(shaderCreateInfo, std::move(oldShader));
+ return NewObject<GLES::Shader>(shaderCreateInfo, *this, std::move(oldShader));
}
Graphics::UniquePtr<Sampler> EglGraphicsController::CreateSampler(const SamplerCreateInfo& samplerCreateInfo, Graphics::UniquePtr<Sampler>&& oldSampler)
#include "gles-graphics-pipeline.h"
#include "gles-graphics-program.h"
-namespace
-{
-constexpr uint32_t CACHE_CLEAN_FLUSH_COUNT = 3600u; // 60fps * 60sec / ~3 flushes per frame
-}
-
namespace Dali::Graphics::GLES
{
/**
explicit Impl(EglGraphicsController& _controller)
: controller(_controller),
pipelineEntriesFlushRequired(false),
- programEntriesFlushRequired(false),
- shaderEntriesFlushRequired(false)
+ programEntriesFlushRequired(false)
{
// Initialise lookup table
InitialiseStateCompareLookupTable();
uint32_t stateBitmask{0u};
};
+ EglGraphicsController& controller;
+ std::vector<CacheEntry> entries;
+
/**
* @brief Sorted array of shaders used to create program
*/
UniquePtr<ProgramImpl> program{nullptr};
};
- struct ShaderCacheEntry
- {
- UniquePtr<ShaderImpl> shaderImpl{nullptr};
- };
-
- EglGraphicsController& controller;
- std::vector<CacheEntry> entries;
std::vector<ProgramCacheEntry> programEntries;
- std::vector<ShaderCacheEntry> shaderEntries;
bool pipelineEntriesFlushRequired : 1;
bool programEntriesFlushRequired : 1;
- bool shaderEntriesFlushRequired : 1;
};
PipelineCache::PipelineCache(EglGraphicsController& controller)
return std::move(wrapper);
}
-ShaderImpl* PipelineCache::FindShaderImpl(const ShaderCreateInfo& shaderCreateInfo)
-{
- if(!mImpl->shaderEntries.empty())
- {
- for(auto& item : mImpl->shaderEntries)
- {
- auto& itemInfo = item.shaderImpl->GetCreateInfo();
- if(itemInfo.pipelineStage != shaderCreateInfo.pipelineStage ||
- itemInfo.shaderlanguage != shaderCreateInfo.shaderlanguage ||
- itemInfo.sourceMode != shaderCreateInfo.sourceMode ||
- itemInfo.sourceSize != shaderCreateInfo.sourceSize)
- {
- continue;
- }
-
- if(memcmp(itemInfo.sourceData, shaderCreateInfo.sourceData, itemInfo.sourceSize) == 0)
- {
- return item.shaderImpl.get();
- }
- }
- }
- return nullptr;
-}
-
-Graphics::UniquePtr<Graphics::Shader> PipelineCache::GetShader(const ShaderCreateInfo& shaderCreateInfo,
- Graphics::UniquePtr<Graphics::Shader>&& oldShader)
-{
- ShaderImpl* cachedShader = FindShaderImpl(shaderCreateInfo);
-
- // Return same pointer if nothing changed
- if(oldShader && *static_cast<GLES::Shader*>(oldShader.get()) == cachedShader)
- {
- return std::move(oldShader);
- }
-
- if(!cachedShader)
- {
- auto shader = MakeUnique<GLES::ShaderImpl>(shaderCreateInfo, mImpl->controller);
- cachedShader = shader.get();
-
- mImpl->shaderEntries.emplace_back();
- mImpl->shaderEntries.back().shaderImpl = std::move(shader);
- }
- auto wrapper = MakeUnique<GLES::Shader, CachedObjectDeleter<GLES::Shader>>(cachedShader);
- return std::move(wrapper);
-}
-
void PipelineCache::FlushCache()
{
if(mImpl->pipelineEntriesFlushRequired)
mImpl->programEntriesFlushRequired = false;
}
-
- if(mImpl->shaderEntriesFlushRequired)
- {
- // There is at least 1 unused shader
- mImpl->shaderEntriesFlushRequired = false;
- bool deleteRequired{false};
- for(auto& entry : mImpl->shaderEntries)
- {
- if(entry.shaderImpl->GetRefCount() == 0)
- {
- mImpl->shaderEntriesFlushRequired = true;
- auto frameCount = entry.shaderImpl->IncreaseFlushCount();
- if(frameCount > CACHE_CLEAN_FLUSH_COUNT)
- {
- deleteRequired = true;
- }
- }
- }
- if(deleteRequired)
- {
- decltype(mImpl->shaderEntries) newShaderEntries;
- newShaderEntries.reserve(mImpl->shaderEntries.size());
- for(auto& entry : mImpl->shaderEntries)
- {
- if(entry.shaderImpl->GetRefCount() > 0 ||
- entry.shaderImpl->GetFlushCount() <= CACHE_CLEAN_FLUSH_COUNT)
- {
- newShaderEntries.emplace_back(std::move(entry));
- }
- }
- mImpl->shaderEntries = std::move(newShaderEntries);
- }
- }
}
void PipelineCache::MarkPipelineCacheFlushRequired()
mImpl->programEntriesFlushRequired = true;
}
-void PipelineCache::MarkShaderCacheFlushRequired()
-{
- mImpl->shaderEntriesFlushRequired = true;
-}
-
} // namespace Dali::Graphics::GLES
#include <dali/graphics-api/graphics-pipeline.h>
#include <dali/graphics-api/graphics-program-create-info.h>
#include <dali/graphics-api/graphics-program.h>
-#include <dali/graphics-api/graphics-shader-create-info.h>
-#include <dali/graphics-api/graphics-shader.h>
// INTERNAL INCLUDES
#include "gles-graphics-resource.h"
class PipelineImpl;
class Program;
class ProgramImpl;
-class Shader;
-class ShaderImpl;
-
/**
* @brief PipelineCache manages pipeline and program
* objects so there are no duplicates created.
Graphics::UniquePtr<Graphics::Program> GetProgram(const ProgramCreateInfo& pipelineCreateInfo, Graphics::UniquePtr<Graphics::Program>&& oldProgram);
/**
- * @brief Retrieves shader matching the spec
- *
- * Function returns either existing shader if one is found
- * in the cache or creates new one.
- *
- * @param[in] shaderCreateInfo Valid ShaderCreateInfo structure
- * @param[in] oldShader previous shader object
- * @return Shader object
- */
- Graphics::UniquePtr<Graphics::Shader> GetShader(const ShaderCreateInfo& shaderCreateInfo, Graphics::UniquePtr<Graphics::Shader>&& oldShader);
-
- /**
* @brief Flushes pipeline and program cache
*
* Removes cached items when they are no longer needed. This function
*/
void MarkProgramCacheFlushRequired();
- /**
- * @brief Notify that we need to flush shader cache next FlushCache API.
- */
- void MarkShaderCacheFlushRequired();
-
private:
/**
* @brief Finds pipeline implementation based on the spec
PipelineImpl* FindPipelineImpl(const PipelineCreateInfo& info);
/**
- * @brief Finds program implementation based on the spec
- * @param[in] info Valid create info structure
- * @return Returns pointer to program or nullptr
- */
+ * @brief Finds program implementation based on the spec
+ * @param[in] info Valid create info structure
+ * @return Returns pointer to program or nullptr
+ */
ProgramImpl* FindProgramImpl(const ProgramCreateInfo& info);
- /**
- * @brief Finds shader implementation based on create info
- *
- * @param[in] shadercreateinfo Valid create info structure
- * @return Returns pointer to shader or nullptr
- */
- ShaderImpl* FindShaderImpl(const ShaderCreateInfo& shaderCreateInfo);
-
private:
struct Impl;
std::unique_ptr<Impl> mImpl;
const auto* shader = static_cast<const GLES::Shader*>(state.shader);
// Compile shader first (ignored when compiled)
- if(shader->GetImplementation()->Compile())
+ if(shader->Compile())
{
- gl->AttachShader(program, shader->GetImplementation()->GetGLShader());
+ gl->AttachShader(program, shader->GetGLShader());
}
}
gl->LinkProgram(program);
#define DALI_GRAPHICS_GLES_PROGRAM_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
///////////////////////////////////////////////////////////////
/**
- * @brief Wrapper for the program implementation
+ * @brief Wrapper for the pipeline implementation
*
* This object is returned back to the client-side
*/
namespace Dali::Graphics::GLES
{
-struct ShaderImpl::Impl
+struct Shader::Impl
{
- explicit Impl(Graphics::EglGraphicsController& _controller, const Graphics::ShaderCreateInfo& _createInfo)
- : controller(_controller)
- {
- createInfo.pipelineStage = _createInfo.pipelineStage;
- createInfo.shaderlanguage = _createInfo.shaderlanguage;
- createInfo.sourceMode = _createInfo.sourceMode;
- createInfo.sourceSize = _createInfo.sourceSize;
-
- // Make a copy of source code
- source.resize(_createInfo.sourceSize);
- std::copy(reinterpret_cast<const char*>(_createInfo.sourceData),
- reinterpret_cast<const char*>(_createInfo.sourceData) + _createInfo.sourceSize,
- source.data());
-
- // Substitute pointer
- createInfo.sourceData = source.data();
- }
+ Impl() = default;
+ ~Impl() = default;
- ~Impl(){};
+ std::vector<char> source{};
+ uint32_t glShader{};
+};
- bool Compile()
- {
- auto gl = controller.GetGL();
+Shader::Shader(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
+: ShaderResource(createInfo, controller)
+{
+ // push shader to the create queue
+ mImpl = std::make_unique<Impl>();
- if(!gl)
- {
- return false;
- }
+ // Make a copy of source code
+ mImpl->source.resize(createInfo.sourceSize);
+ std::copy(reinterpret_cast<const char*>(mCreateInfo.sourceData),
+ reinterpret_cast<const char*>(mCreateInfo.sourceData) + mCreateInfo.sourceSize,
+ mImpl->source.begin());
+
+ // Substitute pointer
+ mCreateInfo.sourceData = mImpl->source.data();
+}
+
+Shader::~Shader() = default;
- if(!glShader)
+bool Shader::Compile() const
+{
+ auto gl = GetController().GetGL();
+
+ if(!gl)
+ {
+ return false;
+ }
+
+ if(!mImpl->glShader)
+ {
+ GLenum pipelineStage{0u};
+ switch(GetCreateInfo().pipelineStage)
{
- GLenum pipelineStage{0u};
- switch(createInfo.pipelineStage)
+ case Graphics::PipelineStage::TOP_OF_PIPELINE:
{
- case Graphics::PipelineStage::TOP_OF_PIPELINE:
- {
- break;
- }
- case Graphics::PipelineStage::VERTEX_SHADER:
- {
- pipelineStage = GL_VERTEX_SHADER;
- break;
- }
- case Graphics::PipelineStage::GEOMETRY_SHADER:
- {
- break;
- }
- case Graphics::PipelineStage::FRAGMENT_SHADER:
- {
- pipelineStage = GL_FRAGMENT_SHADER;
- break;
- }
- case Graphics::PipelineStage::COMPUTE_SHADER:
- {
- break;
- }
- case Graphics::PipelineStage::TESSELATION_CONTROL:
- {
- break;
- }
- case Graphics::PipelineStage::TESSELATION_EVALUATION:
- {
- break;
- }
- case Graphics::PipelineStage::BOTTOM_OF_PIPELINE:
- {
- break;
- }
+ break;
}
-
- if(pipelineStage)
+ case Graphics::PipelineStage::VERTEX_SHADER:
{
- auto shader = gl->CreateShader(pipelineStage);
- const auto src = reinterpret_cast<const char*>(createInfo.sourceData);
- GLint size = createInfo.sourceSize;
- gl->ShaderSource(shader, 1, const_cast<const char**>(&src), &size);
- gl->CompileShader(shader);
-
- GLint status{0};
- gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
- if(status != GL_TRUE)
- {
- char output[4096];
- GLsizei size{0u};
- gl->GetShaderInfoLog(shader, 4096, &size, output);
- DALI_LOG_ERROR("Code: %s\n", reinterpret_cast<const char*>(createInfo.sourceData));
- DALI_LOG_ERROR("glCompileShader() failed: \n%s\n", output);
- gl->DeleteShader(shader);
- return false;
- }
- glShader = shader;
+ pipelineStage = GL_VERTEX_SHADER;
+ break;
+ }
+ case Graphics::PipelineStage::GEOMETRY_SHADER:
+ {
+ break;
+ }
+ case Graphics::PipelineStage::FRAGMENT_SHADER:
+ {
+ pipelineStage = GL_FRAGMENT_SHADER;
+ break;
+ }
+ case Graphics::PipelineStage::COMPUTE_SHADER:
+ {
+ break;
+ }
+ case Graphics::PipelineStage::TESSELATION_CONTROL:
+ {
+ break;
+ }
+ case Graphics::PipelineStage::TESSELATION_EVALUATION:
+ {
+ break;
+ }
+ case Graphics::PipelineStage::BOTTOM_OF_PIPELINE:
+ {
+ break;
}
- return true;
}
- return true;
- }
-
- void Destroy()
- {
- auto gl = controller.GetGL();
- if(gl && glShader)
+ if(pipelineStage)
{
- gl->DeleteShader(glShader);
- glShader = 0;
+ auto shader = gl->CreateShader(pipelineStage);
+ const auto src = reinterpret_cast<const char*>(GetCreateInfo().sourceData);
+ GLint size = GetCreateInfo().sourceSize;
+ gl->ShaderSource(shader, 1, const_cast<const char**>(&src), &size);
+ gl->CompileShader(shader);
+
+ GLint status{0};
+ gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if(status != GL_TRUE)
+ {
+ char output[4096];
+ GLsizei size{0u};
+ gl->GetShaderInfoLog(shader, 4096, &size, output);
+ DALI_LOG_ERROR("Code: %s\n", reinterpret_cast<const char*>(GetCreateInfo().sourceData));
+ DALI_LOG_ERROR("glCompileShader() failed: \n%s\n", output);
+ gl->DeleteShader(shader);
+ return false;
+ }
+ mImpl->glShader = shader;
}
+ return true;
}
-
- EglGraphicsController& controller;
- ShaderCreateInfo createInfo;
- std::vector<char> source{};
-
- uint32_t glShader{};
- uint32_t refCount{0u};
- uint32_t flushCount{0u}; ///< Number of frames at refCount=0
-};
-
-ShaderImpl::ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller)
-{
- mImpl = std::make_unique<Impl>(controller, createInfo);
-}
-
-ShaderImpl::~ShaderImpl()
-{
- if(!mImpl->controller.IsShuttingDown())
- {
- mImpl->Destroy();
- }
-}
-
-uint32_t ShaderImpl::Retain()
-{
- mImpl->flushCount = 0;
- return ++mImpl->refCount;
-}
-
-uint32_t ShaderImpl::Release()
-{
- uint32_t remainingCount = --mImpl->refCount;
- mImpl->flushCount = 0;
- return remainingCount;
-}
-
-[[nodiscard]] uint32_t ShaderImpl::GetRefCount() const
-{
- return mImpl->refCount;
-}
-
-[[nodiscard]] uint32_t ShaderImpl::IncreaseFlushCount()
-{
- return ++mImpl->flushCount;
-}
-
-[[nodiscard]] uint32_t ShaderImpl::GetFlushCount() const
-{
- return mImpl->flushCount;
-}
-
-/**
- * @brief Compiles shader
- *
- * @return True on success
- */
-[[nodiscard]] bool ShaderImpl::Compile() const
-{
- return mImpl->Compile();
+ return true;
}
-[[nodiscard]] uint32_t ShaderImpl::GetGLShader() const
+uint32_t Shader::GetGLShader() const
{
return mImpl->glShader;
}
-const ShaderCreateInfo& ShaderImpl::GetCreateInfo() const
-{
- return mImpl->createInfo;
-}
-
-[[nodiscard]] EglGraphicsController& ShaderImpl::GetController() const
-{
- return mImpl->controller;
-}
-
-Shader::~Shader()
+void Shader::DestroyResource()
{
- if(!mShader->Release())
+ if(mImpl->glShader)
{
- GetImplementation()->GetController().GetPipelineCache().MarkShaderCacheFlushRequired();
+ auto gl = GetController().GetGL();
+ if(!gl)
+ {
+ return;
+ }
+ gl->DeleteShader(mImpl->glShader);
}
}
-[[nodiscard]] const ShaderCreateInfo& Shader::GetCreateInfo() const
-{
- return GetImplementation()->GetCreateInfo();
-}
-
void Shader::DiscardResource()
{
- auto& controller = GetImplementation()->GetController();
- if(!controller.IsShuttingDown())
- {
- controller.DiscardResource(this);
- }
+ GetController().DiscardResource(this);
}
} // namespace Dali::Graphics::GLES
#define DALI_GRAPHICS_GLES_SHADER_H
/*
- * Copyright (c) 2023 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2021 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.
namespace Dali::Graphics::GLES
{
-class ShaderImpl
+using ShaderResource = Resource<Graphics::Shader, Graphics::ShaderCreateInfo>;
+
+class Shader : public ShaderResource
{
public:
/**
* @param[in] createInfo Valid createInfo structure
* @param[in] controller Reference to the controller
*/
- ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
- ~ShaderImpl();
-
- uint32_t Retain();
+ Shader(const Graphics::ShaderCreateInfo& createInfo, Graphics::EglGraphicsController& controller);
- uint32_t Release();
-
- [[nodiscard]] uint32_t GetRefCount() const;
+ /**
+ * @brief Destructor
+ */
+ ~Shader() override;
/**
- * Whilst unreferenced, increase the flush count and return it
- *
- * @return The new flush count
+ * @brief Called when GL resources are destroyed
*/
- [[nodiscard]] uint32_t IncreaseFlushCount();
+ void DestroyResource() override;
/**
- * Get the flush count whilst unreferenced
+ * @brief Called when initializing the resource
*
- * @return the flush count
+ * @return True on success
*/
- [[nodiscard]] uint32_t GetFlushCount() const;
+ bool InitializeResource() override
+ {
+ // The Shader has instant initialization, hence no need to initialize GL resource
+ // here
+ return true;
+ }
/**
* @brief Compiles shader
[[nodiscard]] bool Compile() const;
/**
- * @brief Destroys GL shader
+ * @brief Called when UniquePtr<> on client-side dies
*/
- void Destroy();
+ void DiscardResource() override;
uint32_t GetGLShader() const;
- [[nodiscard]] const ShaderCreateInfo& GetCreateInfo() const;
-
- [[nodiscard]] EglGraphicsController& GetController() const;
-
private:
- friend class Shader;
struct Impl;
std::unique_ptr<Impl> mImpl{nullptr};
};
-class Shader : public Graphics::Shader
-{
-public:
- /**
- * @brief Constructor
- *
- * @param[in] impl Pointer to valid implementation
- */
- explicit Shader(ShaderImpl* impl)
- : mShader(impl)
- {
- mShader->Retain();
- }
-
- /**
- * @brief Destructor
- */
- ~Shader() override;
-
- [[nodiscard]] ShaderImpl* GetImplementation() const
- {
- return mShader;
- }
-
- [[nodiscard]] const ShaderCreateInfo& GetCreateInfo() const;
-
- bool operator==(const GLES::Shader& shader) const
- {
- return (shader.mShader == mShader);
- }
-
- bool operator==(const GLES::ShaderImpl* shaderImpl) const
- {
- return (shaderImpl == mShader);
- }
-
- bool operator!=(const GLES::Shader& shader) const
- {
- return (shader.mShader != mShader);
- }
-
- /**
- * @brief Called when UniquePtr<> on client-side dies.
- */
- void DiscardResource();
-
- /**
- * @brief Destroying GL resources
- *
- * This function is kept for compatibility with Resource<> class
- * so can the object can be use with templated functions.
- */
- void DestroyResource()
- {
- // nothing to do here
- }
-
-private:
- ShaderImpl* mShader{nullptr};
-};
-
} // namespace Dali::Graphics::GLES
#endif