Skip to content

Commit

Permalink
feat: Add WebGPU pipeline and shader implementations
Browse files Browse the repository at this point in the history
Additionally some small maintenance changes were done such as:
- `psl::meta::library` to handle obvious error cases of missing files.
- Logging initializer now no longer returns a bool as there's no false return to begin with.
- Fixed an issue on windows when running clang-format on WSL
- Reading a file in debug no longer causes an assert to be hit as an empty return is a valid return for the function.
  • Loading branch information
JessyDL committed May 28, 2024
1 parent b1c8325 commit f37265f
Show file tree
Hide file tree
Showing 25 changed files with 631 additions and 79 deletions.
18 changes: 18 additions & 0 deletions core/fwd/core/fwd/wgpu/shader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once
#include "core/defines.hpp"
#include "core/fwd/resource/resource.hpp"


namespace core::iwgpu {
class shader;
} // namespace core::iwgpu

namespace core::meta {
class shader;
}
namespace core::resource {
template <>
struct resource_traits<core::iwgpu::shader> {
using meta_type = core::meta::shader;
};
} // namespace core::resource
3 changes: 3 additions & 0 deletions core/inc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,14 @@ if(${PE_WEBGPU})
context
computepass
drawpass
pipeline
shader
swapchain
)

list(APPEND FWD

wgpu/shader
wgpu/texture
)

Expand Down
1 change: 1 addition & 0 deletions core/inc/core/gfx/pipeline_cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class pipeline_cache {
if constexpr(backend == graphics_backend::gles)
return m_GLESHandle;
#endif
psl::fatal("unknown/unsupported backend");
};

private:
Expand Down
12 changes: 11 additions & 1 deletion core/inc/core/gfx/types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "psl/memory/range.hpp"
#include "psl/memory/segment.hpp"
#include "psl/ustring.hpp"
#include "psl/utility/enum.hpp"
#include <optional>
#include <variant>
#include <vector>
Expand Down Expand Up @@ -145,7 +146,10 @@ struct commit_instruction {
/// \brief sizeof source
size_t size {0};
};
///*** [format:enum

/// \brief describes what format the shader source is in.
enum class shader_source_format { unknown = 0, glsl, spirv, hlsl, msl, wgsl };

enum class shader_stage : uint8_t {
vertex = 1 << 0,
tesselation_control = 1 << 1,
Expand Down Expand Up @@ -937,3 +941,9 @@ inline size_t packing_size(format_t value) noexcept {
return 0;
}
} // namespace core::gfx


namespace psl::utility {
template <>
inline constexpr auto enable_enum_ops<core::gfx::graphics_backend> = enum_ops_t::LOGICAL;
} // namespace psl::utility
2 changes: 1 addition & 1 deletion core/inc/core/logging.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,5 +39,5 @@ extern psl::profiling::profiler profiler;
namespace {
bool _loggers_initialized = false;
}
auto initialize_loggers() -> bool;
auto initialize_loggers() -> void;
} // namespace core
18 changes: 13 additions & 5 deletions core/inc/core/meta/shader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,18 +148,24 @@ class shader final : public psl::meta::file {

~shader() = default;

bool per_instance(size_t attribute_index) const noexcept;
bool per_instance(const attribute& attribute) const noexcept;


/// \returns the shader stage of this SPIR-V module (i.e. vertex, fragment, compute, etc..)
core::gfx::shader_stage stage() const noexcept { return m_Stage.value; }

/// \brief sets the stage of this SPIR-V module to the given value.
/// \warning it is assumed this stage flag is the actual stage flag, otherwise binding the
/// shader will fail during creation.
/// \param[in] value the stage to expect.
void stage(core::gfx::shader_stage value) noexcept { m_Stage.value = value; }

/// \returns the source format of this SPIR-V module (i.e. glsl, spirv, etc..)
core::gfx::shader_source_format source_format() const noexcept { return m_SourceFormat.value; }

/// \brief sets the source format of this SPIR-V module to the given value.
/// \param[in] value the source format to expect.
/// \warning it is assumed this source format is the actual source format, otherwise binding the
/// shader will fail during creation.
void source_format(core::gfx::shader_source_format value) noexcept { m_SourceFormat.value = value; }

psl::array_view<attribute> inputs() noexcept {
return psl::array_view<attribute>(m_Attributes.data(), m_InputAttributesSize);
}
Expand Down Expand Up @@ -201,7 +207,7 @@ class shader final : public psl::meta::file {
std::end(m_Attributes));
}

s << m_Stage << inputs << outputs << m_Descriptors;
s << m_Stage << m_SourceFormat << inputs << outputs << m_Descriptors;

std::sort(std::begin(m_Descriptors.value), std::end(m_Descriptors.value), [](const auto& lhs, const auto& rhs) {
return lhs.binding() < rhs.binding();
Expand All @@ -217,6 +223,8 @@ class shader final : public psl::meta::file {

psl::serialization::property<"STAGE", core::gfx::shader_stage> m_Stage;
psl::serialization::property<"DESCRIPTORS", psl::array<descriptor>> m_Descriptors;
psl::serialization::property<"SOURCE_FORMAT", core::gfx::shader_source_format> m_SourceFormat {
core::gfx::shader_source_format::unknown};
psl::array<attribute> m_Attributes;
size_t m_InputAttributesSize {0}; // index of end() for input attributes

Expand Down
Empty file.
182 changes: 182 additions & 0 deletions core/inc/core/wgpu/conversion.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
#pragma once
#include "core/gfx/types.hpp"
#include "iwgpu.hpp"

namespace core::gfx::conversion {
constexpr wgpu::ShaderStage to_wgpu(core::gfx::shader_stage stage) noexcept {
switch(stage) {
case core::gfx::shader_stage::vertex:
return wgpu::ShaderStage::Vertex;
case core::gfx::shader_stage::fragment:
return wgpu::ShaderStage::Fragment;
case core::gfx::shader_stage::compute:
return wgpu::ShaderStage::Compute;
default:
return wgpu::ShaderStage::None;
}
}
constexpr core::gfx::shader_stage to_gfx(wgpu::ShaderStage stage) noexcept {
switch(stage) {
case wgpu::ShaderStage::Vertex:
return core::gfx::shader_stage::vertex;
case wgpu::ShaderStage::Fragment:
return core::gfx::shader_stage::fragment;
case wgpu::ShaderStage::Compute:
return core::gfx::shader_stage::compute;
default:
return core::gfx::shader_stage {0};
}
}

constexpr core::gfx::vertex_input_rate to_gfx(wgpu::VertexStepMode mode) noexcept {
switch(mode) {
case wgpu::VertexStepMode::Vertex:
return core::gfx::vertex_input_rate::vertex;
case wgpu::VertexStepMode::Instance:
return core::gfx::vertex_input_rate::instance;
default:
return core::gfx::vertex_input_rate {0};
}
}

constexpr wgpu::VertexStepMode to_wgpu(core::gfx::vertex_input_rate rate) noexcept {
switch(rate) {
case core::gfx::vertex_input_rate::vertex:
return wgpu::VertexStepMode::Vertex;
case core::gfx::vertex_input_rate::instance:
return wgpu::VertexStepMode::Instance;
default:
return wgpu::VertexStepMode::Vertex;
}
}

constexpr core::gfx::format_t to_gfx(wgpu::VertexFormat format) noexcept {
switch(format) {
case wgpu::VertexFormat::Float32:
return core::gfx::format_t::r32_sfloat;
case wgpu::VertexFormat::Float32x2:
return core::gfx::format_t::r32g32_sfloat;
case wgpu::VertexFormat::Float32x3:
return core::gfx::format_t::r32g32b32_sfloat;
case wgpu::VertexFormat::Float32x4:
return core::gfx::format_t::r32g32b32a32_sfloat;
case wgpu::VertexFormat::Uint32:
return core::gfx::format_t::r32_uint;
case wgpu::VertexFormat::Uint32x2:
return core::gfx::format_t::r32g32_uint;
case wgpu::VertexFormat::Uint32x3:
return core::gfx::format_t::r32g32b32_uint;
case wgpu::VertexFormat::Uint32x4:
return core::gfx::format_t::r32g32b32a32_uint;
case wgpu::VertexFormat::Sint32:
return core::gfx::format_t::r32_sint;
case wgpu::VertexFormat::Sint32x2:
return core::gfx::format_t::r32g32_sint;
case wgpu::VertexFormat::Sint32x3:
return core::gfx::format_t::r32g32b32_sint;
case wgpu::VertexFormat::Sint32x4:
return core::gfx::format_t::r32g32b32a32_sint;
case wgpu::VertexFormat::Sint16x2:
return core::gfx::format_t::r16g16_sint;
case wgpu::VertexFormat::Sint16x4:
return core::gfx::format_t::r16g16b16a16_sint;
case wgpu::VertexFormat::Sint8x2:
return core::gfx::format_t::r8g8_sint;
case wgpu::VertexFormat::Sint8x4:
return core::gfx::format_t::r8g8b8a8_sint;
case wgpu::VertexFormat::Uint16x2:
return core::gfx::format_t::r16g16_uint;
case wgpu::VertexFormat::Uint16x4:
return core::gfx::format_t::r16g16b16a16_uint;
case wgpu::VertexFormat::Uint8x2:
return core::gfx::format_t::r8g8_uint;
case wgpu::VertexFormat::Uint8x4:
return core::gfx::format_t::r8g8b8a8_uint;
case wgpu::VertexFormat::Unorm8x2:
return core::gfx::format_t::r8g8_unorm;
case wgpu::VertexFormat::Unorm8x4:
return core::gfx::format_t::r8g8b8a8_unorm;
case wgpu::VertexFormat::Unorm10_10_10_2:
return core::gfx::format_t::a2r10g10b10_unorm_pack32;
case wgpu::VertexFormat::Snorm8x2:
return core::gfx::format_t::r8g8_snorm;
case wgpu::VertexFormat::Snorm8x4:
return core::gfx::format_t::r8g8b8a8_snorm;
case wgpu::VertexFormat::Snorm16x2:
return core::gfx::format_t::r16g16_snorm;
case wgpu::VertexFormat::Snorm16x4:
return core::gfx::format_t::r16g16b16a16_snorm;
case wgpu::VertexFormat::Unorm16x2:
return core::gfx::format_t::r16g16_unorm;
case wgpu::VertexFormat::Unorm16x4:
return core::gfx::format_t::r16g16b16a16_unorm;
default:
return core::gfx::format_t::undefined;
}
}

constexpr wgpu::VertexFormat to_wgpu(core::gfx::format_t format) noexcept {
switch(format) {
case core::gfx::format_t::r32_sfloat:
return wgpu::VertexFormat::Float32;
case core::gfx::format_t::r32g32_sfloat:
return wgpu::VertexFormat::Float32x2;
case core::gfx::format_t::r32g32b32_sfloat:
return wgpu::VertexFormat::Float32x3;
case core::gfx::format_t::r32g32b32a32_sfloat:
return wgpu::VertexFormat::Float32x4;
case core::gfx::format_t::r32_uint:
return wgpu::VertexFormat::Uint32;
case core::gfx::format_t::r32g32_uint:
return wgpu::VertexFormat::Uint32x2;
case core::gfx::format_t::r32g32b32_uint:
return wgpu::VertexFormat::Uint32x3;
case core::gfx::format_t::r32g32b32a32_uint:
return wgpu::VertexFormat::Uint32x4;
case core::gfx::format_t::r32_sint:
return wgpu::VertexFormat::Sint32;
case core::gfx::format_t::r32g32_sint:
return wgpu::VertexFormat::Sint32x2;
case core::gfx::format_t::r32g32b32_sint:
return wgpu::VertexFormat::Sint32x3;
case core::gfx::format_t::r32g32b32a32_sint:
return wgpu::VertexFormat::Sint32x4;
case core::gfx::format_t::r16g16_sint:
return wgpu::VertexFormat::Sint16x2;
case core::gfx::format_t::r16g16b16a16_sint:
return wgpu::VertexFormat::Sint16x4;
case core::gfx::format_t::r8g8_sint:
return wgpu::VertexFormat::Sint8x2;
case core::gfx::format_t::r8g8b8a8_sint:
return wgpu::VertexFormat::Sint8x4;
case core::gfx::format_t::r16g16_uint:
return wgpu::VertexFormat::Uint16x2;
case core::gfx::format_t::r16g16b16a16_uint:
return wgpu::VertexFormat::Uint16x4;
case core::gfx::format_t::r8g8_uint:
return wgpu::VertexFormat::Uint8x2;
case core::gfx::format_t::r8g8b8a8_uint:
return wgpu::VertexFormat::Uint8x4;
case core::gfx::format_t::r8g8_unorm:
return wgpu::VertexFormat::Unorm8x2;
case core::gfx::format_t::r8g8b8a8_unorm:
return wgpu::VertexFormat::Unorm8x4;
case core::gfx::format_t::a2r10g10b10_unorm_pack32:
return wgpu::VertexFormat::Unorm10_10_10_2;
case core::gfx::format_t::r8g8_snorm:
return wgpu::VertexFormat::Snorm8x2;
case core::gfx::format_t::r8g8b8a8_snorm:
return wgpu::VertexFormat::Snorm8x4;
case core::gfx::format_t::r16g16_snorm:
return wgpu::VertexFormat::Snorm16x2;
case core::gfx::format_t::r16g16b16a16_snorm:
return wgpu::VertexFormat::Snorm16x4;
case core::gfx::format_t::r16g16_unorm:
return wgpu::VertexFormat::Unorm16x2;
case core::gfx::format_t::r16g16b16a16_unorm:
return wgpu::VertexFormat::Unorm16x4;
default:
return wgpu::VertexFormat::Undefined;
}
}
} // namespace core::gfx::conversion
26 changes: 26 additions & 0 deletions core/inc/core/wgpu/pipeline.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#pragma once
#include "core/fwd/resource/resource.hpp"
#include "core/wgpu/iwgpu.hpp"

namespace core::data {
class material_t;
} // namespace core::data

namespace core::iwgpu {
class context;
class pipeline {
public:
pipeline(core::resource::cache_t& cache,
const core::resource::metadata& metaData,
psl::meta::file* metaFile,
core::resource::handle<core::iwgpu::context> context,
core::resource::handle<core::data::material_t> data);
~pipeline();

private:
core::resource::cache_t& m_Cache;
core::resource::handle<core::iwgpu::context> m_Context;
psl::meta::file* m_Meta;
const psl::UID m_UID;
};
} // namespace core::iwgpu
28 changes: 28 additions & 0 deletions core/inc/core/wgpu/pipeline_cache.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once
#include "core/resource/handle.hpp"
#include "core/resource/resource.hpp"
#include "core/wgpu/iwgpu.hpp"


namespace core::data {
class material_t;
}

namespace core::iwgpu {
class context;
class pipeline;
class pipeline_cache {
public:
pipeline_cache(core::resource::cache_t& cache,
const core::resource::metadata& metaData,
psl::meta::file* metaFile,
core::resource::handle<core::iwgpu::context> context);

~pipeline_cache();

core::resource::handle<pipeline> get(core::resource::handle<core::data::material_t> data);

private:
core::resource::handle<core::iwgpu::context> m_Context;
};
} // namespace core::iwgpu
33 changes: 33 additions & 0 deletions core/inc/core/wgpu/shader.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include "core/fwd/wgpu/shader.hpp"
#include "core/resource/resource.hpp"
#include "core/wgpu/iwgpu.hpp"

namespace core::iwgpu {
class context;

class shader {
public:
shader(core::resource::cache_t& cache,
const core::resource::metadata& metaData,
core::meta::shader* metaFile,
core::resource::handle<core::iwgpu::context> context);
~shader();
shader(const shader&) = delete;
shader(shader&&) = delete;
shader& operator=(const shader&) = delete;
shader& operator=(shader&&) = delete;

core::meta::shader* meta() const noexcept;

wgpu::ShaderModule module() const noexcept { return m_Shader; }

private:
core::resource::handle<core::iwgpu::context> m_Context;
core::resource::cache_t& m_Cache;
core::meta::shader* m_Meta;
wgpu::ShaderModule m_Shader;
const psl::UID m_UID;
};
} // namespace core::iwgpu
Loading

0 comments on commit f37265f

Please sign in to comment.