Skip to content

Commit

Permalink
[core] 3d: Refactor lib3d::Material
Browse files Browse the repository at this point in the history
  • Loading branch information
riidefi committed Jan 28, 2022
1 parent 9903062 commit 53139ef
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 51 deletions.
39 changes: 24 additions & 15 deletions source/core/3d/Material.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include <string> // std::string
#include <tuple> // std::pair<string, string>

#include <rsl/PubSub.hpp>

namespace librii::glhelper {
class DelegatedUBOBuilder;
}
Expand All @@ -17,15 +19,12 @@ struct Material;
class Scene;
class Model;

struct IObserver {
virtual ~IObserver() = default;
// TODO: Detach
virtual void update(Material* mat) {}

IObserver() = default;
IObserver(const IObserver&) = delete;
IObserver(IObserver&&) = delete;
struct MaterialEvents {
virtual void update(Material* mat) = 0;
};

using IObserver = typename rsl::Subscriber<MaterialEvents>;

struct Polygon;
struct Material : public virtual kpi::IObject {
virtual ~Material() = default;
Expand All @@ -44,13 +43,10 @@ struct Material : public virtual kpi::IObject {
std::vector<std::string>& textures) = 0;

// TODO: Better system..
void notifyObservers() {
for (auto* it : observers) {
assert(it != nullptr);
it->update(this);
}
}
void notifyObservers() { observers.publish(&MaterialEvents::update, this); }
void onUpdate() {
nextGenerationId();

// (for shader recompilation)
notifyObservers();
}
Expand All @@ -62,12 +58,25 @@ struct Material : public virtual kpi::IObject {
applyCacheAgain = rhs.applyCacheAgain;
return *this;
}
mutable std::vector<IObserver*> observers;
mutable rsl::PubSubChannel<MaterialEvents> observers;

mutable std::string cachedPixelShader;
mutable bool isShaderError = false;
mutable std::string shaderError;
mutable bool applyCacheAgain = false;

// Updating this value will force a cache invalidation. However, perhaps not
// all changes warrant a cache invalidation. If you had the base type, you
// could hold onto a copy of the old texture to determine if said update is
// necessary; but in that case, you wouldn't need this system anyway.
//
// The other issue is that it's up to the user to update the generation ID.
// However, that is also not resolved by using the observer system.
//
virtual s32 getGenerationId() const { return mGenerationId; }
virtual void nextGenerationId() { ++mGenerationId; }

s32 mGenerationId = 0;
};

} // namespace riistudio::lib3d
6 changes: 3 additions & 3 deletions source/frontend/properties/gc/Material/Common.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
before, after, [&](const auto& x) { return x.val; }, \
[&](auto& x, auto& y) { \
x.val = y; \
x.notifyObservers(); \
x.onUpdate(); \
})

#define AUTO_PROP(before, after) \
Expand Down Expand Up @@ -83,8 +83,8 @@ SamplerCombo(int current,

auto sid = std::string("Sampler ID"_j) + "##Img";
if (ImGui::BeginCombo(sid.c_str(), samplers.empty()
? "No Samplers"_j
: format(current).c_str())) {
? "No Samplers"_j
: format(current).c_str())) {
if (allow_none) {
bool selected = current = 0xff;
if (ImGui::Selectable("None"_j, selected)) {
Expand Down
66 changes: 33 additions & 33 deletions source/librii/g3d/gfx/G3dGfx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,27 @@ AddPolygonToVBO(librii::glhelper::VBOBuilder& vbo_builder,
return poly.propagate(mdl, mp_id, vbo_builder);
}

struct ShaderCompileError {
std::string desc;
};

inline std::variant<librii::glhelper::ShaderProgram, ShaderCompileError>
CompileMaterial(const lib3d::Material& _mat) {
DebugReport("Compiling shader for %s..\n", _mat.getName().c_str());
const auto shader_sources = _mat.generateShaders();
librii::glhelper::ShaderProgram new_shader(
shader_sources.first,
_mat.applyCacheAgain ? _mat.cachedPixelShader : shader_sources.second);
if (new_shader.getError()) {
_mat.isShaderError = true;
_mat.shaderError = new_shader.getErrorDesc();
return ShaderCompileError{.desc = _mat.shaderError};
}
_mat.isShaderError = false;

return new_shader;
}

struct CompiledLib3dTexture {
CompiledLib3dTexture() = default;
CompiledLib3dTexture(const lib3d::Texture& tex)
Expand Down Expand Up @@ -100,7 +121,7 @@ struct ObservableShader {

auto& getProgram() { return mImpl->mProgram; }
void attachToMaterial(const lib3d::Material& mat) {
mat.observers.push_back(mImpl.get());
mImpl->subscribe(mat.observers);
}

private:
Expand All @@ -112,18 +133,18 @@ struct ObservableShader {
librii::glhelper::ShaderProgram mProgram;

void update(lib3d::Material* _mat) final {
DebugReport("Recompiling shader for %s..\n", _mat->getName().c_str());
const auto shader_sources = _mat->generateShaders();
librii::glhelper::ShaderProgram new_shader(
shader_sources.first, _mat->applyCacheAgain ? _mat->cachedPixelShader
: shader_sources.second);
if (new_shader.getError()) {
_mat->isShaderError = true;
_mat->shaderError = new_shader.getErrorDesc();
assert(_mat != nullptr);

auto result = CompileMaterial(*_mat);
if (auto* shader = std::get_if<librii::glhelper::ShaderProgram>(&result);
shader != nullptr) {
mProgram = std::move(*shader);
return;
}
mProgram = std::move(new_shader);
_mat->isShaderError = false;

if (auto* err = std::get_if<ShaderCompileError>(&result);
err != nullptr) {
}
}
};
std::unique_ptr<Impl> mImpl;
Expand Down Expand Up @@ -160,27 +181,6 @@ struct GenericShaderCache_WithObserverUpdates {
}
};

struct ShaderCompileError {
std::string desc;
};

inline std::variant<librii::glhelper::ShaderProgram, ShaderCompileError>
CompileMaterial(const lib3d::Material* _mat) {
DebugReport("Compiling shader for %s..\n", _mat->getName().c_str());
const auto shader_sources = _mat->generateShaders();
librii::glhelper::ShaderProgram new_shader(
shader_sources.first,
_mat->applyCacheAgain ? _mat->cachedPixelShader : shader_sources.second);
if (new_shader.getError()) {
_mat->isShaderError = true;
_mat->shaderError = new_shader.getErrorDesc();
return ShaderCompileError{.desc = _mat->shaderError};
}
_mat->isShaderError = false;

return new_shader;
}

struct G3dShaderCache_WithUnusableHashingMechanism {
using MatData = riistudio::g3d::G3dMaterialData;

Expand All @@ -203,7 +203,7 @@ struct G3dShaderCache_WithUnusableHashingMechanism {
if (it != data.end())
return *it->second;

auto result = CompileMaterial(&mat);
auto result = CompileMaterial(mat);

if (auto* shader = std::get_if<librii::glhelper::ShaderProgram>(&result);
shader != nullptr) {
Expand Down

0 comments on commit 53139ef

Please sign in to comment.