Shader reflection added.
This commit is contained in:
parent
3a7a2b4ab7
commit
41c91058b6
|
|
@ -52,14 +52,15 @@ constexpr u32 ASTER_API_VERSION = VK_API_VERSION_1_3;
|
||||||
|
|
||||||
#define Take(ELEMENT) eastl::exchange(ELEMENT, {})
|
#define Take(ELEMENT) eastl::exchange(ELEMENT, {})
|
||||||
|
|
||||||
#define TODO(MSG) assert(false && ("Unimplemented: " MSG))
|
#define TODO(...) assert(!("Unimplemented: " __VA_ARGS__))
|
||||||
#define FIX(MSG) static_assert(false && ("Unimplemented: " MSG))
|
#define FIX(...) static_assert(!("Unimplemented: " __VA_ARGS__))
|
||||||
|
#define UNREACHABLE(...) assert(!("Unreachable: " __VA_ARGS__))
|
||||||
|
|
||||||
#define AbortIfFailed(RESULT) \
|
#define AbortIfFailed(RESULT) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
vk::Result _checkResultValue_; \
|
vk::Result _checkResultValue_; \
|
||||||
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), "Cause: {}", _checkResultValue_) \
|
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), "Cause: {}", _checkResultValue_) \
|
||||||
THEN_ABORT(_checkResultValue_); \
|
THEN_ABORT(_checkResultValue_); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
|
|
@ -67,14 +68,15 @@ constexpr u32 ASTER_API_VERSION = VK_API_VERSION_1_3;
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
vk::Result _checkResultValue_; \
|
vk::Result _checkResultValue_; \
|
||||||
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), MSG " Cause: {}", EXTRA, _checkResultValue_) \
|
ERROR_IF(Failed(_checkResultValue_ = static_cast<vk::Result>(RESULT)), MSG " Cause: {}", EXTRA, \
|
||||||
|
_checkResultValue_) \
|
||||||
THEN_ABORT(_checkResultValue_); \
|
THEN_ABORT(_checkResultValue_); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
#define AbortIfFailedM(RESULT, MSG) \
|
#define AbortIfFailedM(RESULT, MSG) \
|
||||||
do \
|
do \
|
||||||
{ \
|
{ \
|
||||||
auto _checkResultValue_ = static_cast<vk::Result>(RESULT); \
|
auto _checkResultValue_ = static_cast<vk::Result>(RESULT); \
|
||||||
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
|
ERROR_IF(Failed(_checkResultValue_), MSG " Cause: {}", _checkResultValue_) THEN_ABORT(_checkResultValue_); \
|
||||||
} while (false)
|
} while (false)
|
||||||
|
|
||||||
|
|
@ -221,15 +223,20 @@ GetMaskOffset(u32 val)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <typename T>
|
||||||
struct fmt::formatter<vk::Result> : nested_formatter<std::string>
|
concept VkToString = requires(T a) {
|
||||||
|
{ vk::to_string(a) } -> std::convertible_to<std::string>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <VkToString T>
|
||||||
|
struct fmt::formatter<T> : nested_formatter<std::string>
|
||||||
{
|
{
|
||||||
auto
|
auto
|
||||||
// ReSharper disable once CppInconsistentNaming
|
// ReSharper disable once CppInconsistentNaming
|
||||||
format(vk::Result result, format_context &ctx) const
|
format(T result, format_context &ctx) const
|
||||||
{
|
{
|
||||||
return write_padded(ctx,
|
return write_padded(ctx,
|
||||||
[this, result](auto out) { return v11::format_to(out, "{}", nested(to_string(result))); });
|
[this, result](auto out) { return fmt::format_to(out, "{}", nested(to_string(result))); });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,8 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "surface.h"
|
#include "surface.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
#include <EASTL/fixed_vector.h>
|
#include <EASTL/fixed_vector.h>
|
||||||
|
|
||||||
struct Window;
|
struct Window;
|
||||||
|
|
@ -23,6 +25,31 @@ enum class QueueSupportFlagBits
|
||||||
|
|
||||||
using QueueSupportFlags = vk::Flags<QueueSupportFlagBits>;
|
using QueueSupportFlags = vk::Flags<QueueSupportFlagBits>;
|
||||||
|
|
||||||
|
inline std::string
|
||||||
|
// ReSharper disable once CppInconsistentNaming
|
||||||
|
format_as(const QueueSupportFlags &qfi)
|
||||||
|
{
|
||||||
|
std::stringstream sb;
|
||||||
|
if (qfi & QueueSupportFlagBits::eGraphics)
|
||||||
|
{
|
||||||
|
sb << "Graphics | ";
|
||||||
|
}
|
||||||
|
if (qfi & QueueSupportFlagBits::eTransfer)
|
||||||
|
{
|
||||||
|
sb << "Transfer | ";
|
||||||
|
}
|
||||||
|
if (qfi & QueueSupportFlagBits::eCompute)
|
||||||
|
{
|
||||||
|
sb << "Compute | ";
|
||||||
|
}
|
||||||
|
if (qfi & QueueSupportFlagBits::ePresent)
|
||||||
|
{
|
||||||
|
sb << "Present | ";
|
||||||
|
}
|
||||||
|
const auto sbv = sb.view();
|
||||||
|
return std::string(sbv.substr(0, sbv.size() - 3));
|
||||||
|
}
|
||||||
|
|
||||||
struct QueueFamilyInfo
|
struct QueueFamilyInfo
|
||||||
{
|
{
|
||||||
u32 m_Index;
|
u32 m_Index;
|
||||||
|
|
@ -30,6 +57,12 @@ struct QueueFamilyInfo
|
||||||
QueueSupportFlags m_Support;
|
QueueSupportFlags m_Support;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline std::string
|
||||||
|
format_as(const QueueFamilyInfo &qfi)
|
||||||
|
{
|
||||||
|
return fmt::format("Queue {}: Count={} Support={}", qfi.m_Index, qfi.m_Count, qfi.m_Support);
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] vk::SurfaceCapabilitiesKHR
|
[[nodiscard]] vk::SurfaceCapabilitiesKHR
|
||||||
GetSurfaceCapabilities(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface);
|
GetSurfaceCapabilities(vk::PhysicalDevice physicalDevice, vk::SurfaceKHR surface);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "pipeline_helpers.h"
|
||||||
#include "resource.h"
|
#include "resource.h"
|
||||||
|
|
||||||
#include "aster/aster.h"
|
#include "aster/aster.h"
|
||||||
|
|
@ -231,59 +232,6 @@ struct SamplerCreateInfo
|
||||||
#pragma region Pipeline
|
#pragma region Pipeline
|
||||||
// ----------------------------------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
struct PipelineCreationError
|
|
||||||
{
|
|
||||||
enum class Kind
|
|
||||||
{
|
|
||||||
eNone,
|
|
||||||
eVulkan,
|
|
||||||
eSlang,
|
|
||||||
} m_Kind;
|
|
||||||
union {
|
|
||||||
u32 uNone;
|
|
||||||
vk::Result uVulkanResult;
|
|
||||||
SlangResult uSlangResult;
|
|
||||||
};
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
|
||||||
return m_Kind != Kind::eNone;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
What()
|
|
||||||
{
|
|
||||||
switch (m_Kind)
|
|
||||||
{
|
|
||||||
case Kind::eNone:
|
|
||||||
return "No Error";
|
|
||||||
case Kind::eVulkan:
|
|
||||||
return fmt::format("{}", uVulkanResult);
|
|
||||||
case Kind::eSlang:
|
|
||||||
return fmt::format("{}", uSlangResult);
|
|
||||||
}
|
|
||||||
return "No Error";
|
|
||||||
}
|
|
||||||
|
|
||||||
PipelineCreationError()
|
|
||||||
: m_Kind{Kind::eNone}
|
|
||||||
, uNone{}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PipelineCreationError(vk::Result result)
|
|
||||||
: m_Kind{Kind::eVulkan}
|
|
||||||
, uVulkanResult{result}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
PipelineCreationError(SlangResult result)
|
|
||||||
: m_Kind{Kind::eSlang}
|
|
||||||
, uSlangResult{result}
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct AttributeInfo
|
struct AttributeInfo
|
||||||
{
|
{
|
||||||
u32 m_Location;
|
u32 m_Location;
|
||||||
|
|
@ -402,7 +350,7 @@ struct Frame;
|
||||||
|
|
||||||
class Context
|
class Context
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
vk::CommandBuffer m_Cmd;
|
vk::CommandBuffer m_Cmd;
|
||||||
|
|
||||||
friend Device;
|
friend Device;
|
||||||
|
|
@ -426,13 +374,14 @@ class GraphicsContext : public Context
|
||||||
friend Device;
|
friend Device;
|
||||||
friend Frame;
|
friend Frame;
|
||||||
|
|
||||||
|
const Pipeline *m_PipelineInUse;
|
||||||
|
|
||||||
explicit GraphicsContext(const vk::CommandBuffer cmd)
|
explicit GraphicsContext(const vk::CommandBuffer cmd)
|
||||||
: Context{cmd}
|
: Context{cmd}
|
||||||
|
, m_PipelineInUse{nullptr}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const Pipeline *m_PipelineInUse;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEPRECATE_RAW_CALLS void SetViewport(const vk::Viewport &viewport);
|
DEPRECATE_RAW_CALLS void SetViewport(const vk::Viewport &viewport);
|
||||||
void BindVertexBuffer(const Ref<VertexBuffer> &vertexBuffer);
|
void BindVertexBuffer(const Ref<VertexBuffer> &vertexBuffer);
|
||||||
|
|
@ -440,10 +389,14 @@ class GraphicsContext : public Context
|
||||||
void
|
void
|
||||||
PushConstantBlock(auto &block)
|
PushConstantBlock(auto &block)
|
||||||
{
|
{
|
||||||
m_Cmd.pushConstants(m_PipelineInUse->m_Layout, vk::ShaderStageFlagBits::eAllGraphics, 0, sizeof block, &block);
|
if constexpr (sizeof(block) > 128)
|
||||||
|
{
|
||||||
|
WARN("Vulkan only guarantees 128 bytes of Push Constants. Size of PCB is {}", sizeof block);
|
||||||
|
}
|
||||||
|
m_Cmd.pushConstants(m_PipelineInUse->m_Layout, vk::ShaderStageFlagBits::eAll, 0, sizeof block, &block);
|
||||||
}
|
}
|
||||||
void Draw(u32 vertexCount);
|
void Draw(usize vertexCount);
|
||||||
void DrawIndexed(u32 indexCount);
|
void DrawIndexed(usize indexCount);
|
||||||
|
|
||||||
DEPRECATE_RAW_CALLS void BeginRendering(const vk::RenderingInfo &renderingInfo);
|
DEPRECATE_RAW_CALLS void BeginRendering(const vk::RenderingInfo &renderingInfo);
|
||||||
void EndRendering();
|
void EndRendering();
|
||||||
|
|
@ -480,6 +433,8 @@ class TransferContext : public Context
|
||||||
TransferContext &operator=(TransferContext &&other) noexcept;
|
TransferContext &operator=(TransferContext &&other) noexcept;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(TransferContext);
|
DISALLOW_COPY_AND_ASSIGN(TransferContext);
|
||||||
|
|
||||||
|
~TransferContext() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Frame
|
struct Frame
|
||||||
|
|
@ -514,6 +469,8 @@ struct Frame
|
||||||
Frame &operator=(Frame &&other) noexcept;
|
Frame &operator=(Frame &&other) noexcept;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(Frame);
|
DISALLOW_COPY_AND_ASSIGN(Frame);
|
||||||
|
|
||||||
|
~Frame() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Device final
|
class Device final
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
// =============================================
|
||||||
|
// Aster: pipeline_helpers.h
|
||||||
|
// Copyright (c) 2020-2025 Anish Bhobe
|
||||||
|
// =============================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <aster/aster.h>
|
||||||
|
|
||||||
|
#include <EASTL/vector.h>
|
||||||
|
#include <slang.h>
|
||||||
|
#include <variant>
|
||||||
|
|
||||||
|
namespace systems
|
||||||
|
{
|
||||||
|
class Device;
|
||||||
|
|
||||||
|
struct PipelineCreationError
|
||||||
|
{
|
||||||
|
std::variant<std::monostate, vk::Result, SlangResult> m_Data;
|
||||||
|
|
||||||
|
std::string What();
|
||||||
|
i32 Value();
|
||||||
|
|
||||||
|
operator bool() const;
|
||||||
|
|
||||||
|
PipelineCreationError(vk::Result res);
|
||||||
|
PipelineCreationError(SlangResult res);
|
||||||
|
PipelineCreationError();
|
||||||
|
};
|
||||||
|
|
||||||
|
vk::ShaderStageFlagBits SlangToVulkanShaderStage(SlangStage stage);
|
||||||
|
|
||||||
|
namespace _internal
|
||||||
|
{
|
||||||
|
struct PipelineLayoutBuilder
|
||||||
|
{
|
||||||
|
Device *m_Device;
|
||||||
|
eastl::vector<vk::DescriptorSetLayout> m_DescriptorSetLayouts;
|
||||||
|
eastl::vector<vk::PushConstantRange> m_PushConstants;
|
||||||
|
vk::ShaderStageFlags m_Stage;
|
||||||
|
|
||||||
|
explicit PipelineLayoutBuilder(Device *device, vk::DescriptorSetLayout bindlessLayout = {});
|
||||||
|
|
||||||
|
[[nodiscard]] vk::PipelineLayout Build();
|
||||||
|
|
||||||
|
[[nodiscard]] vk::DescriptorSetLayout CreateDescriptorSetLayout(const vk::DescriptorSetLayoutCreateInfo &createInfo) const;
|
||||||
|
void AddDescriptorSetForParameterBlock(slang::TypeLayoutReflection * layout);
|
||||||
|
void AddPushConstantRangeForConstantBuffer(slang::TypeLayoutReflection * layout);
|
||||||
|
void AddSubObjectRange(slang::TypeLayoutReflection * layout, i64 subObjectRangeIndex);
|
||||||
|
void AddSubObjectRanges(slang::TypeLayoutReflection * layout);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DescriptorLayoutBuilder
|
||||||
|
{
|
||||||
|
PipelineLayoutBuilder *m_PipelineLayoutBuilder;
|
||||||
|
eastl::vector<vk::DescriptorSetLayoutBinding> m_LayoutBindings;
|
||||||
|
u32 m_SetIndex;
|
||||||
|
|
||||||
|
vk::ShaderStageFlags &Stage() const;
|
||||||
|
explicit DescriptorLayoutBuilder(PipelineLayoutBuilder *pipelineLayoutBuilder);
|
||||||
|
|
||||||
|
void AddGlobalScopeParameters(slang::ProgramLayout *layout);
|
||||||
|
void AddEntryPointParameters(slang::ProgramLayout *layout);
|
||||||
|
void AddEntryPointParameters(slang::EntryPointLayout *layout);
|
||||||
|
void AddAutomaticallyIntroducedUniformBuffer();
|
||||||
|
void AddRanges(slang::TypeLayoutReflection *layout);
|
||||||
|
void AddRangesForParamBlockElement(slang::TypeLayoutReflection *layout);
|
||||||
|
void AddDescriptorRange(slang::TypeLayoutReflection *layout, i64 relativeSetIndex, i64 rangeIndex);
|
||||||
|
void AddDescriptorRanges(slang::TypeLayoutReflection *layout);
|
||||||
|
void Build();
|
||||||
|
};
|
||||||
|
} // namespace _internal
|
||||||
|
} // namespace systems
|
||||||
|
|
@ -69,13 +69,15 @@ CastView(const Ref<View<TFrom>> &from)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class ResId
|
class ResId
|
||||||
{
|
{
|
||||||
|
using IdType = u32;
|
||||||
public:
|
public:
|
||||||
constexpr static u32 INVALID = MaxValue<u32>;
|
constexpr static IdType INVALID = MaxValue<IdType>;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 m_Index;
|
IdType m_Index;
|
||||||
|
u32 m_Padding; //< Slang DescriptorHandle are a pair of u32. TODO: Use as validation.
|
||||||
|
|
||||||
explicit ResId(const u32 index)
|
explicit ResId(const IdType index)
|
||||||
: m_Index{index}
|
: m_Index{index}
|
||||||
{
|
{
|
||||||
AddRef();
|
AddRef();
|
||||||
|
|
|
||||||
|
|
@ -6,4 +6,5 @@ target_sources(aster_core
|
||||||
PRIVATE
|
PRIVATE
|
||||||
"device.cpp"
|
"device.cpp"
|
||||||
"commit_manager.cpp"
|
"commit_manager.cpp"
|
||||||
|
"pipeline_helpers.cpp"
|
||||||
"sync_server.cpp")
|
"sync_server.cpp")
|
||||||
|
|
|
||||||
|
|
@ -562,7 +562,10 @@ systems::Device::CreatePipeline(Pipeline &pipelineOut, const GraphicsPipelineCre
|
||||||
}
|
}
|
||||||
|
|
||||||
vk::PipelineLayout pipelineLayout;
|
vk::PipelineLayout pipelineLayout;
|
||||||
auto result = CreatePipelineLayout(pipelineLayout, program);
|
if (auto result = CreatePipelineLayout(pipelineLayout, program))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
eastl::fixed_vector<vk::VertexInputBindingDescription, 4, false> inputBindingDescriptions;
|
eastl::fixed_vector<vk::VertexInputBindingDescription, 4, false> inputBindingDescriptions;
|
||||||
eastl::fixed_vector<vk::VertexInputAttributeDescription, 4, false> inputAttributeDescriptions;
|
eastl::fixed_vector<vk::VertexInputAttributeDescription, 4, false> inputAttributeDescriptions;
|
||||||
|
|
@ -699,47 +702,6 @@ systems::Device::CreatePipeline(Pipeline &pipelineOut, const GraphicsPipelineCre
|
||||||
ERROR("Unimplemented Stage " #STAGE); \
|
ERROR("Unimplemented Stage " #STAGE); \
|
||||||
return SLANG_FAIL
|
return SLANG_FAIL
|
||||||
|
|
||||||
static vk::ShaderStageFlagBits
|
|
||||||
SlangToVulkanShaderStage(const SlangStage stage)
|
|
||||||
{
|
|
||||||
switch (stage)
|
|
||||||
{
|
|
||||||
case SLANG_STAGE_VERTEX:
|
|
||||||
return vk::ShaderStageFlagBits::eVertex;
|
|
||||||
case SLANG_STAGE_HULL:
|
|
||||||
return vk::ShaderStageFlagBits::eTessellationControl;
|
|
||||||
case SLANG_STAGE_DOMAIN:
|
|
||||||
return vk::ShaderStageFlagBits::eTessellationEvaluation;
|
|
||||||
case SLANG_STAGE_GEOMETRY:
|
|
||||||
return vk::ShaderStageFlagBits::eGeometry;
|
|
||||||
case SLANG_STAGE_FRAGMENT:
|
|
||||||
return vk::ShaderStageFlagBits::eFragment;
|
|
||||||
case SLANG_STAGE_COMPUTE:
|
|
||||||
return vk::ShaderStageFlagBits::eCompute;
|
|
||||||
case SLANG_STAGE_RAY_GENERATION:
|
|
||||||
return vk::ShaderStageFlagBits::eRaygenKHR;
|
|
||||||
case SLANG_STAGE_INTERSECTION:
|
|
||||||
return vk::ShaderStageFlagBits::eIntersectionKHR;
|
|
||||||
case SLANG_STAGE_ANY_HIT:
|
|
||||||
return vk::ShaderStageFlagBits::eAnyHitKHR;
|
|
||||||
case SLANG_STAGE_CLOSEST_HIT:
|
|
||||||
return vk::ShaderStageFlagBits::eClosestHitKHR;
|
|
||||||
case SLANG_STAGE_MISS:
|
|
||||||
return vk::ShaderStageFlagBits::eMissKHR;
|
|
||||||
case SLANG_STAGE_CALLABLE:
|
|
||||||
return vk::ShaderStageFlagBits::eCallableKHR;
|
|
||||||
case SLANG_STAGE_MESH:
|
|
||||||
return vk::ShaderStageFlagBits::eMeshEXT;
|
|
||||||
case SLANG_STAGE_AMPLIFICATION:
|
|
||||||
return vk::ShaderStageFlagBits::eTaskEXT;
|
|
||||||
case SLANG_STAGE_NONE:
|
|
||||||
case SLANG_STAGE_COUNT:
|
|
||||||
ERROR("Invalid Shader Stage");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
ERROR("Unreachable") THEN_ABORT(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
systems::PipelineCreationError
|
systems::PipelineCreationError
|
||||||
systems::Device::CreateShaders(
|
systems::Device::CreateShaders(
|
||||||
eastl::fixed_vector<vk::PipelineShaderStageCreateInfo, ShaderTypeCount, false> &shadersOut,
|
eastl::fixed_vector<vk::PipelineShaderStageCreateInfo, ShaderTypeCount, false> &shadersOut,
|
||||||
|
|
@ -905,6 +867,39 @@ systems::Device::CreateShaders(
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PipelineLayoutBuilder
|
||||||
|
{
|
||||||
|
systems::Device *m_Device;
|
||||||
|
eastl::vector<vk::DescriptorSetLayout> m_DescriptorSetLayouts;
|
||||||
|
eastl::vector<vk::PushConstantRange> m_PushConstantRanges;
|
||||||
|
|
||||||
|
explicit PipelineLayoutBuilder(systems::Device *device)
|
||||||
|
: m_Device{device}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
systems::PipelineCreationError
|
||||||
|
Build(vk::PipelineLayout &pipelineLayout, eastl::vector<vk::DescriptorSetLayout> &descriptorSetLayouts);
|
||||||
|
};
|
||||||
|
|
||||||
|
systems::PipelineCreationError
|
||||||
|
PipelineLayoutBuilder::Build(vk::PipelineLayout &pipelineLayout,
|
||||||
|
eastl::vector<vk::DescriptorSetLayout> &descriptorSetLayouts)
|
||||||
|
{
|
||||||
|
const vk::PipelineLayoutCreateInfo layoutCreateInfo = {
|
||||||
|
.setLayoutCount = static_cast<u32>(m_DescriptorSetLayouts.size()),
|
||||||
|
.pSetLayouts = m_DescriptorSetLayouts.data(),
|
||||||
|
.pushConstantRangeCount = static_cast<u32>(m_PushConstantRanges.size()),
|
||||||
|
.pPushConstantRanges = m_PushConstantRanges.data(),
|
||||||
|
};
|
||||||
|
const auto result = m_Device->m_Device->createPipelineLayout(&layoutCreateInfo, nullptr, &pipelineLayout);
|
||||||
|
for (const auto &descSet : descriptorSetLayouts)
|
||||||
|
{
|
||||||
|
m_Device->m_Device->destroy(descSet, nullptr);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
systems::PipelineCreationError
|
systems::PipelineCreationError
|
||||||
systems::Device::CreatePipelineLayout(vk::PipelineLayout &pipelineLayout,
|
systems::Device::CreatePipelineLayout(vk::PipelineLayout &pipelineLayout,
|
||||||
const Slang::ComPtr<slang::IComponentType> &program)
|
const Slang::ComPtr<slang::IComponentType> &program)
|
||||||
|
|
@ -919,39 +914,20 @@ systems::Device::CreatePipelineLayout(vk::PipelineLayout &pipelineLayout,
|
||||||
return SLANG_FAIL;
|
return SLANG_FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Reflect to create the push constants and descriptor sets.
|
vk::DescriptorSetLayout setLayout = {};
|
||||||
|
|
||||||
// TODO: Hackery. To FIX.
|
|
||||||
vk::PushConstantRange pcr{
|
|
||||||
.stageFlags = vk::ShaderStageFlagBits::eAllGraphics,
|
|
||||||
.offset = 0,
|
|
||||||
.size = 24,
|
|
||||||
};
|
|
||||||
|
|
||||||
u32 setLayoutCount = 0;
|
|
||||||
const vk::DescriptorSetLayout *setLayout = nullptr;
|
|
||||||
|
|
||||||
if (m_CommitManager)
|
if (m_CommitManager)
|
||||||
{
|
setLayout = m_CommitManager->GetDescriptorSetLayout();
|
||||||
setLayoutCount = 1;
|
|
||||||
setLayout = &m_CommitManager->GetDescriptorSetLayout();
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: END EXPERIMENT
|
_internal::PipelineLayoutBuilder pipelineLayoutBuilder{
|
||||||
|
this,
|
||||||
const vk::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
|
setLayout,
|
||||||
.setLayoutCount = setLayoutCount,
|
|
||||||
.pSetLayouts = setLayout,
|
|
||||||
.pushConstantRangeCount = 1,
|
|
||||||
.pPushConstantRanges = &pcr,
|
|
||||||
};
|
};
|
||||||
vk::Result result = m_Device->createPipelineLayout(&pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
|
_internal::DescriptorLayoutBuilder descriptorLayoutBuilder{&pipelineLayoutBuilder};
|
||||||
if (Failed(result))
|
descriptorLayoutBuilder.AddGlobalScopeParameters(layout);
|
||||||
{
|
descriptorLayoutBuilder.AddEntryPointParameters(layout);
|
||||||
ERROR("Could not create a pipeline layout. Cause: {}", result);
|
descriptorLayoutBuilder.Build();
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
pipelineLayout = pipelineLayoutBuilder.Build();
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -990,7 +966,7 @@ FindAsyncTransferQueue(const PhysicalDevice &physicalDevice, u32 primaryQueueFam
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARN("No async transfer queue. Falling back to primary queue");
|
WARN("No dedicated async transfer queue. Falling back to primary queue family.");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1002,7 +978,8 @@ FindAsyncComputeQueue(const PhysicalDevice &physicalDevice, u32 primaryQueueFami
|
||||||
if (queueFamilyInfo.m_Index == primaryQueueFamilyIndex)
|
if (queueFamilyInfo.m_Index == primaryQueueFamilyIndex)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (queueFamilyInfo.m_Support == QueueSupportFlagBits::eCompute)
|
if (queueFamilyInfo.m_Support ==
|
||||||
|
(QueueSupportFlags{QueueSupportFlagBits::eCompute} | QueueSupportFlagBits::eTransfer))
|
||||||
{
|
{
|
||||||
return QueueAllocation{
|
return QueueAllocation{
|
||||||
.m_Family = queueFamilyInfo.m_Index,
|
.m_Family = queueFamilyInfo.m_Index,
|
||||||
|
|
@ -1010,7 +987,7 @@ FindAsyncComputeQueue(const PhysicalDevice &physicalDevice, u32 primaryQueueFami
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WARN("No async compute queue. Falling back to primary queue");
|
WARN("No async compute queue. Falling back to primary queue family.");
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1471,15 +1448,15 @@ systems::GraphicsContext::BindPipeline(const Pipeline &pipeline)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
systems::GraphicsContext::Draw(u32 vertexCount)
|
systems::GraphicsContext::Draw(const usize vertexCount)
|
||||||
{
|
{
|
||||||
m_Cmd.draw(vertexCount, 1, 0, 0);
|
m_Cmd.draw(static_cast<u32>(vertexCount), 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
systems::GraphicsContext::DrawIndexed(u32 indexCount)
|
systems::GraphicsContext::DrawIndexed(usize indexCount)
|
||||||
{
|
{
|
||||||
m_Cmd.drawIndexed(indexCount, 1, 0, 0, 0);
|
m_Cmd.drawIndexed(static_cast<u32>(indexCount), 1, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,374 @@
|
||||||
|
// =============================================
|
||||||
|
// Aster: pipeline_helpers.cpp
|
||||||
|
// Copyright (c) 2020-2025 Anish Bhobe
|
||||||
|
// =============================================
|
||||||
|
|
||||||
|
#include "systems/device.h"
|
||||||
|
|
||||||
|
#include <aster/systems/pipeline_helpers.h>
|
||||||
|
|
||||||
|
using namespace systems::_internal;
|
||||||
|
|
||||||
|
struct WhatVisitor
|
||||||
|
{
|
||||||
|
std::string
|
||||||
|
operator()(std::monostate) const
|
||||||
|
{
|
||||||
|
return "No Error";
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
operator()(vk::Result result) const
|
||||||
|
{
|
||||||
|
return fmt::format("Vulkan Error: {}", result);
|
||||||
|
}
|
||||||
|
std::string
|
||||||
|
operator()(SlangResult result) const
|
||||||
|
{
|
||||||
|
return fmt::format("Slang Error: {}", result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ValueVisitor
|
||||||
|
{
|
||||||
|
i32
|
||||||
|
operator()(std::monostate) const
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
i32
|
||||||
|
operator()(vk::Result result) const
|
||||||
|
{
|
||||||
|
return static_cast<i32>(result);
|
||||||
|
}
|
||||||
|
i32
|
||||||
|
operator()(SlangResult result) const
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
i32
|
||||||
|
systems::PipelineCreationError::Value()
|
||||||
|
{
|
||||||
|
return std::visit(ValueVisitor{}, m_Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
systems::PipelineCreationError::PipelineCreationError(vk::Result res)
|
||||||
|
: m_Data{res}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
systems::PipelineCreationError::PipelineCreationError(SlangResult res)
|
||||||
|
: m_Data{res}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
systems::PipelineCreationError::PipelineCreationError()
|
||||||
|
: m_Data{std::monostate{}}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
systems::PipelineCreationError::operator bool() const
|
||||||
|
{
|
||||||
|
return not std::holds_alternative<std::monostate>(m_Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
systems::PipelineCreationError::What()
|
||||||
|
{
|
||||||
|
return std::visit(WhatVisitor{}, m_Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::ShaderStageFlagBits
|
||||||
|
systems::SlangToVulkanShaderStage(const SlangStage stage)
|
||||||
|
{
|
||||||
|
switch (stage)
|
||||||
|
{
|
||||||
|
case SLANG_STAGE_VERTEX:
|
||||||
|
return vk::ShaderStageFlagBits::eVertex;
|
||||||
|
case SLANG_STAGE_HULL:
|
||||||
|
return vk::ShaderStageFlagBits::eTessellationControl;
|
||||||
|
case SLANG_STAGE_DOMAIN:
|
||||||
|
return vk::ShaderStageFlagBits::eTessellationEvaluation;
|
||||||
|
case SLANG_STAGE_GEOMETRY:
|
||||||
|
return vk::ShaderStageFlagBits::eGeometry;
|
||||||
|
case SLANG_STAGE_FRAGMENT:
|
||||||
|
return vk::ShaderStageFlagBits::eFragment;
|
||||||
|
case SLANG_STAGE_COMPUTE:
|
||||||
|
return vk::ShaderStageFlagBits::eCompute;
|
||||||
|
case SLANG_STAGE_RAY_GENERATION:
|
||||||
|
return vk::ShaderStageFlagBits::eRaygenKHR;
|
||||||
|
case SLANG_STAGE_INTERSECTION:
|
||||||
|
return vk::ShaderStageFlagBits::eIntersectionKHR;
|
||||||
|
case SLANG_STAGE_ANY_HIT:
|
||||||
|
return vk::ShaderStageFlagBits::eAnyHitKHR;
|
||||||
|
case SLANG_STAGE_CLOSEST_HIT:
|
||||||
|
return vk::ShaderStageFlagBits::eClosestHitKHR;
|
||||||
|
case SLANG_STAGE_MISS:
|
||||||
|
return vk::ShaderStageFlagBits::eMissKHR;
|
||||||
|
case SLANG_STAGE_CALLABLE:
|
||||||
|
return vk::ShaderStageFlagBits::eCallableKHR;
|
||||||
|
case SLANG_STAGE_MESH:
|
||||||
|
return vk::ShaderStageFlagBits::eMeshEXT;
|
||||||
|
case SLANG_STAGE_AMPLIFICATION:
|
||||||
|
return vk::ShaderStageFlagBits::eTaskEXT;
|
||||||
|
case SLANG_STAGE_NONE:
|
||||||
|
case SLANG_STAGE_COUNT:
|
||||||
|
UNREACHABLE();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
UNREACHABLE();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
PipelineLayoutBuilder::PipelineLayoutBuilder(Device *device, vk::DescriptorSetLayout bindlessLayout)
|
||||||
|
: m_Device{device}
|
||||||
|
, m_DescriptorSetLayouts{bindlessLayout} // if `null` will be filtered out during build.
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::PipelineLayout
|
||||||
|
PipelineLayoutBuilder::Build()
|
||||||
|
{
|
||||||
|
vk::PipelineLayout pipelineLayout;
|
||||||
|
|
||||||
|
eastl::vector<vk::DescriptorSetLayout> filteredDescriptorSetLayouts;
|
||||||
|
filteredDescriptorSetLayouts.reserve(m_DescriptorSetLayouts.size());
|
||||||
|
for (auto dsl : m_DescriptorSetLayouts)
|
||||||
|
{
|
||||||
|
if (dsl)
|
||||||
|
{
|
||||||
|
filteredDescriptorSetLayouts.push_back(dsl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const vk::PipelineLayoutCreateInfo createInfo = {
|
||||||
|
.setLayoutCount = static_cast<u32>(filteredDescriptorSetLayouts.size()),
|
||||||
|
.pSetLayouts = filteredDescriptorSetLayouts.data(),
|
||||||
|
.pushConstantRangeCount = static_cast<u32>(m_PushConstants.size()),
|
||||||
|
.pPushConstantRanges = m_PushConstants.data(),
|
||||||
|
};
|
||||||
|
AbortIfFailed(m_Device->m_Device->createPipelineLayout(&createInfo, nullptr, &pipelineLayout));
|
||||||
|
|
||||||
|
return pipelineLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::DescriptorSetLayout
|
||||||
|
PipelineLayoutBuilder::CreateDescriptorSetLayout(const vk::DescriptorSetLayoutCreateInfo &createInfo) const
|
||||||
|
{
|
||||||
|
vk::DescriptorSetLayout dsl;
|
||||||
|
// Failure Cases are OoM errors. No recovery.
|
||||||
|
AbortIfFailed(m_Device->m_Device->createDescriptorSetLayout(&createInfo, nullptr, &dsl));
|
||||||
|
return dsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PipelineLayoutBuilder::AddDescriptorSetForParameterBlock(slang::TypeLayoutReflection *layout)
|
||||||
|
{
|
||||||
|
DescriptorLayoutBuilder descriptorLayoutBuilder{this};
|
||||||
|
descriptorLayoutBuilder.AddRangesForParamBlockElement(layout->getElementTypeLayout());
|
||||||
|
descriptorLayoutBuilder.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PipelineLayoutBuilder::AddPushConstantRangeForConstantBuffer(slang::TypeLayoutReflection *layout)
|
||||||
|
{
|
||||||
|
const auto elementTypeLayout = layout->getElementTypeLayout();
|
||||||
|
const auto elementSize = elementTypeLayout->getSize();
|
||||||
|
|
||||||
|
if (elementSize == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_PushConstants.push_back({
|
||||||
|
.stageFlags = m_Stage,
|
||||||
|
.offset = 0,
|
||||||
|
.size = static_cast<u32>(elementSize),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PipelineLayoutBuilder::AddSubObjectRange(slang::TypeLayoutReflection *layout, i64 subObjectRangeIndex)
|
||||||
|
{
|
||||||
|
auto bindingRangeIndex = layout->getSubObjectRangeBindingRangeIndex(subObjectRangeIndex);
|
||||||
|
switch (layout->getBindingRangeType(bindingRangeIndex))
|
||||||
|
{
|
||||||
|
case slang::BindingType::ParameterBlock: {
|
||||||
|
const auto parameterBlockTypeLayout = layout->getBindingRangeLeafTypeLayout(bindingRangeIndex);
|
||||||
|
|
||||||
|
AddDescriptorSetForParameterBlock(parameterBlockTypeLayout);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case slang::BindingType::PushConstant: {
|
||||||
|
const auto constantBufferTypeLayout = layout->getBindingRangeLeafTypeLayout(bindingRangeIndex);
|
||||||
|
AddPushConstantRangeForConstantBuffer(constantBufferTypeLayout);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE("Unexpected types");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::DescriptorType
|
||||||
|
BindingTypeToDescriptorType(slang::BindingType binding)
|
||||||
|
{
|
||||||
|
using vk::DescriptorType;
|
||||||
|
switch (binding)
|
||||||
|
{
|
||||||
|
case slang::BindingType::Sampler:
|
||||||
|
return DescriptorType::eSampler;
|
||||||
|
case slang::BindingType::Texture:
|
||||||
|
return DescriptorType::eSampledImage;
|
||||||
|
case slang::BindingType::ConstantBuffer:
|
||||||
|
return DescriptorType::eUniformBuffer;
|
||||||
|
case slang::BindingType::TypedBuffer:
|
||||||
|
return DescriptorType::eStorageBuffer;
|
||||||
|
case slang::BindingType::RawBuffer:
|
||||||
|
return DescriptorType::eStorageBuffer;
|
||||||
|
case slang::BindingType::CombinedTextureSampler:
|
||||||
|
return DescriptorType::eCombinedImageSampler;
|
||||||
|
case slang::BindingType::InlineUniformData:
|
||||||
|
return DescriptorType::eInlineUniformBlock;
|
||||||
|
case slang::BindingType::RayTracingAccelerationStructure:
|
||||||
|
return DescriptorType::eAccelerationStructureKHR;
|
||||||
|
case slang::BindingType::MutableTexture:
|
||||||
|
return DescriptorType::eStorageImage;
|
||||||
|
case slang::BindingType::MutableTypedBuffer:
|
||||||
|
return DescriptorType::eStorageBuffer;
|
||||||
|
case slang::BindingType::MutableRawBuffer:
|
||||||
|
return DescriptorType::eStorageBuffer;
|
||||||
|
default:
|
||||||
|
UNREACHABLE("Unsupported Types");
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
vk::ShaderStageFlags &
|
||||||
|
DescriptorLayoutBuilder::Stage() const
|
||||||
|
{
|
||||||
|
return m_PipelineLayoutBuilder->m_Stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorLayoutBuilder::DescriptorLayoutBuilder(PipelineLayoutBuilder *pipelineLayoutBuilder)
|
||||||
|
: m_PipelineLayoutBuilder{pipelineLayoutBuilder}
|
||||||
|
, m_SetIndex{static_cast<u32>(pipelineLayoutBuilder->m_DescriptorSetLayouts.size())}
|
||||||
|
{
|
||||||
|
m_PipelineLayoutBuilder->m_DescriptorSetLayouts.push_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddDescriptorRange(slang::TypeLayoutReflection *layout, const i64 relativeSetIndex,
|
||||||
|
const i64 rangeIndex)
|
||||||
|
{
|
||||||
|
const auto bindingType = layout->getDescriptorSetDescriptorRangeType(relativeSetIndex, rangeIndex);
|
||||||
|
|
||||||
|
if (bindingType == slang::BindingType::PushConstant)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const u32 descriptorCount =
|
||||||
|
static_cast<u32>(layout->getDescriptorSetDescriptorRangeDescriptorCount(relativeSetIndex, rangeIndex));
|
||||||
|
|
||||||
|
const u32 bindingIndex = static_cast<u32>(m_LayoutBindings.size());
|
||||||
|
const auto vkBindingType = BindingTypeToDescriptorType(bindingType);
|
||||||
|
|
||||||
|
m_LayoutBindings.push_back({
|
||||||
|
.binding = bindingIndex,
|
||||||
|
.descriptorType = vkBindingType,
|
||||||
|
.descriptorCount = descriptorCount,
|
||||||
|
.stageFlags = Stage(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddDescriptorRanges(slang::TypeLayoutReflection *layout)
|
||||||
|
{
|
||||||
|
i64 nSets = layout->getDescriptorSetCount();
|
||||||
|
for (i64 relativeSetIndex = 0; relativeSetIndex < nSets; ++relativeSetIndex)
|
||||||
|
{
|
||||||
|
i64 rangeCount = layout->getDescriptorSetDescriptorRangeCount(relativeSetIndex);
|
||||||
|
|
||||||
|
for (i64 rangeIndex = 0; rangeIndex < rangeCount; ++rangeIndex)
|
||||||
|
{
|
||||||
|
AddDescriptorRange(layout, relativeSetIndex, rangeIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::Build()
|
||||||
|
{
|
||||||
|
if (m_LayoutBindings.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto dsl = m_PipelineLayoutBuilder->CreateDescriptorSetLayout({
|
||||||
|
.bindingCount = static_cast<u32>(m_LayoutBindings.size()),
|
||||||
|
.pBindings = m_LayoutBindings.data(),
|
||||||
|
});
|
||||||
|
m_PipelineLayoutBuilder->m_DescriptorSetLayouts[m_SetIndex] = dsl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddAutomaticallyIntroducedUniformBuffer()
|
||||||
|
{
|
||||||
|
const auto vulkanBindingIndex = static_cast<u32>(m_LayoutBindings.size());
|
||||||
|
|
||||||
|
m_LayoutBindings.push_back({
|
||||||
|
.binding = vulkanBindingIndex,
|
||||||
|
.descriptorType = vk::DescriptorType::eUniformBuffer,
|
||||||
|
.descriptorCount = 1,
|
||||||
|
.stageFlags = vk::ShaderStageFlagBits::eAll,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddRanges(slang::TypeLayoutReflection *layout)
|
||||||
|
{
|
||||||
|
AddDescriptorRanges(layout);
|
||||||
|
m_PipelineLayoutBuilder->AddSubObjectRanges(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddRangesForParamBlockElement(slang::TypeLayoutReflection *layout)
|
||||||
|
{
|
||||||
|
if (layout->getSize() > 0)
|
||||||
|
{
|
||||||
|
AddAutomaticallyIntroducedUniformBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
AddRanges(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddGlobalScopeParameters(slang::ProgramLayout *layout)
|
||||||
|
{
|
||||||
|
Stage() = vk::ShaderStageFlagBits::eAll;
|
||||||
|
AddRangesForParamBlockElement(layout->getGlobalParamsTypeLayout());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddEntryPointParameters(slang::ProgramLayout *layout)
|
||||||
|
{
|
||||||
|
u64 entryPointCount = layout->getEntryPointCount();
|
||||||
|
for (u64 i = 0; i < entryPointCount; ++i)
|
||||||
|
{
|
||||||
|
auto *entryPoint = layout->getEntryPointByIndex(i);
|
||||||
|
AddEntryPointParameters(entryPoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
DescriptorLayoutBuilder::AddEntryPointParameters(slang::EntryPointLayout *layout)
|
||||||
|
{
|
||||||
|
Stage() = SlangToVulkanShaderStage(layout->getStage());
|
||||||
|
|
||||||
|
AddRangesForParamBlockElement(layout->getTypeLayout());
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PipelineLayoutBuilder::AddSubObjectRanges(slang::TypeLayoutReflection *layout)
|
||||||
|
{
|
||||||
|
i64 subObjectRangeCount = layout->getSubObjectRangeCount();
|
||||||
|
for (i64 subObjectRangeIndex = 0; subObjectRangeIndex < subObjectRangeCount; ++subObjectRangeIndex)
|
||||||
|
{
|
||||||
|
AddSubObjectRange(layout, subObjectRangeIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -86,7 +86,7 @@ struct Camera
|
||||||
int
|
int
|
||||||
main(int, char **)
|
main(int, char **)
|
||||||
{
|
{
|
||||||
MIN_LOG_LEVEL(Logger::LogType::eInfo);
|
MIN_LOG_LEVEL(Logger::LogType::eDebug);
|
||||||
|
|
||||||
Window window = {"Box (Aster)", {640, 480}};
|
Window window = {"Box (Aster)", {640, 480}};
|
||||||
|
|
||||||
|
|
@ -125,7 +125,7 @@ main(int, char **)
|
||||||
{.m_ShaderFile = SHADER_FILE, .m_EntryPoints = {"vsmain", "fsmain"}},
|
{.m_ShaderFile = SHADER_FILE, .m_EntryPoints = {"vsmain", "fsmain"}},
|
||||||
}});
|
}});
|
||||||
ERROR_IF(pipelineResult, "Could not create pipeline. Cause: {}", pipelineResult.What())
|
ERROR_IF(pipelineResult, "Could not create pipeline. Cause: {}", pipelineResult.What())
|
||||||
THEN_ABORT(pipelineResult.uNone);
|
THEN_ABORT(pipelineResult.Value());
|
||||||
|
|
||||||
auto swapchainSize = device.GetSwapchainSize();
|
auto swapchainSize = device.GetSwapchainSize();
|
||||||
Camera camera = {
|
Camera camera = {
|
||||||
|
|
@ -229,8 +229,8 @@ main(int, char **)
|
||||||
.dstAccessMask = vk::AccessFlagBits2::eShaderRead,
|
.dstAccessMask = vk::AccessFlagBits2::eShaderRead,
|
||||||
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
.oldLayout = vk::ImageLayout::eTransferDstOptimal,
|
||||||
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
.newLayout = vk::ImageLayout::eShaderReadOnlyOptimal,
|
||||||
.srcQueueFamilyIndex = vk::QueueFamilyIgnored,
|
.srcQueueFamilyIndex = device.m_TransferQueueFamily,
|
||||||
.dstQueueFamilyIndex = vk::QueueFamilyIgnored,
|
.dstQueueFamilyIndex = device.m_PrimaryQueueFamily,
|
||||||
.image = crate->GetImage(),
|
.image = crate->GetImage(),
|
||||||
.subresourceRange =
|
.subresourceRange =
|
||||||
{
|
{
|
||||||
|
|
@ -326,11 +326,8 @@ main(int, char **)
|
||||||
struct PCB
|
struct PCB
|
||||||
{
|
{
|
||||||
systems::ResId<Buffer> m_VertexBuffer;
|
systems::ResId<Buffer> m_VertexBuffer;
|
||||||
u32 m_Pad0 = 0;
|
|
||||||
systems::ResId<Buffer> m_Camera;
|
systems::ResId<Buffer> m_Camera;
|
||||||
u32 m_Pad1 = 0;
|
|
||||||
systems::ResId<TextureView> m_Texture;
|
systems::ResId<TextureView> m_Texture;
|
||||||
u32 m_Pad2 = 0;
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PCB) == 24);
|
static_assert(sizeof(PCB) == 24);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,6 @@ struct PCB {
|
||||||
DescriptorHandle<Sampler2D> texture;
|
DescriptorHandle<Sampler2D> texture;
|
||||||
};
|
};
|
||||||
|
|
||||||
//uniform CameraData camera;
|
|
||||||
[vk::push_constant]
|
[vk::push_constant]
|
||||||
uniform PCB pcb;
|
uniform PCB pcb;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue