Skip to content

Commit

Permalink
feat: various shader system improvements
Browse files Browse the repository at this point in the history
- Improve error messages
- shader descriptor sets are now named for automatic association with glsl code
- shader resources are now defined per-shader instead of per-pipeline
  • Loading branch information
Silverlan committed Sep 8, 2024
1 parent 077e937 commit bdb87de
Show file tree
Hide file tree
Showing 18 changed files with 307 additions and 119 deletions.
2 changes: 1 addition & 1 deletion include/prosper_context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ namespace prosper {
virtual std::shared_ptr<ShaderStageProgram> CompileShader(prosper::ShaderStage stage, const std::string &shaderPath, std::string &outInfoLog, std::string &outDebugInfoLog, bool reload = false, const std::unordered_map<std::string, std::string> &definitions = {}) = 0;
virtual std::optional<std::unordered_map<prosper::ShaderStage, std::string>> OptimizeShader(const std::unordered_map<prosper::ShaderStage, std::string> &shaderStages, std::string &outInfoLog) { return {}; }
virtual bool GetParsedShaderSourceCode(prosper::Shader &shader, std::vector<std::string> &outGlslCodePerStage, std::vector<prosper::ShaderStage> &outGlslCodeStages, std::string &outInfoLog, std::string &outDebugInfoLog, prosper::ShaderStage &outErrStage) const = 0;
std::optional<std::string> FindShaderFile(const std::string &fileName, std::string *optOutExt = nullptr);
std::optional<std::string> FindShaderFile(prosper::ShaderStage stage, const std::string &fileName, std::string *optOutExt = nullptr);
virtual std::optional<PipelineID> AddPipeline(prosper::Shader &shader, PipelineID shaderPipelineId, const prosper::ComputePipelineCreateInfo &createInfo, prosper::ShaderStageData &stage, PipelineID basePipelineId = std::numeric_limits<PipelineID>::max()) = 0;
virtual std::optional<PipelineID> AddPipeline(prosper::Shader &shader, PipelineID shaderPipelineId, const prosper::RayTracingPipelineCreateInfo &createInfo, prosper::ShaderStageData &stage, PipelineID basePipelineId = std::numeric_limits<PipelineID>::max()) = 0;
virtual std::optional<PipelineID> AddPipeline(prosper::Shader &shader, PipelineID shaderPipelineId, const prosper::GraphicsPipelineCreateInfo &createInfo, IRenderPass &rp, prosper::ShaderStageData *shaderStageFs = nullptr, prosper::ShaderStageData *shaderStageVs = nullptr,
Expand Down
5 changes: 4 additions & 1 deletion include/prosper_glsl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ namespace prosper {
std::string apiScreenSpaceTransform = "T"; // Arguments: T (mat4)
std::string apiDepthTransform = "T"; // Arguments: T (mat4)
};
DLLPROSPER std::optional<std::string> find_shader_file(const std::string &fileName, std::string *optOutExt = nullptr);
DLLPROSPER const std::vector<std::string> &get_glsl_file_extensions();
DLLPROSPER std::string get_shader_file_extension(prosper::ShaderStage stage);
DLLPROSPER bool is_glsl_file_extension(const std::string &ext);
DLLPROSPER std::optional<std::string> find_shader_file(prosper::ShaderStage stage, const std::string &fileName, std::string *optOutExt = nullptr);
DLLPROSPER void dump_parsed_shader(IPrContext &context, uint32_t stage, const std::string &shaderFile, const std::string &fileName);
DLLPROSPER std::optional<std::string> load_glsl(IPrContext &context, prosper::ShaderStage stage, const std::string &fileName, std::string *infoLog, std::string *debugInfoLog, std::vector<IncludeLine> &outIncludeLines, uint32_t &outLineOffset,
const std::unordered_map<std::string, std::string> &definitions = {}, bool applyPreprocessing = true);
Expand Down
33 changes: 21 additions & 12 deletions include/prosper_structs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -349,26 +349,26 @@ namespace prosper {

class DLLPROSPER DescriptorSetCreateInfo {
public:
static std::unique_ptr<DescriptorSetCreateInfo> Create()
static std::unique_ptr<DescriptorSetCreateInfo> Create(const char *name)
{
std::unique_ptr<DescriptorSetCreateInfo> result_ptr(nullptr, std::default_delete<DescriptorSetCreateInfo>());

result_ptr.reset(new DescriptorSetCreateInfo());

result_ptr->m_name = name;
return result_ptr;
}
struct DLLPROSPER Binding {
Binding() = default;
Binding(const Binding &other) = default;
Binding(uint32_t descriptorArraySize, DescriptorType descriptorType, ShaderStageFlags stageFlags, const ISampler *const *immutableSamplerPtrs, DescriptorBindingFlags flags, PrDescriptorSetBindingFlags prFlags)
: descriptorArraySize {descriptorArraySize}, descriptorType {descriptorType}, stageFlags {stageFlags}, flags {flags}, prFlags {prFlags}
Binding(const char *name, uint32_t descriptorArraySize, DescriptorType descriptorType, ShaderStageFlags stageFlags, const ISampler *const *immutableSamplerPtrs, DescriptorBindingFlags flags, PrDescriptorSetBindingFlags prFlags)
: name {name}, descriptorArraySize {descriptorArraySize}, descriptorType {descriptorType}, stageFlags {stageFlags}, flags {flags}, prFlags {prFlags}
{
if(immutableSamplerPtrs != nullptr) {
for(uint32_t n_sampler = 0; n_sampler < descriptorArraySize; ++n_sampler) {
immutableSamplers.push_back(immutableSamplerPtrs[n_sampler]);
}
}
}
const char *name = "";
uint32_t descriptorArraySize = 0;
DescriptorType descriptorType = DescriptorType::Unknown;
DescriptorBindingFlags flags {};
Expand All @@ -377,27 +377,30 @@ namespace prosper {
ShaderStageFlags stageFlags {};
bool operator==(const Binding &binding) const
{
return binding.descriptorArraySize == descriptorArraySize && binding.descriptorType == descriptorType && binding.flags == flags && binding.immutableSamplers == immutableSamplers && binding.stageFlags == stageFlags && binding.prFlags == prFlags;
return strcmp(binding.name, name) == 0 && binding.descriptorArraySize == descriptorArraySize && binding.descriptorType == descriptorType && binding.flags == flags && binding.immutableSamplers == immutableSamplers && binding.stageFlags == stageFlags
&& binding.prFlags == prFlags;
}
bool operator!=(const Binding &binding) const { return !operator==(binding); }
};
DescriptorSetCreateInfo(const DescriptorSetCreateInfo &other);
DescriptorSetCreateInfo &operator=(const DescriptorSetCreateInfo &other);
DescriptorSetCreateInfo(DescriptorSetCreateInfo &&other);
DescriptorSetCreateInfo &operator=(DescriptorSetCreateInfo &&other);
const char *GetName() const { return m_name; }

bool GetBindingPropertiesByBindingIndex(uint32_t bindingIndex, DescriptorType *outOptDescriptorType = nullptr, uint32_t *outOptDescriptorArraySize = nullptr, ShaderStageFlags *outOptStageFlags = nullptr, bool *outOptImmutableSamplersEnabled = nullptr,
DescriptorBindingFlags *outOptFlags = nullptr, PrDescriptorSetBindingFlags *outOptPrFlags = nullptr) const;
bool GetBindingPropertiesByIndexNumber(uint32_t nBinding, uint32_t *out_opt_binding_index_ptr = nullptr, DescriptorType *outOptDescriptorType = nullptr, uint32_t *outOptDescriptorArraySize = nullptr, ShaderStageFlags *outOptStageFlags = nullptr,
bool *outOptImmutableSamplersEnabled = nullptr, DescriptorBindingFlags *outOptFlags = nullptr, PrDescriptorSetBindingFlags *outOptPrFlags = nullptr);
bool AddBinding(uint32_t in_binding_index, DescriptorType in_descriptor_type, uint32_t in_descriptor_array_size, ShaderStageFlags in_stage_flags, const DescriptorBindingFlags &in_flags = DescriptorBindingFlags::None,
bool AddBinding(const char *name, uint32_t in_binding_index, DescriptorType in_descriptor_type, uint32_t in_descriptor_array_size, ShaderStageFlags in_stage_flags, const DescriptorBindingFlags &in_flags = DescriptorBindingFlags::None,
const PrDescriptorSetBindingFlags &in_pr_flags = PrDescriptorSetBindingFlags::None, const ISampler *const *in_opt_immutable_sampler_ptr_ptr = nullptr);
const char *GetBindingName(uint32_t in_binding_index) const;
uint32_t GetBindingCount() const { return static_cast<uint32_t>(m_bindings.size()); }
private:
using BindingIndexToBindingMap = std::map<BindingIndex, Binding>;

DescriptorSetCreateInfo() = default;

const char *m_name = "";
BindingIndexToBindingMap m_bindings {};

uint32_t m_numVariableDescriptorCountBinding = std::numeric_limits<uint32_t>::max();
Expand Down Expand Up @@ -712,8 +715,9 @@ namespace prosper {
struct DLLPROSPER DescriptorSetInfoBinding {
DescriptorSetInfoBinding() = default;
// If 'bindingIndex' is not specified, it will use the index of the previous binding, incremented by the previous array size
DescriptorSetInfoBinding(DescriptorType type, ShaderStageFlags shaderStages, uint32_t descriptorArraySize = 1u, uint32_t bindingIndex = std::numeric_limits<uint32_t>::max(), PrDescriptorSetBindingFlags flags = PrDescriptorSetBindingFlags::None);
DescriptorSetInfoBinding(DescriptorType type, ShaderStageFlags shaderStages, PrDescriptorSetBindingFlags flags);
DescriptorSetInfoBinding(const char *name, DescriptorType type, ShaderStageFlags shaderStages, uint32_t descriptorArraySize = 1u, uint32_t bindingIndex = std::numeric_limits<uint32_t>::max(), PrDescriptorSetBindingFlags flags = PrDescriptorSetBindingFlags::None);
DescriptorSetInfoBinding(const char *name, DescriptorType type, ShaderStageFlags shaderStages, PrDescriptorSetBindingFlags flags);
const char *name = "";
DescriptorType type = {};
ShaderStageFlags shaderStages = ShaderStageFlags::All;
uint32_t bindingIndex = std::numeric_limits<uint32_t>::max();
Expand All @@ -724,11 +728,12 @@ namespace prosper {
struct DLLPROSPER DescriptorSetInfo {
using Binding = detail::DescriptorSetInfoBinding;
DescriptorSetInfo() = default;
DescriptorSetInfo(const std::vector<Binding> &bindings);
DescriptorSetInfo(const char *name, const std::vector<Binding> &bindings);
DescriptorSetInfo(const DescriptorSetInfo &) = default;
DescriptorSetInfo(DescriptorSetInfo *parent, const std::vector<Binding> &bindings = {});
bool WasBaked() const;
bool IsValid() const;
const char *GetName() const;
mutable DescriptorSetInfo *parent = nullptr;
std::vector<Binding> bindings;
uint32_t setIndex = 0u; // This value will be set after the shader has been baked
Expand All @@ -738,6 +743,7 @@ namespace prosper {
friend Shader;
std::unique_ptr<prosper::DescriptorSetCreateInfo> Bake();
bool m_bWasBaked = false;
const char *m_name = "";
};

class BasePipelineCreateInfo;
Expand All @@ -748,10 +754,13 @@ namespace prosper {
std::shared_ptr<IRenderPass> renderPass = nullptr; // Only used for graphics shader
std::string debugName;

std::vector<PushConstantRange> pushConstantRanges {};
// TODO: These should be unique_ptrs, but that results in compiler errors
// that I haven't been able to get around
std::shared_ptr<prosper::BasePipelineCreateInfo> createInfo = nullptr;
};

struct DLLPROSPER ShaderResources {
std::vector<PushConstantRange> pushConstantRanges {};
std::vector<std::shared_ptr<DescriptorSetCreateInfo>> descSetInfos {};
};
};
Expand Down
14 changes: 9 additions & 5 deletions include/shader/prosper_shader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ namespace prosper {
bool RecordPushConstants(ShaderBindState &bindState, const T &data, uint32_t offset = 0u) const;
bool RecordPushConstants(ShaderBindState &bindState, uint32_t size, const void *data, uint32_t offset = 0u) const;
bool RecordBindDescriptorSets(ShaderBindState &bindState, const std::vector<prosper::IDescriptorSet *> &descSets, uint32_t firstSet = 0u, const std::vector<uint32_t> &dynamicOffsets = {}) const;
void AddDescriptorSetGroup(prosper::BasePipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx, DescriptorSetInfo &descSetInfo);
bool AttachPushConstantRange(prosper::BasePipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx, uint32_t offset, uint32_t size, prosper::ShaderStageFlags stages);
void AddDescriptorSetGroup(DescriptorSetInfo &descSetInfo);
bool AttachPushConstantRange(uint32_t offset, uint32_t size, prosper::ShaderStageFlags stages);
virtual bool RecordBindDescriptorSet(ShaderBindState &bindState, prosper::IDescriptorSet &descSet, uint32_t firstSet = 0u, const std::vector<uint32_t> &dynamicOffsets = {}) const;

prosper::ShaderModule *GetModule(ShaderStage stage);
Expand All @@ -110,7 +110,7 @@ namespace prosper {
bool GetSourceFilePath(ShaderStage stage, std::string &sourceFilePath) const;
std::vector<std::string> GetSourceFilePaths() const;

std::shared_ptr<IDescriptorSetGroup> CreateDescriptorSetGroup(uint32_t setIdx, uint32_t pipelineIdx = 0u) const;
std::shared_ptr<IDescriptorSetGroup> CreateDescriptorSetGroup(uint32_t setIdx) const;

std::array<std::shared_ptr<ShaderStageData>, umath::to_integral(prosper::ShaderStage::Count)> &GetStages();

Expand All @@ -130,17 +130,20 @@ namespace prosper {
virtual void OnInitialized();
virtual void OnPipelinesInitialized();
virtual bool ShouldInitializePipeline(uint32_t pipelineIdx);
virtual void InitializeShaderResources() {};
virtual void ClearShaderResources();
void ClearPipelines();
prosper::PipelineID InitPipelineId(uint32_t pipelineIdx);
void FlushLoad() const;
std::vector<PipelineInfo> &GetPipelineInfos() { return m_pipelineInfos; }

ShaderStageData *GetStage(ShaderStage stage);
const ShaderStageData *GetStage(ShaderStage stage) const;
void InitializeDescriptorSetGroup(prosper::BasePipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx);
void InitializeDescriptorSetGroups(prosper::BasePipelineCreateInfo &pipelineInfo);
// Pipeline this pipeline is derived from
std::weak_ptr<Shader> m_basePipeline = {};
mutable bool m_loading = false;
ShaderResources m_shaderResources;

void SetIndex(ShaderIndex shaderIndex) { m_shaderIndex = shaderIndex; }
private:
Expand Down Expand Up @@ -216,7 +219,7 @@ namespace prosper {
bool RecordBindIndexBuffer(ShaderBindState &bindState, prosper::IBuffer &indexBuffer, prosper::IndexType indexType = prosper::IndexType::UInt16, DeviceSize offset = 0ull) const;
bool RecordDraw(ShaderBindState &bindState, uint32_t vertCount, uint32_t instanceCount = 1u, uint32_t firstVertex = 0u, uint32_t firstInstance = 0u) const;
bool RecordDrawIndexed(ShaderBindState &bindState, uint32_t indexCount, uint32_t instanceCount = 1u, uint32_t firstIndex = 0u, uint32_t firstInstance = 0u) const;
void AddVertexAttribute(prosper::GraphicsPipelineCreateInfo &pipelineInfo, VertexAttribute &attr);
void AddVertexAttribute(VertexAttribute &attr);
bool AddSpecializationConstant(prosper::GraphicsPipelineCreateInfo &pipelineInfo, prosper::ShaderStageFlags stageFlags, uint32_t constantId, uint32_t numBytes, const void *data);
template<typename T>
bool AddSpecializationConstant(prosper::GraphicsPipelineCreateInfo &pipelineInfo, prosper::ShaderStageFlags stageFlags, uint32_t constantId, const T &value)
Expand All @@ -238,6 +241,7 @@ namespace prosper {
void ToggleDynamicScissorState(prosper::GraphicsPipelineCreateInfo &pipelineInfo, bool bEnable);
virtual void InitializeGfxPipeline(prosper::GraphicsPipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx);
virtual void InitializeRenderPass(std::shared_ptr<IRenderPass> &outRenderPass, uint32_t pipelineIdx);
virtual void ClearShaderResources() override;

void CreateCachedRenderPass(size_t hashCode, const prosper::util::RenderPassCreateInfo &renderPassInfo, std::shared_ptr<IRenderPass> &outRenderPass, uint32_t pipelineIdx, const std::string &debugName = "");
template<class TShader>
Expand Down
4 changes: 2 additions & 2 deletions include/shader/prosper_shader_base_image_processing.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ namespace prosper {
bool RecordDraw(ShaderBindState &bindState, prosper::IDescriptorSet &descSetTexture) const;
virtual bool RecordDraw(ShaderBindState &bindState) const override;
protected:
void AddDefaultVertexAttributes(prosper::GraphicsPipelineCreateInfo &pipelineInfo);
virtual void InitializeGfxPipeline(prosper::GraphicsPipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx) override;
void AddDefaultVertexAttributes();
virtual void InitializeShaderResources() override;
virtual uint32_t GetTextureDescriptorSetIndex() const;
};
};
Expand Down
1 change: 1 addition & 0 deletions include/shader/prosper_shader_blur.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ namespace prosper {
protected:
virtual void InitializeRenderPass(std::shared_ptr<IRenderPass> &outRenderPass, uint32_t pipelineIdx) override;
virtual void InitializeGfxPipeline(prosper::GraphicsPipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx) override;
virtual void InitializeShaderResources() override;
};

/////////////////////////
Expand Down
1 change: 1 addition & 0 deletions include/shader/prosper_shader_rect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ namespace prosper {
bool RecordDraw(ShaderBindState &bindState, const Mat4 &modelMatrix) const;
protected:
virtual void InitializeGfxPipeline(prosper::GraphicsPipelineCreateInfo &pipelineInfo, uint32_t pipelineIdx) override;
virtual void InitializeShaderResources() override;
};
};

Expand Down
2 changes: 1 addition & 1 deletion src/prosper_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ void prosper::IPrContext::DrawFrame()

prosper::ShaderManager &prosper::IPrContext::GetShaderManager() const { return *m_shaderManager; }

std::optional<std::string> prosper::IPrContext::FindShaderFile(const std::string &fileName, std::string *optOutExt) { return prosper::glsl::find_shader_file(fileName, optOutExt); }
std::optional<std::string> prosper::IPrContext::FindShaderFile(prosper::ShaderStage stage, const std::string &fileName, std::string *optOutExt) { return prosper::glsl::find_shader_file(stage, fileName, optOutExt); }

void prosper::IPrContext::RegisterShader(const std::string &identifier, const std::function<Shader *(IPrContext &, const std::string &)> &fFactory) { return m_shaderManager->RegisterShader(identifier, fFactory); }
::util::WeakHandle<prosper::Shader> prosper::IPrContext::GetShader(const std::string &identifier) const { return m_shaderManager->GetShader(identifier); }
Expand Down
11 changes: 9 additions & 2 deletions src/prosper_descriptor_set_group.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ bool DescriptorSetCreateInfo::GetBindingPropertiesByIndexNumber(uint32_t nBindin
end:
return result;
}
bool DescriptorSetCreateInfo::AddBinding(uint32_t in_binding_index, DescriptorType in_descriptor_type, uint32_t in_descriptor_array_size, ShaderStageFlags in_stage_flags, const DescriptorBindingFlags &in_flags, const PrDescriptorSetBindingFlags &in_pr_flags,
bool DescriptorSetCreateInfo::AddBinding(const char *name, uint32_t in_binding_index, DescriptorType in_descriptor_type, uint32_t in_descriptor_array_size, ShaderStageFlags in_stage_flags, const DescriptorBindingFlags &in_flags, const PrDescriptorSetBindingFlags &in_pr_flags,
const ISampler *const *in_immutable_sampler_ptrs)
{
bool result = false;
Expand Down Expand Up @@ -188,12 +188,19 @@ bool DescriptorSetCreateInfo::AddBinding(uint32_t in_binding_index, DescriptorTy

/* Add a new binding entry and mark the layout as dirty, so that it is re-baked next time
* the user calls the getter func */
m_bindings[in_binding_index] = Binding(in_descriptor_array_size, in_descriptor_type, in_stage_flags, in_immutable_sampler_ptrs, in_flags, in_pr_flags);
m_bindings[in_binding_index] = Binding(name, in_descriptor_array_size, in_descriptor_type, in_stage_flags, in_immutable_sampler_ptrs, in_flags, in_pr_flags);

result = true;
end:
return result;
}
const char *DescriptorSetCreateInfo::GetBindingName(uint32_t in_binding_index) const
{
auto it = m_bindings.find(in_binding_index);
if(it == m_bindings.end())
return "";
return it->second.name;
}

/////////////////

Expand Down
Loading

0 comments on commit bdb87de

Please sign in to comment.