Shaders can compile to SPIRV in runtime.
Ubuntu glslang dev package is broken so added workaround to deps-check.cmake.
Change-Id: Id6102c743f61ddd324d26dcfa42564ae43977819
ARG_ENABLE( ENABLE_COVERAGE enable_coverage "${ENABLE_VAL}" "Enables coverage" )
ARG_ENABLE( ENABLE_VULKAN enable_vulkan "${ENABLE_VAL}" "Enables Vulkan build")
+
+# force GLSLANG when Vulkan enabled
+IF( enable_vulkan )
+ SET(ENABLE_GLSLANG CACHE STRING "ON")
+ SET(ENABLE_GLSLANG "ON")
+ENDIF()
+
ARG_ENABLE( ENABLE_GLSLANG enable_glslang "${ENABLE_VAL}" "Enables Vulkan GLSLang")
# help option
CHECK_MODULE_AND_SET( GLIB glib-2.0 [] )
CHECK_MODULE_AND_SET( VULKAN vulkan [] )
CHECK_MODULE_AND_SET( GLSLANG glslang [] )
+CHECK_MODULE_AND_SET( SPIRVTOOLS SPIRV-Tools [] )
CHECK_MODULE_AND_SET( X11 x11 [] )
CHECK_MODULE_AND_SET( XCB x11-xcb [] )
CHECK_MODULE_AND_SET( XDAMAGE xdamage [] )
FIND_PACKAGE(glslang)
SET(DALI_LDFLAGS ${DALI_LDFLAGS} glslang::glslang )
ELSE()
- SET(DALI_LDFLAGS ${DALI_LDFLAGS} ${GLSLANG_LDFLAGS} )
+ # On Ubuntu 22.04 glslang seems to be horribly broken, pc file doesn't include
+ # all needed deps and SPIRV-Tools package is needed
+ SET(DALI_LDFLAGS ${DALI_LDFLAGS} ${GLSLANG_LDFLAGS} -lSPIRV ${SPIRVTOOLS_LDFLAGS} -lglslang-default-resource-limits)
ENDIF()
+
ENDIF()
IF(LIBUV_X11_PROFILE)
INCLUDE( ${adaptor_graphics_dir}/gles-impl/file.list )
SET( adaptor_graphics_vulkan_src_files
+ ${adaptor_graphics_dir}/common/shader-parser.cpp
${adaptor_graphics_dir}/vulkan/vulkan-graphics-impl.cpp
${adaptor_graphics_dir}/vulkan/vulkan-graphics-factory.cpp
${adaptor_graphics_dir}/vulkan/vulkan-device.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-image-view-impl.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-memory.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-memory-impl.cpp
+ ${adaptor_graphics_dir}/vulkan-impl/vulkan-program.cpp
+ ${adaptor_graphics_dir}/vulkan-impl/vulkan-program-impl.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-queue-impl.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-render-pass.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-render-pass-impl.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-render-target.cpp
+ ${adaptor_graphics_dir}/vulkan-impl/vulkan-shader.cpp
+ ${adaptor_graphics_dir}/vulkan-impl/vulkan-shader-impl.cpp
+ ${adaptor_graphics_dir}/vulkan-impl/vulkan-spirv.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-surface-impl.cpp
${adaptor_graphics_dir}/vulkan-impl/vulkan-swapchain-impl.cpp
)
#include <dali/internal/graphics/vulkan-impl/vulkan-fence-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer-impl.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-memory.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-program.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-pass.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-target.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-shader.h>
#include <dali/internal/window-system/common/window-render-surface.h>
#if defined(DEBUG_ENABLED)
UniquePtr<Graphics::Program> VulkanGraphicsController::CreateProgram(const Graphics::ProgramCreateInfo& programCreateInfo, UniquePtr<Graphics::Program>&& oldProgram)
{
- return UniquePtr<Graphics::Program>{};
+ return NewObject<Vulkan::Program>(programCreateInfo, *this, std::move(oldProgram));
}
UniquePtr<Graphics::Shader> VulkanGraphicsController::CreateShader(const Graphics::ShaderCreateInfo& shaderCreateInfo, UniquePtr<Graphics::Shader>&& oldShader)
{
- return UniquePtr<Graphics::Shader>{};
+ return NewObject<Vulkan::Shader>(shaderCreateInfo, *this, std::move(oldShader));
}
UniquePtr<Graphics::Sampler> VulkanGraphicsController::CreateSampler(const Graphics::SamplerCreateInfo& samplerCreateInfo, UniquePtr<Graphics::Sampler>&& oldSampler)
return TextureProperties{};
}
-const Reflection& VulkanGraphicsController::GetProgramReflection(const Graphics::Program& program)
+const Graphics::Reflection& VulkanGraphicsController::GetProgramReflection(const Graphics::Program& program)
{
- return *(reinterpret_cast<Reflection*>(0));
+ return *(reinterpret_cast<Graphics::Reflection*>(0));
}
bool VulkanGraphicsController::PipelineEquals(const Graphics::Pipeline& pipeline0, const Graphics::Pipeline& pipeline1) const
// @todo Add discard queues
}
+void VulkanGraphicsController::DiscardResource(Vulkan::Program* program)
+{
+ // @todo Add discard queues
+}
+
Vulkan::Device& VulkanGraphicsController::GetGraphicsDevice()
{
return *mImpl->mGraphicsDevice;
#include <dali/integration-api/debug.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-framebuffer.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-program.h>
#include <dali/internal/graphics/vulkan-impl/vulkan-render-target.h>
namespace Dali
void Add(Vulkan::RenderTarget* renderTarget);
void DiscardResource(Vulkan::RenderTarget* renderTarget);
void DiscardResource(Vulkan::Buffer* buffer);
+ void DiscardResource(Vulkan::Program* renderProgram);
public: // Integration::GraphicsConfig
bool IsBlendEquationSupported(DevelBlendEquation::Type blendEquation) override;
--- /dev/null
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/vulkan-impl/vulkan-program-impl.h>
+
+// INTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+#include <dali/internal/graphics/common/shader-parser.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-shader-impl.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-shader.h>
+
+// EXTERNAL HEADERS
+#include <iostream>
+
+#if defined(DEBUG_ENABLED)
+extern Debug::Filter* gGraphicsProgramLogFilter;
+#endif
+
+namespace Dali::Graphics::Vulkan
+{
+struct ProgramImpl::Impl
+{
+ explicit Impl(VulkanGraphicsController& _controller, const ProgramCreateInfo& info)
+ : controller(_controller)
+ {
+ createInfo = info;
+ if(info.shaderState)
+ {
+ createInfo.shaderState = new std::vector<ShaderState>(*info.shaderState);
+ }
+
+ // Create new reference of std::string_view.
+ name = std::string(info.name);
+ createInfo.name = name;
+ }
+
+ ~Impl()
+ {
+ delete createInfo.shaderState;
+ }
+
+ VulkanGraphicsController& controller;
+ ProgramCreateInfo createInfo;
+ std::string name;
+ uint32_t refCount{0u};
+};
+
+ProgramImpl::ProgramImpl(const Graphics::ProgramCreateInfo& createInfo, VulkanGraphicsController& controller)
+{
+ // Create implementation
+ mImpl = std::make_unique<Impl>(controller, createInfo);
+
+ // Preprocess source code, if successful, compile shaders
+ bool success = true;
+ if(Preprocess())
+ {
+ for(const auto& state : *createInfo.shaderState)
+ {
+ auto shader = static_cast<const Vulkan::Shader*>(state.shader);
+ auto shaderImpl = shader->GetImplementation();
+ if(!shaderImpl->Compile())
+ {
+ DALI_LOG_ERROR("SPIRV Compilation failed!\n");
+ }
+ }
+ }
+}
+
+ProgramImpl::~ProgramImpl() = default;
+
+bool ProgramImpl::Destroy()
+{
+ return false;
+}
+
+bool ProgramImpl::Preprocess()
+{
+ // For now only Vertex and Fragment shader stages supported
+ // and one per stage
+ std::string vertexString;
+ std::string fragmentString;
+ std::string* currentString = nullptr;
+
+ const Vulkan::Shader* vsh = nullptr;
+ const Vulkan::Shader* fsh = nullptr;
+
+ const auto& info = mImpl->createInfo;
+
+ for(const auto& state : *info.shaderState)
+ {
+ const auto* shader = static_cast<const Vulkan::Shader*>(state.shader);
+ if(state.pipelineStage == PipelineStage::VERTEX_SHADER)
+ {
+ // Only TEXT source mode can be processed
+ currentString = &vertexString;
+ vsh = shader;
+ }
+ else if(state.pipelineStage == PipelineStage::FRAGMENT_SHADER)
+ {
+ // Only TEXT source mode can be processed
+ currentString = &fragmentString;
+ fsh = shader;
+ }
+ else
+ {
+ // no valid stream to push
+ currentString = nullptr;
+ DALI_LOG_ERROR("Shader state contains invalid shader source (most likely binary)! Can't process!");
+ }
+
+ // Check if stream valid
+ if(currentString && currentString->empty() && shader->GetCreateInfo().sourceMode == ShaderSourceMode::TEXT)
+ {
+ *currentString = std::string(reinterpret_cast<const char*>(shader->GetCreateInfo().sourceData),
+ shader->GetCreateInfo().sourceSize);
+ }
+ else
+ {
+ DALI_LOG_ERROR("Preprocessing of binary shaders isn't allowed!");
+ }
+ }
+
+ // if we have both streams ready
+ if(!vertexString.empty() && !fragmentString.empty())
+ {
+ // In case we have one modern shader and one legacy counterpart we need to enforce
+ // output language.
+ Internal::ShaderParser::ShaderParserInfo parseInfo{};
+ parseInfo.vertexShaderCode = &vertexString;
+ parseInfo.fragmentShaderCode = &fragmentString;
+ parseInfo.vertexShaderLegacyVersion = vsh->GetGLSLVersion();
+ parseInfo.fragmentShaderLegacyVersion = fsh->GetGLSLVersion();
+ parseInfo.language = Internal::ShaderParser::OutputLanguage::SPIRV_GLSL;
+ parseInfo.outputVersion = std::max(vsh->GetGLSLVersion(), fsh->GetGLSLVersion());
+
+ std::vector<std::string> newShaders;
+
+ Internal::ShaderParser::Parse(parseInfo, newShaders);
+
+ // substitute shader code
+ vsh->GetImplementation()->SetPreprocessedCode(newShaders[0].data(), newShaders[0].size());
+ fsh->GetImplementation()->SetPreprocessedCode(newShaders[1].data(), newShaders[1].size());
+ return true;
+ }
+ else
+ {
+ DALI_LOG_ERROR("Preprocessing shader code failed!");
+ return false;
+ }
+}
+
+bool ProgramImpl::Create()
+{
+ // TODO: redirect to the reflection builder
+ return true;
+}
+
+uint32_t ProgramImpl::GetSPIRVProgram() const
+{
+ return {};
+}
+
+uint32_t ProgramImpl::Retain()
+{
+ return ++mImpl->refCount;
+}
+
+uint32_t ProgramImpl::Release()
+{
+ return --mImpl->refCount;
+}
+
+uint32_t ProgramImpl::GetRefCount() const
+{
+ return mImpl->refCount;
+}
+
+bool ProgramImpl::GetParameter(uint32_t parameterId, void* out)
+{
+ return false;
+}
+
+VulkanGraphicsController& ProgramImpl::GetController() const
+{
+ return mImpl->controller;
+}
+
+const ProgramCreateInfo& ProgramImpl::GetCreateInfo() const
+{
+ return mImpl->createInfo;
+}
+
+}; // namespace Dali::Graphics::Vulkan
--- /dev/null
+#ifndef DALI_GRAPHICS_VULKAN_PROGRAM_IMPL_H
+#define DALI_GRAPHICS_VULKAN_PROGRAM_IMPL_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-program-create-info.h>
+#include <dali/graphics-api/graphics-program.h>
+
+// INTERNAL INCLUDES
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h>
+
+namespace Dali::Graphics::Vulkan
+{
+/**
+ * @brief Program implementation
+ *
+ * Program implementation is owned only by the PipelineCache
+ *
+ * Like pipeline, it's created and managed by the PipelineCache
+ */
+class ProgramImpl
+{
+public:
+ /**
+ * @brief Constructor
+ *
+ * @param[in] createInfo Valid create info structure
+ * @param[in] controller Valid reference to the controller object
+ */
+ ProgramImpl(const Graphics::ProgramCreateInfo& createInfo, VulkanGraphicsController& controller);
+
+ /**
+ * @brief Destructor
+ */
+ ~ProgramImpl();
+
+ /**
+ * @brief Destroys Vulkan resources associated with the Program
+ *
+ * @return True on success
+ */
+ bool Destroy();
+
+ /**
+ * @brief Creates Vulkan resource for this Program
+ *
+ * @return True on success
+ */
+ bool Create();
+
+ /**
+ * @brief Preprocesses shaders
+ */
+ bool Preprocess();
+
+ /**
+ * @brief Returns Graphics program id
+ *
+ * Since Vulkan has no concept of Program, the Graphics resource
+ * should be returned.
+ *
+ * @return Graphics program id
+ */
+ [[nodiscard]] uint32_t GetSPIRVProgram() const;
+
+ /**
+ * @brief Increases ref count
+ *
+ * @return new refcount
+ */
+ uint32_t Retain();
+
+ /**
+ * @brief Decreases ref count
+ *
+ * @return New refcount
+ */
+ uint32_t Release();
+
+ /**
+ * @brief Retrieves ref count
+ * @return Refcount value
+ */
+ [[nodiscard]] uint32_t GetRefCount() const;
+
+ /**
+ * @brief Returns controller
+ *
+ * @return Valid Controller object
+ */
+ [[nodiscard]] VulkanGraphicsController& GetController() const;
+
+ /**
+ * @brief Returns create info structure
+ *
+ * @return Reference to valid create info structure
+ */
+ [[nodiscard]] const ProgramCreateInfo& GetCreateInfo() const;
+
+ /**
+ * @brief Returns parameter value specified by parameterId
+ *
+ * This function can be used as a backdoor into the implementation
+ * used to retrieve internal data.
+ *
+ * @param[in] parameterId Integer parameter id
+ * @param[out] out Pointer to write to
+ *
+ * @return True on success
+ */
+ bool GetParameter(uint32_t parameterId, void* out);
+
+private:
+ friend class Program;
+
+ struct Impl;
+ std::unique_ptr<Impl> mImpl; // TODO: see if we need it (PipelineCache related)
+};
+
+} // namespace Dali::Graphics::Vulkan
+
+#endif //DALI_GRAPHICS_VULKAN_PROGRAM_IMPL_H
--- /dev/null
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/vulkan-impl/vulkan-program.h>
+
+// INTERNAL HEADERS
+#include <dali/integration-api/debug.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-program-impl.h>
+
+// EXTERNAL HEADERS
+#include <iostream>
+
+#if defined(DEBUG_ENABLED)
+Debug::Filter* gGraphicsProgramLogFilter = Debug::Filter::New(Debug::NoLogging, false, "LOG_GRAPHICS_PROGRAM");
+#endif
+
+namespace Dali::Graphics::Vulkan
+{
+Program::Program(const Graphics::ProgramCreateInfo& createInfo, VulkanGraphicsController& controller)
+{
+ mProgram = new ProgramImpl(createInfo, controller);
+}
+
+Program::~Program()
+{
+ // Destroy Vulkan resources of implementation. This should happen
+ // only if there's no more pipelines using this program so
+ // it is safe to do it in the destructor
+ // TODO: implement it via cache!
+ if(!mProgram->Release())
+ {
+ mProgram->Destroy();
+ delete mProgram;
+ }
+}
+
+const Vulkan::Reflection& Program::GetReflection() const
+{
+ // TODO: Implement reflection
+ return *reinterpret_cast<Vulkan::Reflection*>(0u);
+}
+
+VulkanGraphicsController& Program::GetController() const
+{
+ return GetImplementation()->GetController();
+}
+
+const ProgramCreateInfo& Program::GetCreateInfo() const
+{
+ return GetImplementation()->GetCreateInfo();
+}
+
+void Program::DiscardResource()
+{
+ GetController().DiscardResource(this);
+}
+
+}; // namespace Dali::Graphics::Vulkan
--- /dev/null
+#ifndef DALI_GRAPHICS_VULKAN_PROGRAM_H
+#define DALI_GRAPHICS_VULKAN_PROGRAM_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// CLASS HEADER
+#include <dali/graphics-api/graphics-program.h>
+
+// INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-program-create-info.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h>
+
+namespace Dali::Graphics::Vulkan
+{
+class Reflection;
+class ProgramImpl;
+/**
+ * @brief Wrapper for the program implementation
+ *
+ * This object is returned back to the client-side
+ *
+ * Vulkan has no concept of Program. The Vulkan program
+ * within Graphics API is a set of shader stages linked together
+ * so the reflection can do its work on it.
+ */
+class Program : public Graphics::Program
+{
+public:
+ /**
+ * @brief Constructor
+ *
+ * @param[in] impl Pointer to valid implementation
+ */
+ explicit Program(ProgramImpl* impl)
+ {
+ // TODO: needs PipelineCache
+ }
+
+ Program(const Graphics::ProgramCreateInfo& createInfo, VulkanGraphicsController& controller);
+
+ /**
+ * @brief Destructor
+ */
+ ~Program() override;
+
+ /**
+ * @brief Returns reference to the Reflection object
+
+ * @return Reflection
+ */
+ [[nodiscard]] const Vulkan::Reflection& GetReflection() const;
+
+ /**
+ * @brief Retrieves internal program implementation
+ *
+ * @return Valid pointer to the ProgramImpl object
+ */
+ [[nodiscard]] ProgramImpl* GetImplementation() const
+ {
+ return mProgram;
+ }
+
+ /**
+ * @brief Returns controller
+ *
+ * @return controller
+ */
+ [[nodiscard]] VulkanGraphicsController& GetController() const;
+
+ /**
+ * @brief Returns create info structure
+ *
+ * @return create info structure
+ */
+ [[nodiscard]] const ProgramCreateInfo& GetCreateInfo() const;
+
+ bool operator==(const Vulkan::Program& program) const
+ {
+ return (program.mProgram == mProgram);
+ }
+
+ bool operator==(const Vulkan::ProgramImpl* programImpl) const
+ {
+ return (programImpl == mProgram);
+ }
+
+ bool operator!=(const Vulkan::Program& program) const
+ {
+ return (program.mProgram != mProgram);
+ }
+
+ /**
+ * @brief Run by UniquePtr to discard resource
+ */
+ void DiscardResource();
+
+ /**
+ * @brief Destroying 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
+ }
+
+ bool TryRecycle(const Graphics::ProgramCreateInfo& createInfo, VulkanGraphicsController& controller)
+ {
+ return false;
+ }
+
+private:
+ ProgramImpl* mProgram{nullptr};
+};
+} // namespace Dali::Graphics::Vulkan
+
+#endif //DALI_GRAPHICS_VULKAN_PROGRAM_H
--- /dev/null
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include <dali/internal/graphics/vulkan-impl/vulkan-shader-impl.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-controller.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-spirv.h>
+#include <dali/internal/graphics/vulkan/vulkan-device.h>
+
+namespace Dali::Graphics::Vulkan
+{
+struct ShaderImpl::Impl
+{
+ explicit Impl(Graphics::Vulkan::VulkanGraphicsController& _controller, const Graphics::ShaderCreateInfo& _createInfo)
+ : controller(_controller)
+ {
+ createInfo.pipelineStage = _createInfo.pipelineStage;
+ createInfo.shaderlanguage = _createInfo.shaderlanguage;
+ createInfo.sourceMode = _createInfo.sourceMode;
+ createInfo.shaderVersion = _createInfo.shaderVersion;
+
+ if(createInfo.sourceMode == ShaderSourceMode::TEXT)
+ {
+ if(createInfo.shaderVersion > 0)
+ {
+ // Make a copy of source code. if code is meant to be used
+ // by modern parser, skip the prefix part
+ size_t dataStartIndex = 0;
+ size_t dataSize;
+
+ ShaderImpl::StripLegacyCodeIfNeeded(_createInfo, dataStartIndex, glslVersion, dataSize);
+
+ source.resize(dataSize);
+ std::copy(reinterpret_cast<const uint8_t*>(_createInfo.sourceData) + dataStartIndex,
+ reinterpret_cast<const uint8_t*>(_createInfo.sourceData) + dataStartIndex + dataSize,
+ source.data());
+
+ // Substitute pointer
+ createInfo.sourceData = source.data();
+ createInfo.sourceSize = dataSize;
+ }
+ }
+ else // if binary format, we expect ready to use SPIRV shader module
+ {
+ // Make a copy of spirv data
+ source.resize(_createInfo.sourceSize);
+ std::copy(reinterpret_cast<const uint8_t*>(_createInfo.sourceData),
+ reinterpret_cast<const uint8_t*>(_createInfo.sourceData) + _createInfo.sourceSize,
+ source.data());
+ createInfo.sourceData = source.data();
+ createInfo.sourceSize = _createInfo.sourceSize;
+ }
+ }
+
+ ~Impl() = default;
+
+ bool Compile()
+ {
+ bool success = true;
+ if(createInfo.sourceMode == ShaderSourceMode::TEXT)
+ {
+ SPIRVGeneratorInfo info;
+ info.pipelineStage = createInfo.pipelineStage;
+ auto shaderCode = std::string_view(reinterpret_cast<char*>(sourcePreprocessed.data()));
+ info.shaderCode = shaderCode;
+
+ spirv = std::make_unique<SPIRVGenerator>(info);
+
+ spirv->Generate();
+ if(spirv->IsValid())
+ {
+ // substitute data and size with compiled code
+ createInfo.sourceSize = spirv->Get().size() * 4u;
+ createInfo.sourceData = spirv->Get().data();
+ }
+ else
+ {
+ success = false;
+ }
+ }
+ if(!success)
+ {
+ return false;
+ }
+
+ // Create Vulkan shader module
+ auto& gfxDevice = controller.GetGraphicsDevice();
+ auto vkDevice = gfxDevice.GetLogicalDevice();
+ vk::ShaderModuleCreateInfo info;
+ info.pCode = reinterpret_cast<const uint32_t*>(createInfo.sourceData);
+ info.codeSize = size_t(createInfo.sourceSize);
+ VkAssert(vkDevice.createShaderModule(&info, &gfxDevice.GetAllocator(), &shaderModule));
+
+ return true;
+ }
+
+ void Destroy()
+ {
+ auto vkDevice = controller.GetGraphicsDevice().GetLogicalDevice();
+ vkDevice.destroyShaderModule(shaderModule, controller.GetGraphicsDevice().GetAllocator());
+ }
+
+ void SetPreprocessedCode(void* data, uint32_t size)
+ {
+ sourcePreprocessed.resize(size);
+
+ std::copy(reinterpret_cast<const uint8_t*>(data),
+ reinterpret_cast<const uint8_t*>(data) + size,
+ sourcePreprocessed.data());
+ }
+
+ VulkanGraphicsController& controller;
+ ShaderCreateInfo createInfo;
+ std::vector<uint8_t> source{};
+ std::vector<uint8_t> sourcePreprocessed{};
+ std::unique_ptr<SPIRVGenerator> spirv;
+ vk::ShaderModule shaderModule;
+
+ uint32_t refCount{0u};
+ uint32_t flushCount{0u}; ///< Number of frames at refCount=0
+ uint32_t glslVersion{0u}; ///< 0 - unknown, otherwise valid #version like 130, 300, etc.
+};
+
+ShaderImpl::ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::Vulkan::VulkanGraphicsController& controller)
+{
+ mImpl = std::make_unique<Impl>(controller, createInfo);
+}
+
+ShaderImpl::~ShaderImpl() = default;
+
+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;
+}
+
+[[nodiscard]] uint32_t ShaderImpl::GetGLSLVersion() const
+{
+ return mImpl->glslVersion;
+}
+
+/**
+ * @brief Compiles shader
+ *
+ * @return True on success
+ */
+[[nodiscard]] bool ShaderImpl::Compile() const
+{
+ return mImpl->Compile();
+}
+
+[[nodiscard]] vk::ShaderModule ShaderImpl::GetVkShaderModule() const
+{
+ return mImpl->shaderModule;
+}
+
+const ShaderCreateInfo& ShaderImpl::GetCreateInfo() const
+{
+ return mImpl->createInfo;
+}
+
+[[nodiscard]] VulkanGraphicsController& ShaderImpl::GetController() const
+{
+ return mImpl->controller;
+}
+
+void ShaderImpl::StripLegacyCodeIfNeeded(const ShaderCreateInfo& info, size_t& startIndex, uint32_t& glslVersion, size_t& finalDataSize)
+{
+ // Make a copy of source code. if code is meant to be used
+ // by modern parser, skip the prefix part
+ auto text = reinterpret_cast<const char*>(info.sourceData);
+ auto result = std::string_view(text).find("//@legacy-prefix-end");
+ glslVersion = 0u;
+ if(info.shaderVersion != 0)
+ {
+ if(result != 0 && result != std::string::npos)
+ {
+ DALI_LOG_ERROR("Shader processing: @legacy-prefix-end must be a very first statement!\n");
+ }
+ else if(result == 0)
+ {
+ char* end;
+ startIndex = std::strtoul(reinterpret_cast<const char*>(info.sourceData) + 21, &end, 10);
+ }
+ }
+ else
+ {
+ // For legacy shaders we need to make sure that the #version is a very first line
+ // so need to strip //@legacy-prefix-end tag
+ auto versionPos = std::string_view(text).find("#version", 0);
+ if(versionPos == std::string::npos)
+ {
+ startIndex = 0; // not trimming anything
+
+ // if there's no version yet it's a legacy shader we assign 100
+ glslVersion = 100;
+ }
+ else
+ {
+ // save version of legacy shader
+ char* end;
+ glslVersion = uint32_t(std::strtol(std::string_view(text).data() + versionPos + 9, &end, 10));
+ startIndex = versionPos;
+ }
+ }
+ finalDataSize = info.sourceSize - startIndex;
+}
+
+void ShaderImpl::SetPreprocessedCode(void* data, uint32_t size)
+{
+ mImpl->SetPreprocessedCode(data, size);
+}
+
+} // namespace Dali::Graphics::Vulkan
--- /dev/null
+#ifndef DALI_GRAPHICS_VULKAN_SHADER_IMPL_H
+#define DALI_GRAPHICS_VULKAN_SHADER_IMPL_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-shader-create-info.h>
+#include <dali/graphics-api/graphics-shader.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h>
+
+// EXTERNAL INCLUDES
+#include <vulkan/vulkan.hpp>
+
+namespace Dali::Graphics::Vulkan
+{
+class ShaderImpl
+{
+public:
+ /**
+ * @brief Constructor
+ * @param[in] createInfo Valid createInfo structure
+ * @param[in] controller Reference to the controller
+ */
+ ShaderImpl(const Graphics::ShaderCreateInfo& createInfo, Graphics::Vulkan::VulkanGraphicsController& controller);
+
+ /**
+ * @brief destructor
+ */
+ ~ShaderImpl();
+
+ /**
+ * @brief Increases ref count
+ * @return ref count after increment
+ */
+ uint32_t Retain();
+
+ /**
+ * @brief Decreases refcount
+ * @return ref count after decrement
+ */
+ uint32_t Release();
+
+ /**
+ * @brief returns current ref count
+ * @return current ref count
+ */
+ [[nodiscard]] uint32_t GetRefCount() const;
+
+ /**
+ * Whilst unreferenced, increase the flush count and return it
+ *
+ * @return The new flush count
+ */
+ [[nodiscard]] uint32_t IncreaseFlushCount();
+
+ /**
+ * Get the flush count whilst unreferenced
+ *
+ * @return the flush count
+ */
+ [[nodiscard]] uint32_t GetFlushCount() const;
+
+ /**
+ * @brief Compiles shader
+ *
+ * @return True on success
+ */
+ [[nodiscard]] bool Compile() const;
+
+ /**
+ * @brief Destroys Vulkan shader module
+ */
+ void Destroy();
+
+ /**
+ * @brief Returns Vulkan resource
+ * @return Valid Vulkan shader resource
+ */
+ vk::ShaderModule GetVkShaderModule() const;
+
+ /**
+ * @brief Returns create info structure
+ * @return Returns valid create info structure
+ */
+ [[nodiscard]] const ShaderCreateInfo& GetCreateInfo() const;
+
+ /**
+ * @brief Returns reference to the graphics controller
+ * @return Valid reference to the graphics controller
+ */
+ [[nodiscard]] VulkanGraphicsController& GetController() const;
+
+ /**
+ * Strips legacy prefix from the GLSL source code if necessary
+ * @param info valid ShaderCreateInfo structure
+ * @param[out] startIndex Start index of the source code
+ * @param[out] glslVersion Detected GLSL version of legacy shader
+ * @param[out] finalDataSize Size of trimmed data
+ */
+ static void StripLegacyCodeIfNeeded(const ShaderCreateInfo& info, size_t& startIndex, uint32_t& glslVersion, size_t& finalDataSize);
+
+ /**
+ * @brief Sets preprocess code
+ * @param[in] data Valid pointer to the new source code
+ * @param[in] size Size of the source code
+ */
+ void SetPreprocessedCode(void* data, uint32_t size);
+
+ /**
+ * @brief Returns GLSL version
+ * @return Returns valid GLSL version or 0 if undefined
+ */
+ [[nodiscard]] uint32_t GetGLSLVersion() const;
+
+private:
+ friend class Shader;
+ struct Impl;
+ std::unique_ptr<Impl> mImpl{nullptr}; // TODO: see if we need it (PipelineCache related)
+};
+
+} // namespace Dali::Graphics::Vulkan
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// CLASS HEADER
+#include "vulkan-shader.h"
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+#include "vulkan-graphics-controller.h"
+#include "vulkan-shader-impl.h"
+
+namespace Dali::Graphics::Vulkan
+{
+Shader::Shader(ShaderImpl* impl)
+{
+ mShader = impl;
+ mShader->Retain(); // TODO: we may not need it at all
+}
+
+Shader::Shader(const Graphics::ShaderCreateInfo& createInfo, VulkanGraphicsController& controller)
+{
+ mShader = new ShaderImpl(createInfo, controller);
+}
+
+Shader::~Shader()
+{
+ if(!mShader->Release())
+ {
+ // TODO: handle pipeline cache
+ //GetImplementation()->GetController().GetPipelineCache().MarkShaderCacheFlushRequired();
+ }
+
+ // No cache, delete implementation
+ delete mShader;
+}
+
+bool Shader::TryRecycle(const Graphics::ShaderCreateInfo& createInfo, VulkanGraphicsController& controller)
+{
+ return false;
+}
+
+[[nodiscard]] const ShaderCreateInfo& Shader::GetCreateInfo() const
+{
+ return GetImplementation()->GetCreateInfo();
+}
+
+void Shader::DiscardResource()
+{
+}
+
+uint32_t Shader::GetGLSLVersion() const
+{
+ return GetImplementation()->GetGLSLVersion();
+}
+
+} // namespace Dali::Graphics::Vulkan
--- /dev/null
+#ifndef DALI_GRAPHICS_VULKAN_SHADER_H
+#define DALI_GRAPHICS_VULKAN_SHADER_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// INTERNAL INCLUDES
+#include <dali/graphics-api/graphics-shader-create-info.h>
+#include <dali/graphics-api/graphics-shader.h>
+#include <dali/internal/graphics/vulkan-impl/vulkan-graphics-resource.h>
+
+namespace Dali::Graphics::Vulkan
+{
+class ShaderImpl;
+class Shader : public Graphics::Shader
+{
+public:
+ /**
+ * @brief Constructor
+ *
+ * @param[in] impl Pointer to valid implementation
+ */
+ explicit Shader(ShaderImpl* impl); // TODO: this should be controlled by cache
+
+ Shader(const Graphics::ShaderCreateInfo& createInfo, VulkanGraphicsController& controller);
+
+ /**
+ * @brief Destructor
+ */
+ ~Shader() override;
+
+ [[nodiscard]] ShaderImpl* GetImplementation() const
+ {
+ return mShader;
+ }
+
+ [[nodiscard]] const ShaderCreateInfo& GetCreateInfo() const;
+
+ bool operator==(const Vulkan::Shader& shader) const
+ {
+ return (shader.mShader == mShader);
+ }
+
+ bool operator==(const Vulkan::ShaderImpl* shaderImpl) const
+ {
+ return (shaderImpl == mShader);
+ }
+
+ bool operator!=(const Vulkan::Shader& shader) const
+ {
+ return (shader.mShader != mShader);
+ }
+
+ /**
+ * @brief Called when UniquePtr<> on client-side dies.
+ */
+ void DiscardResource();
+
+ /**
+ * @brief Destroying Vulkan 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
+ }
+ bool TryRecycle(const Graphics::ShaderCreateInfo& createInfo, VulkanGraphicsController& controller);
+
+ [[nodiscard]] uint32_t GetGLSLVersion() const;
+
+private:
+ ShaderImpl* mShader{nullptr};
+};
+
+} // namespace Dali::Graphics::Vulkan
+
+#endif
--- /dev/null
+/*
+* Copyright (c) 2024 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.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*/
+
+// CLASS HEADER
+#include <dali/internal/graphics/vulkan-impl/vulkan-spirv.h>
+
+// INTERNAL INCLUDES
+#include <dali/integration-api/debug.h>
+
+// EXTERNAL EXCLUDES
+#include <utility>
+
+namespace Dali::Graphics::Vulkan
+{
+struct SPIRVGeneratorExtraInfo
+{
+ glslang_stage_t stage;
+ bool valid;
+};
+
+SPIRVGenerator::SPIRVGenerator(Dali::Graphics::Vulkan::SPIRVGeneratorInfo generatorInfo)
+{
+ mGeneratorInfo = std::move(generatorInfo);
+
+ // Using new to inject internal data visible only within implementation
+ mGeneratorInfo.extraInfo = new SPIRVGeneratorExtraInfo;
+
+ mGeneratorInfo.extraInfo->valid = true;
+
+ switch(mGeneratorInfo.pipelineStage)
+ {
+ case PipelineStage::VERTEX_SHADER:
+ {
+ mGeneratorInfo.extraInfo->stage = GLSLANG_STAGE_VERTEX;
+ break;
+ }
+ case PipelineStage::FRAGMENT_SHADER:
+ {
+ mGeneratorInfo.extraInfo->stage = GLSLANG_STAGE_FRAGMENT;
+ break;
+ }
+ default:
+ {
+ DALI_LOG_ERROR("SPIRVGenerator: Unsupported stage used!\n");
+ mGeneratorInfo.extraInfo->valid = false;
+ return;
+ }
+ }
+}
+
+SPIRVGenerator::~SPIRVGenerator()
+{
+ delete mGeneratorInfo.extraInfo;
+}
+
+glslang_shader_t* SPIRVGenerator::CompileSource(glslang_stage_t stage, std::string shaderSource)
+{
+ const char* cstr = shaderSource.c_str();
+ const glslang_input_t input = {
+ .language = GLSLANG_SOURCE_GLSL,
+ .stage = stage,
+ .client = GLSLANG_CLIENT_VULKAN,
+ .client_version = GLSLANG_TARGET_VULKAN_1_2,
+ .target_language = GLSLANG_TARGET_SPV,
+ .target_language_version = GLSLANG_TARGET_SPV_1_5,
+ .code = cstr,
+ .default_version = 100,
+ .default_profile = GLSLANG_NO_PROFILE,
+ .force_default_version_and_profile = false,
+ .forward_compatible = false,
+ .messages = GLSLANG_MSG_DEFAULT_BIT,
+ .resource = glslang_default_resource(),
+ };
+
+ glslang_shader_t* shader = glslang_shader_create(&input);
+
+ if(!glslang_shader_preprocess(shader, &input))
+ {
+ DALI_LOG_ERROR("%s\n", glslang_shader_get_info_log(shader));
+ DALI_LOG_ERROR("%s\n", glslang_shader_get_info_debug_log(shader));
+ DALI_LOG_ERROR("%s\n", input.code);
+ glslang_shader_delete(shader);
+ return nullptr;
+ }
+
+ if(!glslang_shader_parse(shader, &input))
+ {
+ DALI_LOG_ERROR("%s\n", glslang_shader_get_info_log(shader));
+ DALI_LOG_ERROR("%s\n", glslang_shader_get_info_debug_log(shader));
+ DALI_LOG_ERROR("%s\n", glslang_shader_get_preprocessed_code(shader));
+ glslang_shader_delete(shader);
+ return nullptr;
+ }
+
+ return shader;
+}
+
+void SPIRVGenerator::Generate()
+{
+ glslang_initialize_process();
+ auto stage = mGeneratorInfo.extraInfo->stage;
+ auto* shader = CompileSource(stage, mGeneratorInfo.shaderCode);
+
+ if(!shader)
+ {
+ return;
+ }
+
+ glslang_program_t* program = glslang_program_create();
+ glslang_program_add_shader(program, shader);
+
+ if(!glslang_program_link(program, GLSLANG_MSG_SPV_RULES_BIT | GLSLANG_MSG_VULKAN_RULES_BIT))
+ {
+ DALI_LOG_ERROR("%s\n", glslang_program_get_info_log(program));
+ DALI_LOG_ERROR("%s\n", glslang_program_get_info_debug_log(program));
+ glslang_program_delete(program);
+ return;
+ }
+
+ glslang_program_SPIRV_generate(program, stage);
+
+ auto size = glslang_program_SPIRV_get_size(program);
+ mBinary.resize(size);
+ glslang_program_SPIRV_get(program, mBinary.data());
+
+ const char* spirv_messages = glslang_program_SPIRV_get_messages(program);
+ if(spirv_messages)
+ DALI_LOG_ERROR("%s\b", spirv_messages);
+
+ glslang_program_delete(program);
+ glslang_finalize_process();
+}
+
+bool SPIRVGenerator::IsValid() const
+{
+ return mGeneratorInfo.extraInfo->valid;
+}
+
+const std::vector<uint32_t>& SPIRVGenerator::Get()
+{
+ if(!mGeneratorInfo.extraInfo->valid)
+ {
+ mBinary.clear(); // return 0-size array
+ }
+
+ return mBinary;
+}
+
+} // namespace Dali::Graphics::Vulkan
\ No newline at end of file
--- /dev/null
+#ifndef DALI_GRAPHICS_VULKAN_SPIRV_H
+#define DALI_GRAPHICS_VULKAN_SPIRV_H
+
+/*
+ * Copyright (c) 2024 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <dali/graphics-api/graphics-shader-create-info.h>
+#include <dali/graphics-api/graphics-shader.h>
+
+// INTERNAL INCLUDES
+#include <vector>
+#include "vulkan-graphics-resource.h"
+
+// EXTERNAL INCLUDES
+#include <glslang/Include/glslang_c_interface.h>
+#include <glslang/Public/resource_limits_c.h>
+
+namespace Dali::Graphics::Vulkan
+{
+class ShaderImpl;
+
+/**
+ * Info structure for generating SPIRV bytecode
+ */
+struct SPIRVGeneratorInfo
+{
+ std::string shaderCode;
+ PipelineStage pipelineStage;
+
+ struct SPIRVGeneratorExtraInfo* extraInfo; ///< Reserved
+};
+
+/**
+ * Class generates SPIRV from GLSL
+ */
+class SPIRVGenerator
+{
+public:
+ /**
+ * @brief Constructor
+ * @param[in] generatorInfo valid SPIRVGeneratorInfo structure
+ */
+ explicit SPIRVGenerator(SPIRVGeneratorInfo generatorInfo);
+
+ /**
+ * @brief Destructor
+ */
+ ~SPIRVGenerator();
+
+ /**
+ * @brief Triggers compilation to SPIRV
+ */
+ void Generate();
+
+ /**
+ * @brief Checks whether generator is valid
+ * @return False if invalid
+ */
+ [[nodiscard]] bool IsValid() const;
+
+ /**
+ * @brief Returns SPIRV buffer
+ * @return Array of 32-bit words
+ */
+ const std::vector<uint32_t>& Get();
+
+private:
+ /**
+ * Compiles GLSL source to SPIRV
+ */
+ glslang_shader_t* CompileSource(glslang_stage_t stage, std::string shaderSource);
+
+ std::vector<uint32_t> mBinary;
+ SPIRVGeneratorInfo mGeneratorInfo;
+};
+
+} // namespace Dali::Graphics::Vulkan
+#endif //DALI_GRAPHICS_VULKAN_SPIRV_H
\ No newline at end of file