/* * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #pragma once #include "Base/ICloseable.hpp" #include "Base/Utils.hpp" #include "VertexInputDescription.hpp" #include "ShaderProgramType.hpp" #include "DescriptorInputDescription.hpp" #include "PushConstant.hpp" #include #include namespace OpenVulkano::Scene { enum class CullMode : uint32_t { NONE = 0, FRONT, BACK, FRONT_AND_BACK }; enum class Topology : uint32_t { POINT_LIST = 0, LINE_LIST, LINE_STRIPE, TRIANGLE_LIST, TRIANGLE_STRIP, TRIANGLE_FAN, LINE_LIST_WITH_ADJACENCY, LINE_STRIP_WITH_ADJACENCY, TRIANGLE_LIST_WITH_ADJACENCY, TRIANGLE_STRIP_WITH_ADJACENCY, PATCH_LIST }; enum class CompareOp : uint32_t { NEVER = 0, LESS = 1, EQUAL = 2, LESS_OR_EQUAL = 3, GREATER = 4, NOT_EQUAL = 5, GREATER_OR_EQUAL = 6, ALWAYS = 7 }; struct ShaderProgram { ShaderProgramType type; std::string name; ShaderProgram(ShaderProgramType type, const std::string& name) : type(type), name(name) {} ShaderProgram(const ShaderProgram& program) = default; ShaderProgram(ShaderProgram&& program) noexcept : type(program.type), name(std::move(program.name)) {} [[nodiscard]] std::string GetShaderNameOpenGL() const { std::string oglName; std::string_view ext = type.GetExtensionOpenGL(); oglName.reserve(name.size() + ext.size()); return oglName.append(name).append(ext); } [[nodiscard]] std::string GetShaderNameVulkan() const { return GetShaderNameOpenGL() + ".spv"; } }; class Shader final : public ICloseable { public: std::vector shaderPrograms{}; std::vector vertexInputDescriptions{}; std::vector> descriptorSets; std::vector pushConstantRanges; Topology topology = Topology::TRIANGLE_LIST; CullMode cullMode = CullMode::BACK; ICloseable* renderShader = nullptr; CompareOp depthCompareOp = CompareOp::LESS; bool alphaBlend = false; // TODO allow fine control over blending bool depthTest = true; bool depthWrite = true; bool dynamicViewport = true; // If disabled the swapchains fullscreen viewport will always be used, regardless of framebuffer or viewport Shader() = default; ~Shader() override { /*if (renderShader) Shader::Close();*/ } Shader& AddShaderProgram(const ShaderProgram& shaderProgram) { CheckShaderInitState(); shaderPrograms.push_back(shaderProgram); return *this; } Shader& AddShaderProgram(ShaderProgram&& shaderProgram) { CheckShaderInitState(); shaderPrograms.push_back(std::move(shaderProgram)); return *this; } template Shader& AddShaderProgram(ARGS&&... args) { CheckShaderInitState(); shaderPrograms.emplace_back(std::forward(args)...); return *this; } #pragma clang diagnostic push #pragma ide diagnostic ignored "LoopDoesntUseConditionVariableInspection" Shader& AddVertexInputDescription(const VertexInputDescription& inputDescription, int bindingId = -1) { CheckShaderInitState(); if (bindingId < 0) bindingId = static_cast(vertexInputDescriptions.size()); while (bindingId > static_cast(vertexInputDescriptions.size())) { vertexInputDescriptions.emplace_back(0, 0); } if (bindingId == static_cast(vertexInputDescriptions.size())) { vertexInputDescriptions.emplace_back(bindingId, inputDescription); } else { vertexInputDescriptions[bindingId] = inputDescription; } return *this; } int AddDescriptorSetLayoutBinding(const DescriptorSetLayoutBinding& binding, int setId = -1) { CheckShaderInitState(); if (setId < 0) setId = static_cast(descriptorSets.size() + 2); if (setId < 2) throw std::runtime_error("Cant bind set id 0 or 1! They are used for node and camera!"); setId -= 2; while (setId >= static_cast(descriptorSets.size())) { descriptorSets.emplace_back(); } descriptorSets[setId].push_back(binding); return setId + 2; } #pragma clang diagnostic pop void AddPushConstantRange(const PushConstantRange& pushConstantRange) { pushConstantRanges.push_back(pushConstantRange); } void Close() override { renderShader->Close(); renderShader = nullptr; } private: void CheckShaderInitState() const { if (renderShader) throw std::runtime_error("Shader already initialized!"); } }; }