[WIP] Shader handling rework

This commit is contained in:
2023-08-29 23:08:11 +02:00
parent 5735b93870
commit 5aec41ead4
13 changed files with 181 additions and 79 deletions

View File

@@ -0,0 +1,57 @@
/*
* 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 "ShaderProgramType.hpp"
namespace openVulkanoCpp
{
struct DescriptorSetLayoutBinding
{
enum Type : uint32_t {
TYPE_SAMPLER = 0,
TYPE_COMBINED_IMAGE_SAMPLER = 1,
TYPE_SAMPLED_IMAGE = 2,
TYPE_STORAGE_IMAGE = 3,
TYPE_UNIFORM_TEXEL_BUFFER = 4,
TYPE_STORAGE_TEXEL_BUFFER = 5,
TYPE_UNIFORM_BUFFER = 6,
TYPE_STORAGE_BUFFER = 7,
TYPE_UNIFORM_BUFFER_DYNAMIC = 8,
TYPE_STORAGE_BUFFER_DYNAMIC = 9,
TYPE_INPUT_ATTACHMENT = 10,
TYPE_INLINE_UNIFORM_BLOCK = 1000138000,
TYPE_ACCELERATION_STRUCTURE_KHR = 1000150000,
TYPE_ACCELERATION_STRUCTURE_NV = 1000165000,
TYPE_SAMPLE_WEIGHT_IMAGE_QCOM = 1000440000,
TYPE_BLOCK_MATCH_IMAGE_QCOM = 1000440001,
TYPE_MUTABLE_VALVE = 1000351000
};
uint32_t bindingId;
Type descriptorType;
uint32_t descriptorCount;
ShaderProgramType::Type stageFlags;
void* immutableSamplers;
DescriptorSetLayoutBinding()
: DescriptorSetLayoutBinding(Type::TYPE_UNIFORM_BUFFER_DYNAMIC, 1, ShaderProgramType::Type::VERTEX)
{}
DescriptorSetLayoutBinding(Type descriptorType, uint32_t descriptorCount,
ShaderProgramType::Type stageFlags, void* immutableSamplers = nullptr)
: bindingId(0), descriptorType(descriptorType)
, descriptorCount(descriptorCount), stageFlags(stageFlags)
, immutableSamplers(immutableSamplers)
{}
DescriptorSetLayoutBinding(uint32_t id, const DescriptorSetLayoutBinding& layout)
: bindingId(id), descriptorType(layout.descriptorType), descriptorCount(layout.descriptorCount)
, stageFlags(layout.stageFlags), immutableSamplers(layout.immutableSamplers)
{}
};
}

View File

@@ -0,0 +1,156 @@
/*
* 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 <string>
#include <stdexcept>
namespace openVulkanoCpp::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
};
struct ShaderProgram
{
ShaderProgramType type;
std::string name;
ShaderProgram(ShaderProgramType type, const std::string& name) : type(type), name(name) {}
ShaderProgram(const ShaderProgram& program) : type(program.type), name(program.name) {}
ShaderProgram(ShaderProgram&& program) : 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<ShaderProgram> shaderPrograms{};
std::vector<VertexInputDescription> vertexInputDescriptions{};
std::vector<DescriptorSetLayoutBinding> descriptorSetLayoutBindings{};
Topology topology = Topology::TRIANGLE_LIST;
CullMode cullMode = CullMode::BACK;
ICloseable* renderShader = nullptr;
bool alphaBlend = false; // TODO allow fine control over blending
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<typename ...ARGS>
Shader& AddShaderProgram(ARGS&&... args)
{
CheckShaderInitState();
shaderPrograms.emplace_back(std::forward<ARGS>(args)...);
return *this;
}
Shader& AddVertexInputDescription(const VertexInputDescription& inputDescription, int bindingId = -1)
{
CheckShaderInitState();
if (bindingId < 0) bindingId = static_cast<int>(vertexInputDescriptions.size());
while (bindingId > vertexInputDescriptions.size())
{
vertexInputDescriptions.emplace_back(0, 0);
}
if (bindingId == vertexInputDescriptions.size())
{
vertexInputDescriptions.emplace_back(bindingId, inputDescription);
}
else
{
vertexInputDescriptions[bindingId] = inputDescription;
}
return *this;
}
Shader& AddDescriptorSetLayoutBinding(const DescriptorSetLayoutBinding& binding, int bindingId = -1)
{
CheckShaderInitState();
if (bindingId < 0) bindingId = static_cast<int>(descriptorSetLayoutBindings.size());
while (bindingId > descriptorSetLayoutBindings.size())
{
descriptorSetLayoutBindings.emplace_back().bindingId = descriptorSetLayoutBindings.size() - 1;
}
if (bindingId == vertexInputDescriptions.size())
{
descriptorSetLayoutBindings.emplace_back(bindingId, binding);
}
else
{
descriptorSetLayoutBindings[bindingId] = binding;
descriptorSetLayoutBindings[bindingId].bindingId = bindingId;
}
return *this;
}
void Close() override
{
renderShader->Close();
renderShader = nullptr;
}
private:
void CheckShaderInitState() const
{
if (renderShader) throw std::runtime_error("Shader already initialized!");
}
};
}

View File

@@ -0,0 +1,76 @@
/*
* 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 <string_view>
#include <cinttypes>
namespace openVulkanoCpp
{
class ShaderProgramType
{
static constexpr std::string_view FILE_EXTENSIONS_OPENGL[] = {
".vert", ".tesc", ".tese", ".geom", ".frag", ".comp", ".mesh", ".task",
".rgen", ".rahit", ".rchit", ".rmiss", ".rint", ".rcall", ".glsl"
};
public:
enum Type : uint32_t {
VERTEX = 1,
TESSELLATION_CONTROL = 2,
TESSELLATION_EVALUATION = 4,
GEOMETRY = 8,
FRAGMENT = 16,
COMPUTE = 32,
// Mesh shader
MESH_TASK = 0x40,
MESH_MESH = 0x80,
// Raytracing
RAY_GEN = 0x100,
RAY_ANY_HIT = 0x200,
RAY_CLOSEST_HIT = 0x400,
RAY_MISS = 0x800,
RAY_INTERSECTION = 0x1000,
RAY_CALLABLE = 0x2000,
ALL_GRAPHICS = 0x0000001F
};
ShaderProgramType(Type type) : m_type(type) {}
[[nodiscard]] constexpr std::string_view GetExtensionOpenGL() const
{
return FILE_EXTENSIONS_OPENGL[GetId()];
}
[[nodiscard]] constexpr uint32_t GetId() const
{
if (m_type == ALL_GRAPHICS) return 14;
return Utils::Log2OfPow2(static_cast<uint32_t>(m_type));
}
[[nodiscard]] bool operator ==(Type rhs) const
{
return m_type == rhs;
}
[[nodiscard]] bool operator !=(Type rhs) const
{
return m_type != rhs;
}
[[nodiscard]] operator uint32_t() const
{
return m_type;
}
private:
Type m_type;
};
}

View File

@@ -0,0 +1,56 @@
/*
* 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 "../DataFormat.hpp"
#include <stdexcept>
#include <vector>
namespace openVulkanoCpp
{
struct VertexInputParameter
{
uint32_t location;
uint32_t binding;
DataFormat format;
uint32_t offset;
VertexInputParameter(uint32_t location, uint32_t binding, DataFormat format, uint32_t offset)
: location(location), binding(binding), format(format), offset(offset)
{}
VertexInputParameter(size_t location, uint32_t binding, DataFormat format, uint32_t offset)
: location(location), binding(binding), format(format), offset(offset)
{}
};
struct VertexInputDescription
{
uint32_t bindingId;
uint32_t vertexSize;
std::vector<VertexInputParameter> inputParameters;
VertexInputDescription(uint32_t bindingId, uint32_t vertexSize) : bindingId(bindingId), vertexSize(vertexSize)
{}
VertexInputDescription(uint32_t bindingId, const VertexInputDescription& vertexDescription)
: bindingId(bindingId), vertexSize(vertexDescription.vertexSize), inputParameters(vertexDescription.inputParameters)
{
for (auto& param : inputParameters)
{
param.binding = bindingId;
}
}
VertexInputDescription& AddInputParameter(DataFormat format, uint32_t offset)
{
if (offset >= vertexSize) throw std::runtime_error("VertexInputParameter offset cannot be greater than vertex size");
inputParameters.emplace_back(inputParameters.size(), bindingId, format, offset);
return *this;
}
};
}