chore: bring back support for pass commands

This commit is contained in:
Almamu 2025-08-19 21:44:25 +02:00
parent 4dc9a61223
commit d6831ad40f
7 changed files with 106 additions and 74 deletions

View File

@ -265,39 +265,47 @@ void StringPrinter::printEffect (const Effect& effect) {
void StringPrinter::printEffectPass (const EffectPass& effectPass) {
if (effectPass.command.has_value ()) {
const auto& command = effectPass.command.value ();
this->m_out << "Command: " << (*effectPass.command == Command_Copy ? "copy" : "swap");
this->m_out << "Command: " << (command.command == Command_Copy ? "copy" : "swap");
this->lineEnd ();
this->m_out << "Source: " << command.source;
this->lineEnd ();
this->m_out << "Target: " << command.target;
} else {
if (effectPass.target.has_value () || effectPass.source.has_value ()) {
this->lineEnd ();
}
}
if (effectPass.target.has_value ()) {
this->m_out << "Target: " << effectPass.target.value ();
if (effectPass.source.has_value ()) {
this->lineEnd ();
}
}
if (effectPass.source.has_value ()) {
this->m_out << "Source: " << effectPass.source.value ();
}
if (!effectPass.binds.empty ()) {
if (effectPass.target.has_value ()) {
this->m_out << "Target: " << effectPass.target.value ();
}
if (!effectPass.binds.empty ()) {
if (effectPass.target.has_value ()) {
this->lineEnd ();
}
this->m_out << "Binds count: " << effectPass.binds.size ();
this->increaseIndentation ();
for (const auto& bind : effectPass.binds) {
this->lineEnd ();
this->m_out << "Bind " << bind.first << ": " << bind.second;
}
this->decreaseIndentation ();
}
if (effectPass.target.has_value () || !effectPass.binds.empty ()) {
this->lineEnd ();
}
this->printMaterial (*effectPass.material);
this->m_out << "Binds count: " << effectPass.binds.size ();
this->increaseIndentation ();
for (const auto& bind : effectPass.binds) {
this->lineEnd ();
this->m_out << "Bind " << bind.first << ": " << bind.second;
}
this->decreaseIndentation ();
}
if (effectPass.target.has_value () || !effectPass.binds.empty ()) {
this->lineEnd ();
}
if (effectPass.material.has_value ()) {
this->printMaterial (**effectPass.material);
}
}

View File

@ -14,24 +14,18 @@ struct FBO {
std::string name;
std::string format;
float scale;
};
struct PassCommand {
/** The type of command to execute */
PassCommandType command;
/** The target of the command (where to draw to) */
std::string target;
/** The source of the command (where to draw from) */
std::string source;
bool unique;
};
struct EffectPass {
/** The material to use for this effect's pass */
MaterialUniquePtr material;
std::optional<MaterialUniquePtr> material;
/** Texture bindings for this effect's pass */
TextureMap binds;
/** The command this material executes (if specified) */
std::optional <PassCommand> command;
std::optional <PassCommandType> command;
/** The source this material renders from (if specified) */
std::optional <std::string> source;
/** The target this material renders to (if specified) */
std::optional <std::string> target;
};

View File

@ -52,27 +52,17 @@ std::vector <EffectPassUniquePtr> EffectParser::parseEffectPasses (const JSON& i
for (const auto& cur : it) {
const auto binds = cur.optional ("bind");
std::optional <PassCommand> command = std::nullopt;
const auto command = cur.optional ("command");
const auto material = cur.optional ("material");
if (cur.contains ("command")) {
command = {
.command = cur.require <std::string> ("command", "Material command must have a command") == "copy"
? Command_Copy
: Command_Swap,
.target = cur.require <std::string> ("target", "Material command must have a target"),
.source = cur.require <std::string> ("source", "Material command must have a source"),
};
}
// TODO: CAN TARGET BE SET IF MATERIAL IS SET?
result.push_back (std::make_unique <EffectPass> (EffectPass {
.material = MaterialParser::load (project, cur.require <std::string> ("material", "Effect pass must have a material")),
.material = material.has_value () ? MaterialParser::load (project, *material) : std::optional<MaterialUniquePtr> {},
.binds = binds.has_value () ? parseBinds (binds.value ()) : std::map<int, std::string> {},
.command = command,
// target is a bit special: if the material is a command this will be nullopt
// and the actual target will be set in the command itself, otherwise it will
// be set to whatever is in the json, which is not required to be present for
// normal materials
.target = command.has_value () ? std::nullopt : cur.optional <std::string> ("target"),
.command = command.has_value () ? (command.value () == "copy" ? Command_Copy : Command_Swap) : std::optional<PassCommandType> {},
.source = command.has_value () ? cur.require <std::string> ("source", "Effect command must have a source") : cur.optional <std::string> ("source"),
.target = command.has_value () ? cur.require <std::string> ("target", "Effect command must have a target") : cur.optional <std::string> ("target"),
}));
}
@ -108,6 +98,7 @@ std::vector <FBOUniquePtr> EffectParser::parseFBOs (const JSON& it) {
.name = cur.require <std::string> ("name", "FBO must have a name"),
.format = cur.optional <std::string> ("format", "rgba8888"),
.scale = cur.optional ("scale", 1.0f),
.unique = cur.optional ("unique", false),
}));
}

View File

@ -2,7 +2,6 @@
#include <sstream>
#include "WallpaperEngine/Data/Parsers/MaterialParser.h"
#include "WallpaperEngine/Data/Builders/UserSettingBuilder.h"
#include "WallpaperEngine/Data/Model/Object.h"
#include "WallpaperEngine/Data/Model/Material.h"
@ -245,7 +244,6 @@ void CImage::setup () {
new CPass (*this, std::make_shared<CFBOProvider>(this), *cur, std::nullopt, std::nullopt, std::nullopt)
);
// TODO: MAYBE GET RID OF THE WHOLE EFFECT CLASS AND PROCESS THE EFFECTS DIRECTLY TO SIMPLIFY RENDERING CODE?
// prepare the passes list
if (!this->getImage ().effects.empty ()) {
// generate the effects used by this material
@ -265,23 +263,63 @@ void CImage::setup () {
auto endOverride = cur->passOverrides.end ();
for (; curEffect != endEffect; curEffect++) {
auto curPass = (*curEffect)->material->passes.begin ();
auto endPass = (*curEffect)->material->passes.end ();
if (!(*curEffect)->material.has_value ()) {
if (!(*curEffect)->command.has_value ()) {
sLog.error ("Pass without material and command not supported");
continue;
}
const auto override = curOverride != endOverride
? **curOverride
: std::optional<std::reference_wrapper<const ImageEffectPassOverride>> (std::nullopt);
const auto target = (*curEffect)->target.has_value ()
? *(*curEffect)->target
: std::optional<std::reference_wrapper<std::string>> (std::nullopt);
if (!(*curEffect)->source.has_value ()) {
sLog.error ("Pass without material and source not supported");
continue;
}
this->m_passes.push_back (
new CPass (
*this, fboProvider, **curPass, override, (*curEffect)->binds, target)
);
if (!(*curEffect)->target.has_value ()) {
sLog.error ("Pass without material and target not supported");
continue;
}
if (curOverride != endOverride) {
curOverride ++;
if ((*curEffect)->command != Command_Copy) {
sLog.error ("Only copy command is supported for pass without material");
continue;
}
const auto virtualPass = MaterialPass {
.blending = "normal",
.cullmode = "nocull",
.depthtest = "disabled",
.depthwrite = "disabled",
.shader = "commands/copy",
.textures = {
{0, *(*curEffect)->source}
},
.combos = {}
};
const auto& config = this->m_virtualPassess.emplace_back (virtualPass);
// build a pass for a copy shader
this->m_passes.push_back (
new CPass (*this, fboProvider, config, std::nullopt, std::nullopt, (*curEffect)->target.value ())
);
} else {
auto curPass = (*curEffect)->material.value ()->passes.begin ();
auto endPass = (*curEffect)->material.value ()->passes.end ();
const auto override =
curOverride != endOverride
? **curOverride
: std::optional<std::reference_wrapper<const ImageEffectPassOverride>> (std::nullopt);
const auto target = (*curEffect)->target.has_value ()
? *(*curEffect)->target
: std::optional<std::reference_wrapper<std::string>> (std::nullopt);
this->m_passes.push_back (
new CPass (*this, fboProvider, **curPass, override, (*curEffect)->binds, target));
if (curOverride != endOverride) {
curOverride++;
}
}
}
}

View File

@ -85,6 +85,7 @@ class CImage final : public CObject, public CFBOProvider {
Effects::CMaterial* m_material = nullptr;
Effects::CMaterial* m_colorBlendMaterial = nullptr;
std::vector<Effects::CPass*> m_passes = {};
std::vector<MaterialPass> m_virtualPassess = {};
glm::vec4 m_pos = {};

View File

@ -349,7 +349,7 @@ const MaterialPass& CPass::getPass () const {
return this->m_pass;
}
const std::optional<std::reference_wrapper<std::string>> CPass::getTarget () const {
std::optional<std::reference_wrapper<std::string>> CPass::getTarget () const {
return this->m_target;
}

View File

@ -45,7 +45,7 @@ class CPass final : public Helpers::CContextAware {
[[nodiscard]] std::shared_ptr<const CFBOProvider> getFBOProvider () const;
[[nodiscard]] const CImage& getImage () const;
[[nodiscard]] const MaterialPass& getPass () const;
[[nodiscard]] const std::optional<std::reference_wrapper<std::string>> getTarget () const;
[[nodiscard]] std::optional<std::reference_wrapper<std::string>> getTarget () const;
[[nodiscard]] Render::Shaders::CShader* getShader () const;
private: