Skip to content

Commit

Permalink
feat: add global shader input component
Browse files Browse the repository at this point in the history
  • Loading branch information
Silverlan committed Dec 22, 2024
1 parent 09f8352 commit b7a88ac
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/* 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 http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2024 Silverlan
*/

#ifndef __C_GLOBAL_SHADER_INPUT_HPP__
#define __C_GLOBAL_SHADER_INPUT_HPP__

#include "pragma/clientdefinitions.h"
#include "pragma/rendering/global_shader_input_manager.hpp"
#include "pragma/entities/components/base_entity_component_member_register.hpp"
#include <pragma/entities/components/base_entity_component.hpp>

namespace pragma {
namespace rendering {
class GlobalShaderInputDataManager;
};
class DLLCLIENT CGlobalShaderInputComponent final : public BaseEntityComponent, public DynamicMemberRegister {
public:
static void RegisterLuaBindings(lua_State *l, luabind::module_ &modEnts);

CGlobalShaderInputComponent(BaseEntity &ent) : BaseEntityComponent(ent) {}

virtual void Initialize() override;
virtual void InitializeLuaObject(lua_State *l) override;
virtual void OnEntitySpawn() override;

template<typename T>
bool SetShaderInputValue(const std::string_view &name, const T &val)
{
auto &inputManager = GetInputManager();
return inputManager.SetValue<T>(name, val);
}

template<typename T>
bool GetShaderInputValue(const std::string_view &name, T &outVal) const
{
auto &inputManager = GetInputManager();
return inputManager.GetValue<T>(name, outVal);
}

virtual const ComponentMemberInfo *GetMemberInfo(ComponentMemberIndex idx) const override;
private:
virtual std::optional<ComponentMemberIndex> DoGetMemberIndex(const std::string &name) const override;
rendering::GlobalShaderInputDataManager &GetInputManager();
const rendering::GlobalShaderInputDataManager &GetInputManager() const { return const_cast<CGlobalShaderInputComponent *>(this)->GetInputManager(); }
void UpdateComponentMembers();
std::vector<std::string> m_inputVarNames;
};
};

#endif
5 changes: 5 additions & 0 deletions core/client/include/pragma/game/c_game.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ namespace pragma {
namespace rendering {
class RenderQueueBuilder;
class RenderQueueWorkerManager;
class GlobalShaderInputDataManager;
struct GameWorldShaderSettings;
struct GlobalRenderSettingsBufferData;
};
Expand Down Expand Up @@ -397,6 +398,9 @@ class DLLCLIENT CGame : public Game {
void ResetGameplayControlCamera();
pragma::CCameraComponent *GetGameplayControlCamera();

pragma::rendering::GlobalShaderInputDataManager &GetGlobalShaderInputDataManager();
const pragma::rendering::GlobalShaderInputDataManager &GetGlobalShaderInputDataManager() const;

pragma::rendering::RenderQueueBuilder &GetRenderQueueBuilder();
pragma::rendering::RenderQueueWorkerManager &GetRenderQueueWorkerManager();
prosper::IDescriptorSet &GetGlobalRenderSettingsDescriptorSet();
Expand Down Expand Up @@ -486,6 +490,7 @@ class DLLCLIENT CGame : public Game {
std::vector<util::DrawSceneInfo> m_sceneRenderQueue {};
std::shared_ptr<pragma::rendering::RenderQueueBuilder> m_renderQueueBuilder = nullptr;
std::shared_ptr<pragma::rendering::RenderQueueWorkerManager> m_renderQueueWorkerManager = nullptr;
std::unique_ptr<pragma::rendering::GlobalShaderInputDataManager> m_globalShaderInputDataManager;
Vector4 m_clipPlane = {};
Vector4 m_colScale = {};
Material *m_matOverride = nullptr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* Copyright (c) 2024 Silverlan
*/

#ifndef __PRAGMA_GLOBAL_RENDER_SETTINGS_BUFFER_DATA_HPP__
#define __PRAGMA_GLOBAL_RENDER_SETTINGS_BUFFER_DATA_HPP__
#ifndef __PRAGMA_GLOBAL_SHADER_INPUT_MANAGER_HPP__
#define __PRAGMA_GLOBAL_SHADER_INPUT_MANAGER_HPP__

#include "pragma/clientdefinitions.h"
#include "pragma/rendering/shader_material/shader_material.hpp"
Expand Down Expand Up @@ -73,6 +73,20 @@ namespace pragma::rendering {
m_dirtyTracker.MarkRange(prop->offset, sizeof(T));
return true;
}

template<typename T>
bool GetValue(const std::string_view &name, T &outVal) const
{
auto *prop = m_inputDescriptor->FindProperty(name.data());
if(!prop)
return false;
auto val = m_inputData->GetValue<T>(name.data());
if(!val)
return false;
outVal = *val;
return true;
}

const pragma::rendering::ShaderInputData &GetData() const { return *m_inputData; }
const pragma::rendering::ShaderInputDescriptor &GetDescriptor() const { return *m_inputDescriptor; }
const std::shared_ptr<prosper::IBuffer> &GetBuffer() const { return m_inputDataBuffer; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ namespace pragma::rendering {
namespace pragma::rendering::shader_graph {
class DLLCLIENT InputDataModule : public pragma::rendering::ShaderGraphModule {
public:
static void set_shader_input_value(const std::string &name, float val);
static void set_shader_input_value(const std::string &name, const Vector3 &val);
InputDataModule(prosper::Shader &shader);
virtual ~InputDataModule() override;
virtual void InitializeGfxPipelineDescriptorSets() override;
Expand All @@ -34,7 +32,6 @@ namespace pragma::rendering::shader_graph {
private:
prosper::DescriptorSetInfo m_globalInputDataDsInfo;
std::shared_ptr<prosper::IDescriptorSetGroup> m_globalInputDsg;
static size_t g_instanceCount;
};
};

Expand Down
91 changes: 91 additions & 0 deletions core/client/src/entities/components/c_global_shader_input.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/* 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 http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2024 Silverlan
*/

#include "stdafx_client.h"
#include "pragma/entities/components/c_global_shader_input.hpp"
#include "pragma/rendering/global_shader_input_manager.hpp"
#include "pragma/lua/lua_util_component.hpp"
#include <pragma/entities/entity_component_manager_t.hpp>
#include <pragma/lua/converters/game_type_converters_t.hpp>

extern DLLCLIENT CGame *c_game;
extern DLLCLIENT CEngine *c_engine;

using namespace pragma;
void CGlobalShaderInputComponent::RegisterLuaBindings(lua_State *l, luabind::module_ &modEnts)
{
auto def = pragma::lua::create_entity_component_class<pragma::CGlobalShaderInputComponent, pragma::BaseEntityComponent>("GlobalShaderInputComponent");
modEnts[def];
}

void CGlobalShaderInputComponent::InitializeLuaObject(lua_State *l) { return BaseEntityComponent::InitializeLuaObject<std::remove_reference_t<decltype(*this)>>(l); }

void CGlobalShaderInputComponent::Initialize() { BaseEntityComponent::Initialize(); }

const ComponentMemberInfo *CGlobalShaderInputComponent::GetMemberInfo(ComponentMemberIndex idx) const
{
auto numStatic = GetStaticMemberCount();
if(idx < numStatic)
return BaseEntityComponent::GetMemberInfo(idx);
return DynamicMemberRegister::GetMemberInfo(idx);
}

std::optional<ComponentMemberIndex> CGlobalShaderInputComponent::DoGetMemberIndex(const std::string &name) const
{
auto idx = BaseEntityComponent::DoGetMemberIndex(name);
if(idx.has_value())
return idx;
idx = DynamicMemberRegister::GetMemberIndex(name);
if(idx.has_value())
return *idx; // +GetStaticMemberCount();
return std::optional<ComponentMemberIndex> {};
}

rendering::GlobalShaderInputDataManager &CGlobalShaderInputComponent::GetInputManager() { return c_game->GetGlobalShaderInputDataManager(); }

void CGlobalShaderInputComponent::OnEntitySpawn()
{
BaseEntityComponent::OnEntitySpawn();
UpdateComponentMembers();
}

void CGlobalShaderInputComponent::UpdateComponentMembers()
{
auto &inputManager = c_game->GetGlobalShaderInputDataManager();
auto &descriptor = inputManager.GetDescriptor();
ReserveMembers(descriptor.properties.size());
m_inputVarNames.reserve(m_inputVarNames.size() + descriptor.properties.size());
for(auto &prop : descriptor.properties) {
auto idx = BaseEntityComponent::GetMemberIndex(prop->name);
if(idx.has_value())
continue;
auto memberInfo = pragma::ComponentMemberInfo::CreateDummy();
memberInfo.SetName(prop->name);
memberInfo.type = static_cast<ents::EntityMemberType>(shadergraph::to_udm_type(prop.parameter.type));
memberInfo.SetMin(prop->min);
memberInfo.SetMax(prop->max);
m_inputVarNames.push_back(prop->name);
idx = m_inputVarNames.size() - 1;
memberInfo.userIndex = *idx;

using TComponent = CGlobalShaderInputComponent;
pragma::shadergraph::visit(prop->type, [this, &memberInfo](auto tag) {
using T = typename decltype(tag)::type;
memberInfo.SetGetterFunction<TComponent, T, static_cast<void (*)(const pragma::ComponentMemberInfo &, TComponent &, T &)>([](const pragma::ComponentMemberInfo &memberInfo, TComponent &component, T &outValue) {
auto &name = component.m_inputVarNames[memberInfo.userIndex];
component.GetShaderInputValue(name, outValue);
})>();
memberInfo.SetSetterFunction<TComponent, T, static_cast<void (*)(const pragma::ComponentMemberInfo &, TComponent &, const T &)>([](const pragma::ComponentMemberInfo &memberInfo, TComponent &component, const T &value) {
auto &name = component.m_inputVarNames[memberInfo.userIndex];
component.SetShaderInputValue(name, value);
})>();
});

RegisterMember(std::move(memberInfo));
}
OnMembersChanged();
}
6 changes: 6 additions & 0 deletions core/client/src/game/c_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
#include "pragma/rendering/renderers/raytracing_renderer.hpp"
#include "pragma/rendering/render_queue_worker.hpp"
#include "pragma/rendering/global_render_settings_buffer_data.hpp"
#include "pragma/rendering/global_shader_input_manager.hpp"
#include "pragma/ai/c_navsystem.h"
#include <texturemanager/texturemanager.h>
#include <pragma/physics/environment.hpp>
Expand Down Expand Up @@ -257,6 +258,8 @@ CGame::CGame(NetworkState *state)
m_renderQueueBuilder = std::make_unique<pragma::rendering::RenderQueueBuilder>();
m_renderQueueWorkerManager = std::make_unique<pragma::rendering::RenderQueueWorkerManager>(umath::clamp(cvWorkerThreadCount->GetInt(), 1, 20));

m_globalShaderInputDataManager = std::make_unique<pragma::rendering::GlobalShaderInputDataManager>();

auto &texManager = static_cast<msys::CMaterialManager &>(static_cast<ClientState *>(GetNetworkState())->GetMaterialManager()).GetTextureManager();
for(auto &tex : g_requiredGameTextures) {
texManager.LoadAsset(tex); // Pre-loaded in ClientState constructor
Expand Down Expand Up @@ -327,6 +330,9 @@ void CGame::OnRemove()
Game::OnRemove();
}

pragma::rendering::GlobalShaderInputDataManager &CGame::GetGlobalShaderInputDataManager() { return *m_globalShaderInputDataManager; }
const pragma::rendering::GlobalShaderInputDataManager &CGame::GetGlobalShaderInputDataManager() const { return const_cast<CGame *>(this)->GetGlobalShaderInputDataManager(); }

void CGame::GetRegisteredEntities(std::vector<std::string> &classes, std::vector<std::string> &luaClasses) const
{
std::unordered_map<std::string, CBaseEntity *(*)(void)> *factories = nullptr;
Expand Down
3 changes: 3 additions & 0 deletions core/client/src/game/c_game_components.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "pragma/entities/components/c_optical_camera_component.hpp"
#include "pragma/entities/components/c_hitbox_bvh_component.hpp"
#include "pragma/entities/components/c_input_component.hpp"
#include "pragma/entities/components/c_global_shader_input.hpp"
#include "pragma/entities/components/liquid/c_buoyancy_component.hpp"
#include "pragma/entities/components/liquid/c_liquid_surface_component.hpp"
#include "pragma/entities/components/liquid/c_liquid_volume_component.hpp"
Expand Down Expand Up @@ -297,6 +298,8 @@ void CGame::InitializeEntityComponents(pragma::EntityComponentManager &component
componentManager.RegisterComponentType<pragma::CLiquidControlComponent>("liquid_control", {"physics/fluid", hideInEditor});
componentManager.RegisterComponentType<pragma::CLiquidSurfaceSimulationComponent>("liquid_surface_simulation", {"physics/fluid", hideInEditor});

componentManager.RegisterComponentType<pragma::CGlobalShaderInputComponent>("global_shader_input", {"rendering"});

componentManager.RegisterComponentType<pragma::CDebugHitboxComponent>("debug_hitbox", {"debug"});
// --template-component-register-location

Expand Down
4 changes: 0 additions & 4 deletions core/client/src/lua/c_luaclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,12 +133,8 @@ static luabind::object shader_mat_value_to_lua_object(lua_State *l, const pragma
});
}

#include "pragma/rendering/shader_graph/modules/input_data.hpp"
static void register_shader_graph(lua_State *l, luabind::module_ &modShader)
{
modShader[luabind::def("set_shader_input_value", static_cast<void (*)(const std::string &, float)>(&pragma::rendering::shader_graph::InputDataModule::set_shader_input_value))];
modShader[luabind::def("set_shader_input_value", static_cast<void (*)(const std::string &, const Vector3 &)>(&pragma::rendering::shader_graph::InputDataModule::set_shader_input_value))];

modShader[luabind::def(
"get_test_node_register", +[]() -> std::shared_ptr<pragma::shadergraph::NodeRegistry> {
auto reg = std::make_shared<pragma::shadergraph::NodeRegistry>();
Expand Down
4 changes: 4 additions & 0 deletions core/client/src/rendering/c_render.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "pragma/entities/components/c_player_component.hpp"
#include <wgui/wgui.h>
#include "pragma/rendering/renderers/rasterization_renderer.hpp"
#include "pragma/rendering/global_shader_input_manager.hpp"
#include "pragma/console/c_cvar.h"
#include "pragma/console/c_cvar_global_functions.h"
#include "pragma/entities/components/c_vehicle_component.hpp"
Expand Down Expand Up @@ -350,6 +351,9 @@ void CGame::RenderScenes(util::DrawSceneInfo &drawSceneInfo)
GetGlobalRenderSettingsBufferData().EvaluateDebugPrint();
#endif

auto &inputDataManager = GetGlobalShaderInputDataManager();
inputDataManager.UpdateBufferData(*drawSceneInfo.commandBuffer);

StartProfilingStage("RenderScenes");
util::ScopeGuard sg {[this]() {
StopProfilingStage(); // RenderScenes
Expand Down
32 changes: 9 additions & 23 deletions core/client/src/rendering/shader_graph/modules/input_data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,40 +18,25 @@
using namespace pragma::rendering::shader_graph;

extern DLLCLIENT CEngine *c_engine;
extern DLLCLIENT CGame *c_game;

static std::unique_ptr<pragma::rendering::GlobalShaderInputDataManager> g_globalShaderInputDataManager {};
size_t InputDataModule::g_instanceCount = 0;
InputDataModule::InputDataModule(prosper::Shader &shader) : pragma::rendering::ShaderGraphModule {shader}
{
if(g_instanceCount == 0)
g_globalShaderInputDataManager = std::make_unique<pragma::rendering::GlobalShaderInputDataManager>();
m_globalInputDataDsInfo = {
"SHADER_GRAPH",
{prosper::DescriptorSetInfo::Binding {"GLOBAL_INPUT_DATA", prosper::DescriptorType::UniformBuffer, prosper::ShaderStageFlags::FragmentBit | prosper::ShaderStageFlags::VertexBit | prosper::ShaderStageFlags::GeometryBit}},
};
}
InputDataModule::~InputDataModule()
{
if(--g_instanceCount == 0) {
g_globalShaderInputDataManager = nullptr;
}
}

void pragma::rendering::shader_graph::InputDataModule::set_shader_input_value(const std::string &name, float val)
{
g_globalShaderInputDataManager->SetValue<float>(name, val);

auto cmd = c_engine->GetRenderContext().GetSetupCommandBuffer();
g_globalShaderInputDataManager->UpdateBufferData(*cmd);
c_engine->GetRenderContext().FlushSetupCommandBuffer();
}
InputDataModule::~InputDataModule() {}

void InputDataModule::GetShaderPreprocessorDefinitions(std::unordered_map<std::string, std::string> &outDefinitions, std::string &outPrefixCode)
{
auto &inputDataManager = c_game->GetGlobalShaderInputDataManager();

std::ostringstream code;
code << "\nlayout(LAYOUT_ID(SHADER_GRAPH, GLOBAL_INPUT_DATA)) uniform GlobalInputData\n";
code << "{\n";
for(auto &prop : g_globalShaderInputDataManager->GetDescriptor().properties) {
for(auto &prop : inputDataManager.GetDescriptor().properties) {
if(prop.parameter.name.empty())
continue;
code << "\t" << pragma::shadergraph::to_glsl_type(prop.parameter.type) << " " << prop.parameter.name << ";\n";
Expand All @@ -62,11 +47,12 @@ void InputDataModule::GetShaderPreprocessorDefinitions(std::unordered_map<std::s

void InputDataModule::InitializeGfxPipelineDescriptorSets()
{
auto &inputDataManager = c_game->GetGlobalShaderInputDataManager();
// TODO:
auto testPbr = c_engine->GetShaderGraphManager().GetGraph("z");
g_globalShaderInputDataManager->PopulateProperties(*testPbr->GetGraph());
inputDataManager.PopulateProperties(*testPbr->GetGraph());
auto cmd = c_engine->GetRenderContext().GetSetupCommandBuffer();
g_globalShaderInputDataManager->UpdateBufferData(*cmd);
inputDataManager.UpdateBufferData(*cmd);
c_engine->GetRenderContext().FlushSetupCommandBuffer();

m_shader.AddDescriptorSetGroup(m_globalInputDataDsInfo);
Expand All @@ -79,7 +65,7 @@ void InputDataModule::InitializeGfxPipelineDescriptorSets()
auto &dummyCubemapTex = context.GetDummyCubemapTexture();
auto &ds = *m_globalInputDsg->GetDescriptorSet(0);
constexpr uint32_t BINDING_IDX = 0;
auto buf = g_globalShaderInputDataManager->GetBuffer();
auto buf = inputDataManager.GetBuffer();
if(!buf)
buf = c_engine->GetRenderContext().GetDummyBuffer();
ds.SetBindingUniformBuffer(*buf, BINDING_IDX);
Expand Down

0 comments on commit b7a88ac

Please sign in to comment.