2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-07-16 15:25:53 +00:00

New code style refactor

This commit is contained in:
Jack Andersen 2018-12-07 19:18:42 -10:00
parent 54c466276b
commit 72193079ae
74 changed files with 14647 additions and 17058 deletions

View File

@ -18,8 +18,7 @@
extern logvisor::Module LogModule;
struct ToolPassInfo
{
struct ToolPassInfo {
hecl::SystemString pname;
hecl::SystemString cwd;
std::vector<hecl::SystemString> args;
@ -48,16 +47,13 @@ struct ToolPassInfo
extern bool XTERM_COLOR;
class ToolBase
{
class ToolBase {
protected:
const ToolPassInfo& m_info;
bool m_good = false;
bool continuePrompt()
{
if (!m_info.yes)
{
bool continuePrompt() {
if (!m_info.yes) {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("\n" BLUE BOLD "Continue?" NORMAL " (Y/n) "));
else
@ -76,8 +72,7 @@ protected:
while ((ch = getch()))
#endif
{
if (ch == 'n' || ch == 'N')
{
if (ch == 'n' || ch == 'N') {
hecl::Printf(_SYS_STR("\n"));
return false;
}
@ -93,51 +88,44 @@ protected:
}
public:
ToolBase(const ToolPassInfo& info)
: m_info(info)
{
ToolBase(const ToolPassInfo& info) : m_info(info) {
hecl::VerbosityLevel = info.verbosityLevel;
hecl::GuiMode = info.gui;
}
virtual ~ToolBase() = default;
virtual hecl::SystemString toolName() const=0;
virtual int run()=0;
virtual hecl::SystemString toolName() const = 0;
virtual int run() = 0;
virtual void cancel() {}
inline operator bool() const {return m_good;}
inline operator bool() const { return m_good; }
};
class HelpOutput
{
class HelpOutput {
public:
typedef void(*HelpFunc)(HelpOutput&);
typedef void (*HelpFunc)(HelpOutput&);
private:
FILE* m_sout;
HelpFunc m_helpFunc;
int m_lineWidth;
hecl::SystemString m_wrapBuffer;
void _wrapBuf(hecl::SystemString& string)
{
void _wrapBuf(hecl::SystemString& string) {
int counter;
hecl::SystemString::iterator it = string.begin();
while (it != string.end())
{
while (it != string.end()) {
std::ptrdiff_t v = it - string.begin();
/* copy string until the end of the line is reached */
for (counter=WRAP_INDENT ; counter < m_lineWidth ; ++counter)
{
for (counter = WRAP_INDENT; counter < m_lineWidth; ++counter) {
if (it >= string.end())
return;
if (*it == _SYS_STR('\n'))
{
if (*it == _SYS_STR('\n')) {
counter = WRAP_INDENT;
++it;
}
if (counter == WRAP_INDENT)
{
for (int i=0 ; i<WRAP_INDENT ; ++i)
if (counter == WRAP_INDENT) {
for (int i = 0; i < WRAP_INDENT; ++i)
it = string.insert(it, _SYS_STR(' ')) + 1;
}
if (it >= string.end())
@ -146,19 +134,14 @@ private:
++it;
}
/* check for whitespace */
if (isspace(*it))
{
if (isspace(*it)) {
*it = _SYS_STR('\n');
counter = WRAP_INDENT;
++it;
}
else
{
} else {
/* check for nearest whitespace back in string */
for (hecl::SystemString::iterator k=it ; k!=string.begin() ; --k)
{
if (isspace(*k))
{
for (hecl::SystemString::iterator k = it; k != string.begin(); --k) {
if (isspace(*k)) {
counter = WRAP_INDENT;
if (k - string.begin() < v)
k = string.insert(it, _SYS_STR('\n'));
@ -173,72 +156,53 @@ private:
}
public:
HelpOutput(HelpFunc helpFunc)
: m_sout(NULL), m_helpFunc(helpFunc), m_lineWidth(hecl::GuiMode ? 120 : hecl::ConsoleWidth())
{}
: m_sout(NULL), m_helpFunc(helpFunc), m_lineWidth(hecl::GuiMode ? 120 : hecl::ConsoleWidth()) {}
void go()
{
void go() {
#if _WIN32
m_sout = stdout;
m_helpFunc(*this);
#else
m_sout = popen("less -R", "w");
if (m_sout)
{
if (m_sout) {
m_helpFunc(*this);
pclose(m_sout);
}
else
{
} else {
m_sout = stdout;
m_helpFunc(*this);
}
#endif
}
void print(const hecl::SystemChar* str)
{
hecl::FPrintf(m_sout, _SYS_STR("%s"), str);
}
void print(const hecl::SystemChar* str) { hecl::FPrintf(m_sout, _SYS_STR("%s"), str); }
void printBold(const hecl::SystemChar* str)
{
void printBold(const hecl::SystemChar* str) {
if (XTERM_COLOR)
hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL ""), str);
else
hecl::FPrintf(m_sout, _SYS_STR("%s"), str);
}
void secHead(const hecl::SystemChar* headName)
{
void secHead(const hecl::SystemChar* headName) {
if (XTERM_COLOR)
hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL "\n"), headName);
else
hecl::FPrintf(m_sout, _SYS_STR("%s\n"), headName);
}
void optionHead(const hecl::SystemChar* flag, const hecl::SystemChar* synopsis)
{
void optionHead(const hecl::SystemChar* flag, const hecl::SystemChar* synopsis) {
if (XTERM_COLOR)
hecl::FPrintf(m_sout, _SYS_STR("" BOLD "%s" NORMAL " (%s)\n"), flag, synopsis);
else
hecl::FPrintf(m_sout, _SYS_STR("%s (%s)\n"), flag, synopsis);
}
void beginWrap()
{
m_wrapBuffer.clear();
}
void beginWrap() { m_wrapBuffer.clear(); }
void wrap(const hecl::SystemChar* str)
{
m_wrapBuffer += str;
}
void wrap(const hecl::SystemChar* str) { m_wrapBuffer += str; }
void wrapBold(const hecl::SystemChar* str)
{
void wrapBold(const hecl::SystemChar* str) {
if (XTERM_COLOR)
m_wrapBuffer += _SYS_STR("" BOLD "");
m_wrapBuffer += str;
@ -246,8 +210,7 @@ public:
m_wrapBuffer += _SYS_STR("" NORMAL "");
}
void endWrap()
{
void endWrap() {
_wrapBuf(m_wrapBuffer);
m_wrapBuffer += _SYS_STR('\n');
hecl::FPrintf(m_sout, _SYS_STR("%s"), m_wrapBuffer.c_str());
@ -255,9 +218,7 @@ public:
}
};
static hecl::SystemString MakePathArgAbsolute(const hecl::SystemString& arg,
const hecl::SystemString& cwd)
{
static hecl::SystemString MakePathArgAbsolute(const hecl::SystemString& arg, const hecl::SystemString& cwd) {
#if _WIN32
if (arg.size() >= 2 && iswalpha(arg[0]) && arg[1] == _SYS_STR(':'))
return arg;
@ -272,4 +233,3 @@ static hecl::SystemString MakePathArgAbsolute(const hecl::SystemString& arg,
return cwd + _SYS_STR('/') + arg;
#endif
}

View File

@ -4,44 +4,35 @@
#include <cstdio>
#include "hecl/ClientProcess.hpp"
class ToolCook final : public ToolBase
{
class ToolCook final : public ToolBase {
std::vector<hecl::ProjectPath> m_selectedItems;
std::unique_ptr<hecl::Database::Project> m_fallbackProj;
hecl::Database::Project* m_useProj;
const hecl::Database::DataSpecEntry* m_spec = nullptr;
bool m_recursive = false;
bool m_fast = false;
public:
ToolCook(const ToolPassInfo& info)
: ToolBase(info), m_useProj(info.project)
{
ToolCook(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) {
/* Check for recursive flag */
for (hecl::SystemChar arg : info.flags)
if (arg == _SYS_STR('r'))
m_recursive = true;
/* Scan args */
if (info.args.size())
{
if (info.args.size()) {
/* See if project path is supplied via args and use that over the getcwd one */
m_selectedItems.reserve(info.args.size());
for (const hecl::SystemString& arg : info.args)
{
for (const hecl::SystemString& arg : info.args) {
if (arg.empty())
continue;
else if (!arg.compare(_SYS_STR("--fast")))
{
else if (!arg.compare(_SYS_STR("--fast"))) {
m_fast = true;
continue;
}
else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec=")))
{
} else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec="))) {
hecl::SystemString specName(arg.begin() + 7, arg.end());
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY)
{
if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str()))
{
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) {
if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str())) {
m_spec = spec;
break;
}
@ -49,20 +40,16 @@ public:
if (!m_spec)
LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str());
continue;
}
else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-'))
} else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-'))
continue;
hecl::SystemString subPath;
hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath);
if (root)
{
if (!m_fallbackProj)
{
if (root) {
if (!m_fallbackProj) {
m_fallbackProj.reset(new hecl::Database::Project(root));
m_useProj = m_fallbackProj.get();
}
else if (m_fallbackProj->getProjectRootPath() != root)
} else if (m_fallbackProj->getProjectRootPath() != root)
LogModule.report(logvisor::Fatal,
_SYS_STR("hecl cook can only process multiple items in the same project; ")
_SYS_STR("'%s' and '%s' are different projects"),
@ -78,16 +65,14 @@ public:
"provided a path within a project");
/* Default case: recursive at root */
if (m_selectedItems.empty())
{
if (m_selectedItems.empty()) {
m_selectedItems.reserve(1);
m_selectedItems.push_back({hecl::ProjectPath(*m_useProj, _SYS_STR(""))});
m_recursive = true;
}
}
static void Help(HelpOutput& help)
{
static void Help(HelpOutput& help) {
help.secHead(_SYS_STR("NAME"));
help.beginWrap();
help.wrap(_SYS_STR("hecl-cook - Cook objects within the project database\n"));
@ -114,8 +99,8 @@ public:
help.wrap(_SYS_STR(" images). If the dependent files are unable to be found, the cook process aborts.\n\n"));
help.wrapBold(_SYS_STR("- Modtime Comparison: "));
help.wrap(_SYS_STR("Files that have previously finished a cook pass are inspected for their time of ")
_SYS_STR("last modification. If the file hasn't changed since its previous cook-pass, the ")
_SYS_STR("process is skipped. If the file has been moved or deleted, the object is automatically ")
_SYS_STR("last modification. If the file hasn't changed since its previous cook-pass, the ") _SYS_STR(
"process is skipped. If the file has been moved or deleted, the object is automatically ")
_SYS_STR("removed from the project database.\n\n"));
help.wrapBold(_SYS_STR("- Cook: "));
help.wrap(_SYS_STR("A type-specific procedure compiles the file's contents into an efficient format ")
@ -151,8 +136,7 @@ public:
help.beginWrap();
help.wrap(_SYS_STR("Specifies a DataSpec to use when cooking. ")
_SYS_STR("This build of hecl supports the following values of <spec>:\n"));
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY)
{
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) {
if (!spec->m_factory)
continue;
help.wrap(_SYS_STR(" "));
@ -161,10 +145,9 @@ public:
}
}
hecl::SystemString toolName() const {return _SYS_STR("cook");}
hecl::SystemString toolName() const { return _SYS_STR("cook"); }
int run()
{
int run() {
hecl::MultiProgressPrinter printer(true);
hecl::ClientProcess cp(&printer);
for (const hecl::ProjectPath& path : m_selectedItems)
@ -173,9 +156,5 @@ public:
return 0;
}
void cancel()
{
m_useProj->interruptCook();
}
void cancel() { m_useProj->interruptCook(); }
};

View File

@ -11,15 +11,12 @@
#include "hecl/MultiProgressPrinter.hpp"
class ToolExtract final : public ToolBase
{
class ToolExtract final : public ToolBase {
hecl::Database::IDataSpec::ExtractPassInfo m_einfo;
struct SpecExtractPass
{
struct SpecExtractPass {
const hecl::Database::DataSpecEntry* m_entry;
std::unique_ptr<hecl::Database::IDataSpec> m_instance;
SpecExtractPass(const hecl::Database::DataSpecEntry* entry,
std::unique_ptr<hecl::Database::IDataSpec>&& instance)
SpecExtractPass(const hecl::Database::DataSpecEntry* entry, std::unique_ptr<hecl::Database::IDataSpec>&& instance)
: m_entry(entry), m_instance(std::move(instance)) {}
SpecExtractPass(const SpecExtractPass& other) = delete;
SpecExtractPass(SpecExtractPass&& other) = default;
@ -28,19 +25,16 @@ class ToolExtract final : public ToolBase
std::vector<hecl::Database::IDataSpec::ExtractReport> m_reps;
std::unique_ptr<hecl::Database::Project> m_fallbackProj;
hecl::Database::Project* m_useProj = nullptr;
public:
ToolExtract(const ToolPassInfo& info)
: ToolBase(info)
{
ToolExtract(const ToolPassInfo& info) : ToolBase(info) {
if (!m_info.args.size())
LogModule.report(logvisor::Fatal, "hecl extract needs a source path as its first argument");
if (!info.project)
{
if (!info.project) {
hecl::SystemString rootDir;
if (info.output.empty())
{
if (info.output.empty()) {
/* Get name from input file and init project there */
hecl::SystemString baseFile = info.args.front();
size_t slashPos = baseFile.rfind(_SYS_STR('/'));
@ -56,9 +50,7 @@ public:
LogModule.report(logvisor::Fatal, "hecl extract must be ran within a project directory");
rootDir = info.cwd + baseFile;
}
else
{
} else {
if (hecl::PathRelative(info.output.c_str()))
rootDir = info.cwd + info.output;
else
@ -73,23 +65,20 @@ public:
LogModule.report(logvisor::Fatal, "unable to init project at '%s'", rootDir.c_str());
LogModule.report(logvisor::Info, _SYS_STR("initialized project at '%s/.hecl'"), rootDir.c_str());
m_useProj = m_fallbackProj.get();
}
else
} else
m_useProj = info.project;
m_einfo.srcpath = m_info.args.front();
m_einfo.force = info.force;
m_einfo.extractArgs.reserve(info.args.size());
auto it=info.args.cbegin();
auto it = info.args.cbegin();
++it;
for (; it != info.args.cend(); ++it)
m_einfo.extractArgs.push_back(*it);
m_specPasses.reserve(hecl::Database::DATA_SPEC_REGISTRY.size());
for (const hecl::Database::DataSpecEntry* entry : hecl::Database::DATA_SPEC_REGISTRY)
{
if (entry->m_factory)
{
for (const hecl::Database::DataSpecEntry* entry : hecl::Database::DATA_SPEC_REGISTRY) {
if (entry->m_factory) {
auto ds = entry->m_factory(*m_useProj, hecl::Database::DataSpecTool::Extract);
if (ds && ds->canExtract(m_einfo, m_reps))
m_specPasses.emplace_back(entry, std::move(ds));
@ -97,8 +86,7 @@ public:
}
}
static void Help(HelpOutput& help)
{
static void Help(HelpOutput& help) {
help.secHead(_SYS_STR("NAME"));
help.beginWrap();
help.wrap(_SYS_STR("hecl-extract - Extract objects from supported package/image formats\n"));
@ -124,11 +112,10 @@ public:
help.endWrap();
}
hecl::SystemString toolName() const {return _SYS_STR("extract");}
hecl::SystemString toolName() const { return _SYS_STR("extract"); }
static void _recursivePrint(int level, hecl::Database::IDataSpec::ExtractReport& rep)
{
for (int l=0 ; l<level ; ++l)
static void _recursivePrint(int level, hecl::Database::IDataSpec::ExtractReport& rep) {
for (int l = 0; l < level; ++l)
hecl::Printf(_SYS_STR(" "));
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD "%s" NORMAL ""), rep.name.c_str());
@ -142,10 +129,8 @@ public:
_recursivePrint(level + 1, child);
}
int run()
{
if (m_specPasses.empty())
{
int run() {
if (m_specPasses.empty()) {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" RED BOLD "NOTHING TO EXTRACT" NORMAL "\n"));
else
@ -158,17 +143,14 @@ public:
else
hecl::Printf(_SYS_STR("ABOUT TO EXTRACT:\n"));
for (hecl::Database::IDataSpec::ExtractReport& rep : m_reps)
{
for (hecl::Database::IDataSpec::ExtractReport& rep : m_reps) {
_recursivePrint(0, rep);
hecl::Printf(_SYS_STR("\n"));
}
fflush(stdout);
if (continuePrompt())
{
for (SpecExtractPass& ds : m_specPasses)
{
if (continuePrompt()) {
for (SpecExtractPass& ds : m_specPasses) {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" MAGENTA BOLD "Using DataSpec %s:" NORMAL "\n"), ds.m_entry->m_name.data());
else
@ -182,4 +164,3 @@ public:
return 0;
}
};

View File

@ -4,59 +4,51 @@
#include <cstdio>
#include <functional>
class ToolHelp final : public ToolBase
{
class ToolHelp final : public ToolBase {
public:
ToolHelp(const ToolPassInfo& info)
: ToolBase(info)
{
if (m_info.args.empty())
{
ToolHelp(const ToolPassInfo& info) : ToolBase(info) {
if (m_info.args.empty()) {
LogModule.report(logvisor::Error, "help requires a tool name argument");
return;
}
m_good = true;
}
~ToolHelp()
{
}
~ToolHelp() {}
static void Help(HelpOutput& help)
{
static void Help(HelpOutput& help) {
help.printBold(
_SYS_STR(" ___________ \n")
_SYS_STR(" ,.-'\"...........``~., \n")
_SYS_STR(" ,.-\".......................\"-., \n")
_SYS_STR(" ,/..................................\":, \n")
_SYS_STR(" .,?........................................, \n")
_SYS_STR(" /...........................................,}\n")
_SYS_STR(" ./........................................,:`^`..}\n")
_SYS_STR(" ./.......................................,:\"...../\n")
_SYS_STR(" ?.....__..................................:`...../\n")
_SYS_STR(" /__.(...\"~-,_...........................,:`....../\n")
_SYS_STR(" /(_....\"~,_....\"~,_.....................,:`...._/ \n")
_SYS_STR(" {.._$;_....\"=,_.....\"-,_......,.-~-,},.~\";/....} \n")
_SYS_STR(" ((...*~_......\"=-._...\";,,./`........../\"..../ \n")
_SYS_STR(" ,,,___.`~,......\"~.,....................`......}....../ \n")
_SYS_STR("............(....`=-,,...`.........................(...;_,,-\" \n")
_SYS_STR(" ___________ \n") _SYS_STR(
" ,.-'\"...........``~., \n") _SYS_STR(" "
",.-\".......................\"-., \n")
_SYS_STR(" ,/..................................\":, \n") _SYS_STR(
" .,?........................................, \n")
_SYS_STR(" /...........................................,}\n") _SYS_STR(
" ./........................................,:`^`..}\n")
_SYS_STR(" ./.......................................,:\"...../\n") _SYS_STR(
" ?.....__..................................:`...../\n")
_SYS_STR(" /__.(...\"~-,_...........................,:`....../\n") _SYS_STR(
" /(_....\"~,_....\"~,_.....................,:`...._/ \n")
_SYS_STR(" {.._$;_....\"=,_.....\"-,_......,.-~-,},.~\";/....} \n") _SYS_STR(
" ((...*~_......\"=-._...\";,,./`........../\"..../ \n")
_SYS_STR(" ,,,___.`~,......\"~.,....................`......}....../ \n") _SYS_STR(
"............(....`=-,,...`.........................(...;_,,-\" \n")
_SYS_STR("............/.`~,......`-.................................../ \n")
_SYS_STR(".............`~.*-,.....................................|,./...,__ \n")
_SYS_STR(",,_..........}.>-._...................................|.......`=~-, \n")
_SYS_STR(".....`=~-,__......`,................................. \n")
_SYS_STR(".............`~.*-,.....................................|,./...,__ "
"\n") _SYS_STR(",,_..........}.>-._..................................."
"|.......`=~-, \n") _SYS_STR(
".....`=~-,__......`,................................. \n")
_SYS_STR("...................`=~-,,.,........................... \n")
_SYS_STR(".........................`:,,..........................`\n")
_SYS_STR("...........................`=-,...............,%%`>--==`` \n")
_SYS_STR(".................................._.........._,-%%...` \n")
_SYS_STR(
"...........................`=-,...............,%%`>--==`` \n")
_SYS_STR(
".................................._.........._,-%%...` \n")
_SYS_STR("...................................,\n"));
}
static void ShowHelp(const hecl::SystemString& toolName)
{
static void ShowHelp(const hecl::SystemString& toolName) {
/* Select tool's help-text streamer */
HelpOutput::HelpFunc helpFunc = NULL;
if (toolName == _SYS_STR("init"))
@ -71,8 +63,7 @@ public:
helpFunc = ToolPackage::Help;
else if (toolName == _SYS_STR("help"))
helpFunc = ToolHelp::Help;
else
{
else {
LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s' - can't help"), toolName.c_str());
return;
}
@ -81,12 +72,10 @@ public:
ho.go();
}
hecl::SystemString toolName() const {return _SYS_STR("help");}
hecl::SystemString toolName() const { return _SYS_STR("help"); }
int run()
{
int run() {
ShowHelp(m_info.args.front());
return 0;
}
};

View File

@ -10,34 +10,27 @@
#include "nod/DiscWii.hpp"
#include "athena/FileReader.hpp"
class ToolImage final : public ToolBase
{
class ToolImage final : public ToolBase {
std::unique_ptr<hecl::Database::Project> m_fallbackProj;
hecl::Database::Project* m_useProj;
public:
ToolImage(const ToolPassInfo& info)
: ToolBase(info), m_useProj(info.project)
{
ToolImage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) {
if (!info.project)
LogModule.report(logvisor::Fatal, "hecl image must be ran within a project directory");
/* Scan args */
if (info.args.size())
{
if (info.args.size()) {
/* See if project path is supplied via args and use that over the getcwd one */
for (const hecl::SystemString& arg : info.args)
{
for (const hecl::SystemString& arg : info.args) {
if (arg.empty())
continue;
hecl::SystemString subPath;
hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath);
if (root)
{
if (!m_fallbackProj)
{
if (root) {
if (!m_fallbackProj) {
m_fallbackProj.reset(new hecl::Database::Project(root));
m_useProj = m_fallbackProj.get();
break;
@ -51,12 +44,9 @@ public:
"provided a path within a project");
}
~ToolImage()
{
}
~ToolImage() {}
static void Help(HelpOutput& help)
{
static void Help(HelpOutput& help) {
help.secHead(_SYS_STR("NAME"));
help.beginWrap();
help.wrap(_SYS_STR("hecl-image - Generate GameCube/Wii disc image from packaged files\n"));
@ -81,10 +71,9 @@ public:
help.endWrap();
}
hecl::SystemString toolName() const {return _SYS_STR("image");}
hecl::SystemString toolName() const { return _SYS_STR("image"); }
int run()
{
int run() {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO IMAGE:" NORMAL "\n"));
else
@ -93,25 +82,21 @@ public:
hecl::Printf(_SYS_STR(" %s\n"), m_useProj->getProjectRootPath().getAbsolutePath().data());
fflush(stdout);
if (continuePrompt())
{
if (continuePrompt()) {
hecl::ProjectPath outPath(m_useProj->getProjectWorkingPath(), _SYS_STR("out"));
if (!outPath.isDirectory())
{
if (!outPath.isDirectory()) {
LogModule.report(logvisor::Error, _SYS_STR("%s is not a directory"), outPath.getAbsolutePath().data());
return 1;
}
hecl::ProjectPath bootBinPath(outPath, _SYS_STR("sys/boot.bin"));
if (!bootBinPath.isFile())
{
if (!bootBinPath.isFile()) {
LogModule.report(logvisor::Error, _SYS_STR("%s is not a file"), bootBinPath.getAbsolutePath().data());
return 1;
}
athena::io::FileReader r(bootBinPath.getAbsolutePath());
if (r.hasError())
{
if (r.hasError()) {
LogModule.report(logvisor::Error, _SYS_STR("unable to open %s"), bootBinPath.getAbsolutePath().data());
return 1;
}
@ -121,12 +106,10 @@ public:
hecl::SystemStringConv idView(id);
hecl::SystemString fileOut = hecl::SystemString(outPath.getAbsolutePath()) + _SYS_STR('/') + idView.c_str();
hecl::MultiProgressPrinter printer(true);
auto progFunc = [&printer](float totalProg, nod::SystemStringView fileName, size_t fileBytesXfered)
{
auto progFunc = [&printer](float totalProg, nod::SystemStringView fileName, size_t fileBytesXfered) {
printer.print(fileName.data(), nullptr, totalProg);
};
if (id[0] == 'G')
{
if (id[0] == 'G') {
fileOut += _SYS_STR(".gcm");
if (nod::DiscBuilderGCN::CalculateTotalSizeRequired(outPath.getAbsolutePath()) == -1)
return 1;
@ -134,9 +117,7 @@ public:
nod::DiscBuilderGCN db(fileOut, progFunc);
if (db.buildFromDirectory(outPath.getAbsolutePath()) != nod::EBuildResult::Success)
return 1;
}
else
{
} else {
fileOut += _SYS_STR(".iso");
bool dualLayer;
if (nod::DiscBuilderWii::CalculateTotalSizeRequired(outPath.getAbsolutePath(), dualLayer) == -1)
@ -154,4 +135,3 @@ public:
};
#endif

View File

@ -3,13 +3,11 @@
#include "ToolBase.hpp"
#include <cstdio>
class ToolInit final : public ToolBase
{
class ToolInit final : public ToolBase {
const hecl::SystemString* m_dir = NULL;
public:
ToolInit(const ToolPassInfo& info)
: ToolBase(info)
{
ToolInit(const ToolPassInfo& info) : ToolBase(info) {
hecl::Sstat theStat;
const hecl::SystemString* dir;
if (info.args.size())
@ -17,24 +15,20 @@ public:
else
dir = &info.cwd;
if (hecl::Stat(dir->c_str(), &theStat))
{
if (hecl::Stat(dir->c_str(), &theStat)) {
hecl::MakeDir(dir->c_str());
if (hecl::Stat(dir->c_str(), &theStat))
{
if (hecl::Stat(dir->c_str(), &theStat)) {
LogModule.report(logvisor::Fatal, _SYS_STR("unable to stat '%s'"), dir->c_str());
return;
}
}
if (!S_ISDIR(theStat.st_mode))
{
if (!S_ISDIR(theStat.st_mode)) {
LogModule.report(logvisor::Fatal, _SYS_STR("'%s' is not a directory"), dir->c_str());
return;
}
hecl::SystemString testPath = *dir + _SYS_STR("/.hecl/beacon");
if (!hecl::Stat(testPath.c_str(), &theStat))
{
if (!hecl::Stat(testPath.c_str(), &theStat)) {
LogModule.report(logvisor::Fatal, _SYS_STR("project already exists at '%s'"), dir->c_str());
return;
}
@ -42,8 +36,7 @@ public:
m_dir = dir;
}
int run()
{
int run() {
if (!m_dir)
return 1;
size_t ErrorRef = logvisor::ErrorCount;
@ -54,8 +47,7 @@ public:
return 0;
}
static void Help(HelpOutput& help)
{
static void Help(HelpOutput& help) {
help.secHead(_SYS_STR("NAME"));
help.beginWrap();
help.wrap(_SYS_STR("hecl-init - Initialize a brand-new project database\n"));
@ -81,6 +73,5 @@ public:
help.endWrap();
}
hecl::SystemString toolName() const {return _SYS_STR("init");}
hecl::SystemString toolName() const { return _SYS_STR("init"); }
};

View File

@ -5,29 +5,25 @@
#include "ToolBase.hpp"
#include <cstdio>
class ToolPackage final : public ToolBase
{
class ToolPackage final : public ToolBase {
std::vector<hecl::ProjectPath> m_selectedItems;
std::unique_ptr<hecl::Database::Project> m_fallbackProj;
hecl::Database::Project* m_useProj;
const hecl::Database::DataSpecEntry* m_spec = nullptr;
bool m_fast = false;
void AddSelectedItem(const hecl::ProjectPath& path)
{
void AddSelectedItem(const hecl::ProjectPath& path) {
for (const hecl::ProjectPath& item : m_selectedItems)
if (item == path)
return;
m_selectedItems.push_back(path);
}
void CheckFile(const hecl::ProjectPath& path)
{
void CheckFile(const hecl::ProjectPath& path) {
if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!world.blend")))
AddSelectedItem(path);
#if RUNTIME_ORIGINAL_IDS
else if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!original_ids.yaml")))
{
else if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!original_ids.yaml"))) {
auto pathComps = path.getPathComponents();
if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out"))
AddSelectedItem(path);
@ -35,19 +31,16 @@ class ToolPackage final : public ToolBase
#endif
}
void FindSelectedItems(const hecl::ProjectPath& path, bool checkGeneral)
{
if (path.isFile())
{
void FindSelectedItems(const hecl::ProjectPath& path, bool checkGeneral) {
if (path.isFile()) {
CheckFile(path);
return;
}
size_t origSize = m_selectedItems.size();
hecl::DirectoryEnumerator dEnum(path.getAbsolutePath(),
hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const auto& ent : dEnum)
{
hecl::DirectoryEnumerator dEnum(path.getAbsolutePath(), hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false,
false, true);
for (const auto& ent : dEnum) {
hecl::ProjectPath childPath(path, ent.m_name);
if (ent.m_isDir)
FindSelectedItems(childPath, checkGeneral && childPath.getPathComponents().size() <= 2);
@ -57,43 +50,33 @@ class ToolPackage final : public ToolBase
/* Directory with 2 components not "Shared" or macOS app bundle
* and no nested !world.blend files == General PAK */
if (checkGeneral && origSize == m_selectedItems.size())
{
if (checkGeneral && origSize == m_selectedItems.size()) {
auto pathComps = path.getPathComponents();
if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out") &&
pathComps[1] != _SYS_STR("Shared") && pathComps[0].find(_SYS_STR(".app")) == hecl::SystemString::npos)
if (pathComps.size() == 2 && pathComps[0] != _SYS_STR("out") && pathComps[1] != _SYS_STR("Shared") &&
pathComps[0].find(_SYS_STR(".app")) == hecl::SystemString::npos)
AddSelectedItem(path);
}
}
public:
ToolPackage(const ToolPassInfo& info)
: ToolBase(info), m_useProj(info.project)
{
ToolPackage(const ToolPassInfo& info) : ToolBase(info), m_useProj(info.project) {
if (!info.project)
LogModule.report(logvisor::Fatal, "hecl package must be ran within a project directory");
/* Scan args */
if (info.args.size())
{
if (info.args.size()) {
/* See if project path is supplied via args and use that over the getcwd one */
m_selectedItems.reserve(info.args.size());
for (const hecl::SystemString& arg : info.args)
{
for (const hecl::SystemString& arg : info.args) {
if (arg.empty())
continue;
else if (!arg.compare(_SYS_STR("--fast")))
{
else if (!arg.compare(_SYS_STR("--fast"))) {
m_fast = true;
continue;
}
else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec=")))
{
} else if (arg.size() >= 8 && !arg.compare(0, 7, _SYS_STR("--spec="))) {
hecl::SystemString specName(arg.begin() + 7, arg.end());
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY)
{
if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str()))
{
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) {
if (!hecl::StrCaseCmp(spec->m_name.data(), specName.c_str())) {
m_spec = spec;
break;
}
@ -101,21 +84,17 @@ public:
if (!m_spec)
LogModule.report(logvisor::Fatal, "unable to find data spec '%s'", specName.c_str());
continue;
}
else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-'))
} else if (arg.size() >= 2 && arg[0] == _SYS_STR('-') && arg[1] == _SYS_STR('-'))
continue;
hecl::SystemString subPath;
hecl::ProjectRootPath root = hecl::SearchForProject(MakePathArgAbsolute(arg, info.cwd), subPath);
if (root)
{
if (!m_fallbackProj)
{
if (root) {
if (!m_fallbackProj) {
m_fallbackProj.reset(new hecl::Database::Project(root));
m_useProj = m_fallbackProj.get();
}
else if (m_fallbackProj->getProjectRootPath() != root)
} else if (m_fallbackProj->getProjectRootPath() != root)
LogModule.report(logvisor::Fatal,
_SYS_STR("hecl package can only process multiple items in the same project; ")
_SYS_STR("'%s' and '%s' are different projects"),
@ -136,12 +115,10 @@ public:
FindSelectedItems({*m_useProj, _SYS_STR("")}, true);
}
static void Help(HelpOutput& help)
{
static void Help(HelpOutput& help) {
help.secHead(_SYS_STR("NAME"));
help.beginWrap();
help.wrap(_SYS_STR("hecl-pack\n")
_SYS_STR("hecl-package - Package objects within the project database\n"));
help.wrap(_SYS_STR("hecl-pack\n") _SYS_STR("hecl-package - Package objects within the project database\n"));
help.endWrap();
help.secHead(_SYS_STR("SYNOPSIS"));
@ -152,8 +129,8 @@ public:
help.secHead(_SYS_STR("DESCRIPTION"));
help.beginWrap();
help.wrap(_SYS_STR("This command initiates a packaging pass on the project database. Packaging ")
_SYS_STR("is analogous to linking in software development. All objects necessary to ")
_SYS_STR("generate a complete package are gathered, grouped, and indexed within a .upak file.\n"));
_SYS_STR("is analogous to linking in software development. All objects necessary to ") _SYS_STR(
"generate a complete package are gathered, grouped, and indexed within a .upak file.\n"));
help.endWrap();
help.secHead(_SYS_STR("OPTIONS"));
@ -161,8 +138,7 @@ public:
help.beginWrap();
help.wrap(_SYS_STR("Specifies a DataSpec to use when cooking and generating the package. ")
_SYS_STR("This build of hecl supports the following values of <spec>:\n"));
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY)
{
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) {
if (!spec->m_factory)
continue;
help.wrap(_SYS_STR(" "));
@ -180,10 +156,9 @@ public:
help.endWrap();
}
hecl::SystemString toolName() const {return _SYS_STR("package");}
hecl::SystemString toolName() const { return _SYS_STR("package"); }
int run()
{
int run() {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" GREEN BOLD "ABOUT TO PACKAGE:" NORMAL "\n"));
else
@ -193,12 +168,10 @@ public:
hecl::Printf(_SYS_STR(" %s\n"), item.getRelativePath().data());
fflush(stdout);
if (continuePrompt())
{
if (continuePrompt()) {
hecl::MultiProgressPrinter printer(true);
hecl::ClientProcess cp(&printer);
for (const hecl::ProjectPath& path : m_selectedItems)
{
for (const hecl::ProjectPath& path : m_selectedItems) {
if (!m_useProj->packagePath(path, printer, m_fast, m_spec, &cp))
LogModule.report(logvisor::Error, _SYS_STR("Unable to package %s"), path.getAbsolutePath().data());
}
@ -208,9 +181,5 @@ public:
return 0;
}
void cancel()
{
m_useProj->interruptCook();
}
void cancel() { m_useProj->interruptCook(); }
};

View File

@ -4,24 +4,16 @@
#include <cstdio>
#include <map>
class ToolSpec final : public ToolBase
{
enum Mode
{
MLIST = 0,
MENABLE,
MDISABLE
} mode = MLIST;
class ToolSpec final : public ToolBase {
enum Mode { MLIST = 0, MENABLE, MDISABLE } mode = MLIST;
public:
ToolSpec(const ToolPassInfo& info)
: ToolBase(info)
{
ToolSpec(const ToolPassInfo& info) : ToolBase(info) {
if (info.args.empty())
return;
if (!info.project)
LogModule.report(logvisor::Fatal,
"hecl spec must be ran within a project directory");
LogModule.report(logvisor::Fatal, "hecl spec must be ran within a project directory");
const auto& specs = info.project->getDataSpecs();
hecl::SystemString firstArg = info.args.front();
@ -39,28 +31,21 @@ public:
auto it = info.args.begin();
++it;
for (;it != info.args.end();
++it)
{
for (; it != info.args.end(); ++it) {
bool found = false;
for (auto& spec : specs)
{
if (!it->compare(spec.spec.m_name))
{
for (auto& spec : specs) {
if (!it->compare(spec.spec.m_name)) {
found = true;
break;
}
}
if (!found)
LogModule.report(logvisor::Fatal,
_SYS_STR("'%s' is not found in the dataspec registry"),
it->c_str());
LogModule.report(logvisor::Fatal, _SYS_STR("'%s' is not found in the dataspec registry"), it->c_str());
}
}
static void Help(HelpOutput& help)
{
static void Help(HelpOutput& help) {
help.secHead(_SYS_STR("NAME"));
help.beginWrap();
help.wrap(_SYS_STR("hecl-spec - Configure target data options\n"));
@ -73,7 +58,8 @@ public:
help.secHead(_SYS_STR("DESCRIPTION"));
help.beginWrap();
help.wrap(_SYS_STR("This command configures the HECL project with the user's preferred target DataSpecs.\n\n")
help.wrap(
_SYS_STR("This command configures the HECL project with the user's preferred target DataSpecs.\n\n")
_SYS_STR("Providing enable/disable argument will bulk-set the enable status of the provided spec(s)")
_SYS_STR("list. If enable/disable is not provided, a list of supported DataSpecs is printed.\n\n"));
help.endWrap();
@ -85,14 +71,11 @@ public:
help.endWrap();
}
hecl::SystemString toolName() const {return _SYS_STR("spec");}
hecl::SystemString toolName() const { return _SYS_STR("spec"); }
int run()
{
if (!m_info.project)
{
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY)
{
int run() {
if (!m_info.project) {
for (const hecl::Database::DataSpecEntry* spec : hecl::Database::DATA_SPEC_REGISTRY) {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL "\n"), spec->m_name.data());
else
@ -103,16 +86,13 @@ public:
}
const auto& specs = m_info.project->getDataSpecs();
if (mode == MLIST)
{
for (auto& spec : specs)
{
if (mode == MLIST) {
for (auto& spec : specs) {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD CYAN "%s" NORMAL ""), spec.spec.m_name.data());
else
hecl::Printf(_SYS_STR("%s"), spec.spec.m_name.data());
if (spec.active)
{
if (spec.active) {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR(" " BOLD GREEN "[ENABLED]" NORMAL ""));
else
@ -126,24 +106,20 @@ public:
std::vector<hecl::SystemString> opSpecs;
auto it = m_info.args.begin();
++it;
for (; it != m_info.args.end() ; ++it)
{
for (; it != m_info.args.end(); ++it) {
hecl::SystemString itName = *it;
hecl::ToLower(itName);
for (auto& spec : specs)
{
for (auto& spec : specs) {
hecl::SystemString compName(spec.spec.m_name);
hecl::ToLower(compName);
if (!itName.compare(compName))
{
if (!itName.compare(compName)) {
opSpecs.emplace_back(spec.spec.m_name);
break;
}
}
}
if (opSpecs.size())
{
if (opSpecs.size()) {
if (mode == MENABLE)
m_info.project->enableDataSpecs(opSpecs);
else if (mode == MDISABLE)
@ -153,4 +129,3 @@ public:
return 0;
}
};

View File

@ -35,7 +35,6 @@ logvisor::Module LogModule("hecl::Driver");
bool XTERM_COLOR = false;
/*
#define HECL_GIT 1234567
#define HECL_GIT_S "1234567"
@ -44,16 +43,15 @@ bool XTERM_COLOR = false;
*/
/* Main usage message */
static void printHelp(const hecl::SystemChar* pname)
{
static void printHelp(const hecl::SystemChar* pname) {
if (XTERM_COLOR)
hecl::Printf(_SYS_STR("" BOLD "HECL" NORMAL ""));
else
hecl::Printf(_SYS_STR("HECL"));
#if HECL_HAS_NOD
# define TOOL_LIST "extract|init|cook|package|image|help"
#define TOOL_LIST "extract|init|cook|package|image|help"
#else
# define TOOL_LIST "extract|init|cook|package|help"
#define TOOL_LIST "extract|init|cook|package|help"
#endif
#if HECL_GIT
hecl::Printf(_SYS_STR(" Commit " HECL_GIT_S " " HECL_BRANCH_S "\nUsage: %s " TOOL_LIST "\n"), pname);
@ -65,13 +63,12 @@ static void printHelp(const hecl::SystemChar* pname)
}
/* Regex patterns */
static const hecl::SystemRegex regOPEN(_SYS_STR("-o([^\"]*|\\S*)"), std::regex::ECMAScript|std::regex::optimize);
static const hecl::SystemRegex regOPEN(_SYS_STR("-o([^\"]*|\\S*)"), std::regex::ECMAScript | std::regex::optimize);
static ToolBase* ToolPtr = nullptr;
/* SIGINT will gracefully close blender connections and delete blends in progress */
static void SIGINTHandler(int sig)
{
static void SIGINTHandler(int sig) {
if (ToolPtr)
ToolPtr->cancel();
hecl::blender::Connection::Shutdown();
@ -80,9 +77,7 @@ static void SIGINTHandler(int sig)
}
static logvisor::Module AthenaLog("Athena");
static void AthenaExc(athena::error::Level level, const char* file,
const char*, int line, const char* fmt, ...)
{
static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
AthenaLog.report(logvisor::Level(level), fmt, ap);
@ -100,8 +95,7 @@ static void SIGWINCHHandler(int sig) {}
int main(int argc, const char** argv)
#endif
{
if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage")))
{
if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) {
printf("%s\n", HECL_DLPACKAGE);
return 100;
}
@ -130,16 +124,13 @@ int main(int argc, const char** argv)
atSetExceptionHandler(AthenaExc);
/* Basic usage check */
if (argc == 1)
{
if (argc == 1) {
printHelp(argv[0]);
#if WIN_PAUSE
system("PAUSE");
#endif
return 0;
}
else if (argc == 0)
{
} else if (argc == 0) {
printHelp(_SYS_STR("hecl"));
#if WIN_PAUSE
system("PAUSE");
@ -153,8 +144,7 @@ int main(int argc, const char** argv)
/* Assemble common tool pass info */
ToolPassInfo info;
info.pname = argv[0];
if (hecl::Getcwd(cwdbuf, 1024))
{
if (hecl::Getcwd(cwdbuf, 1024)) {
info.cwd = cwdbuf;
if (info.cwd.size() && info.cwd.back() != _SYS_STR('/') && info.cwd.back() != _SYS_STR('\\'))
#if _WIN32
@ -173,28 +163,22 @@ int main(int argc, const char** argv)
/* Concatenate args */
std::vector<hecl::SystemString> args;
args.reserve(argc-2);
for (int i=2 ; i<argc ; ++i)
args.reserve(argc - 2);
for (int i = 2; i < argc; ++i)
args.push_back(hecl::SystemString(argv[i]));
if (!args.empty())
{
if (!args.empty()) {
/* Extract output argument */
for (auto it = args.cbegin() ; it != args.cend() ;)
{
for (auto it = args.cbegin(); it != args.cend();) {
const hecl::SystemString& arg = *it;
hecl::SystemRegexMatch oMatch;
if (std::regex_search(arg, oMatch, regOPEN))
{
if (std::regex_search(arg, oMatch, regOPEN)) {
const hecl::SystemString& token = oMatch[1].str();
if (token.size())
{
if (token.size()) {
if (info.output.empty())
info.output = oMatch[1].str();
it = args.erase(it);
}
else
{
} else {
it = args.erase(it);
if (it == args.end())
break;
@ -208,17 +192,14 @@ int main(int argc, const char** argv)
}
/* Iterate flags */
for (auto it = args.cbegin() ; it != args.cend() ;)
{
for (auto it = args.cbegin(); it != args.cend();) {
const hecl::SystemString& arg = *it;
if (arg.size() < 2 || arg[0] != _SYS_STR('-') || arg[1] == _SYS_STR('-'))
{
if (arg.size() < 2 || arg[0] != _SYS_STR('-') || arg[1] == _SYS_STR('-')) {
++it;
continue;
}
for (auto chit = arg.cbegin() + 1 ; chit != arg.cend() ; ++chit)
{
for (auto chit = arg.cbegin() + 1; chit != arg.cend(); ++chit) {
if (*chit == _SYS_STR('v'))
++info.verbosityLevel;
else if (*chit == _SYS_STR('f'))
@ -243,12 +224,10 @@ int main(int argc, const char** argv)
/* Attempt to find hecl project */
hecl::ProjectRootPath rootPath = hecl::SearchForProject(info.cwd);
std::unique_ptr<hecl::Database::Project> project;
if (rootPath)
{
if (rootPath) {
size_t ErrorRef = logvisor::ErrorCount;
hecl::Database::Project* newProj = new hecl::Database::Project(rootPath);
if (logvisor::ErrorCount > ErrorRef)
{
if (logvisor::ErrorCount > ErrorRef) {
#if WIN_PAUSE
system("PAUSE");
#endif
@ -281,13 +260,11 @@ int main(int argc, const char** argv)
#endif
else if (toolName == _SYS_STR("help"))
tool.reset(new ToolHelp(info));
else
{
else {
FILE* fp = hecl::Fopen(argv[1], _SYS_STR("rb"));
if (!fp)
LogModule.report(logvisor::Error, _SYS_STR("unrecognized tool '%s'"), toolName.c_str());
else
{
else {
/* Shortcut-case: implicit extract */
fclose(fp);
info.args.insert(info.args.begin(), argv[1]);
@ -295,8 +272,7 @@ int main(int argc, const char** argv)
}
}
if (logvisor::ErrorCount > ErrorRef)
{
if (logvisor::ErrorCount > ErrorRef) {
#if WIN_PAUSE
system("PAUSE");
#endif
@ -304,16 +280,15 @@ int main(int argc, const char** argv)
}
if (info.verbosityLevel)
LogModule.report(logvisor::Info, _SYS_STR("Constructed tool '%s' %d\n"),
tool->toolName().c_str(), info.verbosityLevel);
LogModule.report(logvisor::Info, _SYS_STR("Constructed tool '%s' %d\n"), tool->toolName().c_str(),
info.verbosityLevel);
/* Run tool */
ErrorRef = logvisor::ErrorCount;
ToolPtr = tool.get();
int retval = tool->run();
ToolPtr = nullptr;
if (logvisor::ErrorCount > ErrorRef)
{
if (logvisor::ErrorCount > ErrorRef) {
hecl::blender::Connection::Shutdown();
#if WIN_PAUSE
system("PAUSE");
@ -327,5 +302,3 @@ int main(int argc, const char** argv)
#endif
return retval;
}

2
hecl/extern/athena vendored

@ -1 +1 @@
Subproject commit e1b29fda7acf3a17a297a02a63a5f11e94eb2328
Subproject commit 7243c687a82eef87a4df604eae6725fae2570573

2
hecl/extern/boo vendored

@ -1 +1 @@
Subproject commit 2c2c72bfd1e59815bfb90041974ef1e9f57325cb
Subproject commit 058ea23a00ce01ac93bf9ad369fa80858b185a00

View File

@ -2,8 +2,7 @@
#include "hecl/Frontend.hpp"
namespace hecl::Backend
{
namespace hecl::Backend {
struct ExtensionSlot;
using IR = Frontend::IR;
@ -11,15 +10,9 @@ using Diagnostics = Frontend::Diagnostics;
using SourceLocation = Frontend::SourceLocation;
using ArithmeticOp = IR::Instruction::ArithmeticOpType;
enum class TexGenSrc : uint8_t
{
Position,
Normal,
UV
};
enum class TexGenSrc : uint8_t { Position, Normal, UV };
enum class BlendFactor : uint8_t
{
enum class BlendFactor : uint8_t {
Zero,
One,
SrcColor,
@ -35,26 +28,11 @@ enum class BlendFactor : uint8_t
Original = 0xff
};
enum class ZTest : uint8_t
{
None,
LEqual,
Greater,
Equal,
GEqual,
Original = 0xff
};
enum class ZTest : uint8_t { None, LEqual, Greater, Equal, GEqual, Original = 0xff };
enum class CullMode : uint8_t
{
None,
Backface,
Frontface,
Original = 0xff
};
enum class CullMode : uint8_t { None, Backface, Frontface, Original = 0xff };
struct TextureInfo
{
struct TextureInfo {
TexGenSrc src;
int mapIdx;
int uvIdx;
@ -62,84 +40,98 @@ struct TextureInfo
bool normalize;
};
enum class ReflectionType
{
None,
Simple,
Indirect
};
enum class ReflectionType { None, Simple, Indirect };
class IBackend
{
class IBackend {
public:
virtual void reset(const IR& ir, Diagnostics& diag)=0;
virtual void reset(const IR& ir, Diagnostics& diag) = 0;
};
/**
* @brief Hash subclass for identifying shaders and their metadata
*/
class ShaderTag : public Hash
{
union
{
class ShaderTag : public Hash {
union {
uint64_t m_meta = 0;
struct
{
struct {
uint8_t m_colorCount;
uint8_t m_uvCount;
uint8_t m_weightCount;
uint8_t m_skinSlotCount;
uint8_t m_primitiveType;
uint8_t m_reflectionType;
bool m_depthTest:1;
bool m_depthWrite:1;
bool m_backfaceCulling:1;
bool m_alphaTest:1;
bool m_depthTest : 1;
bool m_depthWrite : 1;
bool m_backfaceCulling : 1;
bool m_alphaTest : 1;
};
};
public:
ShaderTag() = default;
ShaderTag(std::string_view source, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt,
Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling,
bool alphaTest)
: Hash(source), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s),
m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)),
m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling),
m_alphaTest(alphaTest)
{hash ^= m_meta;}
: Hash(source)
, m_colorCount(c)
, m_uvCount(u)
, m_weightCount(w)
, m_skinSlotCount(s)
, m_primitiveType(uint8_t(pt))
, m_reflectionType(uint8_t(reflectionType))
, m_depthTest(depthTest)
, m_depthWrite(depthWrite)
, m_backfaceCulling(backfaceCulling)
, m_alphaTest(alphaTest) {
hash ^= m_meta;
}
ShaderTag(const hecl::Frontend::IR& ir, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt,
Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling,
bool alphaTest)
: Hash(ir.m_hash), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s),
m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)),
m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling),
m_alphaTest(alphaTest)
{hash ^= m_meta;}
: Hash(ir.m_hash)
, m_colorCount(c)
, m_uvCount(u)
, m_weightCount(w)
, m_skinSlotCount(s)
, m_primitiveType(uint8_t(pt))
, m_reflectionType(uint8_t(reflectionType))
, m_depthTest(depthTest)
, m_depthWrite(depthWrite)
, m_backfaceCulling(backfaceCulling)
, m_alphaTest(alphaTest) {
hash ^= m_meta;
}
ShaderTag(uint64_t hashin, uint8_t c, uint8_t u, uint8_t w, uint8_t s, boo::Primitive pt,
Backend::ReflectionType reflectionType, bool depthTest, bool depthWrite, bool backfaceCulling,
bool alphaTest)
: Hash(hashin), m_colorCount(c), m_uvCount(u), m_weightCount(w), m_skinSlotCount(s),
m_primitiveType(uint8_t(pt)), m_reflectionType(uint8_t(reflectionType)),
m_depthTest(depthTest), m_depthWrite(depthWrite), m_backfaceCulling(backfaceCulling),
m_alphaTest(alphaTest)
{hash ^= m_meta;}
ShaderTag(uint64_t comphashin, uint64_t meta)
: Hash(comphashin), m_meta(meta) {}
: Hash(hashin)
, m_colorCount(c)
, m_uvCount(u)
, m_weightCount(w)
, m_skinSlotCount(s)
, m_primitiveType(uint8_t(pt))
, m_reflectionType(uint8_t(reflectionType))
, m_depthTest(depthTest)
, m_depthWrite(depthWrite)
, m_backfaceCulling(backfaceCulling)
, m_alphaTest(alphaTest) {
hash ^= m_meta;
}
ShaderTag(uint64_t comphashin, uint64_t meta) : Hash(comphashin), m_meta(meta) {}
ShaderTag(const ShaderTag& other) : Hash(other), m_meta(other.m_meta) {}
uint8_t getColorCount() const {return m_colorCount;}
uint8_t getUvCount() const {return m_uvCount;}
uint8_t getWeightCount() const {return m_weightCount;}
uint8_t getSkinSlotCount() const {return m_skinSlotCount;}
boo::Primitive getPrimType() const {return boo::Primitive(m_primitiveType);}
Backend::ReflectionType getReflectionType() const {return Backend::ReflectionType(m_reflectionType);}
bool getDepthTest() const {return m_depthTest;}
bool getDepthWrite() const {return m_depthWrite;}
bool getBackfaceCulling() const {return m_backfaceCulling;}
bool getAlphaTest() const {return m_alphaTest;}
uint64_t getMetaData() const {return m_meta;}
uint8_t getColorCount() const { return m_colorCount; }
uint8_t getUvCount() const { return m_uvCount; }
uint8_t getWeightCount() const { return m_weightCount; }
uint8_t getSkinSlotCount() const { return m_skinSlotCount; }
boo::Primitive getPrimType() const { return boo::Primitive(m_primitiveType); }
Backend::ReflectionType getReflectionType() const { return Backend::ReflectionType(m_reflectionType); }
bool getDepthTest() const { return m_depthTest; }
bool getDepthWrite() const { return m_depthWrite; }
bool getBackfaceCulling() const { return m_backfaceCulling; }
bool getAlphaTest() const { return m_alphaTest; }
uint64_t getMetaData() const { return m_meta; }
std::vector<boo::VertexElementDescriptor> vertexFormat() const
{
std::vector<boo::VertexElementDescriptor> vertexFormat() const {
std::vector<boo::VertexElementDescriptor> ret;
size_t elemCount = 2 + m_colorCount + m_uvCount + m_weightCount;
ret.resize(elemCount);
@ -148,20 +140,17 @@ public:
ret[1].semantic = boo::VertexSemantic::Normal3;
size_t e = 2;
for (size_t i=0 ; i<m_colorCount ; ++i, ++e)
{
for (size_t i = 0; i < m_colorCount; ++i, ++e) {
ret[e].semantic = boo::VertexSemantic::ColorUNorm;
ret[e].semanticIdx = i;
}
for (size_t i=0 ; i<m_uvCount ; ++i, ++e)
{
for (size_t i = 0; i < m_uvCount; ++i, ++e) {
ret[e].semantic = boo::VertexSemantic::UV2;
ret[e].semanticIdx = i;
}
for (size_t i=0 ; i<m_weightCount ; ++i, ++e)
{
for (size_t i = 0; i < m_weightCount; ++i, ++e) {
ret[e].semantic = boo::VertexSemantic::Weight;
ret[e].semanticIdx = i;
}
@ -173,17 +162,14 @@ public:
std::pair<BlendFactor, BlendFactor> blendFactors) const;
};
struct Function
{
struct Function {
std::string_view m_source;
std::string_view m_entry;
Function() = default;
Function(std::string_view source, std::string_view entry)
: m_source(source), m_entry(entry) {}
Function(std::string_view source, std::string_view entry) : m_source(source), m_entry(entry) {}
};
struct ExtensionSlot
{
struct ExtensionSlot {
Function lighting;
Function post;
size_t blockCount = 0;
@ -201,44 +187,45 @@ struct ExtensionSlot
bool noReflection = false;
bool forceAlphaTest = false;
ExtensionSlot(size_t blockCount = 0,
const char** blockNames = nullptr,
size_t texCount = 0,
ExtensionSlot(size_t blockCount = 0, const char** blockNames = nullptr, size_t texCount = 0,
const Backend::TextureInfo* texs = nullptr,
Backend::BlendFactor srcFactor = Backend::BlendFactor::Original,
Backend::BlendFactor dstFactor = Backend::BlendFactor::Original,
Backend::ZTest depthTest = Backend::ZTest::Original,
Backend::CullMode cullMode = Backend::CullMode::Backface,
bool noDepthWrite = false,
bool noColorWrite = false,
bool noAlphaWrite = false,
bool noAlphaOverwrite = false,
bool noReflection = false,
bool forceAlphaTest = false)
: blockCount(blockCount), blockNames(blockNames), texCount(texCount), texs(texs),
srcFactor(srcFactor), dstFactor(dstFactor), depthTest(depthTest), cullMode(cullMode),
noDepthWrite(noDepthWrite), noColorWrite(noColorWrite), noAlphaWrite(noAlphaWrite),
noAlphaOverwrite(noAlphaOverwrite), noReflection(noReflection), forceAlphaTest(forceAlphaTest) {}
Backend::CullMode cullMode = Backend::CullMode::Backface, bool noDepthWrite = false,
bool noColorWrite = false, bool noAlphaWrite = false, bool noAlphaOverwrite = false,
bool noReflection = false, bool forceAlphaTest = false)
: blockCount(blockCount)
, blockNames(blockNames)
, texCount(texCount)
, texs(texs)
, srcFactor(srcFactor)
, dstFactor(dstFactor)
, depthTest(depthTest)
, cullMode(cullMode)
, noDepthWrite(noDepthWrite)
, noColorWrite(noColorWrite)
, noAlphaWrite(noAlphaWrite)
, noAlphaOverwrite(noAlphaOverwrite)
, noReflection(noReflection)
, forceAlphaTest(forceAlphaTest) {}
mutable uint64_t m_hash = 0;
void calculateHash() const
{
void calculateHash() const {
XXH64_state_t st;
XXH64_reset(&st, 0);
if (!lighting.m_source.empty())
XXH64_update(&st, lighting.m_source.data(), lighting.m_source.size());
if (!post.m_source.empty())
XXH64_update(&st, post.m_source.data(), post.m_source.size());
for (size_t i = 0; i < texCount; ++i)
{
for (size_t i = 0; i < texCount; ++i) {
const Backend::TextureInfo& tinfo = texs[i];
XXH64_update(&st, &tinfo, sizeof(tinfo));
}
XXH64_update(&st, &srcFactor, offsetof(ExtensionSlot, m_hash) - offsetof(ExtensionSlot, srcFactor));
m_hash = XXH64_digest(&st);
}
uint64_t hash() const
{
uint64_t hash() const {
if (m_hash == 0)
calculateHash();
return m_hash;
@ -246,11 +233,9 @@ struct ExtensionSlot
};
inline boo::AdditionalPipelineInfo ShaderTag::additionalInfo(const ExtensionSlot& ext,
std::pair<BlendFactor, BlendFactor> blendFactors) const
{
std::pair<BlendFactor, BlendFactor> blendFactors) const {
boo::ZTest zTest;
switch (ext.depthTest)
{
switch (ext.depthTest) {
case hecl::Backend::ZTest::Original:
default:
zTest = getDepthTest() ? boo::ZTest::LEqual : boo::ZTest::None;
@ -272,25 +257,24 @@ inline boo::AdditionalPipelineInfo ShaderTag::additionalInfo(const ExtensionSlot
break;
}
return {
boo::BlendFactor((ext.srcFactor == BlendFactor::Original) ? blendFactors.first : ext.srcFactor),
return {boo::BlendFactor((ext.srcFactor == BlendFactor::Original) ? blendFactors.first : ext.srcFactor),
boo::BlendFactor((ext.dstFactor == BlendFactor::Original) ? blendFactors.second : ext.dstFactor),
getPrimType(), zTest, ext.noDepthWrite ? false : getDepthWrite(),
!ext.noColorWrite, !ext.noAlphaWrite,
(ext.cullMode == hecl::Backend::CullMode::Original) ?
(getBackfaceCulling() ? boo::CullMode::Backface : boo::CullMode::None) :
boo::CullMode(ext.cullMode), !ext.noAlphaOverwrite
};
getPrimType(),
zTest,
ext.noDepthWrite ? false : getDepthWrite(),
!ext.noColorWrite,
!ext.noAlphaWrite,
(ext.cullMode == hecl::Backend::CullMode::Original)
? (getBackfaceCulling() ? boo::CullMode::Backface : boo::CullMode::None)
: boo::CullMode(ext.cullMode),
!ext.noAlphaOverwrite};
}
}
} // namespace hecl::Backend
namespace std
{
template <> struct hash<hecl::Backend::ShaderTag>
{
size_t operator()(const hecl::Backend::ShaderTag& val) const noexcept
{return val.valSizeT();}
namespace std {
template <>
struct hash<hecl::Backend::ShaderTag> {
size_t operator()(const hecl::Backend::ShaderTag& val) const noexcept { return val.valSizeT(); }
};
}
} // namespace std

View File

@ -2,28 +2,19 @@
#include "ProgrammableCommon.hpp"
namespace hecl::Backend
{
namespace hecl::Backend {
#define HECL_GLSL_VERT_UNIFORM_BLOCK_NAME "HECLVertUniform"
#define HECL_GLSL_TEXMTX_UNIFORM_BLOCK_NAME "HECLTexMtxUniform"
struct GLSL : ProgrammableCommon
{
struct GLSL : ProgrammableCommon {
void reset(const IR& ir, Diagnostics& diag);
std::string makeVert(unsigned col, unsigned uv, unsigned w,
unsigned skinSlots, size_t extTexCount,
std::string makeVert(unsigned col, unsigned uv, unsigned w, unsigned skinSlots, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const;
std::string makeFrag(size_t blockCount, const char** blockNames,
bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting=Function()) const;
std::string makeFrag(size_t blockCount, const char** blockNames,
bool alphaTest,
ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting,
const Function& post,
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting = Function()) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post,
size_t extTexCount, const TextureInfo* extTexs) const;
private:
@ -33,14 +24,12 @@ private:
std::string GenerateAlphaTest() const;
std::string GenerateReflectionExpr(ReflectionType type) const;
std::string EmitVec3(const atVec4f& vec) const
{
std::string EmitVec3(const atVec4f& vec) const {
athena::simd_floats f(vec.simd);
return hecl::Format("vec3(%g,%g,%g)", f[0], f[1], f[2]);
}
std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const
{
std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const {
return hecl::Format("vec3(%s,%s,%s)", a.c_str(), b.c_str(), c.c_str());
}
@ -48,5 +37,4 @@ private:
std::string EmitTexGenSource4(TexGenSrc src, int uvIdx) const;
};
}
} // namespace hecl::Backend

View File

@ -9,21 +9,12 @@
#undef min
#undef max
namespace hecl::Backend
{
namespace hecl::Backend {
struct GX final : IBackend
{
enum AttrType
{
NONE,
DIRECT,
INDEX8,
INDEX16
};
struct GX final : IBackend {
enum AttrType { NONE, DIRECT, INDEX8, INDEX16 };
enum TevOp
{
enum TevOp {
TEV_ADD = 0,
TEV_SUB = 1,
TEV_COMP_R8_GT = 8,
@ -38,23 +29,15 @@ struct GX final : IBackend
TEV_COMP_A8_EQ = TEV_COMP_RGB8_EQ // for alpha channel
};
enum TevBias
{
enum TevBias {
TB_ZERO = 0,
TB_ADDHALF = 1,
TB_SUBHALF = 2,
};
enum TevScale
{
CS_SCALE_1 = 0,
CS_SCALE_2 = 1,
CS_SCALE_4 = 2,
CS_DIVIDE_2 = 3
};
enum TevScale { CS_SCALE_1 = 0, CS_SCALE_2 = 1, CS_SCALE_4 = 2, CS_DIVIDE_2 = 3 };
enum TexGenType
{
enum TexGenType {
TG_MTX3x4 = 0,
TG_MTX2x4,
TG_BUMP0,
@ -68,17 +51,9 @@ struct GX final : IBackend
TG_SRTG
};
enum TevRegID
{
TEVPREV = 0,
TEVREG0 = 1,
TEVREG1 = 2,
TEVREG2 = 3,
TEVLAZY = 5
};
enum TevRegID { TEVPREV = 0, TEVREG0 = 1, TEVREG1 = 2, TEVREG2 = 3, TEVLAZY = 5 };
enum TevColorArg
{
enum TevColorArg {
CC_CPREV = 0, /*!< Use the color value from previous TEV stage */
CC_APREV = 1, /*!< Use the alpha value from previous TEV stage */
CC_C0 = 2, /*!< Use the color value from the color/output register 0 */
@ -100,8 +75,7 @@ struct GX final : IBackend
CC_LAZY /*!< Lazy register allocation */
};
enum TevAlphaArg
{
enum TevAlphaArg {
CA_APREV = 0, /*!< Use the alpha value from previous TEV stage */
CA_A0 = 1, /*!< Use the alpha value from the color/output register 0 */
CA_A1 = 2, /*!< Use the alpha value from the color/output register 1 */
@ -115,8 +89,7 @@ struct GX final : IBackend
CA_LAZY /*!< Lazy register allocation */
};
enum TevKColorSel
{
enum TevKColorSel {
TEV_KCSEL_8_8 = 0x00,
TEV_KCSEL_7_8 = 0x01,
TEV_KCSEL_6_8 = 0x02,
@ -153,8 +126,7 @@ struct GX final : IBackend
TEV_KCSEL_K3_A = 0x1F
};
enum TevKAlphaSel
{
enum TevKAlphaSel {
TEV_KASEL_8_8 = 0x00,
TEV_KASEL_7_8 = 0x01,
TEV_KASEL_6_8 = 0x02,
@ -187,8 +159,7 @@ struct GX final : IBackend
TEV_KASEL_K3_A = 0x1F
};
enum ChannelID
{
enum ChannelID {
GX_COLOR0,
GX_COLOR1,
GX_ALPHA0,
@ -201,8 +172,7 @@ struct GX final : IBackend
GX_COLOR_NULL = 0xff
};
enum TexGenSrc
{
enum TexGenSrc {
TG_POS = 0,
TG_NRM,
TG_BINRM,
@ -226,8 +196,7 @@ struct GX final : IBackend
TG_COLOR1
};
enum TexMtx
{
enum TexMtx {
TEXMTX0 = 30,
TEXMTX1 = 33,
TEXMTX2 = 36,
@ -241,8 +210,7 @@ struct GX final : IBackend
IDENTITY = 60
};
enum PTTexMtx
{
enum PTTexMtx {
PTTEXMTX0 = 64,
PTTEXMTX1 = 67,
PTTEXMTX2 = 70,
@ -266,22 +234,11 @@ struct GX final : IBackend
PTIDENTITY = 125
};
enum DiffuseFn
{
DF_NONE = 0,
DF_SIGN,
DF_CLAMP
};
enum DiffuseFn { DF_NONE = 0, DF_SIGN, DF_CLAMP };
enum AttnFn
{
AF_SPEC = 0,
AF_SPOT = 1,
AF_NONE
};
enum AttnFn { AF_SPEC = 0, AF_SPOT = 1, AF_NONE };
enum Primitive
{
enum Primitive {
POINTS = 0xb8,
LINES = 0xa8,
LINESTRIP = 0xb0,
@ -291,8 +248,7 @@ struct GX final : IBackend
QUADS = 0x80
};
struct TexCoordGen
{
struct TexCoordGen {
TexGenSrc m_src = TG_TEX0;
TexMtx m_mtx = IDENTITY;
bool m_norm = false;
@ -309,8 +265,7 @@ struct GX final : IBackend
unsigned m_texMtxCount = 0;
TexCoordGen* m_texMtxRefs[8];
struct TEVStage
{
struct TEVStage {
TevOp m_cop = TEV_ADD;
TevOp m_aop = TEV_ADD;
TevColorArg m_color[4] = {CC_ZERO, CC_ZERO, CC_ZERO, CC_ZERO};
@ -336,9 +291,8 @@ struct GX final : IBackend
unsigned m_tevCount = 0;
TEVStage m_tevs[16];
int getStageIdx(const TEVStage* stage) const
{
for (int i=0 ; i<int(m_tevCount) ; ++i)
int getStageIdx(const TEVStage* stage) const {
for (int i = 0; i < int(m_tevCount); ++i)
if (&m_tevs[i] == stage)
return i;
return -1;
@ -350,14 +304,11 @@ struct GX final : IBackend
int m_aRegMask = 0;
int m_aRegLazy = 0;
int pickCLazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const
{
int pickCLazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const {
int regMask = m_cRegMask;
for (int i=stageIdx+1 ; i<int(m_tevCount) ; ++i)
{
for (int i = stageIdx + 1; i < int(m_tevCount); ++i) {
const TEVStage& stage = m_tevs[i];
for (int c=0 ; c<4 ; ++c)
{
for (int c = 0; c < 4; ++c) {
if (stage.m_color[c] == CC_C0)
regMask |= 1;
if (stage.m_color[c] == CC_C1)
@ -369,7 +320,7 @@ struct GX final : IBackend
/* Allocate from back for compatibility with Retro's
* extended shader arithmetic use */
for (int i=2 ; i>=0 ; --i)
for (int i = 2; i >= 0; --i)
if (!(regMask & (1 << i)))
return i;
@ -377,29 +328,23 @@ struct GX final : IBackend
return -1;
}
int pickALazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const
{
int pickALazy(Diagnostics& diag, const SourceLocation& loc, int stageIdx) const {
int regMask = m_aRegMask;
for (int i=stageIdx+1 ; i<int(m_tevCount) ; ++i)
{
for (int i = stageIdx + 1; i < int(m_tevCount); ++i) {
const TEVStage& stage = m_tevs[i];
for (int c=0 ; c<4 ; ++c)
{
if (stage.m_color[c] == CC_A0 ||
stage.m_alpha[c] == CA_A0)
for (int c = 0; c < 4; ++c) {
if (stage.m_color[c] == CC_A0 || stage.m_alpha[c] == CA_A0)
regMask |= 1;
if (stage.m_color[c] == CC_A1 ||
stage.m_alpha[c] == CA_A1)
if (stage.m_color[c] == CC_A1 || stage.m_alpha[c] == CA_A1)
regMask |= 2;
if (stage.m_color[c] == CC_A2 ||
stage.m_alpha[c] == CA_A2)
if (stage.m_color[c] == CC_A2 || stage.m_alpha[c] == CA_A2)
regMask |= 4;
}
}
/* Allocate from back for compatibility with Retro's
* extended shader arithmetic use */
for (int i=2 ; i>=0 ; --i)
for (int i = 2; i >= 0; --i)
if (!(regMask & (1 << i)))
return i;
@ -407,8 +352,7 @@ struct GX final : IBackend
return -1;
}
enum BlendFactor : uint16_t
{
enum BlendFactor : uint16_t {
BL_ZERO,
BL_ONE,
BL_SRCCLR,
@ -421,16 +365,13 @@ struct GX final : IBackend
BlendFactor m_blendSrc;
BlendFactor m_blendDst;
struct Color : athena::io::DNA<athena::Big>
{
union
{
struct Color : athena::io::DNA<athena::Big> {
union {
uint8_t color[4];
uint32_t num = 0;
};
Color() = default;
Color& operator=(const atVec4f& vec)
{
Color& operator=(const atVec4f& vec) {
athena::simd_floats f(vec.simd);
color[0] = uint8_t(std::min(std::max(f[0] * 255.f, 0.f), 255.f));
color[1] = uint8_t(std::min(std::max(f[1] * 255.f, 0.f), 255.f));
@ -438,8 +379,7 @@ struct GX final : IBackend
color[3] = uint8_t(std::min(std::max(f[3] * 255.f, 0.f), 255.f));
return *this;
}
Color& operator=(const atVec3f& vec)
{
Color& operator=(const atVec3f& vec) {
athena::simd_floats f(vec.simd);
color[0] = uint8_t(std::min(std::max(f[0] * 255.f, 0.f), 255.f));
color[1] = uint8_t(std::min(std::max(f[1] * 255.f, 0.f), 255.f));
@ -447,16 +387,14 @@ struct GX final : IBackend
color[3] = 0xff;
return *this;
}
Color& operator=(uint8_t val)
{
Color& operator=(uint8_t val) {
color[0] = val;
color[1] = val;
color[2] = val;
color[3] = val;
return *this;
}
atVec4f toVec4f() const
{
atVec4f toVec4f() const {
atVec4f out;
athena::simd_floats f;
f[0] = color[0] / 255.f;
@ -466,13 +404,13 @@ struct GX final : IBackend
out.simd.copy_from(f);
return out;
}
Color(const atVec4f& vec) {*this = vec;}
Color(const atVec3f& vec) {*this = vec;}
Color(uint8_t val) {*this = val;}
bool operator==(const Color& other) const {return num == other.num;}
bool operator!=(const Color& other) const {return num != other.num;}
uint8_t operator[](size_t idx) const {return color[idx];}
uint8_t& operator[](size_t idx) {return color[idx];}
Color(const atVec4f& vec) { *this = vec; }
Color(const atVec3f& vec) { *this = vec; }
Color(uint8_t val) { *this = val; }
bool operator==(const Color& other) const { return num == other.num; }
bool operator!=(const Color& other) const { return num != other.num; }
uint8_t operator[](size_t idx) const { return color[idx]; }
uint8_t& operator[](size_t idx) { return color[idx]; }
AT_DECL_EXPLICIT_DNA
};
unsigned m_kcolorCount = 0;
@ -480,8 +418,7 @@ struct GX final : IBackend
int m_alphaTraceStage = -1;
bool operator==(const GX& other) const
{
bool operator==(const GX& other) const {
if (m_tcgCount != other.m_tcgCount)
return false;
if (m_tevCount != other.m_tevCount)
@ -492,8 +429,7 @@ struct GX final : IBackend
return false;
if (m_kcolorCount != other.m_kcolorCount)
return false;
for (unsigned i=0 ; i<m_tcgCount ; ++i)
{
for (unsigned i = 0; i < m_tcgCount; ++i) {
const TexCoordGen& a = m_tcgs[i];
const TexCoordGen& b = other.m_tcgs[i];
if (a.m_src != b.m_src)
@ -505,14 +441,13 @@ struct GX final : IBackend
if (a.m_pmtx != b.m_pmtx)
return false;
}
for (unsigned i=0 ; i<m_tevCount ; ++i)
{
for (unsigned i = 0; i < m_tevCount; ++i) {
const TEVStage& a = m_tevs[i];
const TEVStage& b = other.m_tevs[i];
for (unsigned j=0 ; j<4 ; ++j)
for (unsigned j = 0; j < 4; ++j)
if (a.m_color[j] != b.m_color[j])
return false;
for (unsigned j=0 ; j<4 ; ++j)
for (unsigned j = 0; j < 4; ++j)
if (a.m_alpha[j] != b.m_alpha[j])
return false;
if (a.m_cop != b.m_cop)
@ -532,8 +467,7 @@ struct GX final : IBackend
if (a.m_texGenIdx != b.m_texGenIdx)
return false;
}
for (unsigned i=0 ; i<m_kcolorCount ; ++i)
{
for (unsigned i = 0; i < m_kcolorCount; ++i) {
const Color& a = m_kcolors[i];
const Color& b = other.m_kcolors[i];
if (a.num != b.num)
@ -541,27 +475,14 @@ struct GX final : IBackend
}
return true;
}
bool operator!=(const GX& other) const
{
return !(*this == other);
}
bool operator!=(const GX& other) const { return !(*this == other); }
void reset(const IR& ir, Diagnostics& diag);
private:
struct TraceResult
{
enum class Type
{
Invalid,
TEVStage,
TEVColorArg,
TEVAlphaArg,
TEVKColorSel,
TEVKAlphaSel
} type;
union
{
struct TraceResult {
enum class Type { Invalid, TEVStage, TEVColorArg, TEVAlphaArg, TEVKColorSel, TEVKAlphaSel } type;
union {
GX::TEVStage* tevStage;
GX::TevColorArg tevColorArg;
GX::TevAlphaArg tevAlphaArg;
@ -578,19 +499,15 @@ private:
unsigned addKColor(Diagnostics& diag, const SourceLocation& loc, const Color& color);
unsigned addKAlpha(Diagnostics& diag, const SourceLocation& loc, float alpha);
unsigned addTexCoordGen(Diagnostics& diag, const SourceLocation& loc,
TexGenSrc src, TexMtx mtx, bool norm, PTTexMtx pmtx);
unsigned addTexCoordGen(Diagnostics& diag, const SourceLocation& loc, TexGenSrc src, TexMtx mtx, bool norm,
PTTexMtx pmtx);
TEVStage& addTEVStage(Diagnostics& diag, const SourceLocation& loc);
TEVStage& addAlphaTEVStage(Diagnostics& diag, const SourceLocation& loc);
TraceResult RecursiveTraceColor(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst,
bool swizzleAlpha=false);
TraceResult RecursiveTraceAlpha(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst);
unsigned RecursiveTraceTexGen(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst,
TexMtx mtx, bool normalize, PTTexMtx pmtx);
TraceResult RecursiveTraceColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst,
bool swizzleAlpha = false);
TraceResult RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst);
unsigned RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, TexMtx mtx,
bool normalize, PTTexMtx pmtx);
};
}
} // namespace hecl::Backend

View File

@ -2,25 +2,17 @@
#include "ProgrammableCommon.hpp"
namespace hecl::Backend
{
namespace hecl::Backend {
struct HLSL : ProgrammableCommon
{
struct HLSL : ProgrammableCommon {
void reset(const IR& ir, Diagnostics& diag);
std::string makeVert(unsigned col, unsigned uv, unsigned w,
unsigned skinSlots, size_t extTexCount,
std::string makeVert(unsigned col, unsigned uv, unsigned w, unsigned skinSlots, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const;
std::string makeFrag(size_t blockCount, const char** blockNames,
bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting=Function()) const;
std::string makeFrag(size_t blockCount, const char** blockNames,
bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting,
const Function& post, size_t extTexCount,
const TextureInfo* extTexs) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting = Function()) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post,
size_t extTexCount, const TextureInfo* extTexs) const;
private:
std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const;
@ -29,14 +21,12 @@ private:
std::string GenerateAlphaTest() const;
std::string GenerateReflectionExpr(ReflectionType type) const;
std::string EmitVec3(const atVec4f& vec) const
{
std::string EmitVec3(const atVec4f& vec) const {
athena::simd_floats f(vec.simd);
return hecl::Format("float3(%g,%g,%g)", f[0], f[1], f[2]);
}
std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const
{
std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const {
return hecl::Format("float3(%s,%s,%s)", a.c_str(), b.c_str(), c.c_str());
}
@ -44,5 +34,4 @@ private:
std::string EmitTexGenSource4(TexGenSrc src, int uvIdx) const;
};
}
} // namespace hecl::Backend

View File

@ -2,25 +2,17 @@
#include "ProgrammableCommon.hpp"
namespace hecl::Backend
{
namespace hecl::Backend {
struct Metal : ProgrammableCommon
{
struct Metal : ProgrammableCommon {
void reset(const IR& ir, Diagnostics& diag);
std::string makeVert(unsigned col, unsigned uv, unsigned w,
unsigned skinSlots, size_t extTexCount,
std::string makeVert(unsigned col, unsigned uv, unsigned w, unsigned skinSlots, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting=Function()) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting,
const Function& post, size_t extTexCount,
const TextureInfo* extTexs) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting = Function()) const;
std::string makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post,
size_t extTexCount, const TextureInfo* extTexs) const;
private:
std::string GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const;
@ -30,14 +22,12 @@ private:
std::string GenerateAlphaTest() const;
std::string GenerateReflectionExpr(ReflectionType type) const;
std::string EmitVec3(const atVec4f& vec) const
{
std::string EmitVec3(const atVec4f& vec) const {
athena::simd_floats f(vec.simd);
return hecl::Format("float3(%g,%g,%g)", f[0], f[1], f[2]);
}
std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const
{
std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const {
return hecl::Format("float3(%s,%s,%s)", a.c_str(), b.c_str(), c.c_str());
}
@ -45,5 +35,4 @@ private:
std::string EmitTexGenSource4(TexGenSrc src, int uvIdx) const;
};
}
} // namespace hecl::Backend

View File

@ -7,19 +7,16 @@
#include <cstdlib>
#include <algorithm>
namespace hecl::Backend
{
namespace hecl::Backend {
struct ProgrammableCommon : IBackend
{
struct ProgrammableCommon : IBackend {
std::string m_colorExpr;
std::string m_alphaExpr;
BlendFactor m_blendSrc;
BlendFactor m_blendDst;
bool m_lighting = false;
struct TexSampling
{
struct TexSampling {
int mapIdx = -1;
int tcgIdx = -1;
};
@ -27,8 +24,7 @@ struct ProgrammableCommon : IBackend
unsigned m_texMapEnd = 0;
unsigned m_extMapStart = 8;
struct TexCoordGen
{
struct TexCoordGen {
TexGenSrc m_src;
int m_uvIdx = 0;
int m_mtx = -1;
@ -47,93 +43,46 @@ struct ProgrammableCommon : IBackend
private:
unsigned addTexCoordGen(TexGenSrc src, int uvIdx, int mtx, bool normalize);
unsigned addTexSampling(unsigned mapIdx, unsigned tcgIdx);
std::string RecursiveTraceColor(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst, bool toSwizzle);
std::string RecursiveTraceAlpha(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst, bool toSwizzle);
unsigned RecursiveTraceTexGen(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst,
int mtx, bool normalize);
std::string RecursiveTraceColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, bool toSwizzle);
std::string RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, bool toSwizzle);
unsigned RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, int mtx, bool normalize);
std::string EmitSamplingUseRaw(unsigned samplingIdx) const
{
return hecl::Format("sampling%u", samplingIdx);
}
std::string EmitSamplingUseRaw(unsigned samplingIdx) const { return hecl::Format("sampling%u", samplingIdx); }
std::string EmitSamplingUseRGB(unsigned samplingIdx) const
{
return hecl::Format("sampling%u.rgb", samplingIdx);
}
std::string EmitSamplingUseRGB(unsigned samplingIdx) const { return hecl::Format("sampling%u.rgb", samplingIdx); }
std::string EmitSamplingUseAlpha(unsigned samplingIdx) const
{
return hecl::Format("sampling%u.a", samplingIdx);
}
std::string EmitSamplingUseAlpha(unsigned samplingIdx) const { return hecl::Format("sampling%u.a", samplingIdx); }
std::string EmitColorRegUseRaw(unsigned idx) const
{
return hecl::Format("colorReg%u", idx);
}
std::string EmitColorRegUseRaw(unsigned idx) const { return hecl::Format("colorReg%u", idx); }
std::string EmitColorRegUseRGB(unsigned idx) const
{
return hecl::Format("colorReg%u.rgb", idx);
}
std::string EmitColorRegUseRGB(unsigned idx) const { return hecl::Format("colorReg%u.rgb", idx); }
std::string EmitColorRegUseAlpha(unsigned idx) const
{
return hecl::Format("colorReg%u.a", idx);
}
std::string EmitColorRegUseAlpha(unsigned idx) const { return hecl::Format("colorReg%u.a", idx); }
std::string EmitLightingRaw() const
{
return std::string("lighting");
}
std::string EmitLightingRaw() const { return std::string("lighting"); }
std::string EmitLightingRGB() const
{
return std::string("lighting.rgb");
}
std::string EmitLightingRGB() const { return std::string("lighting.rgb"); }
std::string EmitLightingAlpha() const
{
return std::string("lighting.a");
}
std::string EmitLightingAlpha() const { return std::string("lighting.a"); }
virtual std::string EmitVec3(const atVec4f& vec) const=0;
virtual std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const=0;
virtual std::string EmitVec3(const atVec4f& vec) const = 0;
virtual std::string EmitVec3(const std::string& a, const std::string& b, const std::string& c) const = 0;
std::string EmitVal(float val) const
{
return hecl::Format("%g", val);
}
std::string EmitVal(float val) const { return hecl::Format("%g", val); }
std::string EmitAdd(const std::string& a, const std::string& b) const
{
return '(' + a + '+' + b + ')';
}
std::string EmitAdd(const std::string& a, const std::string& b) const { return '(' + a + '+' + b + ')'; }
std::string EmitSub(const std::string& a, const std::string& b) const
{
return '(' + a + '-' + b + ')';
}
std::string EmitSub(const std::string& a, const std::string& b) const { return '(' + a + '-' + b + ')'; }
std::string EmitMult(const std::string& a, const std::string& b) const
{
return '(' + a + '*' + b + ')';
}
std::string EmitMult(const std::string& a, const std::string& b) const { return '(' + a + '*' + b + ')'; }
std::string EmitDiv(const std::string& a, const std::string& b) const
{
return '(' + a + '/' + b + ')';
}
std::string EmitDiv(const std::string& a, const std::string& b) const { return '(' + a + '/' + b + ')'; }
std::string EmitSwizzle3(Diagnostics& diag, const SourceLocation& loc,
const std::string& a, const atInt8 swiz[4]) const;
std::string EmitSwizzle3(Diagnostics& diag, const SourceLocation& loc, const std::string& a,
const atInt8 swiz[4]) const;
std::string EmitSwizzle1(Diagnostics& diag, const SourceLocation& loc,
const std::string& a, const atInt8 swiz[4]) const;
std::string EmitSwizzle1(Diagnostics& diag, const SourceLocation& loc, const std::string& a,
const atInt8 swiz[4]) const;
};
}
} // namespace hecl::Backend

View File

@ -29,10 +29,9 @@ class BitVector {
enum { BITWORD_SIZE = (unsigned)sizeof(BitWord) * CHAR_BIT };
static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32,
"Unsupported word size");
static_assert(BITWORD_SIZE == 64 || BITWORD_SIZE == 32, "Unsupported word size");
BitWord *Bits; // Actual bits.
BitWord* Bits; // Actual bits.
unsigned Size; // Size of bitvector in bits.
unsigned Capacity; // Number of BitWords allocated in the Bits array.
@ -42,20 +41,20 @@ public:
class reference {
friend class BitVector;
BitWord *WordRef;
BitWord* WordRef;
unsigned BitPos;
reference(); // Undefined
public:
reference(BitVector &b, unsigned Idx) {
reference(BitVector& b, unsigned Idx) {
WordRef = &b.Bits[Idx / BITWORD_SIZE];
BitPos = Idx % BITWORD_SIZE;
}
reference(const reference&) = default;
reference &operator=(reference t) {
reference& operator=(reference t) {
*this = bool(t);
return *this;
}
@ -68,29 +67,24 @@ public:
return *this;
}
operator bool() const {
return ((*WordRef) & (BitWord(1) << BitPos)) != 0;
}
operator bool() const { return ((*WordRef) & (BitWord(1) << BitPos)) != 0; }
};
/// BitVector default ctor - Creates an empty bitvector.
BitVector() : Size(0), Capacity(0) {
Bits = nullptr;
}
BitVector() : Size(0), Capacity(0) { Bits = nullptr; }
/// BitVector ctor - Creates a bitvector of specified number of bits. All
/// bits are initialized to the specified value.
explicit BitVector(unsigned s, bool t = false) : Size(s) {
Capacity = NumBitWords(s);
Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
Bits = (BitWord*)std::malloc(Capacity * sizeof(BitWord));
init_words(Bits, Capacity, t);
if (t)
clear_unused_bits();
}
/// BitVector copy ctor.
BitVector(const BitVector &RHS) : Size(RHS.size()) {
BitVector(const BitVector& RHS) : Size(RHS.size()) {
if (Size == 0) {
Bits = nullptr;
Capacity = 0;
@ -98,19 +92,16 @@ public:
}
Capacity = NumBitWords(RHS.size());
Bits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
Bits = (BitWord*)std::malloc(Capacity * sizeof(BitWord));
std::memcpy(Bits, RHS.Bits, Capacity * sizeof(BitWord));
}
BitVector(BitVector &&RHS)
: Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) {
BitVector(BitVector&& RHS) : Bits(RHS.Bits), Size(RHS.Size), Capacity(RHS.Capacity) {
RHS.Bits = nullptr;
RHS.Size = RHS.Capacity = 0;
}
~BitVector() {
std::free(Bits);
}
~BitVector() { std::free(Bits); }
/// empty - Tests whether there are no bits in this bitvector.
bool empty() const { return Size == 0; }
@ -148,9 +139,7 @@ public:
}
/// none - Returns true if none of the bits are set.
bool none() const {
return !any();
}
bool none() const { return !any(); }
/// find_first - Returns the index of the first set bit, -1 if none
/// of the bits are set.
@ -178,7 +167,7 @@ public:
return WordPos * BITWORD_SIZE + countTrailingZeros(Copy);
// Check subsequent words.
for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i)
for (unsigned i = WordPos + 1; i < NumBitWords(size()); ++i)
if (Bits[i] != 0)
return i * BITWORD_SIZE + countTrailingZeros(Bits[i]);
return -1;
@ -199,8 +188,7 @@ public:
break;
}
}
if (good)
{
if (good) {
unsigned space = BucketSz - (idx % BucketSz);
if (space >= Length)
return idx;
@ -210,16 +198,14 @@ public:
}
/// clear - Clear all bits.
void clear() {
Size = 0;
}
void clear() { Size = 0; }
/// resize - Grow or shrink the bitvector.
void resize(unsigned N, bool t = false) {
if (N > Capacity * BITWORD_SIZE) {
unsigned OldCapacity = Capacity;
grow(N);
init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t);
init_words(&Bits[OldCapacity], (Capacity - OldCapacity), t);
}
// Set any old unused bits that are now included in the BitVector. This
@ -241,24 +227,25 @@ public:
}
// Set, reset, flip
BitVector &set() {
BitVector& set() {
init_words(Bits, Capacity, true);
clear_unused_bits();
return *this;
}
BitVector &set(unsigned Idx) {
BitVector& set(unsigned Idx) {
assert(Bits && "Bits never allocated");
Bits[Idx / BITWORD_SIZE] |= BitWord(1) << (Idx % BITWORD_SIZE);
return *this;
}
/// set - Efficiently set a range of bits in [I, E)
BitVector &set(unsigned I, unsigned E) {
BitVector& set(unsigned I, unsigned E) {
assert(I <= E && "Attempted to set backwards range!");
assert(E <= size() && "Attempted to set out-of-bounds range!");
if (I == E) return *this;
if (I == E)
return *this;
if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
BitWord EMask = 1UL << (E % BITWORD_SIZE);
@ -282,22 +269,23 @@ public:
return *this;
}
BitVector &reset() {
BitVector& reset() {
init_words(Bits, Capacity, false);
return *this;
}
BitVector &reset(unsigned Idx) {
BitVector& reset(unsigned Idx) {
Bits[Idx / BITWORD_SIZE] &= ~(BitWord(1) << (Idx % BITWORD_SIZE));
return *this;
}
/// reset - Efficiently reset a range of bits in [I, E)
BitVector &reset(unsigned I, unsigned E) {
BitVector& reset(unsigned I, unsigned E) {
assert(I <= E && "Attempted to reset backwards range!");
assert(E <= size() && "Attempted to reset out-of-bounds range!");
if (I == E) return *this;
if (I == E)
return *this;
if (I / BITWORD_SIZE == E / BITWORD_SIZE) {
BitWord EMask = 1UL << (E % BITWORD_SIZE);
@ -321,36 +309,34 @@ public:
return *this;
}
BitVector &flip() {
BitVector& flip() {
for (unsigned i = 0; i < NumBitWords(size()); ++i)
Bits[i] = ~Bits[i];
clear_unused_bits();
return *this;
}
BitVector &flip(unsigned Idx) {
BitVector& flip(unsigned Idx) {
Bits[Idx / BITWORD_SIZE] ^= BitWord(1) << (Idx % BITWORD_SIZE);
return *this;
}
// Indexing.
reference operator[](unsigned Idx) {
assert (Idx < Size && "Out-of-bounds Bit access.");
assert(Idx < Size && "Out-of-bounds Bit access.");
return reference(*this, Idx);
}
bool operator[](unsigned Idx) const {
assert (Idx < Size && "Out-of-bounds Bit access.");
assert(Idx < Size && "Out-of-bounds Bit access.");
BitWord Mask = BitWord(1) << (Idx % BITWORD_SIZE);
return (Bits[Idx / BITWORD_SIZE] & Mask) != 0;
}
bool test(unsigned Idx) const {
return (*this)[Idx];
}
bool test(unsigned Idx) const { return (*this)[Idx]; }
/// Test if any common bits are set.
bool anyCommon(const BitVector &RHS) const {
bool anyCommon(const BitVector& RHS) const {
unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size());
for (unsigned i = 0, e = std::min(ThisWords, RHSWords); i != e; ++i)
@ -360,7 +346,7 @@ public:
}
// Comparison operators.
bool operator==(const BitVector &RHS) const {
bool operator==(const BitVector& RHS) const {
unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size());
unsigned i;
@ -381,12 +367,10 @@ public:
return true;
}
bool operator!=(const BitVector &RHS) const {
return !(*this == RHS);
}
bool operator!=(const BitVector& RHS) const { return !(*this == RHS); }
/// Intersection, union, disjoint union.
BitVector &operator&=(const BitVector &RHS) {
BitVector& operator&=(const BitVector& RHS) {
unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size());
unsigned i;
@ -403,7 +387,7 @@ public:
}
/// reset - Reset bits that are set in RHS. Same as *this &= ~RHS.
BitVector &reset(const BitVector &RHS) {
BitVector& reset(const BitVector& RHS) {
unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size());
unsigned i;
@ -414,7 +398,7 @@ public:
/// test - Check if (This - RHS) is zero.
/// This is the same as reset(RHS) and any().
bool test(const BitVector &RHS) const {
bool test(const BitVector& RHS) const {
unsigned ThisWords = NumBitWords(size());
unsigned RHSWords = NumBitWords(RHS.size());
unsigned i;
@ -422,14 +406,14 @@ public:
if ((Bits[i] & ~RHS.Bits[i]) != 0)
return true;
for (; i != ThisWords ; ++i)
for (; i != ThisWords; ++i)
if (Bits[i] != 0)
return true;
return false;
}
BitVector &operator|=(const BitVector &RHS) {
BitVector& operator|=(const BitVector& RHS) {
if (size() < RHS.size())
resize(RHS.size());
for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
@ -437,7 +421,7 @@ public:
return *this;
}
BitVector &operator^=(const BitVector &RHS) {
BitVector& operator^=(const BitVector& RHS) {
if (size() < RHS.size())
resize(RHS.size());
for (size_t i = 0, e = NumBitWords(RHS.size()); i != e; ++i)
@ -446,8 +430,9 @@ public:
}
// Assignment operator.
const BitVector &operator=(const BitVector &RHS) {
if (this == &RHS) return *this;
const BitVector& operator=(const BitVector& RHS) {
if (this == &RHS)
return *this;
Size = RHS.size();
unsigned RHSWords = NumBitWords(Size);
@ -461,7 +446,7 @@ public:
// Grow the bitvector to have enough elements.
Capacity = RHSWords;
assert(Capacity > 0 && "negative capacity?");
BitWord *NewBits = (BitWord *)std::malloc(Capacity * sizeof(BitWord));
BitWord* NewBits = (BitWord*)std::malloc(Capacity * sizeof(BitWord));
std::memcpy(NewBits, RHS.Bits, Capacity * sizeof(BitWord));
// Destroy the old bits.
@ -471,8 +456,9 @@ public:
return *this;
}
const BitVector &operator=(BitVector &&RHS) {
if (this == &RHS) return *this;
const BitVector& operator=(BitVector&& RHS) {
if (this == &RHS)
return *this;
std::free(Bits);
Bits = RHS.Bits;
@ -485,7 +471,7 @@ public:
return *this;
}
void swap(BitVector &RHS) {
void swap(BitVector& RHS) {
std::swap(Bits, RHS.Bits);
std::swap(Size, RHS.Size);
std::swap(Capacity, RHS.Capacity);
@ -505,70 +491,56 @@ public:
/// setBitsInMask - Add '1' bits from Mask to this vector. Don't resize.
/// This computes "*this |= Mask".
void setBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
applyMask<true, false>(Mask, MaskWords);
}
void setBitsInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask<true, false>(Mask, MaskWords); }
/// clearBitsInMask - Clear any bits in this vector that are set in Mask.
/// Don't resize. This computes "*this &= ~Mask".
void clearBitsInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
applyMask<false, false>(Mask, MaskWords);
}
void clearBitsInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask<false, false>(Mask, MaskWords); }
/// setBitsNotInMask - Add a bit to this vector for every '0' bit in Mask.
/// Don't resize. This computes "*this |= ~Mask".
void setBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
applyMask<true, true>(Mask, MaskWords);
}
void setBitsNotInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask<true, true>(Mask, MaskWords); }
/// clearBitsNotInMask - Clear a bit in this vector for every '0' bit in Mask.
/// Don't resize. This computes "*this &= Mask".
void clearBitsNotInMask(const uint32_t *Mask, unsigned MaskWords = ~0u) {
applyMask<false, true>(Mask, MaskWords);
}
void clearBitsNotInMask(const uint32_t* Mask, unsigned MaskWords = ~0u) { applyMask<false, true>(Mask, MaskWords); }
private:
unsigned NumBitWords(unsigned S) const {
return (S + BITWORD_SIZE-1) / BITWORD_SIZE;
}
unsigned NumBitWords(unsigned S) const { return (S + BITWORD_SIZE - 1) / BITWORD_SIZE; }
// Set the unused bits in the high words.
void set_unused_bits(bool t = true) {
// Set high words first.
unsigned UsedWords = NumBitWords(Size);
if (Capacity > UsedWords)
init_words(&Bits[UsedWords], (Capacity-UsedWords), t);
init_words(&Bits[UsedWords], (Capacity - UsedWords), t);
// Then set any stray high bits of the last used word.
unsigned ExtraBits = Size % BITWORD_SIZE;
if (ExtraBits) {
BitWord ExtraBitMask = ~0UL << ExtraBits;
if (t)
Bits[UsedWords-1] |= ExtraBitMask;
Bits[UsedWords - 1] |= ExtraBitMask;
else
Bits[UsedWords-1] &= ~ExtraBitMask;
Bits[UsedWords - 1] &= ~ExtraBitMask;
}
}
// Clear the unused bits in the high words.
void clear_unused_bits() {
set_unused_bits(false);
}
void clear_unused_bits() { set_unused_bits(false); }
void grow(unsigned NewSize) {
Capacity = std::max(NumBitWords(NewSize), Capacity * 2);
assert(Capacity > 0 && "realloc-ing zero space");
Bits = (BitWord *)std::realloc(Bits, Capacity * sizeof(BitWord));
Bits = (BitWord*)std::realloc(Bits, Capacity * sizeof(BitWord));
clear_unused_bits();
}
void init_words(BitWord *B, unsigned NumWords, bool t) {
memset(B, 0 - (int)t, NumWords*sizeof(BitWord));
}
void init_words(BitWord* B, unsigned NumWords, bool t) { memset(B, 0 - (int)t, NumWords * sizeof(BitWord)); }
template<bool AddBits, bool InvertMask>
void applyMask(const uint32_t *Mask, unsigned MaskWords) {
template <bool AddBits, bool InvertMask>
void applyMask(const uint32_t* Mask, unsigned MaskWords) {
static_assert(BITWORD_SIZE % 32 == 0, "Unsupported BitWord size.");
MaskWords = std::min(MaskWords, (size() + 31) / 32);
const unsigned Scale = BITWORD_SIZE / 32;
@ -578,17 +550,23 @@ private:
// This inner loop should unroll completely when BITWORD_SIZE > 32.
for (unsigned b = 0; b != BITWORD_SIZE; b += 32) {
uint32_t M = *Mask++;
if (InvertMask) M = ~M;
if (AddBits) BW |= BitWord(M) << b;
else BW &= ~(BitWord(M) << b);
if (InvertMask)
M = ~M;
if (AddBits)
BW |= BitWord(M) << b;
else
BW &= ~(BitWord(M) << b);
}
Bits[i] = BW;
}
for (unsigned b = 0; MaskWords; b += 32, --MaskWords) {
uint32_t M = *Mask++;
if (InvertMask) M = ~M;
if (AddBits) Bits[i] |= BitWord(M) << b;
else Bits[i] &= ~(BitWord(M) << b);
if (InvertMask)
M = ~M;
if (AddBits)
Bits[i] |= BitWord(M) << b;
else
Bits[i] &= ~(BitWord(M) << b);
}
if (AddBits)
clear_unused_bits();
@ -599,18 +577,12 @@ public:
size_t getMemorySize() const { return Capacity * sizeof(BitWord); }
};
static inline size_t capacity_in_bytes(const BitVector &X) {
return X.getMemorySize();
}
static inline size_t capacity_in_bytes(const BitVector& X) { return X.getMemorySize(); }
} // end namespace llvm
} // end namespace hecl
namespace std {
/// Implement std::swap in terms of BitVector swap.
inline void
swap(hecl::llvm::BitVector &LHS, hecl::llvm::BitVector &RHS) {
LHS.swap(RHS);
}
/// Implement std::swap in terms of BitVector swap.
inline void swap(hecl::llvm::BitVector& LHS, hecl::llvm::BitVector& RHS) { LHS.swap(RHS); }
} // end namespace std

View File

@ -28,39 +28,31 @@
#include "optional.hpp"
#include "Token.hpp"
namespace hecl::blender
{
namespace hecl::blender {
extern logvisor::Module BlenderLog;
class HMDLBuffers;
class Connection;
struct PoolSkinIndex
{
struct PoolSkinIndex {
size_t m_poolSz = 0;
std::unique_ptr<uint32_t[]> m_poolToSkinIndex;
void allocate(size_t poolSz)
{
void allocate(size_t poolSz) {
m_poolSz = poolSz;
if (poolSz)
m_poolToSkinIndex.reset(new uint32_t[poolSz]);
}
};
enum class ANIMCurveType
{
Rotate,
Translate,
Scale
};
enum class ANIMCurveType { Rotate, Translate, Scale };
class ANIMOutStream
{
class ANIMOutStream {
Connection* m_parent;
unsigned m_curCount = 0;
unsigned m_totalCount = 0;
bool m_inCurve = false;
public:
using CurveType = ANIMCurveType;
ANIMOutStream(Connection* parent);
@ -69,99 +61,88 @@ public:
void write(unsigned frame, float val);
};
class PyOutStream : public std::ostream
{
class PyOutStream : public std::ostream {
friend class Connection;
Connection* m_parent;
struct StreamBuf : std::streambuf
{
struct StreamBuf : std::streambuf {
PyOutStream& m_parent;
std::string m_lineBuf;
bool m_deleteOnError;
StreamBuf(PyOutStream& parent, bool deleteOnError)
: m_parent(parent), m_deleteOnError(deleteOnError) {}
StreamBuf(PyOutStream& parent, bool deleteOnError) : m_parent(parent), m_deleteOnError(deleteOnError) {}
StreamBuf(const StreamBuf& other) = delete;
StreamBuf(StreamBuf&& other) = default;
int_type overflow(int_type ch);
} m_sbuf;
PyOutStream(Connection* parent, bool deleteOnError);
public:
PyOutStream(const PyOutStream& other) = delete;
PyOutStream(PyOutStream&& other)
: std::ostream(&m_sbuf), m_parent(other.m_parent), m_sbuf(std::move(other.m_sbuf))
{other.m_parent = nullptr;}
~PyOutStream() {close();}
PyOutStream(PyOutStream&& other) : std::ostream(&m_sbuf), m_parent(other.m_parent), m_sbuf(std::move(other.m_sbuf)) {
other.m_parent = nullptr;
}
~PyOutStream() { close(); }
void close();
#if __GNUC__
__attribute__((__format__ (__printf__, 2, 3)))
__attribute__((__format__(__printf__, 2, 3)))
#endif
void format(const char* fmt, ...);
void linkBlend(const char* target, const char* objName, bool link=true);
void linkBackground(const char* target, const char* sceneName=nullptr);
void
format(const char* fmt, ...);
void linkBlend(const char* target, const char* objName, bool link = true);
void linkBackground(const char* target, const char* sceneName = nullptr);
void AABBToBMesh(const atVec3f& min, const atVec3f& max);
void centerView();
ANIMOutStream beginANIMCurve()
{
return ANIMOutStream(m_parent);
}
Connection& getConnection() {return *m_parent;}
ANIMOutStream beginANIMCurve() { return ANIMOutStream(m_parent); }
Connection& getConnection() { return *m_parent; }
};
/* Vector types with integrated stream reading constructor */
struct Vector2f
{
struct Vector2f {
atVec2f val;
Vector2f() = default;
void read(Connection& conn);
Vector2f(Connection& conn) {read(conn);}
operator const atVec2f&() const {return val;}
Vector2f(Connection& conn) { read(conn); }
operator const atVec2f&() const { return val; }
};
struct Vector3f
{
struct Vector3f {
atVec3f val;
Vector3f() = default;
void read(Connection& conn);
Vector3f(Connection& conn) {read(conn);}
operator const atVec3f&() const {return val;}
Vector3f(Connection& conn) { read(conn); }
operator const atVec3f&() const { return val; }
};
struct Vector4f
{
struct Vector4f {
atVec4f val;
Vector4f() = default;
void read(Connection& conn);
Vector4f(Connection& conn) {read(conn);}
operator const atVec4f&() const {return val;}
Vector4f(Connection& conn) { read(conn); }
operator const atVec4f&() const { return val; }
};
struct Matrix3f
{
struct Matrix3f {
atVec3f m[3];
inline atVec3f& operator[](size_t idx) {return m[idx];}
inline const atVec3f& operator[](size_t idx) const {return m[idx];}
inline atVec3f& operator[](size_t idx) { return m[idx]; }
inline const atVec3f& operator[](size_t idx) const { return m[idx]; }
};
struct Matrix4f
{
struct Matrix4f {
atVec4f val[4];
Matrix4f() = default;
void read(Connection& conn);
Matrix4f(Connection& conn) {read(conn);}
const atVec4f& operator[] (size_t idx) const {return val[idx];}
Matrix4f(Connection& conn) { read(conn); }
const atVec4f& operator[](size_t idx) const { return val[idx]; }
};
struct Index
{
struct Index {
uint32_t val;
Index() = default;
void read(Connection& conn);
Index(Connection& conn) {read(conn);}
operator const uint32_t&() const {return val;}
Index(Connection& conn) { read(conn); }
operator const uint32_t&() const { return val; }
};
atVec3f MtxVecMul4RM(const Matrix4f& mtx, const Vector3f& vec);
atVec3f MtxVecMul3RM(const Matrix4f& mtx, const Vector3f& vec);
/** HECL source and metadata of each material */
struct Material
{
struct Material {
std::string name;
std::string source;
std::vector<ProjectPath> texs;
@ -169,15 +150,13 @@ struct Material
bool transparent;
Material(Connection& conn);
bool operator==(const Material& other) const
{
bool operator==(const Material& other) const {
return source == other.source && texs == other.texs && iprops == other.iprops;
}
};
/** Intermediate mesh representation prepared by blender from a single mesh object */
struct Mesh
{
struct Mesh {
HMDLTopology topology;
/* Object transform in scene */
@ -201,8 +180,7 @@ struct Mesh
/* Skinning data */
std::vector<std::string> boneNames;
struct SkinBind
{
struct SkinBind {
uint32_t boneIdx;
float weight;
SkinBind(Connection& conn);
@ -213,8 +191,7 @@ struct Mesh
void normalizeSkinBinds();
/** Islands of the same material/skinBank are represented here */
struct Surface
{
struct Surface {
Vector3f centroid;
Index materialIdx;
Vector3f aabbMin;
@ -223,8 +200,7 @@ struct Mesh
uint32_t skinBankIdx;
/** Vertex indexing data (all primitives joined as degenerate tri-strip) */
struct Vert
{
struct Vert {
uint32_t iPos = 0xffffffff;
uint32_t iNorm = 0xffffffff;
uint32_t iColor[4] = {0xffffffff};
@ -243,10 +219,8 @@ struct Mesh
std::unordered_map<std::string, std::string> customProps;
struct SkinBanks
{
struct Bank
{
struct SkinBanks {
struct Bank {
std::vector<uint32_t> m_skinIdxs;
std::vector<uint32_t> m_boneIdxs;
@ -270,11 +244,9 @@ struct Mesh
};
/** Intermediate collision mesh representation prepared by blender from a single mesh object */
struct ColMesh
{
struct ColMesh {
/** HECL source and metadata of each material */
struct Material
{
struct Material {
std::string name;
bool unknown;
bool surfaceStone;
@ -325,16 +297,14 @@ struct ColMesh
std::vector<Vector3f> verts;
struct Edge
{
struct Edge {
uint32_t verts[2];
bool seam;
Edge(Connection& conn);
};
std::vector<Edge> edges;
struct Triangle
{
struct Triangle {
uint32_t edges[3];
uint32_t matIdx;
bool flip;
@ -346,15 +316,12 @@ struct ColMesh
};
/** Intermediate world representation */
struct World
{
struct Area
{
struct World {
struct Area {
ProjectPath path;
Vector3f aabb[2];
Matrix4f transform;
struct Dock
{
struct Dock {
Vector3f verts[4];
Index targetArea;
Index targetDock;
@ -368,21 +335,14 @@ struct World
};
/** Intermediate lamp representation */
struct Light
{
struct Light {
/* Object transform in scene */
Matrix4f sceneXf;
Vector3f color;
uint32_t layer;
enum class Type : uint32_t
{
Ambient,
Directional,
Custom,
Spot
} type;
enum class Type : uint32_t { Ambient, Directional, Custom, Spot } type;
float energy;
float spotCutoff;
@ -397,13 +357,11 @@ struct Light
};
/** Intermediate MapArea representation */
struct MapArea
{
struct MapArea {
Index visType;
std::vector<Vector3f> verts;
std::vector<Index> indices;
struct Surface
{
struct Surface {
Vector3f normal;
Vector3f centerOfMass;
Index start;
@ -412,8 +370,7 @@ struct MapArea
Surface(Connection& conn);
};
std::vector<Surface> surfaces;
struct POI
{
struct POI {
uint32_t type;
uint32_t visMode;
uint32_t objid;
@ -425,11 +382,9 @@ struct MapArea
};
/** Intermediate MapUniverse representation */
struct MapUniverse
{
struct MapUniverse {
hecl::ProjectPath hexagonPath;
struct World
{
struct World {
std::string name;
Matrix4f xf;
std::vector<Matrix4f> hexagons;
@ -442,8 +397,7 @@ struct MapUniverse
};
/** Intermediate bone representation used in Armature */
struct Bone
{
struct Bone {
std::string name;
Vector3f origin;
int32_t parent = -1;
@ -452,8 +406,7 @@ struct Bone
};
/** Intermediate armature representation used in Actor */
struct Armature
{
struct Armature {
std::string name;
std::vector<Bone> bones;
const Bone* lookupBone(const char* name) const;
@ -464,19 +417,16 @@ struct Armature
};
/** Intermediate action representation used in Actor */
struct Action
{
struct Action {
std::string name;
float interval;
bool additive;
bool looping;
std::vector<int32_t> frames;
struct Channel
{
struct Channel {
std::string boneName;
uint32_t attrMask;
struct Key
{
struct Key {
Vector4f rotation;
Vector3f position;
Vector3f scale;
@ -491,12 +441,10 @@ struct Action
};
/** Intermediate actor representation prepared by blender from a single HECL actor blend */
struct Actor
{
struct Actor {
std::vector<Armature> armatures;
struct Subtype
{
struct Subtype {
std::string name;
ProjectPath mesh;
int32_t armature = -1;
@ -504,8 +452,7 @@ struct Actor
Subtype(Connection& conn);
};
std::vector<Subtype> subtypes;
struct Attachment
{
struct Attachment {
std::string name;
ProjectPath mesh;
int32_t armature = -1;
@ -518,22 +465,20 @@ struct Actor
};
/** Intermediate pathfinding representation prepared by blender */
struct PathMesh
{
struct PathMesh {
std::vector<uint8_t> data;
PathMesh(Connection& conn);
};
class DataStream
{
class DataStream {
friend class Connection;
Connection* m_parent;
DataStream(Connection* parent);
public:
DataStream(const DataStream& other) = delete;
DataStream(DataStream&& other)
: m_parent(other.m_parent) {other.m_parent = nullptr;}
~DataStream() {close();}
DataStream(DataStream&& other) : m_parent(other.m_parent) { other.m_parent = nullptr; }
~DataStream() { close(); }
void close();
std::vector<std::string> getMeshList();
std::vector<std::string> getLightList();
@ -541,12 +486,11 @@ public:
static const char* MeshOutputModeString(HMDLTopology topology);
/** Compile mesh by context (MESH blends only) */
Mesh compileMesh(HMDLTopology topology, int skinSlotCount=10,
Mesh::SurfProgFunc surfProg=[](int){});
Mesh compileMesh(HMDLTopology topology, int skinSlotCount = 10, Mesh::SurfProgFunc surfProg = [](int) {});
/** Compile mesh by name (AREA blends only) */
Mesh compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount=10, bool useLuv=false,
Mesh::SurfProgFunc surfProg=[](int){});
Mesh compileMesh(std::string_view name, HMDLTopology topology, int skinSlotCount = 10, bool useLuv = false,
Mesh::SurfProgFunc surfProg = [](int) {});
/** Compile collision mesh by name (AREA blends only) */
ColMesh compileColMesh(std::string_view name);
@ -555,8 +499,8 @@ public:
std::vector<ColMesh> compileColMeshes();
/** Compile all meshes into one (AREA blends only) */
Mesh compileAllMeshes(HMDLTopology topology, int skinSlotCount=10, float maxOctantLength=5.0,
Mesh::SurfProgFunc surfProg=[](int){});
Mesh compileAllMeshes(HMDLTopology topology, int skinSlotCount = 10, float maxOctantLength = 5.0,
Mesh::SurfProgFunc surfProg = [](int) {});
/** Compile world intermediate (WORLD blends only) */
World compileWorld();
@ -591,8 +535,7 @@ public:
MapUniverse compileMapUniverse();
};
class Connection
{
class Connection {
friend class DataStream;
friend class PyOutStream;
friend class ANIMOutStream;
@ -644,34 +587,32 @@ class Connection
void _blenderDied();
public:
Connection(int verbosityLevel=1);
Connection(int verbosityLevel = 1);
~Connection();
Connection(const Connection&)=delete;
Connection& operator=(const Connection&)=delete;
Connection(Connection&&)=delete;
Connection& operator=(Connection&&)=delete;
Connection(const Connection&) = delete;
Connection& operator=(const Connection&) = delete;
Connection(Connection&&) = delete;
Connection& operator=(Connection&&) = delete;
bool hasSLERP() const {return m_hasSlerp;}
bool hasSLERP() const { return m_hasSlerp; }
bool createBlend(const ProjectPath& path, BlendType type);
BlendType getBlendType() const {return m_loadedType;}
const ProjectPath& getBlendPath() const {return m_loadedBlend;}
bool getRigged() const {return m_loadedRigged;}
bool openBlend(const ProjectPath& path, bool force=false);
BlendType getBlendType() const { return m_loadedType; }
const ProjectPath& getBlendPath() const { return m_loadedBlend; }
bool getRigged() const { return m_loadedRigged; }
bool openBlend(const ProjectPath& path, bool force = false);
bool saveBlend();
void deleteBlend();
PyOutStream beginPythonOut(bool deleteOnError=false)
{
PyOutStream beginPythonOut(bool deleteOnError = false) {
bool expect = false;
if (!m_lock.compare_exchange_strong(expect, true))
BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginPythonOut()");
return PyOutStream(this, deleteOnError);
}
DataStream beginData()
{
DataStream beginData() {
bool expect = false;
if (!m_lock.compare_exchange_strong(expect, true))
BlenderLog.report(logvisor::Fatal, "lock already held for blender::Connection::beginDataIn()");
@ -680,8 +621,7 @@ public:
void quitBlender();
void closeStream()
{
void closeStream() {
if (m_lock)
deleteBlend();
}
@ -690,16 +630,15 @@ public:
static void Shutdown();
};
class HMDLBuffers
{
class HMDLBuffers {
public:
struct Surface;
private:
friend struct Mesh;
HMDLBuffers(HMDLMeta&& meta,
size_t vboSz, const std::vector<atUint32>& iboData,
std::vector<Surface>&& surfaces,
HMDLBuffers(HMDLMeta&& meta, size_t vboSz, const std::vector<atUint32>& iboData, std::vector<Surface>&& surfaces,
const Mesh::SkinBanks& skinBanks);
public:
HMDLMeta m_meta;
size_t m_vboSz;
@ -707,10 +646,8 @@ public:
size_t m_iboSz;
std::unique_ptr<uint8_t[]> m_iboData;
struct Surface
{
Surface(const Mesh::Surface& origSurf,
atUint32 start, atUint32 count)
struct Surface {
Surface(const Mesh::Surface& origSurf, atUint32 start, atUint32 count)
: m_origSurf(origSurf), m_start(start), m_count(count) {}
const Mesh::Surface& m_origSurf;
atUint32 m_start;
@ -721,5 +658,4 @@ public:
const Mesh::SkinBanks& m_skinBanks;
};
}
} // namespace hecl::blender

View File

@ -4,11 +4,9 @@
#include "athena/DNA.hpp"
#include "athena/MemoryReader.hpp"
namespace hecl::blender
{
namespace hecl::blender {
struct SDNABlock : public athena::io::DNA<athena::Little>
{
struct SDNABlock : public athena::io::DNA<athena::Little> {
AT_DECL_DNA
DNAFourCC magic;
DNAFourCC nameMagic;
@ -24,13 +22,11 @@ struct SDNABlock : public athena::io::DNA<athena::Little>
Align<4> align3;
DNAFourCC strcMagic;
Value<atUint32> numStrcs;
struct SDNAStruct : public athena::io::DNA<athena::Little>
{
struct SDNAStruct : public athena::io::DNA<athena::Little> {
AT_DECL_DNA
Value<atUint16> type;
Value<atUint16> numFields;
struct SDNAField : public athena::io::DNA<athena::Little>
{
struct SDNAField : public athena::io::DNA<athena::Little> {
AT_DECL_DNA
Value<atUint16> type;
Value<atUint16> name;
@ -46,8 +42,7 @@ struct SDNABlock : public athena::io::DNA<athena::Little>
const SDNAStruct* lookupStruct(const char* n, int& idx) const;
};
struct FileBlock : public athena::io::DNA<athena::Little>
{
struct FileBlock : public athena::io::DNA<athena::Little> {
AT_DECL_DNA
DNAFourCC type;
Value<atUint32> size;
@ -56,10 +51,10 @@ struct FileBlock : public athena::io::DNA<athena::Little>
Value<atUint32> count;
};
class SDNARead
{
class SDNARead {
std::vector<uint8_t> m_data;
SDNABlock m_sdnaBlock;
public:
explicit SDNARead(SystemStringView path);
operator bool() const { return !m_data.empty(); }
@ -69,4 +64,4 @@ public:
BlendType GetBlendType(SystemStringView path);
}
} // namespace hecl::blender

View File

@ -2,24 +2,22 @@
#include <memory>
namespace hecl::blender
{
namespace hecl::blender {
class Connection;
class Token
{
class Token {
std::unique_ptr<Connection> m_conn;
public:
Connection& getBlenderConnection();
void shutdown();
Token() = default;
~Token();
Token(const Token&)=delete;
Token& operator=(const Token&)=delete;
Token(Token&&)=default;
Token& operator=(Token&&)=default;
Token(const Token&) = delete;
Token& operator=(const Token&) = delete;
Token(Token&&) = default;
Token& operator=(Token&&) = default;
};
}
} // namespace hecl::blender

50
hecl/include/hecl/CVar.hpp Executable file → Normal file
View File

@ -6,21 +6,11 @@
#include <athena/Global.hpp>
#include <athena/DNAYaml.hpp>
namespace hecl
{
namespace DNACVAR
{
enum class EType : atUint8
{
Boolean,
Integer,
Float,
Literal,
Vec4f
};
namespace hecl {
namespace DNACVAR {
enum class EType : atUint8 { Boolean, Integer, Float, Literal, Vec4f };
enum EFlags
{
enum EFlags {
None = -1,
System = (1 << 0),
Game = (1 << 1),
@ -36,27 +26,24 @@ enum EFlags
};
ENABLE_BITWISE_ENUM(EFlags)
class CVar : public athena::io::DNA<athena::Big>
{
class CVar : public athena::io::DNA<athena::Big> {
public:
AT_DECL_DNA
String<-1> m_name;
String<-1> m_value;
};
struct CVarContainer : public athena::io::DNA<athena::Big>
{
struct CVarContainer : public athena::io::DNA<athena::Big> {
AT_DECL_DNA
Value<atUint32> magic = 'CVAR';
Value<atUint32> cvarCount;
Vector<CVar, AT_DNA_COUNT(cvarCount)> cvars;
};
}
} // namespace DNACVAR
class CVarManager;
class CVar : protected DNACVAR::CVar
{
class CVar : protected DNACVAR::CVar {
friend class CVarManager;
Delete _d;
@ -66,14 +53,14 @@ public:
using EType = DNACVAR::EType;
using EFlags = DNACVAR::EFlags;
CVar(std::string_view name, std::string_view value, std::string_view help, EType type, EFlags flags, CVarManager& parent);
CVar(std::string_view name, std::string_view value, std::string_view help, EType type, EFlags flags,
CVarManager& parent);
CVar(std::string_view name, std::string_view value, std::string_view help, EFlags flags, CVarManager& parent);
CVar(std::string_view name, float value, std::string_view help, EFlags flags, CVarManager& parent);
CVar(std::string_view name, bool value, std::string_view help, EFlags flags, CVarManager& parent);
CVar(std::string_view name, int value, std::string_view help, EFlags flags, CVarManager& parent);
CVar(std::string_view name, const atVec4f& value, std::string_view help, EFlags flags, CVarManager& parent);
std::string_view name() const { return m_name; }
std::string_view rawHelp() const { return m_help; }
std::string help() const;
@ -147,13 +134,18 @@ private:
std::vector<ListenerFunc> m_listeners;
};
class CVarUnlocker
{
class CVarUnlocker {
CVar* m_cvar;
public:
CVarUnlocker(CVar* cvar) : m_cvar(cvar) { if (m_cvar) m_cvar->unlock(); }
~CVarUnlocker() { if (m_cvar) m_cvar->lock(); }
CVarUnlocker(CVar* cvar) : m_cvar(cvar) {
if (m_cvar)
m_cvar->unlock();
}
~CVarUnlocker() {
if (m_cvar)
m_cvar->lock();
}
};
}
} // namespace hecl

View File

@ -5,8 +5,7 @@
#undef min
#undef max
namespace hecl
{
namespace hecl {
using namespace std::literals;
@ -18,75 +17,45 @@ using namespace std::literals;
#define DEFAULT_GRAPHICS_API "OpenGL"sv
#endif
struct CVarCommons
{
struct CVarCommons {
CVarManager& m_mgr;
CVar* m_graphicsApi = nullptr;
CVar* m_drawSamples = nullptr;
CVar* m_texAnisotropy = nullptr;
CVar* m_deepColor = nullptr;
CVarCommons(CVarManager& manager) : m_mgr(manager)
{
m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv,
"API to use for rendering graphics"sv,
DEFAULT_GRAPHICS_API, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart);
m_drawSamples = m_mgr.findOrMakeCVar("drawSamples"sv,
"Number of MSAA samples to use for render targets"sv,
1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart);
m_texAnisotropy = m_mgr.findOrMakeCVar("texAnisotropy"sv,
"Number of anisotropic samples to use for sampling textures"sv,
1, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart);
m_deepColor = m_mgr.findOrMakeCVar("deepColor"sv,
"Allow framebuffer with color depth greater-then 24-bits"sv,
false, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart);
CVarCommons(CVarManager& manager) : m_mgr(manager) {
m_graphicsApi = m_mgr.findOrMakeCVar("graphicsApi"sv, "API to use for rendering graphics"sv, DEFAULT_GRAPHICS_API,
hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive |
hecl::CVar::EFlags::ModifyRestart);
m_drawSamples = m_mgr.findOrMakeCVar("drawSamples"sv, "Number of MSAA samples to use for render targets"sv, 1,
hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive |
hecl::CVar::EFlags::ModifyRestart);
m_texAnisotropy = m_mgr.findOrMakeCVar(
"texAnisotropy"sv, "Number of anisotropic samples to use for sampling textures"sv, 1,
hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart);
m_deepColor = m_mgr.findOrMakeCVar(
"deepColor"sv, "Allow framebuffer with color depth greater-then 24-bits"sv, false,
hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive | hecl::CVar::EFlags::ModifyRestart);
}
std::string getGraphicsApi() const
{
return m_graphicsApi->toLiteral();
}
std::string getGraphicsApi() const { return m_graphicsApi->toLiteral(); }
void setGraphicsApi(std::string_view api)
{
m_graphicsApi->fromLiteral(api);
}
void setGraphicsApi(std::string_view api) { m_graphicsApi->fromLiteral(api); }
uint32_t getSamples() const
{
return std::max(uint32_t(1), uint32_t(m_drawSamples->toInteger()));
}
uint32_t getSamples() const { return std::max(uint32_t(1), uint32_t(m_drawSamples->toInteger())); }
void setSamples(uint32_t v)
{
m_drawSamples->fromInteger(std::max(uint32_t(1), v));
}
void setSamples(uint32_t v) { m_drawSamples->fromInteger(std::max(uint32_t(1), v)); }
uint32_t getAnisotropy() const
{
return std::max(uint32_t(1), uint32_t(m_texAnisotropy->toInteger()));
}
uint32_t getAnisotropy() const { return std::max(uint32_t(1), uint32_t(m_texAnisotropy->toInteger())); }
void setAnisotropy(uint32_t v)
{
m_texAnisotropy->fromInteger(std::max(uint32_t(1), v));
}
void setAnisotropy(uint32_t v) { m_texAnisotropy->fromInteger(std::max(uint32_t(1), v)); }
bool getDeepColor() const
{
return m_deepColor->toBoolean();
}
bool getDeepColor() const { return m_deepColor->toBoolean(); }
void setDeepColor(bool b)
{
m_deepColor->fromBoolean(b);
}
void setDeepColor(bool b) { m_deepColor->fromBoolean(b); }
void serialize()
{
m_mgr.serialize();
}
void serialize() { m_mgr.serialize(); }
};
}
} // namespace hecl

53
hecl/include/hecl/CVarManager.hpp Executable file → Normal file
View File

@ -5,23 +5,18 @@
#include "CVar.hpp"
#include "hecl/SystemChar.hpp"
namespace hecl
{
namespace Runtime
{
namespace hecl {
namespace Runtime {
class FileStoreManager;
}
extern CVar* com_developer;
extern CVar* com_configfile;
extern CVar* com_enableCheats;
class CVarManager final
{
class CVarManager final {
using CVarContainer = DNACVAR::CVarContainer;
template <typename T>
CVar* _newCVar(std::string_view name, std::string_view help, const T& value, CVar::EFlags flags)
{
if (CVar* ret = registerCVar(std::make_unique<CVar>(name, value, help, flags, *this)))
{
CVar* _newCVar(std::string_view name, std::string_view help, const T& value, CVar::EFlags flags) {
if (CVar* ret = registerCVar(std::make_unique<CVar>(name, value, help, flags, *this))) {
deserialize(ret);
return ret;
}
@ -31,6 +26,7 @@ class CVarManager final
hecl::Runtime::FileStoreManager& m_store;
bool m_useBinary;
static CVarManager* m_instance;
public:
CVarManager() = delete;
CVarManager(const CVarManager&) = delete;
@ -39,23 +35,27 @@ public:
CVarManager(hecl::Runtime::FileStoreManager& store, bool useBinary = false);
~CVarManager();
CVar* newCVar(std::string_view name, std::string_view help, const atVec4f& value, CVar::EFlags flags)
{ return _newCVar<atVec4f>(name, help, value, flags); }
CVar* newCVar(std::string_view name, std::string_view help, std::string_view value, CVar::EFlags flags)
{ return _newCVar<std::string_view>(name, help, value, flags); }
CVar* newCVar(std::string_view name, std::string_view help, bool value, CVar::EFlags flags)
{ return _newCVar<bool>(name, help, value, flags); }
CVar* newCVar(std::string_view name, std::string_view help, float value, CVar::EFlags flags)
{ return _newCVar<float>(name, help, value, flags); }
CVar* newCVar(std::string_view name, std::string_view help, int value, CVar::EFlags flags)
{ return _newCVar<int>(name, help, value, flags); }
CVar* newCVar(std::string_view name, std::string_view help, const atVec4f& value, CVar::EFlags flags) {
return _newCVar<atVec4f>(name, help, value, flags);
}
CVar* newCVar(std::string_view name, std::string_view help, std::string_view value, CVar::EFlags flags) {
return _newCVar<std::string_view>(name, help, value, flags);
}
CVar* newCVar(std::string_view name, std::string_view help, bool value, CVar::EFlags flags) {
return _newCVar<bool>(name, help, value, flags);
}
CVar* newCVar(std::string_view name, std::string_view help, float value, CVar::EFlags flags) {
return _newCVar<float>(name, help, value, flags);
}
CVar* newCVar(std::string_view name, std::string_view help, int value, CVar::EFlags flags) {
return _newCVar<int>(name, help, value, flags);
}
CVar* registerCVar(std::unique_ptr<CVar>&& cvar);
CVar* findCVar(std::string_view name);
template<class... _Args>
CVar* findOrMakeCVar(std::string_view name, _Args&&... args)
{
template <class... _Args>
CVar* findOrMakeCVar(std::string_view name, _Args&&... args) {
if (CVar* cv = findCVar(name))
return cv;
return newCVar(name, std::forward<_Args>(args)...);
@ -73,11 +73,11 @@ public:
void setCVar(class Console* con, const std::vector<std::string>& args);
void getCVar(class Console* con, const std::vector<std::string>& args);
void setDeveloperMode(bool v, bool setDeserialized=false);
void setDeveloperMode(bool v, bool setDeserialized = false);
bool restartRequired() const;
void parseCommandLine(const std::vector<SystemString>& args);
private:
bool suppressDeveloper();
void restoreDeveloper(bool oldDeveloper);
@ -86,5 +86,4 @@ private:
std::unordered_map<std::string, std::string> m_deferedCVars;
};
}
} // namespace hecl

View File

@ -9,11 +9,9 @@
#include <mutex>
#include <condition_variable>
namespace hecl
{
namespace hecl {
class ClientProcess
{
class ClientProcess {
std::mutex m_mutex;
std::condition_variable m_cv;
std::condition_variable m_initCv;
@ -23,60 +21,46 @@ class ClientProcess
int m_addedCooks = 0;
public:
struct Transaction
{
struct Transaction {
ClientProcess& m_parent;
enum class Type
{
Buffer,
Cook,
Lambda
} m_type;
enum class Type { Buffer, Cook, Lambda } m_type;
bool m_complete = false;
virtual void run(blender::Token& btok)=0;
virtual void run(blender::Token& btok) = 0;
Transaction(ClientProcess& parent, Type tp) : m_parent(parent), m_type(tp) {}
};
struct BufferTransaction final : Transaction
{
struct BufferTransaction final : Transaction {
ProjectPath m_path;
void* m_targetBuf;
size_t m_maxLen;
size_t m_offset;
void run(blender::Token& btok);
BufferTransaction(ClientProcess& parent, const ProjectPath& path,
void* target, size_t maxLen, size_t offset)
: Transaction(parent, Type::Buffer),
m_path(path), m_targetBuf(target),
m_maxLen(maxLen), m_offset(offset) {}
BufferTransaction(ClientProcess& parent, const ProjectPath& path, void* target, size_t maxLen, size_t offset)
: Transaction(parent, Type::Buffer), m_path(path), m_targetBuf(target), m_maxLen(maxLen), m_offset(offset) {}
};
struct CookTransaction final : Transaction
{
struct CookTransaction final : Transaction {
ProjectPath m_path;
Database::IDataSpec* m_dataSpec;
bool m_returnResult = false;
bool m_force;
bool m_fast;
void run(blender::Token& btok);
CookTransaction(ClientProcess& parent, const ProjectPath& path,
bool force, bool fast, Database::IDataSpec* spec)
: Transaction(parent, Type::Cook), m_path(path), m_dataSpec(spec),
m_force(force), m_fast(fast) {}
CookTransaction(ClientProcess& parent, const ProjectPath& path, bool force, bool fast, Database::IDataSpec* spec)
: Transaction(parent, Type::Cook), m_path(path), m_dataSpec(spec), m_force(force), m_fast(fast) {}
};
struct LambdaTransaction final : Transaction
{
struct LambdaTransaction final : Transaction {
std::function<void(blender::Token&)> m_func;
void run(blender::Token& btok);
LambdaTransaction(ClientProcess& parent, std::function<void(blender::Token&)>&& func)
: Transaction(parent, Type::Lambda), m_func(std::move(func)) {}
};
private:
std::list<std::shared_ptr<Transaction>> m_pendingQueue;
std::list<std::shared_ptr<Transaction>> m_completedQueue;
int m_inProgress = 0;
bool m_running = true;
struct Worker
{
struct Worker {
ClientProcess& m_proc;
int m_idx;
std::thread m_thr;
@ -89,25 +73,20 @@ private:
static ThreadLocalPtr<ClientProcess::Worker> ThreadWorker;
public:
ClientProcess(const MultiProgressPrinter* progPrinter=nullptr);
~ClientProcess() {shutdown();}
std::shared_ptr<const BufferTransaction>
addBufferTransaction(const hecl::ProjectPath& path, void* target,
ClientProcess(const MultiProgressPrinter* progPrinter = nullptr);
~ClientProcess() { shutdown(); }
std::shared_ptr<const BufferTransaction> addBufferTransaction(const hecl::ProjectPath& path, void* target,
size_t maxLen, size_t offset);
std::shared_ptr<const CookTransaction>
addCookTransaction(const hecl::ProjectPath& path, bool force,
bool fast, Database::IDataSpec* spec);
std::shared_ptr<const LambdaTransaction>
addLambdaTransaction(std::function<void(blender::Token&)>&& func);
bool syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, blender::Token& btok,
bool force, bool fast);
std::shared_ptr<const CookTransaction> addCookTransaction(const hecl::ProjectPath& path, bool force, bool fast,
Database::IDataSpec* spec);
std::shared_ptr<const LambdaTransaction> addLambdaTransaction(std::function<void(blender::Token&)>&& func);
bool syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, blender::Token& btok, bool force, bool fast);
void swapCompletedQueue(std::list<std::shared_ptr<Transaction>>& queue);
void waitUntilComplete();
void shutdown();
bool isBusy() const { return m_pendingQueue.size() || m_inProgress; }
static int GetThreadWorkerIdx()
{
static int GetThreadWorkerIdx() {
Worker* w = ThreadWorker.get();
if (w)
return w->m_idx;
@ -115,5 +94,4 @@ public:
}
};
}
} // namespace hecl

View File

@ -5,66 +5,87 @@
#include "boo/graphicsdev/D3D.hpp"
#include "boo/graphicsdev/Metal.hpp"
namespace hecl
{
namespace hecl {
namespace PlatformType
{
namespace PlatformType {
using PlatformEnum = boo::IGraphicsDataFactory::Platform;
struct Null {};
struct OpenGL { static constexpr PlatformEnum Enum = PlatformEnum::OpenGL; static const char* Name;
struct OpenGL {
static constexpr PlatformEnum Enum = PlatformEnum::OpenGL;
static const char* Name;
#if BOO_HAS_GL
using Context = boo::GLDataFactory::Context;
using Context = boo::GLDataFactory::Context;
#endif
};
struct D3D11 { static constexpr PlatformEnum Enum = PlatformEnum::D3D11; static const char* Name;
struct D3D11 {
static constexpr PlatformEnum Enum = PlatformEnum::D3D11;
static const char* Name;
#if _WIN32
using Context = boo::D3D11DataFactory::Context;
using Context = boo::D3D11DataFactory::Context;
#endif
};
struct Metal { static constexpr PlatformEnum Enum = PlatformEnum::Metal; static const char* Name;
struct Metal {
static constexpr PlatformEnum Enum = PlatformEnum::Metal;
static const char* Name;
#if BOO_HAS_METAL
using Context = boo::MetalDataFactory::Context;
using Context = boo::MetalDataFactory::Context;
#endif
};
struct Vulkan { static constexpr PlatformEnum Enum = PlatformEnum::Vulkan; static const char* Name;
struct Vulkan {
static constexpr PlatformEnum Enum = PlatformEnum::Vulkan;
static const char* Name;
#if BOO_HAS_VULKAN
using Context = boo::VulkanDataFactory::Context;
using Context = boo::VulkanDataFactory::Context;
#endif
};
struct NX { static constexpr PlatformEnum Enum = PlatformEnum::NX; static const char* Name;
struct NX {
static constexpr PlatformEnum Enum = PlatformEnum::NX;
static const char* Name;
#if BOO_HAS_NX
using Context = boo::NXDataFactory::Context;
using Context = boo::NXDataFactory::Context;
#endif
};
}
} // namespace PlatformType
namespace PipelineStage
{
namespace PipelineStage {
using StageEnum = boo::PipelineStage;
struct Null { static constexpr StageEnum Enum = StageEnum::Null; static const char* Name; };
struct Vertex { static constexpr StageEnum Enum = StageEnum::Vertex; static const char* Name; };
struct Fragment { static constexpr StageEnum Enum = StageEnum::Fragment; static const char* Name; };
struct Geometry { static constexpr StageEnum Enum = StageEnum::Geometry; static const char* Name; };
struct Control { static constexpr StageEnum Enum = StageEnum::Control; static const char* Name; };
struct Evaluation { static constexpr StageEnum Enum = StageEnum::Evaluation; static const char* Name; };
}
struct Null {
static constexpr StageEnum Enum = StageEnum::Null;
static const char* Name;
};
struct Vertex {
static constexpr StageEnum Enum = StageEnum::Vertex;
static const char* Name;
};
struct Fragment {
static constexpr StageEnum Enum = StageEnum::Fragment;
static const char* Name;
};
struct Geometry {
static constexpr StageEnum Enum = StageEnum::Geometry;
static const char* Name;
};
struct Control {
static constexpr StageEnum Enum = StageEnum::Control;
static const char* Name;
};
struct Evaluation {
static constexpr StageEnum Enum = StageEnum::Evaluation;
static const char* Name;
};
} // namespace PipelineStage
#ifdef __APPLE__
using StageBinaryData = std::shared_ptr<uint8_t>;
static inline StageBinaryData MakeStageBinaryData(size_t sz)
{
static inline StageBinaryData MakeStageBinaryData(size_t sz) {
return StageBinaryData(new uint8_t[sz], std::default_delete<uint8_t[]>{});
}
#else
using StageBinaryData = std::shared_ptr<uint8_t[]>;
static inline StageBinaryData MakeStageBinaryData(size_t sz)
{
return StageBinaryData(new uint8_t[sz]);
}
static inline StageBinaryData MakeStageBinaryData(size_t sz) { return StageBinaryData(new uint8_t[sz]); }
#endif
template<typename P, typename S>
template <typename P, typename S>
std::pair<StageBinaryData, size_t> CompileShader(std::string_view text);
}
} // namespace hecl

View File

@ -7,18 +7,11 @@
#include "boo/IWindow.hpp"
#include "logvisor/logvisor.hpp"
namespace hecl
{
namespace hecl {
class CVarManager;
class CVar;
struct SConsoleCommand
{
enum class ECommandFlags
{
Normal = 0,
Cheat = (1 << 0),
Developer = (1 << 1)
};
struct SConsoleCommand {
enum class ECommandFlags { Normal = 0, Cheat = (1 << 0), Developer = (1 << 1) };
std::string m_displayName;
std::string m_helpString;
std::string m_usage;
@ -27,45 +20,31 @@ struct SConsoleCommand
};
ENABLE_BITWISE_ENUM(SConsoleCommand::ECommandFlags)
class Console
{
class Console {
friend class LogVisorAdapter;
struct LogVisorAdapter : logvisor::ILogger
{
struct LogVisorAdapter : logvisor::ILogger {
Console* m_con;
LogVisorAdapter(Console* con)
: m_con(con) {}
LogVisorAdapter(Console* con) : m_con(con) {}
~LogVisorAdapter() {}
void report(const char* modName, logvisor::Level severity,
void report(const char* modName, logvisor::Level severity, const char* format, va_list ap);
void report(const char* modName, logvisor::Level severity, const wchar_t* format, va_list ap);
void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum,
const char* format, va_list ap);
void report(const char* modName, logvisor::Level severity,
const wchar_t* format, va_list ap);
void reportSource(const char* modName, logvisor::Level severity,
const char* file, unsigned linenum,
const char* format, va_list ap);
void reportSource(const char* modName, logvisor::Level severity,
const char* file, unsigned linenum,
void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum,
const wchar_t* format, va_list ap);
};
public:
static Console* m_instance;
enum class Level
{
enum class Level {
Info, /**< Non-error informative message */
Warning, /**< Non-error warning message */
Error, /**< Recoverable error message */
Fatal /**< Non-recoverable error message (Kept for compatibility with logvisor) */
};
enum State
{
Closed,
Closing,
Opened,
Opening
};
enum State { Closed, Closing, Opened, Opening };
private:
CVarManager* m_cvarMgr;
@ -86,9 +65,12 @@ private:
float m_cachedConHeight;
bool m_showCursor = true;
float m_cursorTime = 0.f;
public:
Console(CVarManager*);
void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function<void(Console*, const std::vector<std::string>&)>&& func, SConsoleCommand::ECommandFlags cmdFlags = SConsoleCommand::ECommandFlags::Normal);
void registerCommand(std::string_view name, std::string_view helpText, std::string_view usage,
const std::function<void(Console*, const std::vector<std::string>&)>&& func,
SConsoleCommand::ECommandFlags cmdFlags = SConsoleCommand::ECommandFlags::Normal);
void unregisterCommand(std::string_view name);
void executeString(const std::string& strToExec);
@ -97,7 +79,7 @@ public:
void listCommands(Console* con, const std::vector<std::string>& args);
bool commandExists(std::string_view cmd);
void report(Level level, const char *fmt, va_list list);
void report(Level level, const char* fmt, va_list list);
void report(Level level, const char* fmt, ...);
void proc();
@ -110,5 +92,4 @@ public:
static void RegisterLogger(Console* con);
bool isOpen() { return m_state == State::Opened; }
};
}
} // namespace hecl

View File

@ -21,12 +21,10 @@
#define RUNTIME_ORIGINAL_IDS 0
namespace hecl
{
namespace hecl {
class ClientProcess;
namespace Database
{
namespace Database {
class Project;
extern logvisor::Module LogModule;
@ -34,27 +32,23 @@ extern logvisor::Module LogModule;
/**
* @brief Nodegraph class for gathering dependency-resolved objects for packaging
*/
class PackageDepsgraph
{
class PackageDepsgraph {
public:
struct Node
{
enum class Type
{
Data,
Group
} type;
struct Node {
enum class Type { Data, Group } type;
ProjectPath path;
ProjectPath cookedPath;
class ObjectBase* projectObj;
Node* sub;
Node* next;
};
private:
friend class Project;
std::vector<Node> m_nodes;
public:
const Node* getRootNode() const {return &m_nodes[0];}
const Node* getRootNode() const { return &m_nodes[0]; }
};
/**
@ -63,9 +57,9 @@ public:
* The DataSpec class manages interfaces for unpackaging, cooking, and packaging
* of data for interacting with a specific system/game-engine.
*/
class IDataSpec
{
class IDataSpec {
const DataSpecEntry* m_specEntry;
public:
IDataSpec(const DataSpecEntry* specEntry) : m_specEntry(specEntry) {}
virtual ~IDataSpec() {}
@ -77,8 +71,7 @@ public:
* An extract pass iterates through a source package or image and
* reverses the cooking process by emitting editable resources
*/
struct ExtractPassInfo
{
struct ExtractPassInfo {
SystemString srcpath;
std::vector<SystemString> extractArgs;
bool force;
@ -90,8 +83,7 @@ public:
* Constructed by canExtract() to advise the user of the content about
* to be extracted
*/
struct ExtractReport
{
struct ExtractReport {
SystemString name;
SystemString desc;
std::vector<ExtractReport> childOpts;
@ -99,42 +91,54 @@ public:
virtual void setThreadProject() {}
virtual bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps)
{(void)info;(void)reps;LogModule.report(logvisor::Error, "not implemented");return false;}
virtual void doExtract(const ExtractPassInfo& info, const MultiProgressPrinter& progress)
{(void)info;(void)progress;}
virtual bool canExtract(const ExtractPassInfo& info, std::vector<ExtractReport>& reps) {
(void)info;
(void)reps;
LogModule.report(logvisor::Error, "not implemented");
return false;
}
virtual void doExtract(const ExtractPassInfo& info, const MultiProgressPrinter& progress) {
(void)info;
(void)progress;
}
virtual bool canCook(const ProjectPath& path, blender::Token& btok, int cookPass = -1)
{(void)path;LogModule.report(logvisor::Error, "not implemented");(void)cookPass;return false;}
virtual const DataSpecEntry* overrideDataSpec(const ProjectPath& path,
const Database::DataSpecEntry* oldEntry,
blender::Token& btok) const
{(void)path;return oldEntry;}
virtual void doCook(const ProjectPath& path, const ProjectPath& cookedPath,
bool fast, blender::Token& btok, FCookProgress progress)
{(void)path;(void)cookedPath;(void)fast;(void)progress;}
virtual bool canCook(const ProjectPath& path, blender::Token& btok, int cookPass = -1) {
(void)path;
LogModule.report(logvisor::Error, "not implemented");
(void)cookPass;
return false;
}
virtual const DataSpecEntry* overrideDataSpec(const ProjectPath& path, const Database::DataSpecEntry* oldEntry,
blender::Token& btok) const {
(void)path;
return oldEntry;
}
virtual void doCook(const ProjectPath& path, const ProjectPath& cookedPath, bool fast, blender::Token& btok,
FCookProgress progress) {
(void)path;
(void)cookedPath;
(void)fast;
(void)progress;
}
virtual bool canPackage(const ProjectPath& path)
{(void)path;return false;}
virtual void doPackage(const ProjectPath& path, const Database::DataSpecEntry* entry,
bool fast, blender::Token& btok, const MultiProgressPrinter& progress,
ClientProcess* cp=nullptr)
{(void)path;}
virtual bool canPackage(const ProjectPath& path) {
(void)path;
return false;
}
virtual void doPackage(const ProjectPath& path, const Database::DataSpecEntry* entry, bool fast, blender::Token& btok,
const MultiProgressPrinter& progress, ClientProcess* cp = nullptr) {
(void)path;
}
virtual void interruptCook() {}
const DataSpecEntry* getDataSpecEntry() const {return m_specEntry;}
const DataSpecEntry* getDataSpecEntry() const { return m_specEntry; }
};
/**
* @brief Pre-emptive indication of what the constructed DataSpec is used for
*/
enum class DataSpecTool
{
Extract,
Cook,
Package
};
enum class DataSpecTool { Extract, Cook, Package };
extern std::vector<const struct DataSpecEntry*> DATA_SPEC_REGISTRY;
@ -143,8 +147,7 @@ extern std::vector<const struct DataSpecEntry*> DATA_SPEC_REGISTRY;
*
* Auto-registers with data spec registry
*/
struct DataSpecEntry
{
struct DataSpecEntry {
SystemStringView m_name;
SystemStringView m_desc;
SystemStringView m_pakExt;
@ -153,8 +156,7 @@ struct DataSpecEntry
DataSpecEntry(SystemStringView name, SystemStringView desc, SystemStringView pakExt, int numCookPasses,
std::function<std::unique_ptr<IDataSpec>(Project& project, DataSpecTool)>&& factory)
: m_name(name), m_desc(desc), m_pakExt(pakExt), m_numCookPasses(numCookPasses),
m_factory(std::move(factory)) {}
: m_name(name), m_desc(desc), m_pakExt(pakExt), m_numCookPasses(numCookPasses), m_factory(std::move(factory)) {}
};
/**
@ -166,17 +168,15 @@ struct DataSpecEntry
*
* DO NOT CONSTRUCT THIS OR SUBCLASSES DIRECTLY!!
*/
class ObjectBase
{
class ObjectBase {
friend class Project;
SystemString m_path;
protected:
protected:
/**
* @brief Byte-order of target system
*/
enum class DataEndianness
{
enum class DataEndianness {
None,
Big, /**< Big-endian (PowerPC) */
Little /**< Little-endian (Intel) */
@ -185,8 +185,7 @@ protected:
/**
* @brief Data-formats of target system
*/
enum class DataPlatform
{
enum class DataPlatform {
None,
Generic, /**< Scanline textures and 3-way shader bundle (GLSL, HLSL, SPIR-V) */
Revolution, /**< Tiled textures and GX register buffers */
@ -206,9 +205,12 @@ protected:
* Part of the cooking process may include embedding database-refs to dependencies.
* This method should store the 64-bit value provided by IDataObject::id() when doing this.
*/
virtual bool cookObject(FDataAppender dataAppender,
DataEndianness endianness, DataPlatform platform)
{(void)dataAppender;(void)endianness;(void)platform;return true;}
virtual bool cookObject(FDataAppender dataAppender, DataEndianness endianness, DataPlatform platform) {
(void)dataAppender;
(void)endianness;
(void)platform;
return true;
}
typedef std::function<void(ObjectBase*)> FDepAdder;
@ -220,25 +222,20 @@ protected:
* Dependencies registered via this method will eventually have this method called on themselves
* as well. This is a non-recursive operation, no need for subclasses to implement recursion-control.
*/
virtual void gatherDeps(FDepAdder depAdder)
{(void)depAdder;}
virtual void gatherDeps(FDepAdder depAdder) { (void)depAdder; }
/**
* @brief Get a packagable FourCC representation of the object's type
* @return FourCC of the type
*/
virtual FourCC getType() const
{return FourCC("NULL");}
virtual FourCC getType() const { return FourCC("NULL"); }
public:
ObjectBase(SystemStringView path)
: m_path(path) {}
SystemStringView getPath() const {return m_path;}
ObjectBase(SystemStringView path) : m_path(path) {}
SystemStringView getPath() const { return m_path; }
};
/**
* @brief Main project interface
*
@ -246,15 +243,14 @@ public:
* resources in their ideal editor-formats. This interface exposes all
* primary operations to perform on a given project.
*/
class Project
{
class Project {
public:
struct ProjectDataSpec
{
struct ProjectDataSpec {
const DataSpecEntry& spec;
ProjectPath cookedPath;
bool active;
};
private:
ProjectRootPath m_rootPath;
ProjectPath m_workRoot;
@ -265,9 +261,10 @@ private:
std::vector<std::unique_ptr<IDataSpec>> m_cookSpecs;
std::unique_ptr<IDataSpec> m_lastPackageSpec;
bool m_valid = false;
public:
Project(const ProjectRootPath& rootPath);
operator bool() const {return m_valid;}
operator bool() const { return m_valid; }
/**
* @brief Configuration file handle
@ -275,14 +272,13 @@ public:
* Holds a path to a line-delimited textual configuration file;
* opening a locked handle for read/write transactions
*/
class ConfigFile
{
class ConfigFile {
SystemString m_filepath;
std::vector<std::string> m_lines;
FILE* m_lockedFile = NULL;
public:
ConfigFile(const Project& project, SystemStringView name,
SystemStringView subdir=_SYS_STR("/.hecl/"));
ConfigFile(const Project& project, SystemStringView name, SystemStringView subdir = _SYS_STR("/.hecl/"));
std::vector<std::string>& lockAndRead();
void addLine(std::string_view line);
void removeLine(std::string_view refLine);
@ -299,13 +295,7 @@ public:
*
* This is used to provide pretty colors during the cook operation
*/
enum class Cost
{
None,
Light,
Medium,
Heavy
};
enum class Cost { None, Light, Medium, Heavy };
/**
* @brief Get the path of the project's root-directory
@ -313,13 +303,13 @@ public:
*
* Self explanatory
*/
const ProjectRootPath& getProjectRootPath() const {return m_rootPath;}
const ProjectRootPath& getProjectRootPath() const { return m_rootPath; }
/**
* @brief Get the path of project's working directory
* @return project working path
*/
const ProjectPath& getProjectWorkingPath() const {return m_workRoot;}
const ProjectPath& getProjectWorkingPath() const { return m_workRoot; }
/**
* @brief Get the path of project's cooked directory for a specific DataSpec
@ -348,7 +338,7 @@ public:
* This method will not delete actual working files from the project
* directory. It will delete associated cooked objects though.
*/
bool removePaths(const std::vector<ProjectPath>& paths, bool recursive=false);
bool removePaths(const std::vector<ProjectPath>& paths, bool recursive = false);
/**
* @brief Register a working sub-directory as a Dependency Group
@ -385,7 +375,7 @@ public:
* @brief Return map populated with dataspecs targetable by this project interface
* @return Platform map with name-string keys and enable-status values
*/
const std::vector<ProjectDataSpec>& getDataSpecs() const {return m_compiledSpecs;}
const std::vector<ProjectDataSpec>& getDataSpecs() const { return m_compiledSpecs; }
/**
* @brief Enable persistent user preference for particular spec string(s)
@ -419,9 +409,8 @@ public:
* This method blocks execution during the procedure, with periodic
* feedback delivered via feedbackCb.
*/
bool cookPath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb,
bool recursive=false, bool force=false, bool fast=false,
const DataSpecEntry* spec=nullptr, ClientProcess* cp=nullptr,
bool cookPath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb, bool recursive = false,
bool force = false, bool fast = false, const DataSpecEntry* spec = nullptr, ClientProcess* cp = nullptr,
int cookPass = -1);
/**
@ -432,9 +421,8 @@ public:
* @param spec if non-null, cook using a manually-selected dataspec
* @param cp if non-null, cook asynchronously via the ClientProcess
*/
bool packagePath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb,
bool fast=false, const DataSpecEntry* spec=nullptr,
ClientProcess* cp=nullptr);
bool packagePath(const ProjectPath& path, const MultiProgressPrinter& feedbackCb, bool fast = false,
const DataSpecEntry* spec = nullptr, ClientProcess* cp = nullptr);
/**
* @brief Interrupts a cook in progress (call from SIGINT handler)
@ -457,7 +445,7 @@ public:
* Developers understand how useful 'clean' is. While ideally not required,
* it's useful for verifying that a rebuild from ground-up is doable.
*/
bool cleanPath(const ProjectPath& path, bool recursive=false);
bool cleanPath(const ProjectPath& path, bool recursive = false);
/**
* @brief Constructs a full depsgraph of the project-subpath provided
@ -474,9 +462,7 @@ public:
/** Lookup ProjectPath from bridge cache */
const ProjectPath* lookupBridgePath(uint64_t id) const;
};
}
}
} // namespace Database
} // namespace hecl

View File

@ -5,8 +5,7 @@
#include <string>
#include "athena/DNA.hpp"
namespace hecl
{
namespace hecl {
/**
* @brief FourCC representation used within HECL's database
@ -15,73 +14,73 @@ namespace hecl
* while fitting comfortably in a 32-bit word. HECL uses a four-char array
* to remain endian-independent.
*/
class FourCC
{
class FourCC {
protected:
union
{
union {
char fcc[4];
uint32_t num;
};
public:
FourCC() /* Sentinel FourCC */
: num(0) {}
FourCC(const FourCC& other)
{num = other.num;}
FourCC(const char* name)
: num(*(uint32_t*)name) {}
FourCC(uint32_t n)
: num(n) {}
bool operator==(const FourCC& other) const {return num == other.num;}
bool operator!=(const FourCC& other) const {return num != other.num;}
bool operator==(const char* other) const {return num == *(uint32_t*)other;}
bool operator!=(const char* other) const {return num != *(uint32_t*)other;}
bool operator==(int32_t other) const { return num == other;}
bool operator!=(int32_t other) const { return num != other;}
bool operator==(uint32_t other) const {return num == other;}
bool operator!=(uint32_t other) const {return num != other;}
std::string toString() const {return std::string(fcc, 4);}
uint32_t toUint32() const {return num;}
operator uint32_t() const {return num;}
const char* getChars() const {return fcc;}
char* getChars() {return fcc;}
FourCC(const FourCC& other) { num = other.num; }
FourCC(const char* name) : num(*(uint32_t*)name) {}
FourCC(uint32_t n) : num(n) {}
bool operator==(const FourCC& other) const { return num == other.num; }
bool operator!=(const FourCC& other) const { return num != other.num; }
bool operator==(const char* other) const { return num == *(uint32_t*)other; }
bool operator!=(const char* other) const { return num != *(uint32_t*)other; }
bool operator==(int32_t other) const { return num == other; }
bool operator!=(int32_t other) const { return num != other; }
bool operator==(uint32_t other) const { return num == other; }
bool operator!=(uint32_t other) const { return num != other; }
std::string toString() const { return std::string(fcc, 4); }
uint32_t toUint32() const { return num; }
operator uint32_t() const { return num; }
const char* getChars() const { return fcc; }
char* getChars() { return fcc; }
};
#define FOURCC(chars) FourCC(SBIG(chars))
using BigDNA = athena::io::DNA<athena::Big>;
/** FourCC with DNA read/write */
class DNAFourCC final : public BigDNA, public FourCC
{
class DNAFourCC final : public BigDNA, public FourCC {
public:
DNAFourCC() : FourCC() {}
DNAFourCC(const FourCC& other)
: FourCC() {num = other.toUint32();}
DNAFourCC(const char* name)
: FourCC(name) {}
DNAFourCC(uint32_t n)
: FourCC(n) {}
DNAFourCC(const FourCC& other) : FourCC() { num = other.toUint32(); }
DNAFourCC(const char* name) : FourCC(name) {}
DNAFourCC(uint32_t n) : FourCC(n) {}
AT_DECL_EXPLICIT_DNA_YAML
};
template <> inline void DNAFourCC::Enumerate<BigDNA::Read>(typename Read::StreamT& r)
{ r.readUBytesToBuf(fcc, 4); }
template <> inline void DNAFourCC::Enumerate<BigDNA::Write>(typename Write::StreamT& w)
{ w.writeUBytes((atUint8*)fcc, 4); }
template <> inline void DNAFourCC::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& r)
{ std::string rs = r.readString(nullptr); strncpy(fcc, rs.c_str(), 4); }
template <> inline void DNAFourCC::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& w)
{ w.writeString(nullptr, std::string(fcc, 4)); }
template <> inline void DNAFourCC::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s)
{ s += 4; }
template <>
inline void DNAFourCC::Enumerate<BigDNA::Read>(typename Read::StreamT& r) {
r.readUBytesToBuf(fcc, 4);
}
template <>
inline void DNAFourCC::Enumerate<BigDNA::Write>(typename Write::StreamT& w) {
w.writeUBytes((atUint8*)fcc, 4);
}
template <>
inline void DNAFourCC::Enumerate<BigDNA::ReadYaml>(typename ReadYaml::StreamT& r) {
std::string rs = r.readString(nullptr);
strncpy(fcc, rs.c_str(), 4);
}
template <>
inline void DNAFourCC::Enumerate<BigDNA::WriteYaml>(typename WriteYaml::StreamT& w) {
w.writeString(nullptr, std::string(fcc, 4));
}
template <>
inline void DNAFourCC::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& s) {
s += 4;
}
namespace std
{
template <> struct hash<hecl::FourCC>
{
size_t operator()(const hecl::FourCC& val) const noexcept
{return val.toUint32();}
} // namespace hecl
namespace std {
template <>
struct hash<hecl::FourCC> {
size_t operator()(const hecl::FourCC& val) const noexcept { return val.toUint32(); }
};
}
} // namespace std

View File

@ -8,75 +8,73 @@
#include <hecl/hecl.hpp>
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
namespace hecl::Frontend
{
namespace hecl::Frontend {
using namespace std::literals;
struct SourceLocation
{
struct SourceLocation {
int line = -1;
int col = -1;
SourceLocation() = default;
SourceLocation(int l, int c) : line(l), col(c) {}
};
class Diagnostics
{
class Diagnostics {
std::string m_name;
std::string m_source;
std::string m_backend = "Backend";
std::string sourceDiagString(const SourceLocation& l, bool ansi=false) const;
std::string sourceDiagString(const SourceLocation& l, bool ansi = false) const;
public:
void reset(std::string_view name, std::string_view source) {m_name = name; m_source = source;}
void reset(std::string_view name) {m_name = name; m_source.clear();}
void setBackend(std::string_view backend) {m_backend = backend;}
void reset(std::string_view name, std::string_view source) {
m_name = name;
m_source = source;
}
void reset(std::string_view name) {
m_name = name;
m_source.clear();
}
void setBackend(std::string_view backend) { m_backend = backend; }
void reportScannerErr(const SourceLocation& l, const char* format, ...);
void reportParserErr(const SourceLocation& l, const char* format, ...);
void reportBackendErr(const SourceLocation& l, const char* format, ...);
std::string_view getName() const {return m_name;}
std::string_view getSource() const {return m_source;}
std::string_view getName() const { return m_name; }
std::string_view getSource() const { return m_source; }
};
struct Token
{
enum class Kind
{
None,
Eof,
Lf,
Plus,
Minus,
Times,
Div,
Lpar,
Rpar,
Comma,
Period,
Ident,
Number
};
struct Token {
enum class Kind { None, Eof, Lf, Plus, Minus, Times, Div, Lpar, Rpar, Comma, Period, Ident, Number };
static std::string_view KindToStr(Kind k)
{
switch (k)
{
static std::string_view KindToStr(Kind k) {
switch (k) {
case Kind::None:
default:
return "none"sv;
case Kind::Eof: return "eof"sv;
case Kind::Lf: return "lf"sv;
case Kind::Plus: return "+"sv;
case Kind::Minus: return "-"sv;
case Kind::Times: return "*"sv;
case Kind::Div: return "/"sv;
case Kind::Lpar: return "("sv;
case Kind::Rpar: return ")"sv;
case Kind::Comma: return ","sv;
case Kind::Period: return "."sv;
case Kind::Ident: return "ident"sv;
case Kind::Number: return "number"sv;
case Kind::Eof:
return "eof"sv;
case Kind::Lf:
return "lf"sv;
case Kind::Plus:
return "+"sv;
case Kind::Minus:
return "-"sv;
case Kind::Times:
return "*"sv;
case Kind::Div:
return "/"sv;
case Kind::Lpar:
return "("sv;
case Kind::Rpar:
return ")"sv;
case Kind::Comma:
return ","sv;
case Kind::Period:
return "."sv;
case Kind::Ident:
return "ident"sv;
case Kind::Number:
return "number"sv;
}
}
@ -85,13 +83,10 @@ struct Token
SourceLocation loc;
Token() = default;
Token(Kind kind, const SourceLocation& loc)
: kind(kind), loc(loc) {}
Token(Kind kind, std::string&& str, const SourceLocation& loc)
: kind(kind), str(std::move(str)), loc(loc) {}
Token(Kind kind, const SourceLocation& loc) : kind(kind), loc(loc) {}
Token(Kind kind, std::string&& str, const SourceLocation& loc) : kind(kind), str(std::move(str)), loc(loc) {}
std::string toString() const
{
std::string toString() const {
if (str.empty())
return hecl::Format("%d:%d: %s", loc.line, loc.col, KindToStr(kind).data());
else
@ -99,8 +94,7 @@ struct Token
}
};
class Scanner
{
class Scanner {
friend class Parser;
static constexpr char LF = '\n';
static constexpr char COMMENT = '#';
@ -115,43 +109,40 @@ class Scanner
std::string lastLine;
std::string currentLine;
Token::Kind CharToTokenKind(char ch)
{
switch (ch)
{
case '(': return Token::Kind::Lpar;
case ')': return Token::Kind::Rpar;
case ',': return Token::Kind::Comma;
case '.': return Token::Kind::Period;
case '+': return Token::Kind::Plus;
case '-': return Token::Kind::Minus;
case '*': return Token::Kind::Times;
case '/': return Token::Kind::Div;
default: return Token::Kind::None;
Token::Kind CharToTokenKind(char ch) {
switch (ch) {
case '(':
return Token::Kind::Lpar;
case ')':
return Token::Kind::Rpar;
case ',':
return Token::Kind::Comma;
case '.':
return Token::Kind::Period;
case '+':
return Token::Kind::Plus;
case '-':
return Token::Kind::Minus;
case '*':
return Token::Kind::Times;
case '/':
return Token::Kind::Div;
default:
return Token::Kind::None;
}
}
template <class... Args>
void error(const SourceLocation& loc, const char* s, Args&&... args)
{
void error(const SourceLocation& loc, const char* s, Args&&... args) {
m_diag.reportScannerErr(loc, s, args...);
}
static bool isDigit(char c)
{
return c >= '0' && c <= '9';
}
static bool isDigit(char c) { return c >= '0' && c <= '9'; }
static bool isStartIdent(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c == '_');
}
static bool isStartIdent(char c) { return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_'); }
static bool isMidIdent(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
(c == '_') || isDigit(c);
static bool isMidIdent(char c) {
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_') || isDigit(c);
}
int _read();
@ -162,8 +153,7 @@ class Scanner
public:
Scanner(Diagnostics& diag) : m_diag(diag) {}
void reset(std::string_view in)
{
void reset(std::string_view in) {
m_source = in;
m_sourceIt = in.cbegin();
ch = 0;
@ -178,18 +168,11 @@ public:
Token next();
};
struct IRNode
{
struct IRNode {
friend struct IR;
enum class Op
{
Add, Sub, Mul, Div
};
enum class Kind
{
None, Call, Imm, Binop, Swizzle
};
enum class Op { Add, Sub, Mul, Div };
enum class Kind { None, Call, Imm, Binop, Swizzle };
Kind kind = Kind::None;
std::string str;
float val;
@ -199,37 +182,40 @@ struct IRNode
std::list<IRNode> children;
SourceLocation loc;
static std::string_view OpToStr(Op op)
{
switch (op)
{
case Op::Add: return "+"sv;
case Op::Sub: return "-"sv;
case Op::Mul: return "*"sv;
case Op::Div: return "/"sv;
default: return ""sv;
static std::string_view OpToStr(Op op) {
switch (op) {
case Op::Add:
return "+"sv;
case Op::Sub:
return "-"sv;
case Op::Mul:
return "*"sv;
case Op::Div:
return "/"sv;
default:
return ""sv;
}
}
static std::string_view KindToStr(Kind k)
{
switch (k)
{
static std::string_view KindToStr(Kind k) {
switch (k) {
case Kind::None:
default:
return "none"sv;
case Kind::Call: return "call"sv;
case Kind::Imm: return "imm"sv;
case Kind::Binop: return "binop"sv;
case Kind::Swizzle: return "swizzle"sv;
case Kind::Call:
return "call"sv;
case Kind::Imm:
return "imm"sv;
case Kind::Binop:
return "binop"sv;
case Kind::Swizzle:
return "swizzle"sv;
}
}
IRNode() = default;
IRNode(Kind kind, std::string&& str, const SourceLocation& loc)
: kind(kind), str(std::move(str)), loc(loc) {}
IRNode(Kind kind, float val, const SourceLocation& loc)
: kind(kind), val(val), loc(loc) {}
IRNode(Kind kind, std::string&& str, const SourceLocation& loc) : kind(kind), str(std::move(str)), loc(loc) {}
IRNode(Kind kind, float val, const SourceLocation& loc) : kind(kind), val(val), loc(loc) {}
IRNode(Kind kind, std::string&& str, std::list<IRNode>&& children, const SourceLocation& loc)
: kind(kind), str(std::move(str)), children(std::move(children)), loc(loc) {}
IRNode(Op op, IRNode&& left, IRNode&& right, const SourceLocation& loc)
@ -245,24 +231,21 @@ private:
std::string describe() const;
};
class Parser
{
class Parser {
Scanner m_scanner;
Token t;
Token la;
Token::Kind sym;
void scan()
{
void scan() {
t = la;
la = m_scanner.next();
sym = la.kind;
}
template <class... Args>
void error(const char* s, Args&&... args)
{
void error(const char* s, Args&&... args) {
m_scanner.m_diag.reportParserErr(la.loc, s, args...);
}
@ -275,21 +258,21 @@ class Parser
IRNode value();
public:
Parser(Diagnostics& diag)
: m_scanner(diag) {}
Parser(Diagnostics& diag) : m_scanner(diag) {}
void reset(std::string_view in) { la = Token(); m_scanner.reset(in); }
void reset(std::string_view in) {
la = Token();
m_scanner.reset(in);
}
std::list<IRNode> parse();
};
using BigDNA = athena::io::DNA<athena::Big>;
struct IR : BigDNA
{
struct IR : BigDNA {
AT_DECL_EXPLICIT_DNA
enum OpType : uint8_t
{
enum OpType : uint8_t {
None, /**< NOP */
Call, /**< Deferred function insertion for HECL backend using specified I/O regs */
LoadImm, /**< Load a constant (numeric literal) into register */
@ -299,58 +282,45 @@ struct IR : BigDNA
using RegID = atUint16;
struct Instruction : BigDNA
{
struct Instruction : BigDNA {
AT_DECL_EXPLICIT_DNA
OpType m_op = OpType::None;
RegID m_target = RegID(-1);
SourceLocation m_loc;
struct Call : BigDNA
{
struct Call : BigDNA {
AT_DECL_DNA
String<-1> m_name;
Value<atUint16> m_argInstCount;
Vector<atUint16, AT_DNA_COUNT(m_argInstCount)> m_argInstIdxs;
} m_call;
struct LoadImm : BigDNA
{
struct LoadImm : BigDNA {
AT_DECL_DNA
Value<atVec4f> m_immVec = {};
} m_loadImm;
enum ArithmeticOpType : uint8_t
{
None,
Add,
Subtract,
Multiply,
Divide
};
enum ArithmeticOpType : uint8_t { None, Add, Subtract, Multiply, Divide };
struct Arithmetic : BigDNA
{
struct Arithmetic : BigDNA {
AT_DECL_DNA
Value<ArithmeticOpType> m_op = ArithmeticOpType::None;
Value<atUint16> m_instIdxs[2];
} m_arithmetic;
struct Swizzle : BigDNA
{
struct Swizzle : BigDNA {
AT_DECL_DNA
Value<atInt8> m_idxs[4] = {-1, -1, -1, -1};
Value<atUint16> m_instIdx;
} m_swizzle;
Instruction(OpType type, RegID target, const SourceLocation& loc)
: m_op(type), m_target(target), m_loc(loc) {}
Instruction(OpType type, RegID target, const SourceLocation& loc) : m_op(type), m_target(target), m_loc(loc) {}
int getChildCount() const;
const IR::Instruction& getChildInst(const IR& ir, size_t idx) const;
const atVec4f& getImmVec() const;
Instruction(athena::io::IStreamReader& reader) {read(reader);}
Instruction(athena::io::IStreamReader& reader) { read(reader); }
};
atUint64 m_hash = 0;
@ -365,15 +335,14 @@ struct IR : BigDNA
int addInstruction(const IRNode& n, IR::RegID target);
};
class Frontend
{
class Frontend {
Diagnostics m_diag;
Parser m_parser;
public:
IR compileSource(std::string_view source, std::string_view diagName);
Diagnostics& getDiagnostics() { return m_diag; }
Frontend() : m_parser(m_diag) {}
};
}
} // namespace hecl::Frontend

View File

@ -3,19 +3,16 @@
#include "hecl/hecl.hpp"
#include "athena/DNA.hpp"
namespace hecl
{
namespace hecl {
enum class HMDLTopology : atUint32
{
enum class HMDLTopology : atUint32 {
Triangles,
TriStrips,
};
#define HECL_HMDL_META_SZ 32
struct HMDLMeta : athena::io::DNA<athena::Big>
{
struct HMDLMeta : athena::io::DNA<athena::Big> {
AT_DECL_DNA
Value<atUint32> magic = 'TACO';
Value<HMDLTopology> topology;
@ -28,5 +25,4 @@ struct HMDLMeta : athena::io::DNA<athena::Big>
Value<atUint16> bankCount;
};
}
} // namespace hecl

View File

@ -17,20 +17,18 @@
/// \brief Extend the default __GNUC_PREREQ even if glibc's features.h isn't
/// available.
#ifndef LLVM_GNUC_PREREQ
# if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
# define LLVM_GNUC_PREREQ(maj, min, patch) \
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
((maj) << 20) + ((min) << 10) + (patch))
# elif defined(__GNUC__) && defined(__GNUC_MINOR__)
# define LLVM_GNUC_PREREQ(maj, min, patch) \
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
# else
# define LLVM_GNUC_PREREQ(maj, min, patch) 0
# endif
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
#define LLVM_GNUC_PREREQ(maj, min, patch) \
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= ((maj) << 20) + ((min) << 10) + (patch))
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
#define LLVM_GNUC_PREREQ(maj, min, patch) ((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
#else
#define LLVM_GNUC_PREREQ(maj, min, patch) 0
#endif
#endif
#ifndef __has_builtin
# define __has_builtin(x) 0
#define __has_builtin(x) 0
#endif
#include "hecl.hpp"
@ -61,7 +59,8 @@ enum ZeroBehavior {
};
namespace detail {
template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
template <typename T, std::size_t SizeOfT>
struct TrailingZerosCounter {
static std::size_t count(T Val, ZeroBehavior) {
if (!Val)
return std::numeric_limits<T>::digits;
@ -85,7 +84,8 @@ template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter {
};
#if __GNUC__ >= 4 || defined(_MSC_VER)
template <typename T> struct TrailingZerosCounter<T, 4> {
template <typename T>
struct TrailingZerosCounter<T, 4> {
static std::size_t count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
@ -101,7 +101,8 @@ template <typename T> struct TrailingZerosCounter<T, 4> {
};
#if !defined(_MSC_VER) || defined(_M_X64)
template <typename T> struct TrailingZerosCounter<T, 8> {
template <typename T>
struct TrailingZerosCounter<T, 8> {
static std::size_t count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
@ -128,14 +129,14 @@ template <typename T> struct TrailingZerosCounter<T, 8> {
/// valid arguments.
template <typename T>
std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB);
}
namespace detail {
template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
template <typename T, std::size_t SizeOfT>
struct LeadingZerosCounter {
static std::size_t count(T Val, ZeroBehavior) {
if (!Val)
return std::numeric_limits<T>::digits;
@ -154,7 +155,8 @@ template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter {
};
#if __GNUC__ >= 4 || defined(_MSC_VER)
template <typename T> struct LeadingZerosCounter<T, 4> {
template <typename T>
struct LeadingZerosCounter<T, 4> {
static std::size_t count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 32;
@ -170,7 +172,8 @@ template <typename T> struct LeadingZerosCounter<T, 4> {
};
#if !defined(_MSC_VER) || defined(_M_X64)
template <typename T> struct LeadingZerosCounter<T, 8> {
template <typename T>
struct LeadingZerosCounter<T, 8> {
static std::size_t count(T Val, ZeroBehavior ZB) {
if (ZB != ZB_Undefined && Val == 0)
return 64;
@ -197,8 +200,7 @@ template <typename T> struct LeadingZerosCounter<T, 8> {
/// valid arguments.
template <typename T>
std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB);
}
@ -210,7 +212,8 @@ std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) {
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
template <typename T>
T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return std::numeric_limits<T>::max();
@ -224,14 +227,14 @@ template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) {
///
/// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are
/// valid arguments.
template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
template <typename T>
T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) {
if (ZB == ZB_Max && Val == 0)
return std::numeric_limits<T>::max();
// Use ^ instead of - because both gcc and llvm can remove the associated ^
// in the __builtin_clz intrinsic on x86.
return countLeadingZeros(Val, ZB_Undefined) ^
(std::numeric_limits<T>::digits - 1);
return countLeadingZeros(Val, ZB_Undefined) ^ (std::numeric_limits<T>::digits - 1);
}
/// \brief Macro compressed bit reversal table for 256 bits.
@ -264,33 +267,31 @@ T reverseBits(T Val) {
// ambiguity.
/// Hi_32 - This function returns the high 32 bits of a 64 bit value.
constexpr inline uint32_t Hi_32(uint64_t Value) {
return static_cast<uint32_t>(Value >> 32);
}
constexpr inline uint32_t Hi_32(uint64_t Value) { return static_cast<uint32_t>(Value >> 32); }
/// Lo_32 - This function returns the low 32 bits of a 64 bit value.
constexpr inline uint32_t Lo_32(uint64_t Value) {
return static_cast<uint32_t>(Value);
}
constexpr inline uint32_t Lo_32(uint64_t Value) { return static_cast<uint32_t>(Value); }
/// Make_64 - This functions makes a 64-bit integer from a high / low pair of
/// 32-bit integers.
constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) {
return ((uint64_t)High << 32) | (uint64_t)Low;
}
constexpr inline uint64_t Make_64(uint32_t High, uint32_t Low) { return ((uint64_t)High << 32) | (uint64_t)Low; }
/// isInt - Checks if an integer fits into the given bit width.
template <unsigned N> constexpr inline bool isInt(int64_t x) {
return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1)));
template <unsigned N>
constexpr inline bool isInt(int64_t x) {
return N >= 64 || (-(INT64_C(1) << (N - 1)) <= x && x < (INT64_C(1) << (N - 1)));
}
// Template specializations to get better code for common cases.
template <> constexpr inline bool isInt<8>(int64_t x) {
template <>
constexpr inline bool isInt<8>(int64_t x) {
return static_cast<int8_t>(x) == x;
}
template <> constexpr inline bool isInt<16>(int64_t x) {
template <>
constexpr inline bool isInt<16>(int64_t x) {
return static_cast<int16_t>(x) == x;
}
template <> constexpr inline bool isInt<32>(int64_t x) {
template <>
constexpr inline bool isInt<32>(int64_t x) {
return static_cast<int32_t>(x) == x;
}
@ -298,8 +299,7 @@ template <> constexpr inline bool isInt<32>(int64_t x) {
/// left by S.
template <unsigned N, unsigned S>
constexpr inline bool isShiftedInt(int64_t x) {
static_assert(
N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number.");
static_assert(N > 0, "isShiftedInt<0> doesn't make sense (refers to a 0-bit number.");
static_assert(N + S <= 64, "isShiftedInt<N, S> with N + S > 64 is too wide.");
return isInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
}
@ -313,35 +313,34 @@ constexpr inline bool isShiftedInt(int64_t x) {
/// to keep MSVC from (incorrectly) warning on isUInt<64> that we're shifting
/// left too many places.
template <unsigned N>
constexpr inline typename std::enable_if<(N < 64), bool>::type
isUInt(uint64_t X) {
constexpr inline typename std::enable_if<(N < 64), bool>::type isUInt(uint64_t X) {
static_assert(N > 0, "isUInt<0> doesn't make sense");
return X < (UINT64_C(1) << (N));
}
template <unsigned N>
constexpr inline typename std::enable_if<N >= 64, bool>::type
isUInt(uint64_t X) {
constexpr inline typename std::enable_if<N >= 64, bool>::type isUInt(uint64_t X) {
return true;
}
// Template specializations to get better code for common cases.
template <> constexpr inline bool isUInt<8>(uint64_t x) {
template <>
constexpr inline bool isUInt<8>(uint64_t x) {
return static_cast<uint8_t>(x) == x;
}
template <> constexpr inline bool isUInt<16>(uint64_t x) {
template <>
constexpr inline bool isUInt<16>(uint64_t x) {
return static_cast<uint16_t>(x) == x;
}
template <> constexpr inline bool isUInt<32>(uint64_t x) {
template <>
constexpr inline bool isUInt<32>(uint64_t x) {
return static_cast<uint32_t>(x) == x;
}
/// Checks if a unsigned integer is an N bit number shifted left by S.
template <unsigned N, unsigned S>
constexpr inline bool isShiftedUInt(uint64_t x) {
static_assert(
N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)");
static_assert(N + S <= 64,
"isShiftedUInt<N, S> with N + S > 64 is too wide.");
static_assert(N > 0, "isShiftedUInt<0> doesn't make sense (refers to a 0-bit number)");
static_assert(N + S <= 64, "isShiftedUInt<N, S> with N + S > 64 is too wide.");
// Per the two static_asserts above, S must be strictly less than 64. So
// 1 << S is not undefined behavior.
return isUInt<N + S>(x) && (x % (UINT64_C(1) << S) == 0);
@ -362,7 +361,7 @@ inline uint64_t maxUIntN(uint64_t N) {
inline int64_t minIntN(int64_t N) {
assert(N > 0 && N <= 64 && "integer width out of range");
return -(UINT64_C(1)<<(N-1));
return -(UINT64_C(1) << (N - 1));
}
/// Gets the maximum value for a N-bit signed integer.
@ -376,72 +375,50 @@ inline int64_t maxIntN(int64_t N) {
/// isUIntN - Checks if an unsigned integer fits into the given (dynamic)
/// bit width.
inline bool isUIntN(unsigned N, uint64_t x) {
return N >= 64 || x <= maxUIntN(N);
}
inline bool isUIntN(unsigned N, uint64_t x) { return N >= 64 || x <= maxUIntN(N); }
/// isIntN - Checks if an signed integer fits into the given (dynamic)
/// bit width.
inline bool isIntN(unsigned N, int64_t x) {
return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N));
}
inline bool isIntN(unsigned N, int64_t x) { return N >= 64 || (minIntN(N) <= x && x <= maxIntN(N)); }
/// isMask_32 - This function returns true if the argument is a non-empty
/// sequence of ones starting at the least significant bit with the remainder
/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true.
constexpr inline bool isMask_32(uint32_t Value) {
return Value && ((Value + 1) & Value) == 0;
}
constexpr inline bool isMask_32(uint32_t Value) { return Value && ((Value + 1) & Value) == 0; }
/// isMask_64 - This function returns true if the argument is a non-empty
/// sequence of ones starting at the least significant bit with the remainder
/// zero (64 bit version).
constexpr inline bool isMask_64(uint64_t Value) {
return Value && ((Value + 1) & Value) == 0;
}
constexpr inline bool isMask_64(uint64_t Value) { return Value && ((Value + 1) & Value) == 0; }
/// isShiftedMask_32 - This function returns true if the argument contains a
/// non-empty sequence of ones with the remainder zero (32 bit version.)
/// Ex. isShiftedMask_32(0x0000FF00U) == true.
constexpr inline bool isShiftedMask_32(uint32_t Value) {
return Value && isMask_32((Value - 1) | Value);
}
constexpr inline bool isShiftedMask_32(uint32_t Value) { return Value && isMask_32((Value - 1) | Value); }
/// isShiftedMask_64 - This function returns true if the argument contains a
/// non-empty sequence of ones with the remainder zero (64 bit version.)
constexpr inline bool isShiftedMask_64(uint64_t Value) {
return Value && isMask_64((Value - 1) | Value);
}
constexpr inline bool isShiftedMask_64(uint64_t Value) { return Value && isMask_64((Value - 1) | Value); }
/// isPowerOf2_32 - This function returns true if the argument is a power of
/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.)
constexpr inline bool isPowerOf2_32(uint32_t Value) {
return Value && !(Value & (Value - 1));
}
constexpr inline bool isPowerOf2_32(uint32_t Value) { return Value && !(Value & (Value - 1)); }
/// isPowerOf2_64 - This function returns true if the argument is a power of two
/// > 0 (64 bit edition.)
constexpr inline bool isPowerOf2_64(uint64_t Value) {
return Value && !(Value & (Value - int64_t(1L)));
}
constexpr inline bool isPowerOf2_64(uint64_t Value) { return Value && !(Value & (Value - int64_t(1L))); }
/// ByteSwap_16 - This function returns a byte-swapped representation of the
/// 16-bit argument, Value.
inline uint16_t ByteSwap_16(uint16_t Value) {
return hecl::bswap16(Value);
}
inline uint16_t ByteSwap_16(uint16_t Value) { return hecl::bswap16(Value); }
/// ByteSwap_32 - This function returns a byte-swapped representation of the
/// 32-bit argument, Value.
inline uint32_t ByteSwap_32(uint32_t Value) {
return hecl::bswap32(Value);
}
inline uint32_t ByteSwap_32(uint32_t Value) { return hecl::bswap32(Value); }
/// ByteSwap_64 - This function returns a byte-swapped representation of the
/// 64-bit argument, Value.
inline uint64_t ByteSwap_64(uint64_t Value) {
return hecl::bswap64(Value);
}
inline uint64_t ByteSwap_64(uint64_t Value) { return hecl::bswap64(Value); }
/// \brief Count the number of ones from the most significant bit to the first
/// zero bit.
@ -453,8 +430,7 @@ inline uint64_t ByteSwap_64(uint64_t Value) {
/// ZB_Undefined are valid arguments.
template <typename T>
std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
return countLeadingZeros(~Value, ZB);
}
@ -469,14 +445,14 @@ std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
/// ZB_Undefined are valid arguments.
template <typename T>
std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
return countTrailingZeros(~Value, ZB);
}
namespace detail {
template <typename T, std::size_t SizeOfT> struct PopulationCounter {
template <typename T, std::size_t SizeOfT>
struct PopulationCounter {
static unsigned count(T Value) {
// Generic version, forward to 32 bits.
static_assert(SizeOfT <= 4, "Not implemented!");
@ -491,7 +467,8 @@ template <typename T, std::size_t SizeOfT> struct PopulationCounter {
}
};
template <typename T> struct PopulationCounter<T, 8> {
template <typename T>
struct PopulationCounter<T, 8> {
static unsigned count(T Value) {
#if __GNUC__ >= 4
return __builtin_popcountll(Value);
@ -511,8 +488,7 @@ template <typename T> struct PopulationCounter<T, 8> {
/// Returns 0 if the word is zero.
template <typename T>
inline unsigned countPopulation(T Value) {
static_assert(std::numeric_limits<T>::is_integer &&
!std::numeric_limits<T>::is_signed,
static_assert(std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed,
"Only unsigned integral types are allowed.");
return detail::PopulationCounter<T, sizeof(T)>::count(Value);
}
@ -529,28 +505,20 @@ inline double Log2(double Value) {
/// Log2_32 - This function returns the floor log base 2 of the specified value,
/// -1 if the value is zero. (32 bit edition.)
/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2
inline unsigned Log2_32(uint32_t Value) {
return 31 - countLeadingZeros(Value);
}
inline unsigned Log2_32(uint32_t Value) { return 31 - countLeadingZeros(Value); }
/// Log2_64 - This function returns the floor log base 2 of the specified value,
/// -1 if the value is zero. (64 bit edition.)
inline unsigned Log2_64(uint64_t Value) {
return 63 - countLeadingZeros(Value);
}
inline unsigned Log2_64(uint64_t Value) { return 63 - countLeadingZeros(Value); }
/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified
/// value, 32 if the value is zero. (32 bit edition).
/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3
inline unsigned Log2_32_Ceil(uint32_t Value) {
return 32 - countLeadingZeros(Value - 1);
}
inline unsigned Log2_32_Ceil(uint32_t Value) { return 32 - countLeadingZeros(Value - 1); }
/// Log2_64_Ceil - This function returns the ceil log base 2 of the specified
/// value, 64 if the value is zero. (64 bit edition.)
inline unsigned Log2_64_Ceil(uint64_t Value) {
return 64 - countLeadingZeros(Value - 1);
}
inline unsigned Log2_64_Ceil(uint64_t Value) { return 64 - countLeadingZeros(Value - 1); }
/// GreatestCommonDivisor64 - Return the greatest common divisor of the two
/// values using Euclid's algorithm.
@ -626,9 +594,8 @@ constexpr inline uint64_t MinAlign(uint64_t A, uint64_t B) {
///
/// Alignment should be a power of two. This method rounds up, so
/// alignAddr(7, 4) == 8 and alignAddr(8, 4) == 8.
inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
assert(Alignment && isPowerOf2_64((uint64_t)Alignment) &&
"Alignment is not a power of two!");
inline uintptr_t alignAddr(const void* Addr, size_t Alignment) {
assert(Alignment && isPowerOf2_64((uint64_t)Alignment) && "Alignment is not a power of two!");
assert((uintptr_t)Addr + Alignment - 1 >= (uintptr_t)Addr);
@ -637,7 +604,7 @@ inline uintptr_t alignAddr(const void *Addr, size_t Alignment) {
/// \brief Returns the necessary adjustment for aligning \c Ptr to \c Alignment
/// bytes, rounding up.
inline size_t alignmentAdjustment(const void *Ptr, size_t Alignment) {
inline size_t alignmentAdjustment(const void* Ptr, size_t Alignment) {
return alignAddr(Ptr, Alignment) - (uintptr_t)Ptr;
}
@ -656,7 +623,8 @@ inline uint64_t NextPowerOf2(uint64_t A) {
/// Returns the power of two which is less than or equal to the given value.
/// Essentially, it is a floor operation across the domain of powers of two.
inline uint64_t PowerOf2Floor(uint64_t A) {
if (!A) return 0;
if (!A)
return 0;
return 1ull << (63 - countLeadingZeros(A, ZB_Undefined));
}
@ -696,7 +664,8 @@ inline uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
/// Returns the next integer (mod 2**64) that is greater than or equal to
/// \p Value and is a multiple of \c Align. \c Align must be non-zero.
template <uint64_t Align> constexpr inline uint64_t alignTo(uint64_t Value) {
template <uint64_t Align>
constexpr inline uint64_t alignTo(uint64_t Value) {
static_assert(Align != 0u, "Align must be non-zero");
return (Value + Align - 1) / Align * Align;
}
@ -725,13 +694,12 @@ inline uint64_t alignDown(uint64_t Value, uint64_t Align, uint64_t Skew = 0) {
/// Returns the offset to the next integer (mod 2**64) that is greater than
/// or equal to \p Value and is a multiple of \p Align. \p Align must be
/// non-zero.
inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) {
return alignTo(Value, Align) - Value;
}
inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { return alignTo(Value, Align) - Value; }
/// Sign-extend the number in the bottom B bits of X to a 32-bit integer.
/// Requires 0 < B <= 32.
template <unsigned B> constexpr inline int32_t SignExtend32(uint32_t X) {
template <unsigned B>
constexpr inline int32_t SignExtend32(uint32_t X) {
static_assert(B > 0, "Bit width can't be 0.");
static_assert(B <= 32, "Bit width out of range.");
return int32_t(X << (32 - B)) >> (32 - B);
@ -747,7 +715,8 @@ inline int32_t SignExtend32(uint32_t X, unsigned B) {
/// Sign-extend the number in the bottom B bits of X to a 64-bit integer.
/// Requires 0 < B < 64.
template <unsigned B> constexpr inline int64_t SignExtend64(uint64_t x) {
template <unsigned B>
constexpr inline int64_t SignExtend64(uint64_t x) {
static_assert(B > 0, "Bit width can't be 0.");
static_assert(B <= 64, "Bit width out of range.");
return int64_t(x << (64 - B)) >> (64 - B);
@ -764,8 +733,7 @@ inline int64_t SignExtend64(uint64_t X, unsigned B) {
/// Subtract two unsigned integers, X and Y, of type T and return the absolute
/// value of the result.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
AbsoluteDifference(T X, T Y) {
typename std::enable_if<std::is_unsigned<T>::value, T>::type AbsoluteDifference(T X, T Y) {
return std::max(X, Y) - std::min(X, Y);
}
@ -773,10 +741,9 @@ AbsoluteDifference(T X, T Y) {
/// maximum representable value of T on overflow. ResultOverflowed indicates if
/// the result is larger than the maximum representable value of type T.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
typename std::enable_if<std::is_unsigned<T>::value, T>::type SaturatingAdd(T X, T Y, bool* ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
bool& Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
// Hacker's Delight, p. 29
T Z = X + Y;
Overflowed = (Z < X || Z < Y);
@ -790,10 +757,10 @@ SaturatingAdd(T X, T Y, bool *ResultOverflowed = nullptr) {
/// maximum representable value of T on overflow. ResultOverflowed indicates if
/// the result is larger than the maximum representable value of type T.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
typename std::enable_if<std::is_unsigned<T>::value, T>::type SaturatingMultiply(T X, T Y,
bool* ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
bool& Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
// Hacker's Delight, p. 30 has a different algorithm, but we don't use that
// because it fails for uint16_t (where multiplication can have undefined
@ -836,10 +803,10 @@ SaturatingMultiply(T X, T Y, bool *ResultOverflowed = nullptr) {
/// overflow. ResultOverflowed indicates if the result is larger than the
/// maximum representable value of type T.
template <typename T>
typename std::enable_if<std::is_unsigned<T>::value, T>::type
SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
typename std::enable_if<std::is_unsigned<T>::value, T>::type SaturatingMultiplyAdd(T X, T Y, T A,
bool* ResultOverflowed = nullptr) {
bool Dummy;
bool &Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
bool& Overflowed = ResultOverflowed ? *ResultOverflowed : Dummy;
T Product = SaturatingMultiply(X, Y, &Overflowed);
if (Overflowed)
@ -850,6 +817,5 @@ SaturatingMultiplyAdd(T X, T Y, T A, bool *ResultOverflowed = nullptr) {
/// Use this rather than HUGE_VALF; the latter causes warnings on MSVC.
extern const float huge_valf;
} // End llvm namespace
} // End hecl namespace
} // namespace llvm
} // namespace hecl

View File

@ -3,17 +3,14 @@
#include "hecl.hpp"
#include <thread>
namespace hecl
{
namespace hecl {
class MultiProgressPrinter
{
class MultiProgressPrinter {
std::thread m_logThread;
mutable std::mutex m_logLock;
bool m_newLineAfter;
struct TermInfo
{
struct TermInfo {
#if _WIN32
HANDLE console;
#endif
@ -22,8 +19,7 @@ class MultiProgressPrinter
bool truncate = false;
} m_termInfo;
struct ThreadStat
{
struct ThreadStat {
hecl::SystemString m_message, m_submessage;
float m_factor = 0.f;
bool m_active = false;
@ -44,16 +40,16 @@ class MultiProgressPrinter
void DoPrint();
void DrawIndeterminateBar();
void MoveCursorUp(int n);
public:
MultiProgressPrinter(bool activate = false);
~MultiProgressPrinter();
void print(const hecl::SystemChar* message, const hecl::SystemChar* submessage,
float factor = -1.f, int threadIdx = 0) const;
void print(const hecl::SystemChar* message, const hecl::SystemChar* submessage, float factor = -1.f,
int threadIdx = 0) const;
void setMainFactor(float factor) const;
void setMainIndeterminate(bool indeterminate) const;
void startNewLine() const;
void flush() const;
};
}
} // namespace hecl

View File

@ -11,38 +11,35 @@
/* CMake-curated rep classes for the application */
#include "ApplicationReps.hpp"
namespace hecl
{
namespace hecl {
#if HECL_RUNTIME
template<typename P, typename S>
class StageRuntimeObject : public StageRep<P, S>
{
template <typename P, typename S>
class StageRuntimeObject : public StageRep<P, S> {
boo::ObjToken<boo::IShaderStage> m_stage;
public:
static constexpr StageTargetType TargetType = StageTargetType::Runtime;
static constexpr PipelineTargetType PipelineTarget = PipelineTargetType::StageRuntimeCollection;
static constexpr bool HasHash = false;
StageRuntimeObject() = default;
StageRuntimeObject(StageConverter<P, S>& conv, FactoryCtx& ctx, const StageBinary<P, S>& in)
{
StageRuntimeObject(StageConverter<P, S>& conv, FactoryCtx& ctx, const StageBinary<P, S>& in) {
m_stage = static_cast<typename P::Context&>(ctx).newShaderStage(in.data(), in.size(), S::Enum);
}
boo::ObjToken<boo::IShaderStage> stage() const { return m_stage; }
};
#endif
class HECLIR : public PipelineRep<PlatformType::Null>
{
class HECLIR : public PipelineRep<PlatformType::Null> {
const hecl::Backend::IR& m_ir;
const hecl::Backend::ShaderTag& m_tag;
const hecl::Backend::ExtensionSlot& m_extension;
uint64_t m_hash;
public:
HECLIR(const hecl::Backend::IR& ir, const hecl::Backend::ShaderTag& tag,
const hecl::Backend::ExtensionSlot& extension)
: m_ir(ir), m_tag(tag), m_extension(extension)
{
: m_ir(ir), m_tag(tag), m_extension(extension) {
m_hash = tag.val64();
m_hash ^= extension.hash();
}
@ -54,86 +51,75 @@ public:
const hecl::Backend::ExtensionSlot& extension() const { return m_extension; }
};
template<typename P, class BackendTp>
class HECLBackendImpl : public PipelineRep<P>
{
template <typename P, class BackendTp>
class HECLBackendImpl : public PipelineRep<P> {
hecl::Backend::ShaderTag m_tag;
BackendTp m_backend;
const hecl::Backend::ExtensionSlot& m_extension;
public:
static constexpr bool HasHash = false;
HECLBackendImpl(PipelineConverter<P>& conv, FactoryCtx& ctx, const HECLIR& in)
: m_tag(in.tag()), m_extension(in.extension())
{
: m_tag(in.tag()), m_extension(in.extension()) {
hecl::Backend::Diagnostics diag;
m_backend.reset(in.ir(), diag);
}
std::string makeVert() const
{
return m_backend.makeVert(
m_tag.getColorCount(), m_tag.getUvCount(), m_tag.getWeightCount(),
m_tag.getSkinSlotCount(), m_extension.texCount,
m_extension.texs, m_tag.getReflectionType());
std::string makeVert() const {
return m_backend.makeVert(m_tag.getColorCount(), m_tag.getUvCount(), m_tag.getWeightCount(),
m_tag.getSkinSlotCount(), m_extension.texCount, m_extension.texs,
m_tag.getReflectionType());
}
std::string makeFrag() const
{
std::string makeFrag() const {
return m_backend.makeFrag(m_extension.blockCount, m_extension.blockNames,
m_tag.getAlphaTest() || m_extension.forceAlphaTest, m_tag.getReflectionType(),
m_backend.m_blendSrc, m_backend.m_blendDst,
m_extension.lighting, m_extension.post,
m_backend.m_blendSrc, m_backend.m_blendDst, m_extension.lighting, m_extension.post,
m_extension.texCount, m_extension.texs);
}
const hecl::Backend::ShaderTag& getTag() const { return m_tag; }
const hecl::Backend::ExtensionSlot& extension() const { return m_extension; }
std::pair<hecl::Backend::BlendFactor, hecl::Backend::BlendFactor> blendFactors() const
{ return {m_backend.m_blendSrc, m_backend.m_blendDst}; }
std::pair<hecl::Backend::BlendFactor, hecl::Backend::BlendFactor> blendFactors() const {
return {m_backend.m_blendSrc, m_backend.m_blendDst};
}
};
template<typename P>
class HECLBackend : public PipelineRep<P>
{
template <typename P>
class HECLBackend : public PipelineRep<P> {
public:
static constexpr bool HasHash = false;
};
template<>
class HECLBackend<PlatformType::OpenGL> : public HECLBackendImpl<PlatformType::OpenGL, hecl::Backend::GLSL>
{
template <>
class HECLBackend<PlatformType::OpenGL> : public HECLBackendImpl<PlatformType::OpenGL, hecl::Backend::GLSL> {
public:
using HECLBackendImpl::HECLBackendImpl;
};
template<>
class HECLBackend<PlatformType::Vulkan> : public HECLBackendImpl<PlatformType::Vulkan, hecl::Backend::GLSL>
{
template <>
class HECLBackend<PlatformType::Vulkan> : public HECLBackendImpl<PlatformType::Vulkan, hecl::Backend::GLSL> {
public:
using HECLBackendImpl::HECLBackendImpl;
};
template<>
class HECLBackend<PlatformType::D3D11> : public HECLBackendImpl<PlatformType::D3D11, hecl::Backend::HLSL>
{
template <>
class HECLBackend<PlatformType::D3D11> : public HECLBackendImpl<PlatformType::D3D11, hecl::Backend::HLSL> {
public:
using HECLBackendImpl::HECLBackendImpl;
};
template<>
class HECLBackend<PlatformType::Metal> : public HECLBackendImpl<PlatformType::Metal, hecl::Backend::Metal>
{
template <>
class HECLBackend<PlatformType::Metal> : public HECLBackendImpl<PlatformType::Metal, hecl::Backend::Metal> {
public:
using HECLBackendImpl::HECLBackendImpl;
};
template<>
class HECLBackend<PlatformType::NX> : public HECLBackendImpl<PlatformType::NX, hecl::Backend::GLSL>
{
template <>
class HECLBackend<PlatformType::NX> : public HECLBackendImpl<PlatformType::NX, hecl::Backend::GLSL> {
public:
using HECLBackendImpl::HECLBackendImpl;
};
template<template<typename, typename> class T, typename P, typename... Rest>
StageCollection<T<P, Rest...>>::StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const HECLBackend<P>& in)
{
template <template <typename, typename> class T, typename P, typename... Rest>
StageCollection<T<P, Rest...>>::StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const HECLBackend<P>& in) {
m_vertex = conv.getVertexConverter().convert(ctx, StageSourceText<P, PipelineStage::Vertex>(in.makeVert()));
m_fragment = conv.getFragmentConverter().convert(ctx, StageSourceText<P, PipelineStage::Fragment>(in.makeFrag()));
m_vtxFmtData = in.getTag().vertexFormat();
@ -143,109 +129,90 @@ StageCollection<T<P, Rest...>>::StageCollection(PipelineConverter<P>& conv, Fact
}
#if HECL_RUNTIME
template<typename P>
class FinalPipeline : public PipelineRep<P>
{
template <typename P>
class FinalPipeline : public PipelineRep<P> {
boo::ObjToken<boo::IShaderPipeline> m_pipeline;
public:
static constexpr PipelineTargetType TargetType = PipelineTargetType::FinalPipeline;
static constexpr bool HasHash = false;
FinalPipeline(PipelineConverter<P>& conv, FactoryCtx& ctx,
const StageCollection<StageRuntimeObject<P, PipelineStage::Null>>& in)
{
const StageCollection<StageRuntimeObject<P, PipelineStage::Null>>& in) {
m_pipeline = static_cast<typename P::Context&>(ctx).newShaderPipeline(
in.m_vertex.stage(), in.m_fragment.stage(), in.m_geometry.stage(),
in.m_control.stage(), in.m_evaluation.stage(), in.m_vtxFmt, in.m_additionalInfo);
in.m_vertex.stage(), in.m_fragment.stage(), in.m_geometry.stage(), in.m_control.stage(),
in.m_evaluation.stage(), in.m_vtxFmt, in.m_additionalInfo);
}
boo::ObjToken<boo::IShaderPipeline> pipeline() const { return m_pipeline; }
};
#endif
template<typename... Args> struct pack {};
template <typename... Args>
struct pack {};
struct null_t {};
template<typename P> struct ShaderDB {};
template <typename P>
struct ShaderDB {};
#define STAGE_COLLECTION_SPECIALIZATIONS(T, P) StageCollection<T<P, PipelineStage::Null>>,
#define PIPELINE_RUNTIME_SPECIALIZATIONS(P) \
HECLBackend<P>, \
STAGE_COLLECTION_SPECIALIZATIONS(StageSourceText, P) \
STAGE_COLLECTION_SPECIALIZATIONS(StageBinary, P) \
STAGE_COLLECTION_SPECIALIZATIONS(StageRuntimeObject, P) \
FinalPipeline<P>,
#define PIPELINE_OFFLINE_SPECIALIZATIONS(P) \
HECLBackend<P>, \
STAGE_COLLECTION_SPECIALIZATIONS(StageSourceText, P)
STAGE_COLLECTION_SPECIALIZATIONS(StageSourceText, P) STAGE_COLLECTION_SPECIALIZATIONS(StageBinary, P) \
STAGE_COLLECTION_SPECIALIZATIONS(StageRuntimeObject, P) FinalPipeline<P>,
#define PIPELINE_OFFLINE_SPECIALIZATIONS(P) HECLBackend<P>, STAGE_COLLECTION_SPECIALIZATIONS(StageSourceText, P)
#define STAGE_RUNTIME_SPECIALIZATIONS(P, S) \
StageBinary<P, S>, \
HECL_APPLICATION_STAGE_REPS(P, S) \
StageRuntimeObject<P, S>,
#define STAGE_OFFLINE_SPECIALIZATIONS(P, S) \
HECL_APPLICATION_STAGE_REPS(P, S)
StageBinary<P, S>, HECL_APPLICATION_STAGE_REPS(P, S) StageRuntimeObject<P, S>,
#define STAGE_OFFLINE_SPECIALIZATIONS(P, S) HECL_APPLICATION_STAGE_REPS(P, S)
#define SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, S) \
template<> struct ShaderDB<P>::StageDB<S> \
{ \
using StageTypes = pack< \
STAGE_RUNTIME_SPECIALIZATIONS(P, S) \
null_t \
>; \
};
template <> \
struct ShaderDB<P>::StageDB<S> { \
using StageTypes = pack<STAGE_RUNTIME_SPECIALIZATIONS(P, S) null_t>; \
};
#define SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, S) \
template<> struct ShaderDB<P>::StageDB<S> \
{ \
using StageTypes = pack< \
null_t \
>; \
};
template <> \
struct ShaderDB<P>::StageDB<S> { \
using StageTypes = pack<null_t>; \
};
#define SPECIALIZE_OFFLINE_STAGE(P, S) \
template<> struct ShaderDB<P>::StageDB<S> \
{ \
using StageTypes = pack< \
STAGE_OFFLINE_SPECIALIZATIONS(P, S) \
null_t \
>; \
};
template <> \
struct ShaderDB<P>::StageDB<S> { \
using StageTypes = pack<STAGE_OFFLINE_SPECIALIZATIONS(P, S) null_t>; \
};
#define SPECIALIZE_RUNTIME_AVAILABLE_PLATFORM(P) \
template<> struct ShaderDB<P> \
{ \
using PipelineTypes = pack< \
PIPELINE_RUNTIME_SPECIALIZATIONS(P) \
null_t \
>; \
template<typename S> struct StageDB {}; \
}; \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Vertex) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Fragment) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Geometry) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Control) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Evaluation)
template <> \
struct ShaderDB<P> { \
using PipelineTypes = pack<PIPELINE_RUNTIME_SPECIALIZATIONS(P) null_t>; \
template <typename S> \
struct StageDB {}; \
}; \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Vertex) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Fragment) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Geometry) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Control) \
SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, hecl::PipelineStage::Evaluation)
#define SPECIALIZE_RUNTIME_UNAVAILABLE_PLATFORM(P) \
template<> struct ShaderDB<P> \
{ \
using PipelineTypes = pack< \
null_t \
>; \
template<typename S> struct StageDB {}; \
}; \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Vertex) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Fragment) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Geometry) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Control) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Evaluation)
template <> \
struct ShaderDB<P> { \
using PipelineTypes = pack<null_t>; \
template <typename S> \
struct StageDB {}; \
}; \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Vertex) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Fragment) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Geometry) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Control) \
SPECIALIZE_RUNTIME_UNAVAILABLE_STAGE(P, hecl::PipelineStage::Evaluation)
#define SPECIALIZE_OFFLINE_PLATFORM(P) \
template<> struct ShaderDB<P> \
{ \
using PipelineTypes = pack< \
PIPELINE_OFFLINE_SPECIALIZATIONS(P) \
null_t \
>; \
template<typename S> struct StageDB {}; \
}; \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Vertex) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Fragment) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Geometry) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Control) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Evaluation)
template <> \
struct ShaderDB<P> { \
using PipelineTypes = pack<PIPELINE_OFFLINE_SPECIALIZATIONS(P) null_t>; \
template <typename S> \
struct StageDB {}; \
}; \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Vertex) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Fragment) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Geometry) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Control) \
SPECIALIZE_OFFLINE_STAGE(P, hecl::PipelineStage::Evaluation)
#if HECL_RUNTIME
#if BOO_HAS_GL
@ -283,9 +250,8 @@ SPECIALIZE_OFFLINE_PLATFORM(hecl::PlatformType::NX)
class ShaderCacheZipStream;
template<typename P, typename S>
class StageConverter
{
template <typename P, typename S>
class StageConverter {
friend class PipelineConverter<P>;
#if HECL_RUNTIME
using StageTargetTp = StageRuntimeObject<P, S>;
@ -353,79 +319,76 @@ class StageConverter
static constexpr bool is_stage_constructible_v =
std::is_constructible<ToTp, StageConverter<P, S>&, FactoryCtx&, FromTp>::value;
template<typename OriginTp, typename ToTp, typename T, typename... Targs>
struct _next_type { using type = std::conditional_t<is_stage_constructible_v<ToTp, OriginTp>,
ToTp,
typename _next_type<OriginTp, T, Targs...>::type>; };
template<typename OriginTp, typename ToTp>
struct _next_type<OriginTp, ToTp, null_t> { using type = null_t; };
template<typename OriginTp, typename... AllTypes>
struct next_type { using type = null_t; };
template<typename OriginTp, typename... AllTypes>
template <typename OriginTp, typename ToTp, typename T, typename... Targs>
struct _next_type {
using type = std::conditional_t<is_stage_constructible_v<ToTp, OriginTp>, ToTp,
typename _next_type<OriginTp, T, Targs...>::type>;
};
template <typename OriginTp, typename ToTp>
struct _next_type<OriginTp, ToTp, null_t> {
using type = null_t;
};
template <typename OriginTp, typename... AllTypes>
struct next_type {
using type = null_t;
};
template <typename OriginTp, typename... AllTypes>
struct next_type<OriginTp, pack<AllTypes...>> : _next_type<OriginTp, AllTypes...> {};
template <typename OriginTp>
using next_type_t = typename next_type<OriginTp, StageTypes>::type;
/* StageSourceText derivative -> StageBinary */
template<class ToTp, class FromTp, class NextTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> &&
std::is_base_of_v<StageSourceText<P, S>, NextTp>, StageBinary<P, S>>
_DoDerivative(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp, class NextTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> && std::is_base_of_v<StageSourceText<P, S>, NextTp>,
StageBinary<P, S>>
_DoDerivative(FactoryCtx& ctx, const FromTp& in) {
return StageBinary<P, S>(*this, ctx, NextTp(*this, ctx, in));
}
/* StageBinary derivative -> StageBinary */
template<class ToTp, class FromTp, class NextTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> &&
std::is_base_of_v<StageBinary<P, S>, NextTp>, StageBinary<P, S>>
_DoDerivative(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp, class NextTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> && std::is_base_of_v<StageBinary<P, S>, NextTp>,
StageBinary<P, S>>
_DoDerivative(FactoryCtx& ctx, const FromTp& in) {
return NextTp(*this, ctx, in);
}
/* Non-StageSourceText derivative -> StageBinary */
template<class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> &&
!std::is_base_of_v<StageSourceText<P, S>, FromTp>, StageBinary<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> && !std::is_base_of_v<StageSourceText<P, S>, FromTp>,
StageBinary<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in) {
using NextTp = next_type_t<FromTp>;
static_assert(!std::is_same_v<NextTp, null_t>,
"Unable to resolve StageBinary or StageSourceText derivative");
static_assert(!std::is_same_v<NextTp, null_t>, "Unable to resolve StageBinary or StageSourceText derivative");
return _DoDerivative<ToTp, FromTp, NextTp>(ctx, in);
}
/* StageSourceText derivative -> StageBinary */
template<class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> &&
std::is_base_of_v<StageSourceText<P, S>, FromTp>, StageBinary<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageBinary<P, S>> && std::is_base_of_v<StageSourceText<P, S>, FromTp>,
StageBinary<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in) {
return StageBinary<P, S>(*this, ctx, in);
}
/* Non-StageBinary derivative -> StageRuntimeObject */
template<class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageRuntimeObject<P, S>> &&
!std::is_base_of_v<StageBinary<P, S>, FromTp>, StageRuntimeObject<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageRuntimeObject<P, S>> && !std::is_base_of_v<StageBinary<P, S>, FromTp>,
StageRuntimeObject<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in) {
return StageRuntimeObject<P, S>(*this, ctx, _Do<StageBinary<P, S>, FromTp>(ctx, in));
}
/* StageBinary derivative -> StageRuntimeObject */
template<class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageRuntimeObject<P, S>> &&
std::is_base_of_v<StageBinary<P, S>, FromTp>, StageRuntimeObject<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
std::enable_if_t<std::is_same_v<ToTp, StageRuntimeObject<P, S>> && std::is_base_of_v<StageBinary<P, S>, FromTp>,
StageRuntimeObject<P, S>>
_Do(FactoryCtx& ctx, const FromTp& in) {
return StageRuntimeObject<P, S>(*this, ctx, in);
}
template<class ToTp, class FromTp>
ToTp Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
ToTp Do(FactoryCtx& ctx, const FromTp& in) {
return _Do<ToTp, FromTp>(ctx, in);
}
@ -434,11 +397,9 @@ public:
void loadFromStream(FactoryCtx& ctx, ShaderCacheZipStream& r);
#endif
template<class FromTp>
StageTargetTp convert(FactoryCtx& ctx, const FromTp& in)
{
if (FromTp::HasHash)
{
template <class FromTp>
StageTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
if (FromTp::HasHash) {
uint64_t hash = in.Hash();
auto search = m_stageCache.find(hash);
if (search != m_stageCache.end())
@ -449,26 +410,26 @@ public:
}
};
class PipelineConverterBase
{
class PipelineConverterBase {
boo::IGraphicsDataFactory* m_gfxF;
boo::IGraphicsDataFactory::Platform m_platform;
protected:
PipelineConverterBase(boo::IGraphicsDataFactory* gfxF, boo::IGraphicsDataFactory::Platform platform)
: m_gfxF(gfxF), m_platform(platform) {}
public:
virtual ~PipelineConverterBase() = default;
#if HECL_RUNTIME
template<class FromTp>
template <class FromTp>
boo::ObjToken<boo::IShaderPipeline> convert(FactoryCtx& ctx, const FromTp& in);
template<class FromTp>
template <class FromTp>
boo::ObjToken<boo::IShaderPipeline> convert(const FromTp& in);
#endif
};
template<typename P>
class PipelineConverter : public PipelineConverterBase
{
template <typename P>
class PipelineConverter : public PipelineConverterBase {
#if HECL_RUNTIME
using PipelineTargetTp = FinalPipeline<P>;
#else
@ -487,58 +448,57 @@ class PipelineConverter : public PipelineConverterBase
static constexpr bool is_pipeline_constructible_v =
std::is_constructible<ToTp, PipelineConverter<P>&, FactoryCtx&, FromTp>::value;
template<typename FinalTp, typename OriginTp, typename... AllTypes>
template <typename FinalTp, typename OriginTp, typename... AllTypes>
struct is_eventually_constructible : std::false_type {};
template<typename FinalTp, typename OriginTp, typename ToTp, typename T, typename... Targs>
template <typename FinalTp, typename OriginTp, typename ToTp, typename T, typename... Targs>
struct _is_eventually_constructible
: std::conditional_t<is_pipeline_constructible_v<FinalTp, OriginTp>,
std::true_type,
: std::conditional_t<is_pipeline_constructible_v<FinalTp, OriginTp>, std::true_type,
std::conditional_t<is_pipeline_constructible_v<ToTp, OriginTp>,
is_eventually_constructible<FinalTp, ToTp, PipelineTypes>,
_is_eventually_constructible<FinalTp, OriginTp, T, Targs...>>> {};
template<typename FinalTp, typename OriginTp, typename ToTp>
template <typename FinalTp, typename OriginTp, typename ToTp>
struct _is_eventually_constructible<FinalTp, OriginTp, ToTp, null_t> : std::false_type {};
template<typename FinalTp, typename OriginTp, typename... AllTypes>
template <typename FinalTp, typename OriginTp, typename... AllTypes>
struct is_eventually_constructible<FinalTp, OriginTp, pack<AllTypes...>>
: _is_eventually_constructible<FinalTp, OriginTp, AllTypes...> {};
template <typename FinalTp, typename OriginTp>
static constexpr bool is_eventually_constructible_v =
is_eventually_constructible<FinalTp, OriginTp, PipelineTypes>::value;
template<typename FinalTp, typename OriginTp, typename ToTp, typename T, typename... Targs>
struct _next_type { using type = std::conditional_t<is_pipeline_constructible_v<FinalTp, ToTp> &&
is_eventually_constructible_v<ToTp, OriginTp>,
ToTp,
typename _next_type<FinalTp, OriginTp, T, Targs...>::type>; };
template<typename FinalTp, typename OriginTp, typename ToTp>
struct _next_type<FinalTp, OriginTp, ToTp, null_t> { using type = null_t; };
template<typename FinalTp, typename OriginTp, typename... AllTypes>
struct next_type { using type = null_t; };
template<typename FinalTp, typename OriginTp, typename... AllTypes>
template <typename FinalTp, typename OriginTp, typename ToTp, typename T, typename... Targs>
struct _next_type {
using type =
std::conditional_t<is_pipeline_constructible_v<FinalTp, ToTp> && is_eventually_constructible_v<ToTp, OriginTp>,
ToTp, typename _next_type<FinalTp, OriginTp, T, Targs...>::type>;
};
template <typename FinalTp, typename OriginTp, typename ToTp>
struct _next_type<FinalTp, OriginTp, ToTp, null_t> {
using type = null_t;
};
template <typename FinalTp, typename OriginTp, typename... AllTypes>
struct next_type {
using type = null_t;
};
template <typename FinalTp, typename OriginTp, typename... AllTypes>
struct next_type<FinalTp, OriginTp, pack<AllTypes...>> : _next_type<FinalTp, OriginTp, AllTypes...> {};
template <typename FinalTp, typename OriginTp>
using next_type_t = typename next_type<FinalTp, OriginTp, PipelineTypes>::type;
template<class ToTp, class FromTp>
std::enable_if_t<!is_pipeline_constructible_v<ToTp, FromTp>, ToTp>
_Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
std::enable_if_t<!is_pipeline_constructible_v<ToTp, FromTp>, ToTp> _Do(FactoryCtx& ctx, const FromTp& in) {
using NextTp = next_type_t<ToTp, FromTp>;
return ToTp(*this, ctx, _Do<NextTp, FromTp>(ctx, in));
}
template<class ToTp, class FromTp>
std::enable_if_t<is_pipeline_constructible_v<ToTp, FromTp>, ToTp>
_Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
std::enable_if_t<is_pipeline_constructible_v<ToTp, FromTp>, ToTp> _Do(FactoryCtx& ctx, const FromTp& in) {
return ToTp(*this, ctx, in);
}
template<class ToTp, class FromTp>
ToTp Do(FactoryCtx& ctx, const FromTp& in)
{
template <class ToTp, class FromTp>
ToTp Do(FactoryCtx& ctx, const FromTp& in) {
/* No idea why this fails; it works fine with manual template arguments (clang bug?) */
//static_assert(is_eventually_constructible_v<ToTp, FromTp>, "Unable to resolve pipeline conversion chain");
// static_assert(is_eventually_constructible_v<ToTp, FromTp>, "Unable to resolve pipeline conversion chain");
return _Do<ToTp, FromTp>(ctx, in);
}
@ -548,11 +508,9 @@ public:
bool loadFromFile(FactoryCtx& ctx, const hecl::SystemChar* path);
#endif
template<class FromTp>
PipelineTargetTp convert(FactoryCtx& ctx, const FromTp& in)
{
if (FromTp::HasHash)
{
template <class FromTp>
PipelineTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
if (FromTp::HasHash) {
uint64_t hash = in.Hash();
auto search = m_pipelineCache.find(hash);
if (search != m_pipelineCache.end())
@ -571,12 +529,10 @@ public:
#if HECL_RUNTIME
template<class FromTp>
inline boo::ObjToken<boo::IShaderPipeline> PipelineConverterBase::convert(FactoryCtx& ctx, const FromTp& in)
{
template <class FromTp>
inline boo::ObjToken<boo::IShaderPipeline> PipelineConverterBase::convert(FactoryCtx& ctx, const FromTp& in) {
assert(ctx.platform() == m_platform && "PipelineConverterBase platform mismatch");
switch (m_platform)
{
switch (m_platform) {
#if BOO_HAS_GL
case boo::IGraphicsDataFactory::Platform::OpenGL:
return static_cast<PipelineConverter<PlatformType::OpenGL>&>(*this).convert(ctx, in).pipeline();
@ -602,22 +558,18 @@ inline boo::ObjToken<boo::IShaderPipeline> PipelineConverterBase::convert(Factor
}
}
template<class FromTp>
inline boo::ObjToken<boo::IShaderPipeline> PipelineConverterBase::convert(const FromTp& in)
{
template <class FromTp>
inline boo::ObjToken<boo::IShaderPipeline> PipelineConverterBase::convert(const FromTp& in) {
boo::ObjToken<boo::IShaderPipeline> ret;
m_gfxF->commitTransaction([this, &ret, &in](boo::IGraphicsDataFactory::Context& ctx)
{
m_gfxF->commitTransaction([this, &ret, &in](boo::IGraphicsDataFactory::Context& ctx) {
ret = convert(ctx, in);
return true;
} BooTrace);
return ret;
}
inline std::unique_ptr<PipelineConverterBase> NewPipelineConverter(boo::IGraphicsDataFactory* gfxF)
{
switch (gfxF->platform())
{
inline std::unique_ptr<PipelineConverterBase> NewPipelineConverter(boo::IGraphicsDataFactory* gfxF) {
switch (gfxF->platform()) {
#if BOO_HAS_GL
case boo::IGraphicsDataFactory::Platform::OpenGL:
return std::make_unique<PipelineConverter<PlatformType::OpenGL>>(gfxF);
@ -648,4 +600,4 @@ extern PipelineConverterBase* conv;
#endif
}
} // namespace hecl

View File

@ -1,33 +1,26 @@
#pragma once
#include "Compilers.hpp"
extern "C" unsigned long long XXH64 (const void* input, size_t length, unsigned long long seed);
extern "C" unsigned long long XXH64(const void* input, size_t length, unsigned long long seed);
#define HECL_RUNTIME 1
namespace hecl
{
namespace hecl {
using AdditionalPipelineInfo = boo::AdditionalPipelineInfo;
enum class StageTargetType
{
SourceText,
Binary,
Runtime
};
enum class StageTargetType { SourceText, Binary, Runtime };
enum class PipelineTargetType
{
enum class PipelineTargetType {
StageSourceTextCollection,
StageBinaryCollection,
StageRuntimeCollection,
FinalPipeline
};
template<typename P, typename S>
template <typename P, typename S>
class StageConverter;
template<typename P>
template <typename P>
class PipelineConverter;
#if HECL_RUNTIME
@ -36,17 +29,15 @@ using FactoryCtx = boo::IGraphicsDataFactory::Context;
struct FactoryCtx {};
#endif
template<typename P, typename S>
class StageRep
{
template <typename P, typename S>
class StageRep {
public:
using Platform = P;
using Stage = S;
};
template<typename P>
class PipelineRep
{
template <typename P>
class PipelineRep {
public:
using Platform = P;
};
@ -54,59 +45,55 @@ public:
class GeneralShader : public hecl::PipelineRep<hecl::PlatformType::Null> {};
class TessellationShader : public hecl::PipelineRep<hecl::PlatformType::Null> {};
template<typename P, typename S>
class StageSourceText : public StageRep<P, S>
{
template <typename P, typename S>
class StageSourceText : public StageRep<P, S> {
std::string_view m_text;
uint64_t m_hash;
public:
static constexpr StageTargetType TargetType = StageTargetType::SourceText;
static constexpr PipelineTargetType PipelineTarget = PipelineTargetType::StageSourceTextCollection;
static constexpr bool HasHash = true;
uint64_t Hash() const { return m_hash; }
explicit StageSourceText(std::string_view text)
: m_text(text), m_hash(XXH64(m_text.data(), m_text.size(), 0)) {}
explicit StageSourceText(std::string_view text) : m_text(text), m_hash(XXH64(m_text.data(), m_text.size(), 0)) {}
std::string_view text() const { return m_text; }
};
template<typename P, typename S>
class StageBinary : public StageRep<P, S>
{
template <typename P, typename S>
class StageBinary : public StageRep<P, S> {
StageBinaryData m_ownedData;
const uint8_t* m_data = nullptr;
size_t m_size = 0;
uint64_t m_hash = 0;
public:
static constexpr StageTargetType TargetType = StageTargetType::Binary;
static constexpr PipelineTargetType PipelineTarget = PipelineTargetType::StageBinaryCollection;
static constexpr bool HasHash = true;
uint64_t Hash() const { return m_hash; }
StageBinary(const uint8_t* data, size_t size)
: m_data(data), m_size(size)
{ m_hash = XXH64(m_data, m_size, 0); }
StageBinary(const uint8_t* data, size_t size) : m_data(data), m_size(size) { m_hash = XXH64(m_data, m_size, 0); }
StageBinary(StageBinaryData data, size_t size)
: m_ownedData(std::move(data)),
m_data(m_ownedData.get()), m_size(size)
{ m_hash = XXH64(m_data, m_size, 0); }
explicit StageBinary(std::pair<StageBinaryData, size_t> data)
: StageBinary(data.first, data.second) {}
: m_ownedData(std::move(data)), m_data(m_ownedData.get()), m_size(size) {
m_hash = XXH64(m_data, m_size, 0);
}
explicit StageBinary(std::pair<StageBinaryData, size_t> data) : StageBinary(data.first, data.second) {}
StageBinary(StageConverter<P, S>& conv, FactoryCtx& ctx, const StageSourceText<P, S>& in)
: StageBinary(CompileShader<P, S>(in.text())) {}
const uint8_t* data() const { return m_data; }
size_t size() const { return m_size; }
};
template<typename P>
template <typename P>
class FinalPipeline;
template<typename P>
template <typename P>
class HECLBackend;
template <class T>
using __IsStageSubclass = typename std::disjunction<
std::is_base_of<StageRep<typename T::Platform, PipelineStage::Vertex>, T>,
using __IsStageSubclass =
typename std::disjunction<std::is_base_of<StageRep<typename T::Platform, PipelineStage::Vertex>, T>,
std::is_base_of<StageRep<typename T::Platform, PipelineStage::Fragment>, T>,
std::is_base_of<StageRep<typename T::Platform, PipelineStage::Geometry>, T>,
std::is_base_of<StageRep<typename T::Platform, PipelineStage::Control>, T>,
@ -114,10 +101,10 @@ using __IsStageSubclass = typename std::disjunction<
template <class T>
inline constexpr bool __IsStageSubclass_v = __IsStageSubclass<T>::value;
template<typename T> class StageCollection;
template<template<typename, typename> class T, typename P, typename... Rest>
class StageCollection<T<P, Rest...>> : public PipelineRep<P>
{
template <typename T>
class StageCollection;
template <template <typename, typename> class T, typename P, typename... Rest>
class StageCollection<T<P, Rest...>> : public PipelineRep<P> {
using base = PipelineRep<P>;
friend class FinalPipeline<P>;
static_assert(__IsStageSubclass_v<T<P, PipelineStage::Vertex>>,
@ -131,16 +118,18 @@ class StageCollection<T<P, Rest...>> : public PipelineRep<P>
std::vector<boo::VertexElementDescriptor> m_vtxFmtData;
boo::VertexFormatInfo m_vtxFmt;
uint64_t m_hash;
public:
static constexpr PipelineTargetType TargetType = T<P, PipelineStage::Vertex>::PipelineTarget;
static constexpr bool HasHash = T<P, PipelineStage::Vertex>::HasHash;
template<typename U = StageCollection<T<P, Rest...>>>
std::enable_if_t<U::HasHash, uint64_t> Hash() const { return m_hash; }
template<typename U = StageCollection<T<P, Rest...>>>
template <typename U = StageCollection<T<P, Rest...>>>
std::enable_if_t<U::HasHash, uint64_t> Hash() const {
return m_hash;
}
template <typename U = StageCollection<T<P, Rest...>>>
void MakeHash(std::enable_if_t<!U::HasHash>* = 0) {}
template<typename U = StageCollection<T<P, Rest...>>>
void MakeHash(std::enable_if_t<U::HasHash>* = 0)
{
template <typename U = StageCollection<T<P, Rest...>>>
void MakeHash(std::enable_if_t<U::HasHash>* = 0) {
m_hash = 0;
m_hash ^= m_vertex.Hash();
m_hash ^= m_fragment.Hash();
@ -150,26 +139,23 @@ public:
m_hash ^= XXH64(&m_additionalInfo, sizeof(m_additionalInfo), 0);
}
StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const HECLBackend<P>& in);
template<typename I>
template <typename I>
StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const I& in,
typename std::enable_if_t<std::is_base_of_v<GeneralShader, I>>* = 0)
{
typename std::enable_if_t<std::is_base_of_v<GeneralShader, I>>* = 0) {
m_vertex = conv.getVertexConverter().convert(ctx, in);
m_fragment = conv.getFragmentConverter().convert(ctx, in);
m_vtxFmt = in.VtxFmt;
m_additionalInfo = in.PipelineInfo;
MakeHash();
}
template<typename I>
StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const I& in,
typename std::enable_if_t<std::conjunction_v<
std::is_base_of<TessellationShader, I>,
std::negation<std::is_same<P, PlatformType::Metal>>>>* = 0)
{
template <typename I>
StageCollection(
PipelineConverter<P>& conv, FactoryCtx& ctx, const I& in,
typename std::enable_if_t<std::conjunction_v<std::is_base_of<TessellationShader, I>,
std::negation<std::is_same<P, PlatformType::Metal>>>>* = 0) {
m_vertex = conv.getVertexConverter().convert(ctx, in);
m_fragment = conv.getFragmentConverter().convert(ctx, in);
if (in.HasTessellation)
{
if (in.HasTessellation) {
m_control = conv.getControlConverter().convert(ctx, in);
m_evaluation = conv.getEvaluationConverter().convert(ctx, in);
}
@ -177,19 +163,14 @@ public:
m_additionalInfo = in.PipelineInfo;
MakeHash();
}
template<typename I>
template <typename I>
StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const I& in,
typename std::enable_if_t<std::conjunction_v<
std::is_base_of<TessellationShader, I>,
std::is_same<P, PlatformType::Metal>>>* = 0)
{
if (in.HasTessellation)
{
typename std::enable_if_t<std::conjunction_v<std::is_base_of<TessellationShader, I>,
std::is_same<P, PlatformType::Metal>>>* = 0) {
if (in.HasTessellation) {
m_control = conv.getControlConverter().convert(ctx, in);
m_evaluation = conv.getEvaluationConverter().convert(ctx, in);
}
else
{
} else {
m_vertex = conv.getVertexConverter().convert(ctx, in);
}
m_fragment = conv.getFragmentConverter().convert(ctx, in);
@ -197,39 +178,40 @@ public:
m_additionalInfo = in.PipelineInfo;
MakeHash();
}
StageCollection(const T<P, PipelineStage::Vertex>& vertex,
const T<P, PipelineStage::Fragment>& fragment,
const T<P, PipelineStage::Geometry>& geometry,
const T<P, PipelineStage::Control>& control,
const T<P, PipelineStage::Evaluation>& evaluation,
const AdditionalPipelineInfo& info,
StageCollection(const T<P, PipelineStage::Vertex>& vertex, const T<P, PipelineStage::Fragment>& fragment,
const T<P, PipelineStage::Geometry>& geometry, const T<P, PipelineStage::Control>& control,
const T<P, PipelineStage::Evaluation>& evaluation, const AdditionalPipelineInfo& info,
const boo::VertexFormatInfo& vtxFmt)
: m_vertex(vertex), m_fragment(fragment), m_geometry(geometry),
m_control(control), m_evaluation(evaluation), m_additionalInfo(info),
m_vtxFmt(vtxFmt) {}
: m_vertex(vertex)
, m_fragment(fragment)
, m_geometry(geometry)
, m_control(control)
, m_evaluation(evaluation)
, m_additionalInfo(info)
, m_vtxFmt(vtxFmt) {}
};
}
} // namespace hecl
#ifndef _WIN32
#define _STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, P) \
template <> const hecl::StageBinary<P, hecl::PipelineStage::Vertex> \
T<P, hecl::PipelineStage::Vertex>::Prototype; \
template <> const hecl::StageBinary<P, hecl::PipelineStage::Fragment> \
T<P, hecl::PipelineStage::Fragment>::Prototype; \
template <> const hecl::StageBinary<P, hecl::PipelineStage::Geometry> \
T<P, hecl::PipelineStage::Geometry>::Prototype; \
template <> const hecl::StageBinary<P, hecl::PipelineStage::Control> \
T<P, hecl::PipelineStage::Control>::Prototype; \
template <> const hecl::StageBinary<P, hecl::PipelineStage::Evaluation> \
T<P, hecl::PipelineStage::Evaluation>::Prototype;
template <> \
const hecl::StageBinary<P, hecl::PipelineStage::Vertex> T<P, hecl::PipelineStage::Vertex>::Prototype; \
template <> \
const hecl::StageBinary<P, hecl::PipelineStage::Fragment> T<P, hecl::PipelineStage::Fragment>::Prototype; \
template <> \
const hecl::StageBinary<P, hecl::PipelineStage::Geometry> T<P, hecl::PipelineStage::Geometry>::Prototype; \
template <> \
const hecl::StageBinary<P, hecl::PipelineStage::Control> T<P, hecl::PipelineStage::Control>::Prototype; \
template <> \
const hecl::StageBinary<P, hecl::PipelineStage::Evaluation> T<P, hecl::PipelineStage::Evaluation>::Prototype;
#else
#define _STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, P)
#endif
#define STAGEOBJECT_PROTOTYPE_DECLARATIONS(T) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::OpenGL) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::Vulkan) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::D3D11) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::Metal) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::NX)
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::OpenGL) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::Vulkan) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::D3D11) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::Metal) \
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::NX)

View File

@ -4,54 +4,49 @@
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
#include <unordered_map>
namespace hecl
{
namespace hecl {
struct HMDLMeta;
namespace Runtime
{
namespace Runtime {
/**
* @brief Per-platform file store resolution
*/
class FileStoreManager
{
class FileStoreManager {
SystemString m_domain;
SystemString m_storeRoot;
public:
FileStoreManager(SystemStringView domain);
SystemStringView getDomain() const {return m_domain;}
SystemStringView getDomain() const { return m_domain; }
/**
* @brief Returns the full path to the file store, including domain
* @return Full path to store e.g /home/foo/.hecl/bar
*/
SystemStringView getStoreRoot() const {return m_storeRoot;}
SystemStringView getStoreRoot() const { return m_storeRoot; }
};
/**
* @brief Integrated reader/constructor/container for HMDL data
*/
struct HMDLData
{
struct HMDLData {
boo::ObjToken<boo::IGraphicsBufferS> m_vbo;
boo::ObjToken<boo::IGraphicsBufferS> m_ibo;
std::unique_ptr<boo::VertexElementDescriptor[]> m_vtxFmtData;
boo::VertexFormatInfo m_vtxFmt;
HMDLData(boo::IGraphicsDataFactory::Context& ctx,
const void* metaData, const void* vbo, const void* ibo);
HMDLData(boo::IGraphicsDataFactory::Context& ctx, const void* metaData, const void* vbo, const void* ibo);
boo::ObjToken<boo::IShaderDataBinding>
newShaderDataBindng(boo::IGraphicsDataFactory::Context& ctx,
boo::ObjToken<boo::IShaderDataBinding> newShaderDataBindng(boo::IGraphicsDataFactory::Context& ctx,
const boo::ObjToken<boo::IShaderPipeline>& shader,
size_t ubufCount, const boo::ObjToken<boo::IGraphicsBuffer>* ubufs,
const boo::PipelineStage* ubufStages,
size_t texCount, const boo::ObjToken<boo::ITexture>* texs)
{return ctx.newShaderDataBinding(shader, m_vbo.get(), nullptr, m_ibo.get(),
ubufCount, ubufs, ubufStages, nullptr, nullptr,
texCount, texs, nullptr, nullptr);}
size_t ubufCount,
const boo::ObjToken<boo::IGraphicsBuffer>* ubufs,
const boo::PipelineStage* ubufStages, size_t texCount,
const boo::ObjToken<boo::ITexture>* texs) {
return ctx.newShaderDataBinding(shader, m_vbo.get(), nullptr, m_ibo.get(), ubufCount, ubufs, ubufStages, nullptr,
nullptr, texCount, texs, nullptr, nullptr);
}
};
}
}
} // namespace Runtime
} // namespace hecl

View File

@ -2,11 +2,8 @@
#include "hecl/SystemChar.hpp"
namespace hecl
{
namespace hecl {
hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name);
}

View File

@ -18,8 +18,7 @@
#include <cstring>
#include <algorithm>
namespace hecl
{
namespace hecl {
#if _WIN32 && UNICODE
#define HECL_UCS2 1
@ -27,15 +26,13 @@ namespace hecl
#if HECL_UCS2
typedef wchar_t SystemChar;
static inline size_t StrLen(const SystemChar* str) {return wcslen(str);}
static inline size_t StrLen(const SystemChar* str) { return wcslen(str); }
typedef std::wstring SystemString;
typedef std::wstring_view SystemStringView;
static inline void ToLower(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), towlower);}
static inline void ToUpper(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), towupper);}
static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towlower); }
static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), towupper); }
#ifndef _SYS_STR
#define _SYS_STR(val) L ## val
#define _SYS_STR(val) L##val
#endif
#ifndef FMT_CSTR_SYS
#define FMT_CSTR_SYS "S"
@ -43,13 +40,11 @@ static inline void ToUpper(SystemString& str)
typedef struct _stat Sstat;
#else
typedef char SystemChar;
static inline size_t StrLen(const SystemChar* str) {return strlen(str);}
static inline size_t StrLen(const SystemChar* str) { return strlen(str); }
typedef std::string SystemString;
typedef std::string_view SystemStringView;
static inline void ToLower(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), tolower);}
static inline void ToUpper(SystemString& str)
{std::transform(str.begin(), str.end(), str.begin(), toupper);}
static inline void ToLower(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), tolower); }
static inline void ToUpper(SystemString& str) { std::transform(str.begin(), str.end(), str.begin(), toupper); }
#ifndef _SYS_STR
#define _SYS_STR(val) val
#endif
@ -59,5 +54,4 @@ static inline void ToUpper(SystemString& str)
typedef struct stat Sstat;
#endif
}
} // namespace hecl

View File

@ -6,8 +6,7 @@
#include <atomic>
#include "BitVector.hpp"
namespace hecl
{
namespace hecl {
#define HECL_UBUFPOOL_ALLOCATION_BLOCK 262144
@ -18,8 +17,7 @@ namespace hecl
* widgets. These can potentially have numerous binding instances, so this avoids
* allocating a full GPU buffer object for each. */
template <typename UniformStruct>
class UniformBufferPool
{
class UniformBufferPool {
public:
/* Resolve div_t type using ssize_t as basis */
#if _WIN32
@ -29,7 +27,8 @@ public:
#endif
private:
struct InvalidTp {};
using DivTp = std::conditional_t<std::is_same<IndexTp, long long>::value, std::lldiv_t,
using DivTp = std::conditional_t<
std::is_same<IndexTp, long long>::value, std::lldiv_t,
std::conditional_t<std::is_same<IndexTp, long>::value, std::ldiv_t,
std::conditional_t<std::is_same<IndexTp, int>::value, std::div_t, InvalidTp>>>;
static_assert(!std::is_same<DivTp, InvalidTp>::value, "unsupported IndexTp for DivTp resolution");
@ -54,8 +53,7 @@ private:
boo::IGraphicsDataFactory* m_factory = nullptr;
/** Private bucket info */
struct Bucket
{
struct Bucket {
boo::ObjToken<boo::IGraphicsBufferD> buffer;
uint8_t* cpuBuffer = nullptr;
std::atomic_size_t useCount = {};
@ -66,29 +64,22 @@ private:
Bucket(Bucket&& other) = default;
Bucket& operator=(Bucket&& other) = default;
void updateBuffer()
{
if (cpuBuffer)
{
void updateBuffer() {
if (cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
dirty = false;
}
void increment(UniformBufferPool& pool)
{
void increment(UniformBufferPool& pool) {
if (useCount.fetch_add(1) == 0)
buffer = pool.m_factory->newPoolBuffer(boo::BufferUse::Uniform,
pool.m_stride, pool.m_countPerBucket BooTrace);
buffer = pool.m_factory->newPoolBuffer(boo::BufferUse::Uniform, pool.m_stride, pool.m_countPerBucket BooTrace);
}
void decrement(UniformBufferPool& pool)
{
if (useCount.fetch_sub(1) == 1)
{
if (cpuBuffer)
{
void decrement(UniformBufferPool& pool) {
if (useCount.fetch_sub(1) == 1) {
if (cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
@ -100,25 +91,19 @@ private:
public:
/** User block-owning token */
class Token
{
class Token {
friend class UniformBufferPool;
UniformBufferPool* m_pool = nullptr;
IndexTp m_index = -1;
DivTp m_div;
Token(UniformBufferPool* pool)
: m_pool(pool)
{
Token(UniformBufferPool* pool) : m_pool(pool) {
auto& freeSpaces = pool->m_freeBlocks;
int idx = freeSpaces.find_first();
if (idx == -1)
{
if (idx == -1) {
pool->m_buckets.push_back(std::make_unique<Bucket>());
m_index = freeSpaces.size();
freeSpaces.resize(freeSpaces.size() + pool->m_countPerBucket, true);
}
else
{
} else {
m_index = idx;
}
freeSpaces.reset(m_index);
@ -132,33 +117,24 @@ public:
Token() = default;
Token(const Token& other) = delete;
Token& operator=(const Token& other) = delete;
Token& operator=(Token&& other)
{
Token& operator=(Token&& other) {
m_pool = other.m_pool;
m_index = other.m_index;
m_div = other.m_div;
other.m_index = -1;
return *this;
}
Token(Token&& other)
: m_pool(other.m_pool), m_index(other.m_index),
m_div(other.m_div)
{
other.m_index = -1;
}
Token(Token&& other) : m_pool(other.m_pool), m_index(other.m_index), m_div(other.m_div) { other.m_index = -1; }
~Token()
{
if (m_index != -1)
{
~Token() {
if (m_index != -1) {
m_pool->m_freeBlocks.set(m_index);
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
bucket.decrement(*m_pool);
}
}
UniformStruct& access()
{
UniformStruct& access() {
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
if (!bucket.cpuBuffer)
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
@ -166,8 +142,7 @@ public:
return reinterpret_cast<UniformStruct&>(bucket.cpuBuffer[m_div.rem * m_pool->m_stride]);
}
std::pair<boo::ObjToken<boo::IGraphicsBufferD>, IndexTp> getBufferInfo() const
{
std::pair<boo::ObjToken<boo::IGraphicsBufferD>, IndexTp> getBufferInfo() const {
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
return {bucket.buffer, m_div.rem * m_pool->m_stride};
}
@ -180,26 +155,22 @@ public:
UniformBufferPool& operator=(const UniformBufferPool& other) = delete;
/** Load dirty buffer data into GPU */
void updateBuffers()
{
void updateBuffers() {
for (auto& bucket : m_buckets)
if (bucket->dirty)
bucket->updateBuffer();
}
/** Allocate free block into client-owned Token */
Token allocateBlock(boo::IGraphicsDataFactory* factory)
{
Token allocateBlock(boo::IGraphicsDataFactory* factory) {
m_factory = factory;
return Token(this);
}
void doDestroy()
{
void doDestroy() {
for (auto& bucket : m_buckets)
bucket->buffer.reset();
}
};
}
} // namespace hecl

View File

@ -6,8 +6,7 @@
#include <atomic>
#include "BitVector.hpp"
namespace hecl
{
namespace hecl {
#define HECL_VBUFPOOL_ALLOCATION_BLOCK 262144
@ -18,8 +17,7 @@ namespace hecl
* widgets. These can potentially have numerous binding instances, so this avoids
* allocating a full GPU buffer object for each. */
template <typename VertStruct>
class VertexBufferPool
{
class VertexBufferPool {
public:
/* Resolve div_t type using ssize_t as basis */
#if _WIN32
@ -29,7 +27,8 @@ public:
#endif
private:
struct InvalidTp {};
using DivTp = std::conditional_t<std::is_same<IndexTp, long long>::value, std::lldiv_t,
using DivTp = std::conditional_t<
std::is_same<IndexTp, long long>::value, std::lldiv_t,
std::conditional_t<std::is_same<IndexTp, long>::value, std::ldiv_t,
std::conditional_t<std::is_same<IndexTp, int>::value, std::div_t, InvalidTp>>>;
static_assert(!std::is_same<DivTp, InvalidTp>::value, "unsupported IndexTp for DivTp resolution");
@ -54,8 +53,7 @@ private:
boo::IGraphicsDataFactory* m_factory = nullptr;
/** Private bucket info */
struct Bucket
{
struct Bucket {
boo::ObjToken<boo::IGraphicsBufferD> buffer;
uint8_t* cpuBuffer = nullptr;
std::atomic_size_t useCount = {};
@ -66,29 +64,22 @@ private:
Bucket(Bucket&& other) = delete;
Bucket& operator=(Bucket&& other) = delete;
void updateBuffer()
{
if (cpuBuffer)
{
void updateBuffer() {
if (cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
dirty = false;
}
void increment(VertexBufferPool& pool)
{
void increment(VertexBufferPool& pool) {
if (useCount.fetch_add(1) == 0)
buffer = pool.m_factory->newPoolBuffer(boo::BufferUse::Vertex,
pool.m_stride, pool.m_countPerBucket BooTrace);
buffer = pool.m_factory->newPoolBuffer(boo::BufferUse::Vertex, pool.m_stride, pool.m_countPerBucket BooTrace);
}
void decrement(VertexBufferPool& pool)
{
if (useCount.fetch_sub(1) == 1)
{
if (cpuBuffer)
{
void decrement(VertexBufferPool& pool) {
if (useCount.fetch_sub(1) == 1) {
if (cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
@ -100,27 +91,21 @@ private:
public:
/** User element-owning token */
class Token
{
class Token {
friend class VertexBufferPool;
VertexBufferPool* m_pool = nullptr;
IndexTp m_index = -1;
IndexTp m_count = 0;
DivTp m_div;
Token(VertexBufferPool* pool, IndexTp count)
: m_pool(pool), m_count(count)
{
Token(VertexBufferPool* pool, IndexTp count) : m_pool(pool), m_count(count) {
assert(count <= pool->m_countPerBucket && "unable to fit in bucket");
auto& freeSpaces = pool->m_freeElements;
int idx = freeSpaces.find_first_contiguous(count, pool->m_countPerBucket);
if (idx == -1)
{
if (idx == -1) {
pool->m_buckets.push_back(std::make_unique<Bucket>());
m_index = freeSpaces.size();
freeSpaces.resize(freeSpaces.size() + pool->m_countPerBucket, true);
}
else
{
} else {
m_index = idx;
}
freeSpaces.reset(m_index, m_index + count);
@ -129,12 +114,12 @@ public:
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
bucket.increment(*pool);
}
public:
Token() = default;
Token(const Token& other) = delete;
Token& operator=(const Token& other) = delete;
Token& operator=(Token&& other)
{
Token& operator=(Token&& other) {
m_pool = other.m_pool;
m_index = other.m_index;
m_count = other.m_count;
@ -142,25 +127,19 @@ public:
other.m_index = -1;
return *this;
}
Token(Token&& other)
: m_pool(other.m_pool), m_index(other.m_index),
m_count(other.m_count), m_div(other.m_div)
{
Token(Token&& other) : m_pool(other.m_pool), m_index(other.m_index), m_count(other.m_count), m_div(other.m_div) {
other.m_index = -1;
}
~Token()
{
if (m_index != -1)
{
~Token() {
if (m_index != -1) {
m_pool->m_freeElements.set(m_index, m_index + m_count);
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
bucket.decrement(*m_pool);
}
}
VertStruct* access()
{
VertStruct* access() {
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
if (!bucket.cpuBuffer)
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
@ -168,8 +147,7 @@ public:
return reinterpret_cast<VertStruct*>(&bucket.cpuBuffer[m_div.rem * m_pool->m_stride]);
}
std::pair<boo::ObjToken<boo::IGraphicsBufferD>, IndexTp> getBufferInfo() const
{
std::pair<boo::ObjToken<boo::IGraphicsBufferD>, IndexTp> getBufferInfo() const {
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
return {bucket.buffer, m_div.rem};
}
@ -182,22 +160,19 @@ public:
VertexBufferPool& operator=(const VertexBufferPool& other) = delete;
/** Load dirty buffer data into GPU */
void updateBuffers()
{
void updateBuffers() {
for (auto& bucket : m_buckets)
if (bucket->dirty)
bucket->updateBuffer();
}
/** Allocate free block into client-owned Token */
Token allocateBlock(boo::IGraphicsDataFactory* factory, IndexTp count)
{
Token allocateBlock(boo::IGraphicsDataFactory* factory, IndexTp count) {
m_factory = factory;
return Token(this, count);
}
void doDestroy()
{
void doDestroy() {
for (auto& bucket : m_buckets)
bucket->buffer.reset();
}
@ -205,5 +180,4 @@ public:
static constexpr IndexTp bucketCapacity() { return m_countPerBucket; }
};
}
} // namespace hecl

File diff suppressed because it is too large Load Diff

View File

@ -8,6 +8,5 @@
#endif
#include "windows.h"
void* memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen);
void* memmem(const void* haystack, size_t hlen, const void* needle, size_t nlen);
int asprintf(char** buf, const char* format, ...);

View File

@ -6,68 +6,60 @@
static logvisor::Module Log("hecl::Backend::GLSL");
namespace hecl::Backend
{
namespace hecl::Backend {
std::string GLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const
{
switch (src)
{
std::string GLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const {
switch (src) {
case TexGenSrc::Position:
return "objPos.xy";
case TexGenSrc::Normal:
return "objNorm.xy";
case TexGenSrc::UV:
return hecl::Format("uvIn[%u]", uvIdx);
default: break;
default:
break;
}
return std::string();
}
std::string GLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const
{
switch (src)
{
std::string GLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const {
switch (src) {
case TexGenSrc::Position:
return "vec4(objPos.xyz, 1.0)";
case TexGenSrc::Normal:
return "vec4(objNorm.xyz, 1.0)";
case TexGenSrc::UV:
return hecl::Format("vec4(uvIn[%u], 0.0, 1.0)", uvIdx);
default: break;
default:
break;
}
return std::string();
}
std::string GLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const
{
std::string GLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const {
std::string retval =
"layout(location=0) in vec3 posIn;\n"
"layout(location=1) in vec3 normIn;\n";
unsigned idx = 2;
if (col)
{
if (col) {
retval += hecl::Format("layout(location=%u) in vec4 colIn[%u];\n", idx, col);
idx += col;
}
if (uv)
{
if (uv) {
retval += hecl::Format("layout(location=%u) in vec2 uvIn[%u];\n", idx, uv);
idx += uv;
}
if (w)
{
if (w) {
retval += hecl::Format("layout(location=%u) in vec4 weightIn[%u];\n", idx, w);
}
return retval;
}
std::string GLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const
{
std::string GLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const {
std::string retval =
"struct VertToFrag\n"
"{\n"
@ -80,27 +72,26 @@ std::string GLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCo
retval += hecl::Format(" vec2 extTcgs[%u];\n", unsigned(extTexCount));
if (reflectionCoords)
retval += " vec2 reflectTcgs[2];\n"
retval +=
" vec2 reflectTcgs[2];\n"
" float reflectAlpha;\n";
return retval + "};\n";
}
std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const
{
std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const {
std::string retval;
if (skinSlots == 0)
{
retval = "UBINDING0 uniform HECLVertUniform\n"
if (skinSlots == 0) {
retval =
"UBINDING0 uniform HECLVertUniform\n"
"{\n"
" mat4 mv;\n"
" mat4 mvInv;\n"
" mat4 proj;\n"
"};\n";
}
else
{
retval = hecl::Format("UBINDING0 uniform HECLVertUniform\n"
} else {
retval = hecl::Format(
"UBINDING0 uniform HECLVertUniform\n"
"{\n"
" mat4 objs[%u];\n"
" mat4 objsInv[%u];\n"
@ -111,7 +102,8 @@ std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionC
skinSlots, skinSlots);
}
retval += "struct HECLTCGMatrix\n"
retval +=
"struct HECLTCGMatrix\n"
"{\n"
" mat4 mtx;\n"
" mat4 postMtx;\n"
@ -122,7 +114,8 @@ std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionC
"};\n";
if (reflectionCoords)
retval += "UBINDING3 uniform HECLReflectMtx\n"
retval +=
"UBINDING3 uniform HECLReflectMtx\n"
"{\n"
" mat4 indMtx;\n"
" mat4 reflectMtx;\n"
@ -133,18 +126,15 @@ std::string GLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionC
return retval;
}
std::string GLSL::GenerateAlphaTest() const
{
std::string GLSL::GenerateAlphaTest() const {
return " if (colorOut.a < 0.01)\n"
" {\n"
" discard;\n"
" }\n";
}
std::string GLSL::GenerateReflectionExpr(ReflectionType type) const
{
switch (type)
{
std::string GLSL::GenerateReflectionExpr(ReflectionType type) const {
switch (type) {
case ReflectionType::None:
default:
return "vec3(0.0, 0.0, 0.0)";
@ -156,43 +146,41 @@ std::string GLSL::GenerateReflectionExpr(ReflectionType type) const
}
}
void GLSL::reset(const IR& ir, Diagnostics& diag)
{
void GLSL::reset(const IR& ir, Diagnostics& diag) {
/* Common programmable interpretation */
ProgrammableCommon::reset(ir, diag, "GLSL");
}
std::string GLSL::makeVert(unsigned col, unsigned uv, unsigned w,
unsigned s, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const
{
std::string GLSL::makeVert(unsigned col, unsigned uv, unsigned w, unsigned s, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const {
extTexCount = std::min(int(extTexCount), BOO_GLSL_MAX_TEXTURE_COUNT - int(m_tcgs.size()));
std::string retval =
GenerateVertInStruct(col, uv, w) + "\n" +
std::string retval = GenerateVertInStruct(col, uv, w) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateVertUniformStruct(s, reflectionType != ReflectionType::None) +
"SBINDING(0) out VertToFrag vtf;\n\n"
"void main()\n{\n";
if (s)
{
if (s) {
/* skinned */
retval += " vec4 objPos = vec4(0.0,0.0,0.0,0.0);\n"
retval +=
" vec4 objPos = vec4(0.0,0.0,0.0,0.0);\n"
" vec4 objNorm = vec4(0.0,0.0,0.0,0.0);\n";
for (size_t i=0 ; i<s ; ++i)
retval += hecl::Format(" objPos += (objs[%" PRISize "] * vec4(posIn, 1.0)) * weightIn[%" PRISize "][%" PRISize "];\n"
" objNorm += (objsInv[%" PRISize "] * vec4(normIn, 1.0)) * weightIn[%" PRISize "][%" PRISize "];\n",
i, i/4, i%4, i, i/4, i%4);
retval += " objPos[3] = 1.0;\n"
for (size_t i = 0; i < s; ++i)
retval += hecl::Format(" objPos += (objs[%" PRISize "] * vec4(posIn, 1.0)) * weightIn[%" PRISize "][%" PRISize
"];\n"
" objNorm += (objsInv[%" PRISize "] * vec4(normIn, 1.0)) * weightIn[%" PRISize
"][%" PRISize "];\n",
i, i / 4, i % 4, i, i / 4, i % 4);
retval +=
" objPos[3] = 1.0;\n"
" objNorm = vec4(normalize(objNorm.xyz), 0.0);\n"
" vtf.mvPos = mv * objPos;\n"
" vtf.mvNorm = vec4(normalize((mvInv * objNorm).xyz), 0.0);\n"
" gl_Position = proj * vtf.mvPos;\n";
}
else
{
} else {
/* non-skinned */
retval += " vec4 objPos = vec4(posIn, 1.0);\n"
retval +=
" vec4 objPos = vec4(posIn, 1.0);\n"
" vec4 objNorm = vec4(normIn, 0.0);\n"
" vtf.mvPos = mv * objPos;\n"
" vtf.mvNorm = mvInv * objNorm;\n"
@ -202,94 +190,86 @@ std::string GLSL::makeVert(unsigned col, unsigned uv, unsigned w,
retval += " vec4 tmpProj;\n";
int tcgIdx = 0;
for (const TexCoordGen& tcg : m_tcgs)
{
for (const TexCoordGen& tcg : m_tcgs) {
if (tcg.m_mtx < 0)
retval += hecl::Format(" vtf.tcgs[%u] = %s;\n", tcgIdx,
EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str());
retval += hecl::Format(" vtf.tcgs[%u] = %s;\n", tcgIdx, EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str());
else
retval += hecl::Format(" tmpProj = texMtxs[%u].postMtx * vec4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
retval += hecl::Format(
" tmpProj = texMtxs[%u].postMtx * vec4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
" vtf.tcgs[%u] = (tmpProj / tmpProj.w).xy;\n",
tcg.m_mtx, tcg.m_norm ? "normalize" : "",
tcg.m_mtx, EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(), tcgIdx);
tcg.m_mtx, tcg.m_norm ? "normalize" : "", tcg.m_mtx, EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(),
tcgIdx);
++tcgIdx;
}
for (int i=0 ; i<extTexCount ; ++i)
{
for (int i = 0; i < extTexCount; ++i) {
const TextureInfo& extTex = extTexs[i];
if (extTex.mtxIdx < 0)
retval += hecl::Format(" vtf.extTcgs[%u] = %s;\n", i,
EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str());
retval += hecl::Format(" vtf.extTcgs[%u] = %s;\n", i, EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str());
else
retval += hecl::Format(" tmpProj = texMtxs[%u].postMtx * vec4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
retval += hecl::Format(
" tmpProj = texMtxs[%u].postMtx * vec4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
" vtf.extTcgs[%u] = (tmpProj / tmpProj.w).xy;\n",
extTex.mtxIdx, extTex.normalize ? "normalize" : "",
extTex.mtxIdx, EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str(), i);
extTex.mtxIdx, extTex.normalize ? "normalize" : "", extTex.mtxIdx,
EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str(), i);
}
if (reflectionType != ReflectionType::None)
retval += " vtf.reflectTcgs[0] = normalize((indMtx * vec4(posIn, 1.0)).xz) * vec2(0.5, 0.5) + vec2(0.5, 0.5);\n"
retval +=
" vtf.reflectTcgs[0] = normalize((indMtx * vec4(posIn, 1.0)).xz) * vec2(0.5, 0.5) + vec2(0.5, 0.5);\n"
" vtf.reflectTcgs[1] = (reflectMtx * vec4(posIn, 1.0)).xy;\n"
" vtf.reflectAlpha = reflectAlpha;\n";
return retval + "}\n";
}
std::string GLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
ReflectionType reflectionType, BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting) const
{
std::string GLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting) const {
std::string lightingSrc;
if (!lighting.m_source.empty())
lightingSrc = lighting.m_source;
else
lightingSrc = "const vec4 colorReg0 = vec4(1.0);\n"
lightingSrc =
"const vec4 colorReg0 = vec4(1.0);\n"
"const vec4 colorReg1 = vec4(1.0);\n"
"const vec4 colorReg2 = vec4(1.0);\n"
"const vec4 mulColor = vec4(1.0);\n"
"\n";
std::string texMapDecl;
for (unsigned i=0 ; i<m_texMapEnd ; ++i)
for (unsigned i = 0; i < m_texMapEnd; ++i)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D tex%u;\n", i, i);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionIndTex;\n"
texMapDecl += hecl::Format(
"TBINDING%u uniform sampler2D reflectionIndTex;\n"
"TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd, m_texMapEnd+1);
m_texMapEnd, m_texMapEnd + 1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd);
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n", m_texMapEnd);
std::string retval =
std::string("#extension GL_ARB_shader_image_load_store: enable\n") +
"#define BLEND_SRC_" + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
"#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
std::string retval = std::string("#extension GL_ARB_shader_image_load_store: enable\n") + "#define BLEND_SRC_" +
BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" +
BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) +
(!alphaTest ?
"#ifdef GL_ARB_shader_image_load_store\n"
(!alphaTest ? "#ifdef GL_ARB_shader_image_load_store\n"
"layout(early_fragment_tests) in;\n"
"#endif\n" : "") +
"layout(location=0) out vec4 colorOut;\n" +
texMapDecl +
"SBINDING(0) in VertToFrag vtf;\n\n" +
lightingSrc + "\n" +
"void main()\n{\n";
"#endif\n"
: "") +
"layout(location=0) out vec4 colorOut;\n" + texMapDecl + "SBINDING(0) in VertToFrag vtf;\n\n" +
lightingSrc + "\n" + "void main()\n{\n";
if (m_lighting)
{
if (m_lighting) {
if (!lighting.m_entry.empty())
retval += hecl::Format(" vec4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n",
lighting.m_entry.data());
retval +=
hecl::Format(" vec4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n", lighting.m_entry.data());
else
retval += " vec4 lighting = vec4(1.0,1.0,1.0,1.0);\n";
}
unsigned sampIdx = 0;
for (const TexSampling& sampling : m_texSamplings)
retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx,
sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
@ -301,19 +281,15 @@ std::string GLSL::makeFrag(size_t blockCount, const char** blockNames, bool alph
return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n";
}
std::string GLSL::makeFrag(size_t blockCount, const char** blockNames,
bool alphaTest,
ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting,
const Function& post,
size_t extTexCount, const TextureInfo* extTexs) const
{
std::string GLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post,
size_t extTexCount, const TextureInfo* extTexs) const {
std::string lightingSrc;
if (!lighting.m_source.empty())
lightingSrc = lighting.m_source;
else
lightingSrc = "const vec4 colorReg0 = vec4(1.0);\n"
lightingSrc =
"const vec4 colorReg0 = vec4(1.0);\n"
"const vec4 colorReg1 = vec4(1.0);\n"
"const vec4 colorReg2 = vec4(1.0);\n"
"const vec4 mulColor = vec4(1.0);\n"
@ -328,67 +304,58 @@ std::string GLSL::makeFrag(size_t blockCount, const char** blockNames,
postEntry = post.m_entry;
std::string texMapDecl;
for (unsigned i=0 ; i<m_texMapEnd ; ++i)
for (unsigned i = 0; i < m_texMapEnd; ++i)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D tex%u;\n", i, i);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionIndTex;\n"
texMapDecl += hecl::Format(
"TBINDING%u uniform sampler2D reflectionIndTex;\n"
"TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd, m_texMapEnd+1);
m_texMapEnd, m_texMapEnd + 1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n",
m_texMapEnd);
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D reflectionTex;\n", m_texMapEnd);
uint32_t extTexBits = 0;
for (int i=0 ; i<extTexCount ; ++i)
{
for (int i = 0; i < extTexCount; ++i) {
const TextureInfo& extTex = extTexs[i];
if (!(extTexBits & (1 << extTex.mapIdx)))
{
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D extTex%u;\n",
extTex.mapIdx, extTex.mapIdx);
if (!(extTexBits & (1 << extTex.mapIdx))) {
texMapDecl += hecl::Format("TBINDING%u uniform sampler2D extTex%u;\n", extTex.mapIdx, extTex.mapIdx);
extTexBits |= (1 << extTex.mapIdx);
}
}
std::string retval =
std::string("#extension GL_ARB_shader_image_load_store: enable\n") +
"#define BLEND_SRC_" + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
"#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
std::string retval = std::string("#extension GL_ARB_shader_image_load_store: enable\n") + "#define BLEND_SRC_" +
BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" +
BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) +
(!alphaTest ?
"\n#ifdef GL_ARB_shader_image_load_store\n"
(!alphaTest ? "\n#ifdef GL_ARB_shader_image_load_store\n"
"layout(early_fragment_tests) in;\n"
"#endif\n" : "") +
"\nlayout(location=0) out vec4 colorOut;\n" +
texMapDecl +
"SBINDING(0) in VertToFrag vtf;\n\n" +
lightingSrc + "\n" +
postSrc +
"\nvoid main()\n{\n";
"#endif\n"
: "") +
"\nlayout(location=0) out vec4 colorOut;\n" + texMapDecl + "SBINDING(0) in VertToFrag vtf;\n\n" +
lightingSrc + "\n" + postSrc + "\nvoid main()\n{\n";
if (m_lighting)
{
if (m_lighting) {
if (!lighting.m_entry.empty())
retval += hecl::Format(" vec4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n",
lighting.m_entry.data());
retval +=
hecl::Format(" vec4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz));\n", lighting.m_entry.data());
else
retval += " vec4 lighting = vec4(1.0,1.0,1.0,1.0);\n";
}
unsigned sampIdx = 0;
for (const TexSampling& sampling : m_texSamplings)
retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
retval += hecl::Format(" vec4 sampling%u = texture(tex%u, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx,
sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
if (m_alphaExpr.size())
retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr +
")) * mulColor;\n";
else
retval += " colorOut = " + postEntry + "(vec4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0)) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n";
}
}
} // namespace hecl::Backend

View File

@ -1,21 +1,22 @@
#include "hecl/Backend/GX.hpp"
namespace hecl::Backend
{
namespace hecl::Backend {
template <>
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::Read>(typename Read::StreamT& reader)
{ reader.readUBytesToBuf(&num, 4); }
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::Read>(typename Read::StreamT& reader) {
reader.readUBytesToBuf(&num, 4);
}
template <>
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::Write>(typename Write::StreamT& writer)
{ writer.writeUBytes(reinterpret_cast<const atUint8*>(&num), 4); }
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::Write>(typename Write::StreamT& writer) {
writer.writeUBytes(reinterpret_cast<const atUint8*>(&num), 4);
}
template <>
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::BinarySize>(typename BinarySize::StreamT& s)
{ s += 4; }
void GX::Color::Enumerate<athena::io::DNA<athena::Big>::BinarySize>(typename BinarySize::StreamT& s) {
s += 4;
}
unsigned GX::addKColor(Diagnostics& diag, const SourceLocation& loc, const Color& color)
{
for (unsigned i=0 ; i<m_kcolorCount ; ++i)
unsigned GX::addKColor(Diagnostics& diag, const SourceLocation& loc, const Color& color) {
for (unsigned i = 0; i < m_kcolorCount; ++i)
if (m_kcolors[i] == color)
return i;
if (m_kcolorCount >= 4)
@ -25,15 +26,12 @@ unsigned GX::addKColor(Diagnostics& diag, const SourceLocation& loc, const Color
return m_kcolorCount++;
}
unsigned GX::addKAlpha(Diagnostics& diag, const SourceLocation& loc, float alpha)
{
unsigned GX::addKAlpha(Diagnostics& diag, const SourceLocation& loc, float alpha) {
uint8_t ai = uint8_t(std::min(std::max(alpha * 255.f, 0.f), 255.f));
for (unsigned i=0 ; i<m_kcolorCount ; ++i)
{
for (unsigned i = 0; i < m_kcolorCount; ++i) {
if (m_kcolors[i].color[3] == ai)
return i;
else if (m_kcolors[i].color[3] == 0)
{
else if (m_kcolors[i].color[3] == 0) {
m_kcolors[i].color[3] = ai;
return i;
}
@ -44,14 +42,11 @@ unsigned GX::addKAlpha(Diagnostics& diag, const SourceLocation& loc, float alpha
return m_kcolorCount++;
}
unsigned GX::addTexCoordGen(Diagnostics& diag, const SourceLocation& loc,
TexGenSrc src, TexMtx mtx, bool norm, PTTexMtx pmtx)
{
for (unsigned i=0 ; i<m_tcgCount ; ++i)
{
unsigned GX::addTexCoordGen(Diagnostics& diag, const SourceLocation& loc, TexGenSrc src, TexMtx mtx, bool norm,
PTTexMtx pmtx) {
for (unsigned i = 0; i < m_tcgCount; ++i) {
TexCoordGen& tcg = m_tcgs[i];
if (tcg.m_src == src && tcg.m_mtx == mtx &&
tcg.m_norm == norm && tcg.m_pmtx == pmtx)
if (tcg.m_src == src && tcg.m_mtx == mtx && tcg.m_norm == norm && tcg.m_pmtx == pmtx)
return i;
}
if (m_tcgCount >= 8)
@ -64,26 +59,22 @@ unsigned GX::addTexCoordGen(Diagnostics& diag, const SourceLocation& loc,
return m_tcgCount++;
}
GX::TEVStage& GX::addTEVStage(Diagnostics& diag, const SourceLocation& loc)
{
GX::TEVStage& GX::addTEVStage(Diagnostics& diag, const SourceLocation& loc) {
if (m_tevCount >= 16)
diag.reportBackendErr(loc, "GX TEV stage overflow");
GX::TEVStage& newTEV = m_tevs[m_tevCount];
newTEV.m_loc = loc;
if (m_tevCount)
{
newTEV.m_prev = &m_tevs[m_tevCount-1];
if (m_tevCount) {
newTEV.m_prev = &m_tevs[m_tevCount - 1];
newTEV.m_prev->m_next = &newTEV;
}
++m_tevCount;
return newTEV;
}
GX::TEVStage& GX::addAlphaTEVStage(Diagnostics& diag, const SourceLocation& loc)
{
GX::TEVStage& GX::addAlphaTEVStage(Diagnostics& diag, const SourceLocation& loc) {
++m_alphaTraceStage;
while (m_tevCount < m_alphaTraceStage + 1)
{
while (m_tevCount < m_alphaTraceStage + 1) {
TEVStage& stage = addTEVStage(diag, loc);
stage.m_color[3] = CC_CPREV;
stage.m_alpha[3] = CA_APREV;
@ -92,21 +83,18 @@ GX::TEVStage& GX::addAlphaTEVStage(Diagnostics& diag, const SourceLocation& loc)
}
unsigned GX::RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, TexMtx mtx,
bool normalize, PTTexMtx pmtx)
{
bool normalize, PTTexMtx pmtx) {
if (inst.m_op != IR::OpType::Call)
diag.reportBackendErr(inst.m_loc, "TexCoordGen resolution requires function");
const std::string& tcgName = inst.m_call.m_name;
if (!tcgName.compare("UV"))
{
if (!tcgName.compare("UV")) {
if (inst.getChildCount() < 1)
diag.reportBackendErr(inst.m_loc, "TexCoordGen UV(layerIdx) requires one argument");
const IR::Instruction& idxInst = inst.getChildInst(ir, 0);
auto& idxImm = idxInst.getImmVec();
return addTexCoordGen(diag, inst.m_loc, TexGenSrc(TG_TEX0 + unsigned(idxImm.simd[0])), mtx, normalize, pmtx);
}
else if (!tcgName.compare("Normal"))
} else if (!tcgName.compare("Normal"))
return addTexCoordGen(diag, inst.m_loc, TG_NRM, mtx, normalize, pmtx);
else if (!tcgName.compare("View"))
return addTexCoordGen(diag, inst.m_loc, TG_POS, mtx, normalize, pmtx);
@ -114,15 +102,14 @@ unsigned GX::RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Ins
/* Otherwise treat as game-specific function */
const IR::Instruction& tcgSrcInst = inst.getChildInst(ir, 0);
bool doNorm = normalize || tcgName.back() == 'N';
unsigned idx = RecursiveTraceTexGen(ir, diag, tcgSrcInst, TexMtx(TEXMTX0 + m_texMtxCount * 3),
doNorm, doNorm ? PTTexMtx(PTTEXMTX0 + m_texMtxCount * 3) : PTIDENTITY);
unsigned idx = RecursiveTraceTexGen(ir, diag, tcgSrcInst, TexMtx(TEXMTX0 + m_texMtxCount * 3), doNorm,
doNorm ? PTTexMtx(PTTEXMTX0 + m_texMtxCount * 3) : PTIDENTITY);
GX::TexCoordGen& tcg = m_tcgs[idx];
m_texMtxRefs[m_texMtxCount] = &tcg;
++m_texMtxCount;
tcg.m_gameFunction = tcgName;
tcg.m_gameArgs.clear();
for (int i=1 ; i<inst.getChildCount() ; ++i)
{
for (int i = 1; i < inst.getChildCount(); ++i) {
const IR::Instruction& ci = inst.getChildInst(ir, i);
tcg.m_gameArgs.push_back(ci.getImmVec());
}
@ -130,16 +117,12 @@ unsigned GX::RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Ins
}
GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst,
bool swizzleAlpha)
{
switch (inst.m_op)
{
case IR::OpType::Call:
{
bool swizzleAlpha) {
switch (inst.m_op) {
case IR::OpType::Call: {
const std::string& name = inst.m_call.m_name;
bool normalize = false;
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN")))
{
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN"))) {
TEVStage& newStage = addTEVStage(diag, inst.m_loc);
if (inst.getChildCount() < 2)
@ -154,9 +137,7 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
newStage.m_texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, IDENTITY, normalize, PTIDENTITY);
return TraceResult(&newStage);
}
else if (!name.compare("ColorReg"))
{
} else if (!name.compare("ColorReg")) {
const IR::Instruction& idxInst = inst.getChildInst(ir, 0);
unsigned idx = unsigned(idxInst.getImmVec().simd[0]);
if (swizzleAlpha)
@ -164,17 +145,13 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
else
m_cRegMask |= 1 << idx;
return TraceResult(TevColorArg((swizzleAlpha ? CC_A0 : CC_C0) + idx * 2));
}
else if (!name.compare("Lighting"))
{
} else if (!name.compare("Lighting")) {
return TraceResult(swizzleAlpha ? CC_RASA : CC_RASC);
}
else
} else
diag.reportBackendErr(inst.m_loc, "GX backend unable to interpret '%s'", name.c_str());
break;
}
case IR::OpType::LoadImm:
{
case IR::OpType::LoadImm: {
const atVec4f& vec = inst.m_loadImm.m_immVec;
if (vec.simd[0] == 0.f && vec.simd[1] == 0.f && vec.simd[2] == 0.f)
return TraceResult(CC_ZERO);
@ -183,96 +160,69 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
unsigned idx = addKColor(diag, inst.m_loc, vec);
return TraceResult(TevKColorSel(TEV_KCSEL_K0 + idx));
}
case IR::OpType::Arithmetic:
{
case IR::OpType::Arithmetic: {
ArithmeticOp op = inst.m_arithmetic.m_op;
const IR::Instruction& aInst = inst.getChildInst(ir, 0);
const IR::Instruction& bInst = inst.getChildInst(ir, 1);
TraceResult aTrace;
TraceResult bTrace;
if (aInst.m_op != IR::OpType::Arithmetic && bInst.m_op == IR::OpType::Arithmetic)
{
if (aInst.m_op != IR::OpType::Arithmetic && bInst.m_op == IR::OpType::Arithmetic) {
bTrace = RecursiveTraceColor(ir, diag, bInst);
aTrace = RecursiveTraceColor(ir, diag, aInst);
}
else
{
} else {
aTrace = RecursiveTraceColor(ir, diag, aInst);
bTrace = RecursiveTraceColor(ir, diag, bInst);
}
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage &&
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage &&
getStageIdx(aTrace.tevStage) > getStageIdx(bTrace.tevStage))
std::swap(aTrace, bTrace);
TevKColorSel newKColor = TEV_KCSEL_1;
if (aTrace.type == TraceResult::Type::TEVKColorSel &&
bTrace.type == TraceResult::Type::TEVKColorSel)
if (aTrace.type == TraceResult::Type::TEVKColorSel && bTrace.type == TraceResult::Type::TEVKColorSel)
diag.reportBackendErr(inst.m_loc, "unable to handle 2 KColors in one stage");
else if (aTrace.type == TraceResult::Type::TEVKColorSel)
{
else if (aTrace.type == TraceResult::Type::TEVKColorSel) {
newKColor = aTrace.tevKColorSel;
aTrace.type = TraceResult::Type::TEVColorArg;
aTrace.tevColorArg = CC_KONST;
}
else if (bTrace.type == TraceResult::Type::TEVKColorSel)
{
} else if (bTrace.type == TraceResult::Type::TEVKColorSel) {
newKColor = bTrace.tevKColorSel;
bTrace.type = TraceResult::Type::TEVColorArg;
bTrace.tevColorArg = CC_KONST;
}
switch (op)
{
case ArithmeticOp::Add:
{
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage)
{
switch (op) {
case ArithmeticOp::Add: {
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* a = aTrace.tevStage;
TEVStage* b = bTrace.tevStage;
if (b->m_prev != a)
{
if (b->m_prev != a) {
a->m_cRegOut = TEVLAZY;
b->m_color[3] = CC_LAZY;
b->m_lazyCInIdx = m_cRegLazy;
a->m_lazyCOutIdx = m_cRegLazy++;
}
else if (b == &m_tevs[m_tevCount-1] &&
a->m_texMapIdx == b->m_texMapIdx && a->m_texGenIdx == b->m_texGenIdx &&
a->m_color[3] == CC_ZERO && b->m_color[0] != CC_ZERO)
{
} else if (b == &m_tevs[m_tevCount - 1] && a->m_texMapIdx == b->m_texMapIdx &&
a->m_texGenIdx == b->m_texGenIdx && a->m_color[3] == CC_ZERO && b->m_color[0] != CC_ZERO) {
a->m_color[3] = b->m_color[0];
--m_tevCount;
return TraceResult(a);
}
else
} else
b->m_color[3] = CC_CPREV;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVColorArg)
{
} else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVColorArg) {
TEVStage* a = aTrace.tevStage;
if (a->m_color[3] != CC_ZERO)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine");
a->m_color[3] = bTrace.tevColorArg;
a->m_kColor = newKColor;
return TraceResult(a);
}
else if (aTrace.type == TraceResult::Type::TEVColorArg &&
bTrace.type == TraceResult::Type::TEVStage)
{
} else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* b = bTrace.tevStage;
if (b->m_color[3] != CC_ZERO)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine");
b->m_color[3] = aTrace.tevColorArg;
b->m_kColor = newKColor;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVColorArg &&
bTrace.type == TraceResult::Type::TEVColorArg)
{
} else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVColorArg) {
TEVStage& stage = addTEVStage(diag, inst.m_loc);
stage.m_color[0] = aTrace.tevColorArg;
stage.m_color[3] = bTrace.tevColorArg;
@ -281,28 +231,20 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
}
break;
}
case ArithmeticOp::Subtract:
{
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage)
{
case ArithmeticOp::Subtract: {
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* a = aTrace.tevStage;
TEVStage* b = bTrace.tevStage;
if (b->m_prev != a)
{
if (b->m_prev != a) {
a->m_cRegOut = TEVLAZY;
b->m_color[3] = CC_LAZY;
b->m_lazyCInIdx = m_cRegLazy;
a->m_lazyCOutIdx = m_cRegLazy++;
}
else
} else
b->m_color[3] = CC_CPREV;
b->m_cop = TEV_SUB;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVColorArg)
{
} else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVColorArg) {
TEVStage* a = aTrace.tevStage;
if (a->m_color[3] != CC_ZERO)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for subtract combine");
@ -310,10 +252,7 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
a->m_kColor = newKColor;
a->m_cop = TEV_SUB;
return TraceResult(a);
}
else if (aTrace.type == TraceResult::Type::TEVColorArg &&
bTrace.type == TraceResult::Type::TEVColorArg)
{
} else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVColorArg) {
TEVStage& stage = addTEVStage(diag, inst.m_loc);
stage.m_color[0] = aTrace.tevColorArg;
stage.m_color[3] = bTrace.tevColorArg;
@ -323,44 +262,32 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
}
break;
}
case ArithmeticOp::Multiply:
{
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage)
{
case ArithmeticOp::Multiply: {
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* a = aTrace.tevStage;
TEVStage* b = bTrace.tevStage;
if (b->m_color[2] != CC_ZERO)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine");
if (b->m_prev != a)
{
if (b->m_prev != a) {
a->m_cRegOut = TEVLAZY;
b->m_color[2] = CC_LAZY;
b->m_lazyCInIdx = m_cRegLazy;
a->m_lazyCOutIdx = m_cRegLazy++;
}
else
} else
b->m_color[2] = CC_CPREV;
b->m_color[1] = b->m_color[0];
b->m_color[0] = CC_ZERO;
b->m_color[3] = CC_ZERO;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVColorArg &&
bTrace.type == TraceResult::Type::TEVColorArg)
{
} else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVColorArg) {
TEVStage& stage = addTEVStage(diag, inst.m_loc);
stage.m_color[1] = aTrace.tevColorArg;
stage.m_color[2] = bTrace.tevColorArg;
stage.m_kColor = newKColor;
return TraceResult(&stage);
}
else if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVColorArg)
{
} else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVColorArg) {
TEVStage* a = aTrace.tevStage;
if (a->m_color[1] != CC_ZERO)
{
if (a->m_color[1] != CC_ZERO) {
if (a->m_cRegOut != TEVPREV)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine");
TEVStage& stage = addTEVStage(diag, inst.m_loc);
@ -374,13 +301,9 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
a->m_color[2] = bTrace.tevColorArg;
a->m_kColor = newKColor;
return TraceResult(a);
}
else if (aTrace.type == TraceResult::Type::TEVColorArg &&
bTrace.type == TraceResult::Type::TEVStage)
{
} else if (aTrace.type == TraceResult::Type::TEVColorArg && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* b = bTrace.tevStage;
if (b->m_color[1] != CC_ZERO)
{
if (b->m_color[1] != CC_ZERO) {
if (b->m_cRegOut != TEVPREV)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine");
TEVStage& stage = addTEVStage(diag, inst.m_loc);
@ -403,17 +326,14 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
diag.reportBackendErr(inst.m_loc, "unable to convert arithmetic to TEV stage");
}
case IR::OpType::Swizzle:
{
if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 &&
inst.m_swizzle.m_idxs[2] == 3 && inst.m_swizzle.m_idxs[3] == -1)
{
case IR::OpType::Swizzle: {
if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 && inst.m_swizzle.m_idxs[2] == 3 &&
inst.m_swizzle.m_idxs[3] == -1) {
const IR::Instruction& cInst = inst.getChildInst(ir, 0);
if (cInst.m_op != IR::OpType::Call)
diag.reportBackendErr(inst.m_loc, "only functions accepted for alpha swizzle");
return RecursiveTraceColor(ir, diag, cInst, true);
}
else
} else
diag.reportBackendErr(inst.m_loc, "only alpha extract may be performed with swizzle operation");
}
default:
@ -423,16 +343,12 @@ GX::TraceResult GX::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const I
return TraceResult();
}
GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst)
{
switch (inst.m_op)
{
case IR::OpType::Call:
{
GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst) {
switch (inst.m_op) {
case IR::OpType::Call: {
const std::string& name = inst.m_call.m_name;
bool normalize = false;
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN")))
{
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN"))) {
if (inst.getChildCount() < 2)
diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments");
@ -441,18 +357,15 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
unsigned mapIdx = unsigned(mapImm.simd[0]);
int foundStage = -1;
for (int i=m_alphaTraceStage+1 ; i<int(m_tevCount) ; ++i)
{
for (int i = m_alphaTraceStage + 1; i < int(m_tevCount); ++i) {
TEVStage& testStage = m_tevs[i];
if (testStage.m_texMapIdx == mapIdx)
{
if (testStage.m_texMapIdx == mapIdx) {
foundStage = i;
break;
}
}
if (foundStage >= 0)
{
if (foundStage >= 0) {
m_alphaTraceStage = foundStage;
TEVStage& stage = m_tevs[foundStage];
stage.m_alpha[0] = CA_TEXA;
@ -469,24 +382,18 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
newStage.m_texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, IDENTITY, normalize, PTIDENTITY);
return TraceResult(&newStage);
}
else if (!name.compare("ColorReg"))
{
} else if (!name.compare("ColorReg")) {
const IR::Instruction& idxInst = inst.getChildInst(ir, 0);
unsigned idx = unsigned(idxInst.getImmVec().simd[0]);
m_aRegMask |= 1 << idx;
return TraceResult(TevAlphaArg(CA_A0 + idx));
}
else if (!name.compare("Lighting"))
{
} else if (!name.compare("Lighting")) {
return TraceResult(CA_RASA);
}
else
} else
diag.reportBackendErr(inst.m_loc, "GX backend unable to interpret '%s'", name.c_str());
break;
}
case IR::OpType::LoadImm:
{
case IR::OpType::LoadImm: {
const atVec4f& vec = inst.m_loadImm.m_immVec;
if (vec.simd[0] == 0.f)
return TraceResult(CA_ZERO);
@ -495,93 +402,68 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
unsigned idx = addKAlpha(diag, inst.m_loc, vec.simd[0]);
return TraceResult(TevKAlphaSel(TEV_KASEL_K0_A + idx));
}
case IR::OpType::Arithmetic:
{
case IR::OpType::Arithmetic: {
ArithmeticOp op = inst.m_arithmetic.m_op;
const IR::Instruction& aInst = inst.getChildInst(ir, 0);
const IR::Instruction& bInst = inst.getChildInst(ir, 1);
TraceResult aTrace;
TraceResult bTrace;
if (aInst.m_op != IR::OpType::Arithmetic && bInst.m_op == IR::OpType::Arithmetic)
{
if (aInst.m_op != IR::OpType::Arithmetic && bInst.m_op == IR::OpType::Arithmetic) {
bTrace = RecursiveTraceAlpha(ir, diag, bInst);
aTrace = RecursiveTraceAlpha(ir, diag, aInst);
}
else
{
} else {
aTrace = RecursiveTraceAlpha(ir, diag, aInst);
bTrace = RecursiveTraceAlpha(ir, diag, bInst);
}
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage &&
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage &&
getStageIdx(aTrace.tevStage) > getStageIdx(bTrace.tevStage))
std::swap(aTrace, bTrace);
TevKAlphaSel newKAlpha = TEV_KASEL_1;
if (aTrace.type == TraceResult::Type::TEVKAlphaSel &&
bTrace.type == TraceResult::Type::TEVKAlphaSel)
if (aTrace.type == TraceResult::Type::TEVKAlphaSel && bTrace.type == TraceResult::Type::TEVKAlphaSel)
diag.reportBackendErr(inst.m_loc, "unable to handle 2 KAlphas in one stage");
else if (aTrace.type == TraceResult::Type::TEVKAlphaSel)
{
else if (aTrace.type == TraceResult::Type::TEVKAlphaSel) {
newKAlpha = aTrace.tevKAlphaSel;
aTrace.type = TraceResult::Type::TEVAlphaArg;
aTrace.tevAlphaArg = CA_KONST;
}
else if (bTrace.type == TraceResult::Type::TEVKAlphaSel)
{
} else if (bTrace.type == TraceResult::Type::TEVKAlphaSel) {
newKAlpha = bTrace.tevKAlphaSel;
bTrace.type = TraceResult::Type::TEVAlphaArg;
bTrace.tevAlphaArg = CA_KONST;
}
switch (op)
{
case ArithmeticOp::Add:
{
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage)
{
switch (op) {
case ArithmeticOp::Add: {
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* a = aTrace.tevStage;
TEVStage* b = bTrace.tevStage;
if (b->m_prev != a)
{
if (b->m_prev != a) {
a->m_aRegOut = TEVLAZY;
b->m_alpha[3] = CA_LAZY;
if (a->m_lazyAOutIdx != -1)
b->m_lazyAInIdx = a->m_lazyAOutIdx;
else
{
else {
b->m_lazyAInIdx = m_aRegLazy;
a->m_lazyAOutIdx = m_aRegLazy++;
}
}
else
} else
b->m_alpha[3] = CA_APREV;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVAlphaArg)
{
} else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVAlphaArg) {
TEVStage* a = aTrace.tevStage;
if (a->m_alpha[3] != CA_ZERO)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine");
a->m_alpha[3] = bTrace.tevAlphaArg;
a->m_kAlpha = newKAlpha;
return TraceResult(a);
}
else if (aTrace.type == TraceResult::Type::TEVAlphaArg &&
bTrace.type == TraceResult::Type::TEVStage)
{
} else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* b = bTrace.tevStage;
if (b->m_alpha[3] != CA_ZERO)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for add combine");
b->m_alpha[3] = aTrace.tevAlphaArg;
b->m_kAlpha = newKAlpha;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVAlphaArg &&
bTrace.type == TraceResult::Type::TEVAlphaArg)
{
} else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVAlphaArg) {
TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc);
stage.m_alpha[0] = aTrace.tevAlphaArg;
stage.m_alpha[3] = bTrace.tevAlphaArg;
@ -590,34 +472,25 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
}
break;
}
case ArithmeticOp::Subtract:
{
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage)
{
case ArithmeticOp::Subtract: {
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* a = aTrace.tevStage;
TEVStage* b = bTrace.tevStage;
if (b->m_aop != TEV_SUB)
diag.reportBackendErr(inst.m_loc, "unable to integrate alpha subtraction into stage chain");
if (b->m_prev != a)
{
if (b->m_prev != a) {
a->m_aRegOut = TEVLAZY;
b->m_alpha[3] = CA_LAZY;
if (a->m_lazyAOutIdx != -1)
b->m_lazyAInIdx = a->m_lazyAOutIdx;
else
{
else {
b->m_lazyAInIdx = m_aRegLazy;
a->m_lazyAOutIdx = m_aRegLazy++;
}
}
else
} else
b->m_alpha[3] = CA_APREV;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVAlphaArg)
{
} else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVAlphaArg) {
TEVStage* a = aTrace.tevStage;
if (a->m_aop != TEV_SUB)
diag.reportBackendErr(inst.m_loc, "unable to integrate alpha subtraction into stage chain");
@ -626,10 +499,7 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
a->m_alpha[3] = bTrace.tevAlphaArg;
a->m_kAlpha = newKAlpha;
return TraceResult(a);
}
else if (aTrace.type == TraceResult::Type::TEVAlphaArg &&
bTrace.type == TraceResult::Type::TEVAlphaArg)
{
} else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVAlphaArg) {
TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc);
stage.m_alpha[0] = aTrace.tevAlphaArg;
stage.m_alpha[3] = bTrace.tevAlphaArg;
@ -639,45 +509,33 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
}
break;
}
case ArithmeticOp::Multiply:
{
if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVStage)
{
case ArithmeticOp::Multiply: {
if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* a = aTrace.tevStage;
TEVStage* b = bTrace.tevStage;
if (b->m_alpha[2] != CA_ZERO)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine");
if (b->m_prev != a)
{
if (b->m_prev != a) {
a->m_aRegOut = TEVLAZY;
b->m_alpha[2] = CA_LAZY;
b->m_lazyAInIdx = m_aRegLazy;
a->m_lazyAOutIdx = m_aRegLazy++;
}
else
} else
b->m_alpha[2] = CA_APREV;
b->m_alpha[1] = b->m_alpha[0];
b->m_alpha[0] = CA_ZERO;
b->m_alpha[3] = CA_ZERO;
return TraceResult(b);
}
else if (aTrace.type == TraceResult::Type::TEVAlphaArg &&
bTrace.type == TraceResult::Type::TEVAlphaArg)
{
} else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVAlphaArg) {
TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc);
stage.m_color[3] = CC_CPREV;
stage.m_alpha[1] = aTrace.tevAlphaArg;
stage.m_alpha[2] = bTrace.tevAlphaArg;
stage.m_kAlpha = newKAlpha;
return TraceResult(&stage);
}
else if (aTrace.type == TraceResult::Type::TEVStage &&
bTrace.type == TraceResult::Type::TEVAlphaArg)
{
} else if (aTrace.type == TraceResult::Type::TEVStage && bTrace.type == TraceResult::Type::TEVAlphaArg) {
TEVStage* a = aTrace.tevStage;
if (a->m_alpha[1] != CA_ZERO)
{
if (a->m_alpha[1] != CA_ZERO) {
if (a->m_aRegOut != TEVPREV)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine");
TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc);
@ -691,13 +549,9 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
a->m_alpha[2] = bTrace.tevAlphaArg;
a->m_kAlpha = newKAlpha;
return TraceResult(a);
}
else if (aTrace.type == TraceResult::Type::TEVAlphaArg &&
bTrace.type == TraceResult::Type::TEVStage)
{
} else if (aTrace.type == TraceResult::Type::TEVAlphaArg && bTrace.type == TraceResult::Type::TEVStage) {
TEVStage* b = bTrace.tevStage;
if (b->m_alpha[1] != CA_ZERO)
{
if (b->m_alpha[1] != CA_ZERO) {
if (b->m_aRegOut != TEVPREV)
diag.reportBackendErr(inst.m_loc, "unable to modify TEV stage for multiply combine");
TEVStage& stage = addAlphaTEVStage(diag, inst.m_loc);
@ -720,17 +574,14 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
diag.reportBackendErr(inst.m_loc, "unable to convert arithmetic to TEV stage");
}
case IR::OpType::Swizzle:
{
if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 &&
inst.m_swizzle.m_idxs[2] == 3 && inst.m_swizzle.m_idxs[3] == -1)
{
case IR::OpType::Swizzle: {
if (inst.m_swizzle.m_idxs[0] == 3 && inst.m_swizzle.m_idxs[1] == 3 && inst.m_swizzle.m_idxs[2] == 3 &&
inst.m_swizzle.m_idxs[3] == -1) {
const IR::Instruction& cInst = inst.getChildInst(ir, 0);
if (cInst.m_op != IR::OpType::Call)
diag.reportBackendErr(inst.m_loc, "only functions accepted for alpha swizzle");
return RecursiveTraceAlpha(ir, diag, cInst);
}
else
} else
diag.reportBackendErr(inst.m_loc, "only alpha extract may be performed with swizzle operation");
}
default:
@ -740,8 +591,7 @@ GX::TraceResult GX::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const I
return TraceResult();
}
void GX::reset(const IR& ir, Diagnostics& diag)
{
void GX::reset(const IR& ir, Diagnostics& diag) {
diag.setBackend("GX");
m_tevCount = 0;
@ -756,109 +606,88 @@ void GX::reset(const IR& ir, Diagnostics& diag)
/* Final instruction is the root call by hecl convention */
const IR::Instruction& rootCall = ir.m_instructions.back();
if (!rootCall.m_call.m_name.compare("HECLOpaque"))
{
if (!rootCall.m_call.m_name.compare("HECLOpaque")) {
m_blendSrc = BL_ONE;
m_blendDst = BL_ZERO;
}
else if (!rootCall.m_call.m_name.compare("HECLAlpha"))
{
} else if (!rootCall.m_call.m_name.compare("HECLAlpha")) {
m_blendSrc = BL_SRCALPHA;
m_blendDst = BL_INVSRCALPHA;
}
else if (!rootCall.m_call.m_name.compare("HECLAdditive"))
{
} else if (!rootCall.m_call.m_name.compare("HECLAdditive")) {
m_blendSrc = BL_SRCALPHA;
m_blendDst = BL_ONE;
}
else
{
diag.reportBackendErr(rootCall.m_loc, "GX backend doesn't handle '%s' root",
rootCall.m_call.m_name.c_str());
} else {
diag.reportBackendErr(rootCall.m_loc, "GX backend doesn't handle '%s' root", rootCall.m_call.m_name.c_str());
return;
}
/* Follow Color Chain */
const IR::Instruction& colorRoot =
ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(0));
const IR::Instruction& colorRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(0));
TraceResult result = RecursiveTraceColor(ir, diag, colorRoot);
switch (result.type)
{
case TraceResult::Type::TEVColorArg:
{
switch (result.type) {
case TraceResult::Type::TEVColorArg: {
TEVStage& stage = addTEVStage(diag, colorRoot.m_loc);
stage.m_color[3] = result.tevColorArg;
break;
}
case TraceResult::Type::TEVKColorSel:
{
case TraceResult::Type::TEVKColorSel: {
TEVStage& stage = addTEVStage(diag, colorRoot.m_loc);
stage.m_color[3] = CC_KONST;
stage.m_kColor = result.tevKColorSel;
break;
}
default: break;
default:
break;
}
/* Follow Alpha Chain */
if (rootCall.m_call.m_argInstIdxs.size() > 1)
{
const IR::Instruction& alphaRoot =
ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(1));
if (rootCall.m_call.m_argInstIdxs.size() > 1) {
const IR::Instruction& alphaRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(1));
TraceResult result = RecursiveTraceAlpha(ir, diag, alphaRoot);
switch (result.type)
{
case TraceResult::Type::TEVAlphaArg:
{
switch (result.type) {
case TraceResult::Type::TEVAlphaArg: {
TEVStage& stage = addAlphaTEVStage(diag, alphaRoot.m_loc);
stage.m_alpha[3] = result.tevAlphaArg;
break;
}
case TraceResult::Type::TEVKAlphaSel:
{
case TraceResult::Type::TEVKAlphaSel: {
TEVStage& stage = addAlphaTEVStage(diag, alphaRoot.m_loc);
stage.m_alpha[3] = CA_KONST;
stage.m_kAlpha = result.tevKAlphaSel;
break;
}
default: break;
default:
break;
}
/* Ensure Alpha reaches end of chain */
if (m_alphaTraceStage >= 0)
for (unsigned i=m_alphaTraceStage+1 ; i<m_tevCount ; ++i)
for (unsigned i = m_alphaTraceStage + 1; i < m_tevCount; ++i)
m_tevs[i].m_alpha[3] = CA_APREV;
}
/* Resolve lazy color/alpha regs */
if (m_cRegLazy)
{
for (int i=0 ; i<int(m_tevCount) ; ++i)
{
if (m_cRegLazy) {
for (int i = 0; i < int(m_tevCount); ++i) {
TEVStage& stage = m_tevs[i];
if (stage.m_cRegOut == TEVLAZY)
{
if (stage.m_cRegOut == TEVLAZY) {
int picked = pickCLazy(diag, stage.m_loc, i);
stage.m_cRegOut = TevRegID(TEVREG0 + picked);
for (int j=i+1 ; j<int(m_tevCount) ; ++j)
{
for (int j = i + 1; j < int(m_tevCount); ++j) {
TEVStage& nstage = m_tevs[j];
if (nstage.m_lazyCInIdx == stage.m_lazyCOutIdx)
for (int c=0 ; c<4 ; ++c)
for (int c = 0; c < 4; ++c)
if (nstage.m_color[c] == CC_LAZY)
nstage.m_color[c] = TevColorArg(CC_C0 + picked * 2);
}
}
if (stage.m_aRegOut == TEVLAZY)
{
if (stage.m_aRegOut == TEVLAZY) {
int picked = pickALazy(diag, stage.m_loc, i);
stage.m_aRegOut = TevRegID(TEVREG0 + picked);
for (int j=i+1 ; j<int(m_tevCount) ; ++j)
{
for (int j = i + 1; j < int(m_tevCount); ++j) {
TEVStage& nstage = m_tevs[j];
if (nstage.m_lazyAInIdx == stage.m_lazyAOutIdx)
for (int c=0 ; c<4 ; ++c)
for (int c = 0; c < 4; ++c)
if (nstage.m_alpha[c] == CA_LAZY)
nstage.m_alpha[c] = TevAlphaArg(CA_A0 + picked);
}
@ -867,4 +696,4 @@ void GX::reset(const IR& ir, Diagnostics& diag)
}
}
}
} // namespace hecl::Backend

View File

@ -6,41 +6,37 @@
static logvisor::Module Log("hecl::Backend::HLSL");
namespace hecl::Backend
{
namespace hecl::Backend {
std::string HLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const
{
switch (src)
{
std::string HLSL::EmitTexGenSource2(TexGenSrc src, int uvIdx) const {
switch (src) {
case TexGenSrc::Position:
return "objPos.xy\n";
case TexGenSrc::Normal:
return "objNorm.xy\n";
case TexGenSrc::UV:
return hecl::Format("v.uvIn[%u]", uvIdx);
default: break;
default:
break;
}
return std::string();
}
std::string HLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const
{
switch (src)
{
std::string HLSL::EmitTexGenSource4(TexGenSrc src, int uvIdx) const {
switch (src) {
case TexGenSrc::Position:
return "float4(objPos.xyz, 1.0)\n";
case TexGenSrc::Normal:
return "float4(objNorm.xyz, 1.0)\n";
case TexGenSrc::UV:
return hecl::Format("float4(v.uvIn[%u], 0.0, 1.0)", uvIdx);
default: break;
default:
break;
}
return std::string();
}
std::string HLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const
{
std::string HLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const {
std::string retval =
"struct VertData\n"
"{\n"
@ -59,8 +55,7 @@ std::string HLSL::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) co
return retval + "};\n";
}
std::string HLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const
{
std::string HLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const {
std::string retval =
"struct VertToFrag\n"
"{\n"
@ -74,27 +69,26 @@ std::string HLSL::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCo
retval += hecl::Format(" float2 extTcgs[%u] : EXTUV;\n", unsigned(extTexCount));
if (reflectionCoords)
retval += " float2 reflectTcgs[2] : REFLECTUV;\n"
retval +=
" float2 reflectTcgs[2] : REFLECTUV;\n"
" float reflectAlpha : REFLECTALPHA;\n";
return retval + "};\n";
}
std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const
{
std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionCoords) const {
std::string retval;
if (skinSlots == 0)
{
retval = "cbuffer HECLVertUniform : register(b0)\n"
if (skinSlots == 0) {
retval =
"cbuffer HECLVertUniform : register(b0)\n"
"{\n"
" float4x4 mv;\n"
" float4x4 mvInv;\n"
" float4x4 proj;\n"
"};\n";
}
else
{
retval = hecl::Format("cbuffer HECLVertUniform : register(b0)\n"
} else {
retval = hecl::Format(
"cbuffer HECLVertUniform : register(b0)\n"
"{\n"
" float4x4 objs[%u];\n"
" float4x4 objsInv[%u];\n"
@ -104,7 +98,8 @@ std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionC
"};\n",
skinSlots, skinSlots);
}
retval += "struct TCGMtx\n"
retval +=
"struct TCGMtx\n"
"{\n"
" float4x4 mtx;\n"
" float4x4 postMtx;\n"
@ -115,7 +110,8 @@ std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionC
"};\n";
if (reflectionCoords)
retval += "cbuffer HECLReflectMtx : register(b3)\n"
retval +=
"cbuffer HECLReflectMtx : register(b3)\n"
"{\n"
" float4x4 indMtx;\n"
" float4x4 reflectMtx;\n"
@ -126,18 +122,15 @@ std::string HLSL::GenerateVertUniformStruct(unsigned skinSlots, bool reflectionC
return retval;
}
std::string HLSL::GenerateAlphaTest() const
{
std::string HLSL::GenerateAlphaTest() const {
return " if (colorOut.a < 0.01)\n"
" {\n"
" discard;\n"
" }\n";
}
std::string HLSL::GenerateReflectionExpr(ReflectionType type) const
{
switch (type)
{
std::string HLSL::GenerateReflectionExpr(ReflectionType type) const {
switch (type) {
case ReflectionType::None:
default:
return "float3(0.0, 0.0, 0.0)";
@ -149,43 +142,41 @@ std::string HLSL::GenerateReflectionExpr(ReflectionType type) const
}
}
void HLSL::reset(const IR& ir, Diagnostics& diag)
{
void HLSL::reset(const IR& ir, Diagnostics& diag) {
/* Common programmable interpretation */
ProgrammableCommon::reset(ir, diag, "HLSL");
}
std::string HLSL::makeVert(unsigned col, unsigned uv, unsigned w,
unsigned s, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const
{
std::string retval =
GenerateVertInStruct(col, uv, w) + "\n" +
std::string HLSL::makeVert(unsigned col, unsigned uv, unsigned w, unsigned s, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const {
std::string retval = GenerateVertInStruct(col, uv, w) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateVertUniformStruct(s, reflectionType != ReflectionType::None) + "\n" +
"VertToFrag main(in VertData v)\n"
"{\n"
" VertToFrag vtf;\n";
if (s)
{
if (s) {
/* skinned */
retval += " float4 objPos = float4(0.0,0.0,0.0,0.0);\n"
retval +=
" float4 objPos = float4(0.0,0.0,0.0,0.0);\n"
" float4 objNorm = float4(0.0,0.0,0.0,0.0);\n";
for (size_t i=0 ; i<s ; ++i)
retval += hecl::Format(" objPos += mul(mv[%" PRISize "], float4(v.posIn, 1.0)) * v.weightIn[%" PRISize "][%" PRISize "];\n"
for (size_t i = 0; i < s; ++i)
retval += hecl::Format(
" objPos += mul(mv[%" PRISize "], float4(v.posIn, 1.0)) * v.weightIn[%" PRISize "][%" PRISize
"];\n"
" objNorm += mul(mvInv[%" PRISize "], float4(v.normIn, 1.0)) * v.weightIn[%" PRISize "][%" PRISize "];\n",
i, i/4, i%4, i, i/4, i%4);
retval += " objPos[3] = 1.0;\n"
i, i / 4, i % 4, i, i / 4, i % 4);
retval +=
" objPos[3] = 1.0;\n"
" objNorm = float4(normalize(objNorm.xyz), 0.0);\n"
" vtf.mvPos = mul(mv, objPos);\n"
" vtf.mvNorm = float4(normalize(mul(mvInv, objNorm).xyz), 0.0);\n"
" vtf.mvpPos = mul(proj, vtf.mvPos);\n";
}
else
{
} else {
/* non-skinned */
retval += " float4 objPos = float4(posIn, 1.0);\n"
retval +=
" float4 objPos = float4(posIn, 1.0);\n"
" float4 objNorm = float4(normIn, 0.0);\n"
" vtf.mvPos = mul(mv, objPos);\n"
" vtf.mvNorm = mul(mvInv, objNorm);\n"
@ -195,51 +186,50 @@ std::string HLSL::makeVert(unsigned col, unsigned uv, unsigned w,
retval += " float4 tmpProj;\n";
int tcgIdx = 0;
for (const TexCoordGen& tcg : m_tcgs)
{
for (const TexCoordGen& tcg : m_tcgs) {
if (tcg.m_mtx < 0)
retval += hecl::Format(" vtf.tcgs[%u] = %s;\n", tcgIdx,
EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str());
retval += hecl::Format(" vtf.tcgs[%u] = %s;\n", tcgIdx, EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str());
else
retval += hecl::Format(" tmpProj = mul(texMtxs[%u].postMtx, float4(%s(mul(texMtxs[%u].mtx, %s).xyz), 1.0));\n"
" vtf.tcgs[%u] = (tmpProj / tmpProj.w).xy;\n", tcg.m_mtx,
tcg.m_norm ? "normalize" : "", tcg.m_mtx,
EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(), tcgIdx);
retval += hecl::Format(
" tmpProj = mul(texMtxs[%u].postMtx, float4(%s(mul(texMtxs[%u].mtx, %s).xyz), 1.0));\n"
" vtf.tcgs[%u] = (tmpProj / tmpProj.w).xy;\n",
tcg.m_mtx, tcg.m_norm ? "normalize" : "", tcg.m_mtx, EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(),
tcgIdx);
++tcgIdx;
}
for (int i=0 ; i<extTexCount ; ++i)
{
for (int i = 0; i < extTexCount; ++i) {
const TextureInfo& extTex = extTexs[i];
if (extTex.mtxIdx < 0)
retval += hecl::Format(" vtf.extTcgs[%u] = %s;\n", i,
EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str());
retval += hecl::Format(" vtf.extTcgs[%u] = %s;\n", i, EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str());
else
retval += hecl::Format(" tmpProj = mul(texMtxs[%u].postMtx, float4(%s(mul(texMtxs[%u].mtx, %s).xyz), 1.0));\n"
retval += hecl::Format(
" tmpProj = mul(texMtxs[%u].postMtx, float4(%s(mul(texMtxs[%u].mtx, %s).xyz), 1.0));\n"
" vtf.extTcgs[%u] = (tmpProj / tmpProj.w).xy;\n",
extTex.mtxIdx, extTex.normalize ? "normalize" : "", extTex.mtxIdx,
EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str(), i);
}
if (reflectionType != ReflectionType::None)
retval += " vtf.reflectTcgs[0] = normalize(mul(indMtx, float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + float2(0.5, 0.5);\n"
retval +=
" vtf.reflectTcgs[0] = normalize(mul(indMtx, float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + float2(0.5, "
"0.5);\n"
" vtf.reflectTcgs[1] = mul(reflectMtx, float4(v.posIn, 1.0)).xy;\n"
" vtf.reflectAlpha = reflectAlpha;\n";
return retval + " return vtf;\n"
return retval +
" return vtf;\n"
"}\n";
}
std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting) const
{
std::string HLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting) const {
std::string lightingSrc;
if (!lighting.m_source.empty())
lightingSrc = lighting.m_source;
else
lightingSrc = "static const float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
lightingSrc =
"static const float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
"static const float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n"
"static const float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n"
"static const float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n";
@ -248,27 +238,22 @@ std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
if (m_texMapEnd)
texMapDecl = hecl::Format("Texture2D texs[%u] : register(t0);\n", m_texMapEnd);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("Texture2D reflectionIndTex : register(t%u);\n"
texMapDecl += hecl::Format(
"Texture2D reflectionIndTex : register(t%u);\n"
"Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd, m_texMapEnd+1);
m_texMapEnd, m_texMapEnd + 1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd);
std::string retval =
std::string("#define BLEND_SRC_") + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n", m_texMapEnd);
std::string retval = std::string("#define BLEND_SRC_") + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
"#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
"SamplerState samp : register(s0);\n"
"SamplerState clampSamp : register(s1);\n"
"SamplerState reflectSamp : register(s2);\n" +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) +
texMapDecl + "\n" +
lightingSrc + "\n" +
(!alphaTest ? "\n[earlydepthstencil]\n" : "\n") +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) + texMapDecl + "\n" +
lightingSrc + "\n" + (!alphaTest ? "\n[earlydepthstencil]\n" : "\n") +
"float4 main(in VertToFrag vtf) : SV_Target0\n{\n";
if (m_lighting)
{
if (m_lighting) {
if (!lighting.m_entry.empty())
retval += hecl::Format(" float4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf);\n",
lighting.m_entry.data());
@ -278,8 +263,8 @@ std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
unsigned sampIdx = 0;
for (const TexSampling& sampling : m_texSamplings)
retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx,
sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
@ -292,18 +277,15 @@ std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n";
}
std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting,
const Function& post, size_t extTexCount,
const TextureInfo* extTexs) const
{
std::string HLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting, const Function& post,
size_t extTexCount, const TextureInfo* extTexs) const {
std::string lightingSrc;
if (!lighting.m_source.empty())
lightingSrc = lighting.m_source;
else
lightingSrc = "static const float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
lightingSrc =
"static const float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
"static const float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n"
"static const float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n"
"static const float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n";
@ -320,41 +302,32 @@ std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
if (m_texMapEnd)
texMapDecl = hecl::Format("Texture2D texs[%u] : register(t0);\n", m_texMapEnd);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format("Texture2D reflectionIndTex : register(t%u);\n"
texMapDecl += hecl::Format(
"Texture2D reflectionIndTex : register(t%u);\n"
"Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd, m_texMapEnd+1);
m_texMapEnd, m_texMapEnd + 1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n",
m_texMapEnd);
texMapDecl += hecl::Format("Texture2D reflectionTex : register(t%u);\n", m_texMapEnd);
uint32_t extTexBits = 0;
for (int i=0 ; i<extTexCount ; ++i)
{
for (int i = 0; i < extTexCount; ++i) {
const TextureInfo& extTex = extTexs[i];
if (!(extTexBits & (1 << extTex.mapIdx)))
{
texMapDecl += hecl::Format("Texture2D extTex%u : register(t%u);\n",
extTex.mapIdx, extTex.mapIdx);
if (!(extTexBits & (1 << extTex.mapIdx))) {
texMapDecl += hecl::Format("Texture2D extTex%u : register(t%u);\n", extTex.mapIdx, extTex.mapIdx);
extTexBits |= (1 << extTex.mapIdx);
}
}
std::string retval =
std::string("#define BLEND_SRC_") + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
std::string retval = std::string("#define BLEND_SRC_") + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
"#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
"SamplerState samp : register(s0);\n"
"SamplerState clampSamp : register(s1);\n"
"SamplerState reflectSamp : register(s2);\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) +
texMapDecl + "\n" +
lightingSrc + "\n" +
postSrc +
(!alphaTest ? "\n[earlydepthstencil]\n" : "\n") +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + texMapDecl +
"\n" + lightingSrc + "\n" + postSrc + (!alphaTest ? "\n[earlydepthstencil]\n" : "\n") +
"float4 main(in VertToFrag vtf) : SV_Target0\n{\n";
if (m_lighting)
{
if (m_lighting) {
if (!lighting.m_entry.empty())
retval += hecl::Format(" float4 lighting = %s(vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf);\n",
lighting.m_entry.data());
@ -364,18 +337,20 @@ std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
unsigned sampIdx = 0;
for (const TexSampling& sampling : m_texSamplings)
retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
retval += hecl::Format(" float4 sampling%u = texs[%u].Sample(samp, vtf.tcgs[%u]);\n", sampIdx++, sampling.mapIdx,
sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
retval += " float4 colorOut;\n";
if (m_alphaExpr.size())
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr +
" + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
else
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0)) * mulColor;\n";
retval += " colorOut = " + postEntry + "(" + (postEntry.size() ? "vtf, " : "") + "float4(" + m_colorExpr +
" + " + reflectionExpr + ", 1.0)) * mulColor;\n";
return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n";
}
}
} // namespace hecl::Backend

View File

@ -5,41 +5,37 @@
static logvisor::Module Log("hecl::Backend::Metal");
namespace hecl::Backend
{
namespace hecl::Backend {
std::string Metal::EmitTexGenSource2(TexGenSrc src, int uvIdx) const
{
switch (src)
{
std::string Metal::EmitTexGenSource2(TexGenSrc src, int uvIdx) const {
switch (src) {
case TexGenSrc::Position:
return "objPos.xy\n";
case TexGenSrc::Normal:
return "objNorm.xy\n";
case TexGenSrc::UV:
return hecl::Format("v.uvIn%u", uvIdx);
default: break;
default:
break;
}
return std::string();
}
std::string Metal::EmitTexGenSource4(TexGenSrc src, int uvIdx) const
{
switch (src)
{
std::string Metal::EmitTexGenSource4(TexGenSrc src, int uvIdx) const {
switch (src) {
case TexGenSrc::Position:
return "float4(objPos.xyz, 1.0)\n";
case TexGenSrc::Normal:
return "float4(objNorm.xyz, 1.0)\n";
case TexGenSrc::UV:
return hecl::Format("float4(v.uvIn%u, 0.0, 1.0)", uvIdx);
default: break;
default:
break;
}
return std::string();
}
std::string Metal::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const
{
std::string Metal::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) const {
std::string retval =
"struct VertData\n"
"{\n"
@ -47,29 +43,25 @@ std::string Metal::GenerateVertInStruct(unsigned col, unsigned uv, unsigned w) c
" float3 normIn [[ attribute(1) ]];\n";
unsigned idx = 2;
if (col)
{
for (unsigned i=0 ; i<col ; ++i, ++idx)
if (col) {
for (unsigned i = 0; i < col; ++i, ++idx)
retval += hecl::Format(" float4 colIn%u [[ attribute(%u) ]];\n", i, idx);
}
if (uv)
{
for (unsigned i=0 ; i<uv ; ++i, ++idx)
if (uv) {
for (unsigned i = 0; i < uv; ++i, ++idx)
retval += hecl::Format(" float2 uvIn%u [[ attribute(%u) ]];\n", i, idx);
}
if (w)
{
for (unsigned i=0 ; i<w ; ++i, ++idx)
if (w) {
for (unsigned i = 0; i < w; ++i, ++idx)
retval += hecl::Format(" float4 weightIn%u [[ attribute(%u) ]];\n", i, idx);
}
return retval + "};\n";
}
std::string Metal::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const
{
std::string Metal::GenerateVertToFragStruct(size_t extTexCount, bool reflectionCoords) const {
std::string retval =
"struct VertToFrag\n"
"{\n"
@ -78,26 +70,26 @@ std::string Metal::GenerateVertToFragStruct(size_t extTexCount, bool reflectionC
" float4 mvNorm;\n";
if (m_tcgs.size())
for (size_t i=0 ; i<m_tcgs.size() ; ++i)
for (size_t i = 0; i < m_tcgs.size(); ++i)
retval += hecl::Format(" float2 tcgs%" PRISize ";\n", i);
if (extTexCount)
for (size_t i=0 ; i<extTexCount ; ++i)
for (size_t i = 0; i < extTexCount; ++i)
retval += hecl::Format(" float2 extTcgs%" PRISize ";\n", i);
if (reflectionCoords)
retval += " float2 reflectTcgs0;\n"
retval +=
" float2 reflectTcgs0;\n"
" float2 reflectTcgs1;\n"
" float reflectAlpha;\n";
return retval + "};\n";
}
std::string Metal::GenerateVertUniformStruct(unsigned skinSlots) const
{
std::string Metal::GenerateVertUniformStruct(unsigned skinSlots) const {
std::string retval;
if (skinSlots == 0)
{
retval = "struct HECLVertUniform\n"
if (skinSlots == 0) {
retval =
"struct HECLVertUniform\n"
"{\n"
" float4x4 mv;\n"
" float4x4 mvInv;\n"
@ -105,10 +97,9 @@ std::string Metal::GenerateVertUniformStruct(unsigned skinSlots) const
"};\n"
"struct TexMtxs {float4x4 mtx; float4x4 postMtx;};\n"
"struct ReflectTexMtxs {float4x4 indMtx; float4x4 reflectMtx; float reflectAlpha;};\n";
}
else
{
retval = hecl::Format("struct HECLVertUniform\n"
} else {
retval = hecl::Format(
"struct HECLVertUniform\n"
"{\n"
" float4x4 objs[%u];\n"
" float4x4 objsInv[%u];\n"
@ -123,8 +114,7 @@ std::string Metal::GenerateVertUniformStruct(unsigned skinSlots) const
return retval;
}
std::string Metal::GenerateFragOutStruct() const
{
std::string Metal::GenerateFragOutStruct() const {
return "struct FragOut\n"
"{\n"
" float4 color [[ color(0) ]];\n"
@ -132,18 +122,15 @@ std::string Metal::GenerateFragOutStruct() const
"};\n";
}
std::string Metal::GenerateAlphaTest() const
{
std::string Metal::GenerateAlphaTest() const {
return " if (out.color.a < 0.01)\n"
" {\n"
" discard_fragment();\n"
" }\n";
}
std::string Metal::GenerateReflectionExpr(ReflectionType type) const
{
switch (type)
{
std::string Metal::GenerateReflectionExpr(ReflectionType type) const {
switch (type) {
case ReflectionType::None:
default:
return "float3(0.0, 0.0, 0.0)";
@ -155,47 +142,47 @@ std::string Metal::GenerateReflectionExpr(ReflectionType type) const
}
}
void Metal::reset(const IR& ir, Diagnostics& diag)
{
void Metal::reset(const IR& ir, Diagnostics& diag) {
/* Common programmable interpretation */
ProgrammableCommon::reset(ir, diag, "Metal");
}
std::string Metal::makeVert(unsigned col, unsigned uv, unsigned w,
unsigned s, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const
{
std::string Metal::makeVert(unsigned col, unsigned uv, unsigned w, unsigned s, size_t extTexCount,
const TextureInfo* extTexs, ReflectionType reflectionType) const {
std::string tmStr = ",\nconstant TexMtxs* texMtxs [[ buffer(3) ]]";
if (reflectionType != ReflectionType::None)
tmStr += ",\nconstant ReflectTexMtxs& reflectMtxs [[ buffer(5) ]]";
std::string retval = "#include <metal_stdlib>\nusing namespace metal;\n" +
GenerateVertInStruct(col, uv, w) + "\n" +
std::string retval = "#include <metal_stdlib>\nusing namespace metal;\n" + GenerateVertInStruct(col, uv, w) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateVertUniformStruct(s) +
"\nvertex VertToFrag vmain(VertData v [[ stage_in ]],\n"
" constant HECLVertUniform& vu [[ buffer(2) ]]" + tmStr + ")\n"
" constant HECLVertUniform& vu [[ buffer(2) ]]" +
tmStr +
")\n"
"{\n"
" VertToFrag vtf;\n";
if (s)
{
if (s) {
/* skinned */
retval += " float4 objPos = float4(0.0,0.0,0.0,0.0);\n"
retval +=
" float4 objPos = float4(0.0,0.0,0.0,0.0);\n"
" float4 objNorm = float4(0.0,0.0,0.0,0.0);\n";
for (size_t i=0 ; i<s ; ++i)
retval += hecl::Format(" objPos += (vu.objs[%" PRISize "] * float4(v.posIn, 1.0)) * v.weightIn%" PRISize "[%" PRISize "];\n"
for (size_t i = 0; i < s; ++i)
retval += hecl::Format(
" objPos += (vu.objs[%" PRISize "] * float4(v.posIn, 1.0)) * v.weightIn%" PRISize "[%" PRISize
"];\n"
" objNorm += (vu.objsInv[%" PRISize "] * float4(v.normIn, 1.0)) * v.weightIn%" PRISize "[%" PRISize "];\n",
i, i/4, i%4, i, i/4, i%4);
retval += " objPos[3] = 1.0;\n"
i, i / 4, i % 4, i, i / 4, i % 4);
retval +=
" objPos[3] = 1.0;\n"
" objNorm = float4(normalize(objNorm.xyz), 0.0);\n"
" vtf.mvPos = vu.mv * objPos;\n"
" vtf.mvNorm = float4(normalize((vu.mvInv * objNorm).xyz), 0.0);\n"
" vtf.mvpPos = vu.proj * vtf.mvPos;\n";
}
else
{
} else {
/* non-skinned */
retval += " float4 objPos = float4(v.posIn, 1.0);\n"
retval +=
" float4 objPos = float4(v.posIn, 1.0);\n"
" float4 objNorm = float4(v.normIn, 0.0);\n"
" vtf.mvPos = vu.mv * objPos;\n"
" vtf.mvNorm = vu.mvInv * objNorm;\n"
@ -205,98 +192,94 @@ std::string Metal::makeVert(unsigned col, unsigned uv, unsigned w,
retval += " float4 tmpProj;\n";
int tcgIdx = 0;
for (const TexCoordGen& tcg : m_tcgs)
{
for (const TexCoordGen& tcg : m_tcgs) {
if (tcg.m_mtx < 0)
retval += hecl::Format(" vtf.tcgs%u = %s;\n", tcgIdx,
EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str());
retval += hecl::Format(" vtf.tcgs%u = %s;\n", tcgIdx, EmitTexGenSource2(tcg.m_src, tcg.m_uvIdx).c_str());
else
retval += hecl::Format(" tmpProj = texMtxs[%u].postMtx * float4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
" vtf.tcgs%u = (tmpProj / tmpProj.w).xy;\n", tcg.m_mtx,
tcg.m_norm ? "normalize" : "", tcg.m_mtx,
EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(), tcgIdx);
retval += hecl::Format(
" tmpProj = texMtxs[%u].postMtx * float4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
" vtf.tcgs%u = (tmpProj / tmpProj.w).xy;\n",
tcg.m_mtx, tcg.m_norm ? "normalize" : "", tcg.m_mtx, EmitTexGenSource4(tcg.m_src, tcg.m_uvIdx).c_str(),
tcgIdx);
++tcgIdx;
}
for (int i=0 ; i<extTexCount ; ++i)
{
for (int i = 0; i < extTexCount; ++i) {
const TextureInfo& extTex = extTexs[i];
if (extTex.mtxIdx < 0)
retval += hecl::Format(" vtf.extTcgs%u = %s;\n", i,
EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str());
retval += hecl::Format(" vtf.extTcgs%u = %s;\n", i, EmitTexGenSource2(extTex.src, extTex.uvIdx).c_str());
else
retval += hecl::Format(" tmpProj = texMtxs[%u].postMtx * float4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
" vtf.extTcgs%u = (tmpProj / tmpProj.w).xy;\n", extTex.mtxIdx,
extTex.normalize ? "normalize" : "", extTex.mtxIdx,
retval += hecl::Format(
" tmpProj = texMtxs[%u].postMtx * float4(%s((texMtxs[%u].mtx * %s).xyz), 1.0);\n"
" vtf.extTcgs%u = (tmpProj / tmpProj.w).xy;\n",
extTex.mtxIdx, extTex.normalize ? "normalize" : "", extTex.mtxIdx,
EmitTexGenSource4(extTex.src, extTex.uvIdx).c_str(), i);
}
if (reflectionType != ReflectionType::None)
retval += " vtf.reflectTcgs0 = normalize((reflectMtxs.indMtx * float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + float2(0.5, 0.5);\n"
retval +=
" vtf.reflectTcgs0 = normalize((reflectMtxs.indMtx * float4(v.posIn, 1.0)).xz) * float2(0.5, 0.5) + "
"float2(0.5, 0.5);\n"
" vtf.reflectTcgs1 = (reflectMtxs.reflectMtx * float4(v.posIn, 1.0)).xy;\n"
" vtf.reflectAlpha = reflectMtxs.reflectAlpha;\n";
return retval + " return vtf;\n}\n";
}
std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting) const
{
std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting) const {
std::string lightingSrc;
if (!lighting.m_source.empty())
lightingSrc = lighting.m_source;
std::string texMapDecl;
if (m_texMapEnd)
for (int i=0 ; i<m_texMapEnd ; ++i)
for (int i = 0; i < m_texMapEnd; ++i)
texMapDecl += hecl::Format(",\ntexture2d<float> tex%u [[ texture(%u) ]]", i, i);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
texMapDecl += hecl::Format(
",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd, m_texMapEnd+1);
m_texMapEnd, m_texMapEnd + 1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd);
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n", m_texMapEnd);
std::string blockCall;
for (size_t i=0 ; i<blockCount ; ++i)
{
for (size_t i = 0; i < blockCount; ++i) {
texMapDecl += hecl::Format(",\nconstant %s& block%" PRISize " [[ buffer(%" PRISize ") ]]", blockNames[i], i, i + 4);
if (blockCall.size())
blockCall += ", ";
blockCall += hecl::Format("block%" PRISize, i);
}
std::string retval = std::string("#include <metal_stdlib>\nusing namespace metal;\n") +
"#define BLEND_SRC_" + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
"#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) + "\n" +
GenerateFragOutStruct() + "\n" +
std::string retval =
std::string("#include <metal_stdlib>\nusing namespace metal;\n") + "#define BLEND_SRC_" +
BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" +
BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
GenerateVertToFragStruct(0, reflectionType != ReflectionType::None) + "\n" + GenerateFragOutStruct() + "\n" +
lightingSrc + "\n" +
"fragment FragOut fmain(VertToFrag vtf [[ stage_in ]],\n"
"sampler samp [[ sampler(0) ]], sampler clampSamp [[ sampler(1) ]], sampler reflectSamp [[ sampler(2) ]]" + texMapDecl + ")\n"
"sampler samp [[ sampler(0) ]], sampler clampSamp [[ sampler(1) ]], sampler reflectSamp [[ sampler(2) ]]" +
texMapDecl +
")\n"
"{\n"
" FragOut out;\n";
if (!lighting.m_source.empty())
{
retval += " float4 colorReg0 = block0.colorReg0;\n"
if (!lighting.m_source.empty()) {
retval +=
" float4 colorReg0 = block0.colorReg0;\n"
" float4 colorReg1 = block0.colorReg1;\n"
" float4 colorReg2 = block0.colorReg2;\n"
" float4 mulColor = block0.mulColor;\n";
}
else
{
retval += " float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
} else {
retval +=
" float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
" float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n"
" float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n"
" float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n";
}
if (m_lighting)
{
if (m_lighting) {
if (!lighting.m_entry.empty())
retval += hecl::Format(" float4 lighting = %s(%s, vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf);\n",
lighting.m_entry.data(), blockCall.c_str());
@ -306,8 +289,8 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
unsigned sampIdx = 0;
for (const TexSampling& sampling : m_texSamplings)
retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n", sampIdx++, sampling.mapIdx,
sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
@ -322,13 +305,9 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
"}\n";
}
std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor,
const Function& lighting,
const Function& post, size_t extTexCount,
const TextureInfo* extTexs) const
{
std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest, ReflectionType reflectionType,
BlendFactor srcFactor, BlendFactor dstFactor, const Function& lighting,
const Function& post, size_t extTexCount, const TextureInfo* extTexs) const {
std::string lightingSrc;
if (!lighting.m_source.empty())
lightingSrc = lighting.m_source;
@ -346,32 +325,29 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
postEntry = post.m_entry;
int extTexBits = 0;
for (int i=0 ; i<extTexCount ; ++i)
{
for (int i = 0; i < extTexCount; ++i) {
const TextureInfo& extTex = extTexs[i];
extTexBits |= 1 << extTex.mapIdx;
}
std::string texMapDecl;
if (m_texMapEnd)
for (int i=0 ; i<m_texMapEnd ; ++i)
for (int i = 0; i < m_texMapEnd; ++i)
if (!(extTexBits & (1 << i)))
texMapDecl += hecl::Format(",\ntexture2d<float> tex%u [[ texture(%u) ]]", i, i);
if (reflectionType == ReflectionType::Indirect)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
texMapDecl += hecl::Format(
",\ntexture2d<float> reflectionIndTex [[ texture(%u) ]]\n"
",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd, m_texMapEnd+1);
m_texMapEnd, m_texMapEnd + 1);
else if (reflectionType == ReflectionType::Simple)
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n",
m_texMapEnd);
texMapDecl += hecl::Format(",\ntexture2d<float> reflectionTex [[ texture(%u) ]]\n", m_texMapEnd);
std::string extTexCall;
int extTexBits2 = 0;
for (int i=0 ; i<extTexCount ; ++i)
{
for (int i = 0; i < extTexCount; ++i) {
const TextureInfo& extTex = extTexs[i];
if (!(extTexBits2 & (1 << extTex.mapIdx)))
{
if (!(extTexBits2 & (1 << extTex.mapIdx))) {
if (extTexCall.size())
extTexCall += ", ";
extTexCall += hecl::Format("tex%u", extTex.mapIdx);
@ -381,71 +357,74 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
}
std::string blockCall;
for (size_t i=0 ; i<blockCount ; ++i)
{
for (size_t i = 0; i < blockCount; ++i) {
texMapDecl += hecl::Format(",\nconstant %s& block%" PRISize " [[ buffer(%" PRISize ") ]]", blockNames[i], i, i + 4);
if (blockCall.size())
blockCall += ", ";
blockCall += hecl::Format("block%" PRISize, i);
}
std::string retval = std::string("#include <metal_stdlib>\nusing namespace metal;\n") +
"#define BLEND_SRC_" + BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" +
"#define BLEND_DST_" + BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" +
GenerateFragOutStruct() + "\n" +
lightingSrc + "\n" +
postSrc + "\n" +
std::string retval =
std::string("#include <metal_stdlib>\nusing namespace metal;\n") + "#define BLEND_SRC_" +
BlendFactorToDefine(srcFactor, m_blendSrc) + "\n" + "#define BLEND_DST_" +
BlendFactorToDefine(dstFactor, m_blendDst) + "\n" +
GenerateVertToFragStruct(extTexCount, reflectionType != ReflectionType::None) + "\n" + GenerateFragOutStruct() +
"\n" + lightingSrc + "\n" + postSrc + "\n" +
"fragment FragOut fmain(VertToFrag vtf [[ stage_in ]],\n"
"sampler samp [[ sampler(0) ]], sampler clampSamp [[ sampler(1) ]], sampler reflectSamp [[ sampler(2) ]]" + texMapDecl + ")\n"
"sampler samp [[ sampler(0) ]], sampler clampSamp [[ sampler(1) ]], sampler reflectSamp [[ sampler(2) ]]" +
texMapDecl +
")\n"
"{\n"
" FragOut out;\n";
if (!lighting.m_source.empty())
{
retval += " float4 colorReg0 = block0.colorReg0;\n"
if (!lighting.m_source.empty()) {
retval +=
" float4 colorReg0 = block0.colorReg0;\n"
" float4 colorReg1 = block0.colorReg1;\n"
" float4 colorReg2 = block0.colorReg2;\n"
" float4 mulColor = block0.mulColor;\n";
}
else
{
retval += " float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
} else {
retval +=
" float4 colorReg0 = float4(1.0, 1.0, 1.0, 1.0);\n"
" float4 colorReg1 = float4(1.0, 1.0, 1.0, 1.0);\n"
" float4 colorReg2 = float4(1.0, 1.0, 1.0, 1.0);\n"
" float4 mulColor = float4(1.0, 1.0, 1.0, 1.0);\n";
}
if (m_lighting)
{
if (!lighting.m_entry.empty())
{
retval += " float4 lighting = " + lightingEntry + "(" + blockCall + ", vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf" +
(!strncmp(lighting.m_entry.data(), "EXT", 3) ? (extTexCall.size() ? (", samp, clampSamp," + extTexCall) : "") : "") + ");\n";
}
else
if (m_lighting) {
if (!lighting.m_entry.empty()) {
retval +=
" float4 lighting = " + lightingEntry + "(" + blockCall +
", vtf.mvPos.xyz, normalize(vtf.mvNorm.xyz), vtf" +
(!strncmp(lighting.m_entry.data(), "EXT", 3) ? (extTexCall.size() ? (", samp, clampSamp," + extTexCall) : "")
: "") +
");\n";
} else
retval += " float4 lighting = float4(1.0,1.0,1.0,1.0);\n";
}
unsigned sampIdx = 0;
for (const TexSampling& sampling : m_texSamplings)
retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n",
sampIdx++, sampling.mapIdx, sampling.tcgIdx);
retval += hecl::Format(" float4 sampling%u = tex%u.sample(samp, vtf.tcgs%u);\n", sampIdx++, sampling.mapIdx,
sampling.tcgIdx);
std::string reflectionExpr = GenerateReflectionExpr(reflectionType);
if (m_alphaExpr.size())
{
if (m_alphaExpr.size()) {
retval += " out.color = " + postEntry + "(" +
(postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") +
(!strncmp(post.m_entry.data(), "EXT", 3) ? (extTexCall.size() ? ("samp, clampSamp," + extTexCall + ", ") : "") : "")) : "") +
(!strncmp(post.m_entry.data(), "EXT", 3)
? (extTexCall.size() ? ("samp, clampSamp," + extTexCall + ", ") : "")
: ""))
: "") +
"float4(" + m_colorExpr + " + " + reflectionExpr + ", " + m_alphaExpr + ")) * mulColor;\n";
}
else
{
} else {
retval += " out.color = " + postEntry + "(" +
(postEntry.size() ? ("vtf, " + (blockCall.size() ? (blockCall + ", ") : "") +
(!strncmp(post.m_entry.data(), "EXT", 3) ? (extTexCall.size() ? ("samp, clampSamp," + extTexCall + ", ") : "") : "")) : "") +
(!strncmp(post.m_entry.data(), "EXT", 3)
? (extTexCall.size() ? ("samp, clampSamp," + extTexCall + ", ") : "")
: ""))
: "") +
"float4(" + m_colorExpr + " + " + reflectionExpr + ", 1.0)) * mulColor;\n";
}
@ -455,5 +434,4 @@ std::string Metal::makeFrag(size_t blockCount, const char** blockNames, bool alp
"}\n";
}
}
} // namespace hecl::Backend

View File

@ -1,13 +1,10 @@
#include "hecl/Backend/ProgrammableCommon.hpp"
#include <map>
namespace hecl::Backend
{
namespace hecl::Backend {
const char* ProgrammableCommon::BlendFactorToDefine(BlendFactor factor, BlendFactor defaultFactor)
{
switch (factor)
{
const char* ProgrammableCommon::BlendFactorToDefine(BlendFactor factor, BlendFactor defaultFactor) {
switch (factor) {
case BlendFactor::Zero:
return "ZERO";
case BlendFactor::One:
@ -37,10 +34,8 @@ const char* ProgrammableCommon::BlendFactorToDefine(BlendFactor factor, BlendFac
}
}
unsigned ProgrammableCommon::addTexCoordGen(TexGenSrc src, int uvIdx, int mtx, bool normalize)
{
for (unsigned i=0 ; i<m_tcgs.size() ; ++i)
{
unsigned ProgrammableCommon::addTexCoordGen(TexGenSrc src, int uvIdx, int mtx, bool normalize) {
for (unsigned i = 0; i < m_tcgs.size(); ++i) {
TexCoordGen& tcg = m_tcgs[i];
if (tcg.m_src == src && tcg.m_uvIdx == uvIdx && tcg.m_mtx == mtx && tcg.m_norm == normalize)
return i;
@ -54,10 +49,8 @@ unsigned ProgrammableCommon::addTexCoordGen(TexGenSrc src, int uvIdx, int mtx, b
return m_tcgs.size() - 1;
}
unsigned ProgrammableCommon::addTexSampling(unsigned mapIdx, unsigned tcgIdx)
{
for (unsigned i=0 ; i<m_texSamplings.size() ; ++i)
{
unsigned ProgrammableCommon::addTexSampling(unsigned mapIdx, unsigned tcgIdx) {
for (unsigned i = 0; i < m_texSamplings.size(); ++i) {
TexSampling& samp = m_texSamplings[i];
if (samp.mapIdx == mapIdx && samp.tcgIdx == tcgIdx)
return i;
@ -71,53 +64,44 @@ unsigned ProgrammableCommon::addTexSampling(unsigned mapIdx, unsigned tcgIdx)
return m_texSamplings.size() - 1;
}
unsigned ProgrammableCommon::RecursiveTraceTexGen(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst, int mtx, bool normalize)
{
unsigned ProgrammableCommon::RecursiveTraceTexGen(const IR& ir, Diagnostics& diag, const IR::Instruction& inst, int mtx,
bool normalize) {
if (inst.m_op != IR::OpType::Call)
diag.reportBackendErr(inst.m_loc, "TexCoordGen resolution requires function");
const std::string& tcgName = inst.m_call.m_name;
if (!tcgName.compare("UV"))
{
if (!tcgName.compare("UV")) {
if (inst.getChildCount() < 1)
diag.reportBackendErr(inst.m_loc, "TexCoordGen UV(layerIdx) requires one argument");
const IR::Instruction& idxInst = inst.getChildInst(ir, 0);
auto& idxImm = idxInst.getImmVec();
return addTexCoordGen(TexGenSrc::UV, int(idxImm.simd[0]), mtx, normalize);
}
else if (!tcgName.compare("Normal"))
} else if (!tcgName.compare("Normal"))
return addTexCoordGen(TexGenSrc::Normal, -1, mtx, normalize);
else if (!tcgName.compare("View"))
return addTexCoordGen(TexGenSrc::Position, -1, mtx, normalize);
/* Otherwise treat as game-specific function */
const IR::Instruction& tcgSrcInst = inst.getChildInst(ir, 0);
unsigned idx = RecursiveTraceTexGen(ir, diag, tcgSrcInst, m_texMtxRefs.size(),
normalize || tcgName.back() == 'N');
unsigned idx = RecursiveTraceTexGen(ir, diag, tcgSrcInst, m_texMtxRefs.size(), normalize || tcgName.back() == 'N');
TexCoordGen& tcg = m_tcgs[idx];
m_texMtxRefs.push_back(idx);
tcg.m_gameFunction = tcgName;
tcg.m_gameArgs.clear();
for (int i=1 ; i<inst.getChildCount() ; ++i)
{
for (int i = 1; i < inst.getChildCount(); ++i) {
const IR::Instruction& ci = inst.getChildInst(ir, i);
tcg.m_gameArgs.push_back(ci.getImmVec());
}
return idx;
}
std::string ProgrammableCommon::RecursiveTraceColor(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst, bool toSwizzle)
{
switch (inst.m_op)
{
case IR::OpType::Call:
{
std::string ProgrammableCommon::RecursiveTraceColor(const IR& ir, Diagnostics& diag, const IR::Instruction& inst,
bool toSwizzle) {
switch (inst.m_op) {
case IR::OpType::Call: {
const std::string& name = inst.m_call.m_name;
bool normalize = false;
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN")))
{
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN"))) {
if (inst.getChildCount() < 2)
diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments");
@ -128,72 +112,56 @@ std::string ProgrammableCommon::RecursiveTraceColor(const IR& ir, Diagnostics& d
const IR::Instruction& tcgInst = inst.getChildInst(ir, 1);
unsigned texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, -1, normalize);
return toSwizzle ? EmitSamplingUseRaw(addTexSampling(mapIdx, texGenIdx)) :
EmitSamplingUseRGB(addTexSampling(mapIdx, texGenIdx));
}
else if (!name.compare("ColorReg"))
{
return toSwizzle ? EmitSamplingUseRaw(addTexSampling(mapIdx, texGenIdx))
: EmitSamplingUseRGB(addTexSampling(mapIdx, texGenIdx));
} else if (!name.compare("ColorReg")) {
const IR::Instruction& idxInst = inst.getChildInst(ir, 0);
unsigned idx = unsigned(idxInst.getImmVec().simd[0]);
return toSwizzle ? EmitColorRegUseRaw(idx) : EmitColorRegUseRGB(idx);
}
else if (!name.compare("Lighting"))
{
} else if (!name.compare("Lighting")) {
m_lighting = true;
return toSwizzle ? EmitLightingRaw() : EmitLightingRGB();
}
else if (!name.compare("vec3"))
{
} else if (!name.compare("vec3")) {
if (inst.getChildCount() < 3)
diag.reportBackendErr(inst.m_loc, "vec3(r,g,b) requires 3 arguments");
const IR::Instruction& aInst = inst.getChildInst(ir, 0);
const IR::Instruction& bInst = inst.getChildInst(ir, 1);
const IR::Instruction& cInst = inst.getChildInst(ir, 2);
return EmitVec3(RecursiveTraceAlpha(ir, diag, aInst, false),
RecursiveTraceAlpha(ir, diag, bInst, false),
return EmitVec3(RecursiveTraceAlpha(ir, diag, aInst, false), RecursiveTraceAlpha(ir, diag, bInst, false),
RecursiveTraceAlpha(ir, diag, cInst, false));
}
else
} else
diag.reportBackendErr(inst.m_loc, "unable to interpret '%s'", name.c_str());
break;
}
case IR::OpType::LoadImm:
{
case IR::OpType::LoadImm: {
const atVec4f& vec = inst.m_loadImm.m_immVec;
return EmitVec3(vec);
}
case IR::OpType::Arithmetic:
{
case IR::OpType::Arithmetic: {
ArithmeticOp op = inst.m_arithmetic.m_op;
const IR::Instruction& aInst = inst.getChildInst(ir, 0);
const IR::Instruction& bInst = inst.getChildInst(ir, 1);
std::string aTrace = RecursiveTraceColor(ir, diag, aInst, false);
std::string bTrace = RecursiveTraceColor(ir, diag, bInst, false);
switch (op)
{
case ArithmeticOp::Add:
{
switch (op) {
case ArithmeticOp::Add: {
return EmitAdd(aTrace, bTrace);
}
case ArithmeticOp::Subtract:
{
case ArithmeticOp::Subtract: {
return EmitSub(aTrace, bTrace);
}
case ArithmeticOp::Multiply:
{
case ArithmeticOp::Multiply: {
return EmitMult(aTrace, bTrace);
}
case ArithmeticOp::Divide:
{
case ArithmeticOp::Divide: {
return EmitDiv(aTrace, bTrace);
}
default:
diag.reportBackendErr(inst.m_loc, "invalid arithmetic op");
}
}
case IR::OpType::Swizzle:
{
case IR::OpType::Swizzle: {
const IR::Instruction& aInst = inst.getChildInst(ir, 0);
std::string aTrace = RecursiveTraceColor(ir, diag, aInst, true);
return EmitSwizzle3(diag, inst.m_loc, aTrace, inst.m_swizzle.m_idxs);
@ -205,17 +173,13 @@ std::string ProgrammableCommon::RecursiveTraceColor(const IR& ir, Diagnostics& d
return std::string();
}
std::string ProgrammableCommon::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag,
const IR::Instruction& inst, bool toSwizzle)
{
switch (inst.m_op)
{
case IR::OpType::Call:
{
std::string ProgrammableCommon::RecursiveTraceAlpha(const IR& ir, Diagnostics& diag, const IR::Instruction& inst,
bool toSwizzle) {
switch (inst.m_op) {
case IR::OpType::Call: {
const std::string& name = inst.m_call.m_name;
bool normalize = false;
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN")))
{
if (!name.compare("Texture") || (normalize = true && !name.compare("TextureN"))) {
if (inst.getChildCount() < 2)
diag.reportBackendErr(inst.m_loc, "Texture(map, texgen) requires 2 arguments");
@ -226,61 +190,48 @@ std::string ProgrammableCommon::RecursiveTraceAlpha(const IR& ir, Diagnostics& d
const IR::Instruction& tcgInst = inst.getChildInst(ir, 1);
unsigned texGenIdx = RecursiveTraceTexGen(ir, diag, tcgInst, -1, normalize);
return toSwizzle ? EmitSamplingUseRaw(addTexSampling(mapIdx, texGenIdx)) :
EmitSamplingUseAlpha(addTexSampling(mapIdx, texGenIdx));
}
else if (!name.compare("ColorReg"))
{
return toSwizzle ? EmitSamplingUseRaw(addTexSampling(mapIdx, texGenIdx))
: EmitSamplingUseAlpha(addTexSampling(mapIdx, texGenIdx));
} else if (!name.compare("ColorReg")) {
const IR::Instruction& idxInst = inst.getChildInst(ir, 0);
unsigned idx = unsigned(idxInst.getImmVec().simd[0]);
return toSwizzle ? EmitColorRegUseRaw(idx) : EmitColorRegUseAlpha(idx);
}
else if (!name.compare("Lighting"))
{
} else if (!name.compare("Lighting")) {
m_lighting = true;
return toSwizzle ? EmitLightingRaw() : EmitLightingAlpha();
}
else
} else
diag.reportBackendErr(inst.m_loc, "unable to interpret '%s'", name.c_str());
break;
}
case IR::OpType::LoadImm:
{
case IR::OpType::LoadImm: {
const atVec4f& vec = inst.m_loadImm.m_immVec;
return EmitVal(vec.simd[0]);
}
case IR::OpType::Arithmetic:
{
case IR::OpType::Arithmetic: {
ArithmeticOp op = inst.m_arithmetic.m_op;
const IR::Instruction& aInst = inst.getChildInst(ir, 0);
const IR::Instruction& bInst = inst.getChildInst(ir, 1);
std::string aTrace = RecursiveTraceAlpha(ir, diag, aInst, false);
std::string bTrace = RecursiveTraceAlpha(ir, diag, bInst, false);
switch (op)
{
case ArithmeticOp::Add:
{
switch (op) {
case ArithmeticOp::Add: {
return EmitAdd(aTrace, bTrace);
}
case ArithmeticOp::Subtract:
{
case ArithmeticOp::Subtract: {
return EmitSub(aTrace, bTrace);
}
case ArithmeticOp::Multiply:
{
case ArithmeticOp::Multiply: {
return EmitMult(aTrace, bTrace);
}
case ArithmeticOp::Divide:
{
case ArithmeticOp::Divide: {
return EmitDiv(aTrace, bTrace);
}
default:
diag.reportBackendErr(inst.m_loc, "invalid arithmetic op");
}
}
case IR::OpType::Swizzle:
{
case IR::OpType::Swizzle: {
const IR::Instruction& aInst = inst.getChildInst(ir, 0);
std::string aTrace = RecursiveTraceAlpha(ir, diag, aInst, true);
return EmitSwizzle1(diag, inst.m_loc, aTrace, inst.m_swizzle.m_idxs);
@ -292,8 +243,7 @@ std::string ProgrammableCommon::RecursiveTraceAlpha(const IR& ir, Diagnostics& d
return std::string();
}
void ProgrammableCommon::reset(const IR& ir, Diagnostics& diag, const char* backendName)
{
void ProgrammableCommon::reset(const IR& ir, Diagnostics& diag, const char* backendName) {
m_lighting = false;
m_texSamplings.clear();
m_texMapEnd = 0;
@ -306,50 +256,38 @@ void ProgrammableCommon::reset(const IR& ir, Diagnostics& diag, const char* back
/* Final instruction is the root call by hecl convention */
const IR::Instruction& rootCall = ir.m_instructions.back();
if (!rootCall.m_call.m_name.compare("HECLOpaque"))
{
if (!rootCall.m_call.m_name.compare("HECLOpaque")) {
m_blendSrc = BlendFactor::One;
m_blendDst = BlendFactor::Zero;
}
else if (!rootCall.m_call.m_name.compare("HECLAlpha"))
{
} else if (!rootCall.m_call.m_name.compare("HECLAlpha")) {
m_blendSrc = BlendFactor::SrcAlpha;
m_blendDst = BlendFactor::InvSrcAlpha;
}
else if (!rootCall.m_call.m_name.compare("HECLAdditive"))
{
} else if (!rootCall.m_call.m_name.compare("HECLAdditive")) {
m_blendSrc = BlendFactor::SrcAlpha;
m_blendDst = BlendFactor::One;
}
else
{
diag.reportBackendErr(rootCall.m_loc, "%s backend doesn't handle '%s' root",
backendName, rootCall.m_call.m_name.c_str());
} else {
diag.reportBackendErr(rootCall.m_loc, "%s backend doesn't handle '%s' root", backendName,
rootCall.m_call.m_name.c_str());
return;
}
/* Follow Color Chain */
const IR::Instruction& colorRoot =
ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(0));
const IR::Instruction& colorRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(0));
m_colorExpr = RecursiveTraceColor(ir, diag, colorRoot, false);
/* Follow Alpha Chain */
if (rootCall.m_call.m_argInstIdxs.size() > 1)
{
const IR::Instruction& alphaRoot =
ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(1));
if (rootCall.m_call.m_argInstIdxs.size() > 1) {
const IR::Instruction& alphaRoot = ir.m_instructions.at(rootCall.m_call.m_argInstIdxs.at(1));
m_alphaExpr = RecursiveTraceAlpha(ir, diag, alphaRoot, false);
}
}
static const char SWIZZLE_CHARS[] = "rgba";
std::string ProgrammableCommon::EmitSwizzle3(Diagnostics& diag, const SourceLocation& loc,
const std::string& a, const atInt8 swiz[4]) const
{
std::string ProgrammableCommon::EmitSwizzle3(Diagnostics& diag, const SourceLocation& loc, const std::string& a,
const atInt8 swiz[4]) const {
std::string retval = a + '.';
for (int i=0 ; i<3 ; ++i)
{
for (int i = 0; i < 3; ++i) {
if (swiz[i] < 0 || swiz[i] > 3)
diag.reportBackendErr(loc, "unable to use swizzle as RGB value");
retval += SWIZZLE_CHARS[swiz[i]];
@ -357,9 +295,8 @@ std::string ProgrammableCommon::EmitSwizzle3(Diagnostics& diag, const SourceLoca
return retval;
}
std::string ProgrammableCommon::EmitSwizzle1(Diagnostics& diag, const SourceLocation& loc,
const std::string& a, const atInt8 swiz[4]) const
{
std::string ProgrammableCommon::EmitSwizzle1(Diagnostics& diag, const SourceLocation& loc, const std::string& a,
const atInt8 swiz[4]) const {
std::string retval = a + '.';
if (swiz[0] < 0 || swiz[0] > 3)
diag.reportBackendErr(loc, "unable to use swizzle as Alpha value");
@ -367,4 +304,4 @@ std::string ProgrammableCommon::EmitSwizzle1(Diagnostics& diag, const SourceLoca
return retval;
}
}
} // namespace hecl::Backend

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,9 @@
#undef min
#undef max
namespace hecl::blender
{
namespace hecl::blender {
atVec3f MtxVecMul4RM(const Matrix4f& mtx, const Vector3f& vec)
{
atVec3f MtxVecMul4RM(const Matrix4f& mtx, const Vector3f& vec) {
atVec3f res;
athena::simd_floats resf;
athena::simd_floats mtxf[3];
@ -23,8 +21,7 @@ atVec3f MtxVecMul4RM(const Matrix4f& mtx, const Vector3f& vec)
return res;
}
atVec3f MtxVecMul3RM(const Matrix4f& mtx, const Vector3f& vec)
{
atVec3f MtxVecMul3RM(const Matrix4f& mtx, const Vector3f& vec) {
atVec3f res;
athena::simd_floats resf;
athena::simd_floats mtxf[3];
@ -38,8 +35,7 @@ atVec3f MtxVecMul3RM(const Matrix4f& mtx, const Vector3f& vec)
return res;
}
HMDLBuffers Mesh::getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinIndex) const
{
HMDLBuffers Mesh::getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinIndex) const {
/* If skinned, compute max weight vec count */
size_t weightCount = 0;
for (const SkinBanks::Bank& bank : skinBanks.banks)
@ -74,31 +70,25 @@ HMDLBuffers Mesh::getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinInd
std::vector<atUint32> iboData;
iboData.reserve(boundVerts);
for (const Surface& surf : surfaces)
{
for (const Surface& surf : surfaces) {
size_t iboStart = iboData.size();
for (const Surface::Vert& v : surf.verts)
{
if (v.iPos == 0xffffffff)
{
for (const Surface::Vert& v : surf.verts) {
if (v.iPos == 0xffffffff) {
iboData.push_back(0xffffffff);
continue;
}
size_t ti = 0;
bool found = false;
for (const std::pair<const Surface*, const Surface::Vert*>& tv : vertPool)
{
if (v == *tv.second && surf.skinBankIdx == tv.first->skinBankIdx)
{
for (const std::pair<const Surface*, const Surface::Vert*>& tv : vertPool) {
if (v == *tv.second && surf.skinBankIdx == tv.first->skinBankIdx) {
iboData.push_back(ti);
found = true;
break;
}
++ti;
}
if (!found)
{
if (!found) {
iboData.push_back(vertPool.size());
vertPool.emplace_back(&surf, &v);
}
@ -114,13 +104,11 @@ HMDLBuffers Mesh::getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinInd
HMDLBuffers ret(std::move(metaOut), vboSz, iboData, std::move(outSurfaces), skinBanks);
athena::io::MemoryWriter vboW(ret.m_vboData.get(), vboSz);
uint32_t curPoolIdx = 0;
for (const std::pair<const Surface*, const Surface::Vert*>& sv : vertPool)
{
for (const std::pair<const Surface*, const Surface::Vert*>& sv : vertPool) {
const Surface& s = *sv.first;
const Surface::Vert& v = *sv.second;
if (absoluteCoords)
{
if (absoluteCoords) {
atVec3f preXfPos = MtxVecMul4RM(sceneXf, pos[v.iPos]);
vboW.writeVec3fLittle(preXfPos);
@ -131,15 +119,12 @@ HMDLBuffers Mesh::getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinInd
mag = 1.f / std::sqrt(mag);
preXfNorm.simd *= mag;
vboW.writeVec3fLittle(preXfNorm);
}
else
{
} else {
vboW.writeVec3fLittle(pos[v.iPos]);
vboW.writeVec3fLittle(norm[v.iNorm]);
}
for (size_t i=0 ; i<colorLayerCount ; ++i)
{
for (size_t i = 0; i < colorLayerCount; ++i) {
const Vector3f& c = color[v.iColor[i]];
athena::simd_floats f(c.val.simd);
vboW.writeUByte(std::max(0, std::min(255, int(f[0] * 255))));
@ -148,25 +133,21 @@ HMDLBuffers Mesh::getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinInd
vboW.writeUByte(255);
}
for (size_t i=0 ; i<uvLayerCount ; ++i)
for (size_t i = 0; i < uvLayerCount; ++i)
vboW.writeVec2fLittle(uv[v.iUv[i]]);
if (weightVecCount)
{
if (weightVecCount) {
const SkinBanks::Bank& bank = skinBanks.banks[s.skinBankIdx];
const std::vector<SkinBind>& binds = skins[v.iSkin];
auto it = bank.m_boneIdxs.cbegin();
for (size_t i=0 ; i<weightVecCount ; ++i)
{
for (size_t i = 0; i < weightVecCount; ++i) {
atVec4f vec = {};
for (size_t j=0 ; j<4 ; ++j)
{
for (size_t j = 0; j < 4; ++j) {
if (it == bank.m_boneIdxs.cend())
break;
for (const SkinBind& bind : binds)
if (bind.boneIdx == *it)
{
if (bind.boneIdx == *it) {
vec.simd[j] = bind.weight;
break;
}
@ -184,4 +165,4 @@ HMDLBuffers Mesh::getHMDLBuffers(bool absoluteCoords, PoolSkinIndex& poolSkinInd
return ret;
}
}
} // namespace hecl::blender

View File

@ -2,22 +2,16 @@
#include "athena/FileReader.hpp"
#include <zlib.h>
namespace hecl::blender
{
namespace hecl::blender {
void SDNABlock::SDNAStruct::computeOffsets(const SDNABlock& block)
{
void SDNABlock::SDNAStruct::computeOffsets(const SDNABlock& block) {
atUint32 offset = 0;
for (SDNAField& f : fields)
{
for (SDNAField& f : fields) {
const auto& name = block.names[f.name];
f.offset = offset;
if (name.front() == '*')
{
if (name.front() == '*') {
offset += 8;
}
else
{
} else {
atUint32 length = block.tlens[f.type];
auto bracket = name.find('[');
if (bracket != std::string::npos)
@ -27,28 +21,23 @@ void SDNABlock::SDNAStruct::computeOffsets(const SDNABlock& block)
}
}
const SDNABlock::SDNAStruct::SDNAField* SDNABlock::SDNAStruct::lookupField(const SDNABlock& block, const char* n) const
{
for (const SDNAField& field : fields)
{
const SDNABlock::SDNAStruct::SDNAField* SDNABlock::SDNAStruct::lookupField(const SDNABlock& block,
const char* n) const {
for (const SDNAField& field : fields) {
const auto& name = block.names[field.name];
auto bracket = name.find('[');
if (bracket != std::string::npos)
{
if (bracket != std::string::npos) {
if (!name.compare(0, bracket, n))
return &field;
}
else if (!name.compare(n))
} else if (!name.compare(n))
return &field;
}
return nullptr;
}
const SDNABlock::SDNAStruct* SDNABlock::lookupStruct(const char* n, int& idx) const
{
const SDNABlock::SDNAStruct* SDNABlock::lookupStruct(const char* n, int& idx) const {
idx = 0;
for (const SDNAStruct& strc : strcs)
{
for (const SDNAStruct& strc : strcs) {
const auto& name = types[strc.type];
if (!name.compare(n))
return &strc;
@ -57,12 +46,10 @@ const SDNABlock::SDNAStruct* SDNABlock::lookupStruct(const char* n, int& idx) co
return nullptr;
}
void SDNARead::enumerate(const std::function<bool(const FileBlock& block, athena::io::MemoryReader& r)>& func) const
{
void SDNARead::enumerate(const std::function<bool(const FileBlock& block, athena::io::MemoryReader& r)>& func) const {
athena::io::MemoryReader r(m_data.data(), m_data.size());
r.seek(12);
while (r.position() < r.length())
{
while (r.position() < r.length()) {
FileBlock block;
block.read(r);
if (block.type == FOURCC('ENDB'))
@ -74,8 +61,7 @@ void SDNARead::enumerate(const std::function<bool(const FileBlock& block, athena
}
}
SDNARead::SDNARead(SystemStringView path)
{
SDNARead::SDNARead(SystemStringView path) {
athena::io::FileReader r(path);
if (r.hasError())
return;
@ -84,8 +70,7 @@ SDNARead::SDNARead(SystemStringView path)
char magicBuf[7];
r.readUBytesToBuf(magicBuf, 7);
r.seek(0, athena::Begin);
if (strncmp(magicBuf, "BLENDER", 7))
{
if (strncmp(magicBuf, "BLENDER", 7)) {
/* Try gzip decompression */
std::unique_ptr<uint8_t[]> compBuf(new uint8_t[4096]);
m_data.resize((length * 2 + 4095) & ~4095);
@ -96,15 +81,12 @@ SDNARead::SDNARead(SystemStringView path)
zstrm.total_out = 0;
atUint64 rs;
while ((rs = r.readUBytesToBuf(compBuf.get(), 4096)))
{
while ((rs = r.readUBytesToBuf(compBuf.get(), 4096))) {
int inflateRet;
zstrm.next_in = compBuf.get();
zstrm.avail_in = rs;
while (zstrm.avail_in)
{
if (!zstrm.avail_out)
{
while (zstrm.avail_in) {
if (!zstrm.avail_out) {
zstrm.avail_out = m_data.size();
m_data.resize(zstrm.avail_out * 2);
zstrm.next_out = (Bytef*)m_data.data() + zstrm.avail_out;
@ -112,8 +94,7 @@ SDNARead::SDNARead(SystemStringView path)
inflateRet = inflate(&zstrm, Z_NO_FLUSH);
if (inflateRet == Z_STREAM_END)
break;
if (inflateRet != Z_OK)
{
if (inflateRet != Z_OK) {
inflateEnd(&zstrm);
m_data = std::vector<uint8_t>();
return;
@ -125,22 +106,17 @@ SDNARead::SDNARead(SystemStringView path)
inflateEnd(&zstrm);
if (strncmp((char*)m_data.data(), "BLENDER", 7))
{
if (strncmp((char*)m_data.data(), "BLENDER", 7)) {
m_data = std::vector<uint8_t>();
return;
}
}
else
{
} else {
m_data.resize(length);
r.readUBytesToBuf(m_data.data(), length);
}
enumerate([this](const FileBlock& block, athena::io::MemoryReader& r)
{
if (block.type == FOURCC('DNA1'))
{
enumerate([this](const FileBlock& block, athena::io::MemoryReader& r) {
if (block.type == FOURCC('DNA1')) {
m_sdnaBlock.read(r);
for (SDNABlock::SDNAStruct& s : m_sdnaBlock.strcs)
s.computeOffsets(m_sdnaBlock);
@ -150,8 +126,7 @@ SDNARead::SDNARead(SystemStringView path)
});
}
BlendType GetBlendType(SystemStringView path)
{
BlendType GetBlendType(SystemStringView path) {
SDNARead r(path);
if (!r)
return BlendType::None;
@ -183,10 +158,9 @@ BlendType GetBlendType(SystemStringView path)
atUint32 valOffset = dataOffset + valField->offset;
BlendType ret = BlendType::None;
r.enumerate([idPropIdx, typeOffset, nameOffset, valOffset, &ret](const FileBlock& block, athena::io::MemoryReader& r)
{
if (block.type == FOURCC('DATA') && block.sdnaIdx == idPropIdx)
{
r.enumerate(
[idPropIdx, typeOffset, nameOffset, valOffset, &ret](const FileBlock& block, athena::io::MemoryReader& r) {
if (block.type == FOURCC('DATA') && block.sdnaIdx == idPropIdx) {
r.seek(typeOffset, athena::Begin);
if (r.readUByte() != 1)
return true;
@ -205,4 +179,4 @@ BlendType GetBlendType(SystemStringView path)
return ret;
}
}
} // namespace hecl::blender

162
hecl/lib/CVar.cpp Executable file → Normal file
View File

@ -6,16 +6,15 @@
#include <algorithm>
#include <sstream>
namespace hecl
{
namespace hecl {
extern CVar* com_developer;
extern CVar* com_enableCheats;
using namespace std::literals;
CVar::CVar(std::string_view name, std::string_view value, std::string_view help, EType type, EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
CVar::CVar(std::string_view name, std::string_view value, std::string_view help, EType type, EFlags flags,
CVarManager& parent)
: m_mgr(parent) {
m_name = std::string(name);
m_value = std::string(value);
m_defaultValue = std::string(value);
@ -24,9 +23,9 @@ CVar::CVar(std::string_view name, std::string_view value, std::string_view help,
m_flags = flags;
}
CVar::CVar(std::string_view name, std::string_view value, std::string_view help, CVar::EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
CVar::CVar(std::string_view name, std::string_view value, std::string_view help, CVar::EFlags flags,
CVarManager& parent)
: m_mgr(parent) {
m_flags = flags;
m_name = std::string(name);
m_help = help;
@ -45,8 +44,7 @@ CVar::CVar(std::string_view name, std::string_view value, std::string_view help,
}
CVar::CVar(std::string_view name, const atVec4f& value, std::string_view help, EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
: m_mgr(parent) {
m_name = std::string(name);
m_help = help;
m_type = EType::Vec4f;
@ -65,8 +63,7 @@ CVar::CVar(std::string_view name, const atVec4f& value, std::string_view help, E
}
CVar::CVar(std::string_view name, float value, std::string_view help, EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
: m_mgr(parent) {
m_name = std::string(name);
m_help = help;
m_type = EType::Float;
@ -85,8 +82,7 @@ CVar::CVar(std::string_view name, float value, std::string_view help, EFlags fla
}
CVar::CVar(std::string_view name, bool value, std::string_view help, CVar::EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
: m_mgr(parent) {
m_name = std::string(name);
m_help = help;
m_type = EType::Boolean;
@ -105,8 +101,7 @@ CVar::CVar(std::string_view name, bool value, std::string_view help, CVar::EFlag
}
CVar::CVar(std::string_view name, int value, std::string_view help, CVar::EFlags flags, CVarManager& parent)
: m_mgr(parent)
{
: m_mgr(parent) {
m_name = std::string(name);
m_help = help;
m_type = EType::Integer;
@ -124,16 +119,13 @@ CVar::CVar(std::string_view name, int value, std::string_view help, CVar::EFlags
m_flags = flags;
}
std::string CVar::help() const
{
std::string CVar::help() const {
return std::string(m_help + (m_defaultValue != std::string() ? "\ndefault: " + m_defaultValue : "") +
(isReadOnly() ? " [ReadOnly]" : ""));
}
atVec4f CVar::toVec4f(bool* isValid) const
{
if (m_type != EType::Vec4f)
{
atVec4f CVar::toVec4f(bool* isValid) const {
if (m_type != EType::Vec4f) {
if (isValid != nullptr)
*isValid = false;
@ -151,10 +143,8 @@ atVec4f CVar::toVec4f(bool* isValid) const
return vec;
}
float CVar::toFloat(bool* isValid) const
{
if (m_type != EType::Float)
{
float CVar::toFloat(bool* isValid) const {
if (m_type != EType::Float) {
if (isValid)
*isValid = false;
return 0.0f;
@ -163,10 +153,8 @@ float CVar::toFloat(bool* isValid) const
return strtof(m_value.c_str(), nullptr);
}
bool CVar::toBoolean(bool* isValid) const
{
if (m_type != EType::Boolean)
{
bool CVar::toBoolean(bool* isValid) const {
if (m_type != EType::Boolean) {
if (isValid)
*isValid = false;
@ -177,14 +165,11 @@ bool CVar::toBoolean(bool* isValid) const
std::string tmp = m_value;
athena::utility::tolower(tmp);
if (!tmp.compare("yes") || !tmp.compare("true") || !tmp.compare("1"))
{
if (!tmp.compare("yes") || !tmp.compare("true") || !tmp.compare("1")) {
if (isValid)
*isValid = true;
return true;
}
else if (!tmp.compare("no") || !tmp.compare("false") || !tmp.compare("0"))
{
} else if (!tmp.compare("no") || !tmp.compare("false") || !tmp.compare("0")) {
if (isValid)
*isValid = true;
return false;
@ -196,10 +181,8 @@ bool CVar::toBoolean(bool* isValid) const
return false;
}
int CVar::toInteger(bool* isValid) const
{
if (m_type != EType::Integer)
{
int CVar::toInteger(bool* isValid) const {
if (m_type != EType::Integer) {
if (isValid)
*isValid = false;
return 0;
@ -208,36 +191,29 @@ int CVar::toInteger(bool* isValid) const
return strtol(m_value.c_str(), nullptr, 0);
}
const std::string CVar::toLiteral(bool* isValid) const
{
if (m_type != EType::Literal && (com_developer && com_developer->toBoolean()))
{
const std::string CVar::toLiteral(bool* isValid) const {
if (m_type != EType::Literal && (com_developer && com_developer->toBoolean())) {
if (isValid != nullptr)
*isValid = false;
}
else if (isValid != nullptr)
} else if (isValid != nullptr)
*isValid = true;
// Even if it's not a literal, it's still safe to return
return m_value;
}
const std::wstring CVar::toWideLiteral(bool* isValid) const
{
if (m_type != EType::Literal && (com_developer && com_developer->toBoolean()))
{
const std::wstring CVar::toWideLiteral(bool* isValid) const {
if (m_type != EType::Literal && (com_developer && com_developer->toBoolean())) {
if (isValid != nullptr)
*isValid = false;
}
else if (isValid != nullptr)
} else if (isValid != nullptr)
*isValid = true;
// Even if it's not a literal, it's still safe to return
return hecl::UTF8ToWide(m_value);
}
bool CVar::fromVec4f(const atVec4f& val)
{
bool CVar::fromVec4f(const atVec4f& val) {
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
@ -255,8 +231,7 @@ bool CVar::fromVec4f(const atVec4f& val)
return true;
}
bool CVar::fromFloat(float val)
{
bool CVar::fromFloat(float val) {
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
@ -273,8 +248,7 @@ bool CVar::fromFloat(float val)
return true;
}
bool CVar::fromBoolean(bool val)
{
bool CVar::fromBoolean(bool val) {
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
@ -295,8 +269,7 @@ bool CVar::fromBoolean(bool val)
return true;
}
bool CVar::fromInteger(int val)
{
bool CVar::fromInteger(int val) {
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
@ -313,8 +286,7 @@ bool CVar::fromInteger(int val)
return true;
}
bool CVar::fromLiteral(std::string_view val)
{
bool CVar::fromLiteral(std::string_view val) {
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
@ -331,8 +303,7 @@ bool CVar::fromLiteral(std::string_view val)
return true;
}
bool CVar::fromLiteral(std::wstring_view val)
{
bool CVar::fromLiteral(std::wstring_view val) {
if (isCheat() && (com_developer && !com_developer->toBoolean() && !com_enableCheats->toBoolean()))
return false;
else if (isCheat())
@ -349,37 +320,32 @@ bool CVar::fromLiteral(std::wstring_view val)
return true;
}
bool CVar::fromLiteralToType(std::string_view val, bool setDefault)
{
switch (m_type)
{
case EType::Literal: return fromLiteral(val);
case EType::Boolean:
{
bool CVar::fromLiteralToType(std::string_view val, bool setDefault) {
switch (m_type) {
case EType::Literal:
return fromLiteral(val);
case EType::Boolean: {
std::stringstream ss;
ss << std::boolalpha << val;
bool v;
ss >> v;
return fromBoolean(v);
}
case EType::Float:
{
case EType::Float: {
std::stringstream ss;
ss << val;
float v;
ss >> v;
return fromFloat(v);
}
case EType::Integer:
{
case EType::Integer: {
std::stringstream ss;
ss << val;
int v;
ss >> v;
return fromInteger(v);
}
case EType::Vec4f:
{
case EType::Vec4f: {
atVec4f vec;
athena::simd_floats f;
std::sscanf(val.data(), "%f %f %f %f", &f[0], &f[1], &f[2], &f[3]);
@ -392,37 +358,32 @@ bool CVar::fromLiteralToType(std::string_view val, bool setDefault)
return false;
}
bool CVar::fromLiteralToType(std::wstring_view val, bool setDefault)
{
switch (m_type)
{
case EType::Literal: return fromLiteral(val);
case EType::Boolean:
{
bool CVar::fromLiteralToType(std::wstring_view val, bool setDefault) {
switch (m_type) {
case EType::Literal:
return fromLiteral(val);
case EType::Boolean: {
std::wstringstream ss;
ss << std::boolalpha << val;
bool v;
ss >> v;
return fromBoolean(v);
}
case EType::Float:
{
case EType::Float: {
std::wstringstream ss;
ss << val;
float v;
ss >> v;
return fromFloat(v);
}
case EType::Integer:
{
case EType::Integer: {
std::wstringstream ss;
ss << val;
int v;
ss >> v;
return fromInteger(v);
}
case EType::Vec4f:
{
case EType::Vec4f: {
atVec4f vec;
athena::simd_floats f;
std::swscanf(val.data(), L"%f %f %f %f", &f[0], &f[1], &f[2], &f[3]);
@ -435,7 +396,7 @@ bool CVar::fromLiteralToType(std::wstring_view val, bool setDefault)
return false;
}
bool CVar::isModified() const { return int(m_flags & EFlags::Modified) != 0;}
bool CVar::isModified() const { return int(m_flags & EFlags::Modified) != 0; }
bool CVar::modificationRequiresRestart() const { return int(m_flags & EFlags::ModifyRestart) != 0; }
bool CVar::isReadOnly() const { return int(m_flags & EFlags::ReadOnly) != 0; }
@ -452,37 +413,30 @@ bool CVar::wasDeserialized() const { return m_wasDeserialized; }
bool CVar::hasDefaultValue() const { return m_defaultValue == m_value; }
void CVar::clearModified()
{
void CVar::clearModified() {
if (!modificationRequiresRestart())
m_flags &= ~EFlags::Modified;
}
void CVar::setModified() { m_flags |= EFlags::Modified; }
void CVar::unlock()
{
if (isReadOnly() && !m_unlocked)
{
void CVar::unlock() {
if (isReadOnly() && !m_unlocked) {
m_oldFlags = m_flags;
m_flags &= ~EFlags::ReadOnly;
m_unlocked = true;
}
}
void CVar::lock()
{
if (!isReadOnly() && m_unlocked)
{
void CVar::lock() {
if (!isReadOnly() && m_unlocked) {
m_flags = m_oldFlags;
m_unlocked = false;
}
}
void CVar::dispatch()
{
void CVar::dispatch() {
for (const ListenerFunc& listen : m_listeners)
listen(this);
}
}
} // namespace hecl

165
hecl/lib/CVarManager.cpp Executable file → Normal file
View File

@ -7,8 +7,7 @@
#include <memory>
#include <regex>
namespace hecl
{
namespace hecl {
CVar* com_developer = nullptr;
CVar* com_configfile = nullptr;
@ -19,21 +18,18 @@ CVarManager* CVarManager::m_instance = nullptr;
static logvisor::Module CVarLog("CVarManager");
CVarManager::CVarManager(hecl::Runtime::FileStoreManager& store, bool useBinary)
: m_store(store),
m_useBinary(useBinary)
{
: m_store(store), m_useBinary(useBinary) {
m_instance = this;
com_configfile = newCVar("config", "File to store configuration", std::string("config"), CVar::EFlags::System);
com_developer = newCVar("developer", "Enables developer mode", false, (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::InternalArchivable));
com_enableCheats = newCVar("cheats", "Enable cheats", false, (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::Hidden));
com_developer = newCVar("developer", "Enables developer mode", false,
(CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::InternalArchivable));
com_enableCheats =
newCVar("cheats", "Enable cheats", false, (CVar::EFlags::System | CVar::EFlags::ReadOnly | CVar::EFlags::Hidden));
}
CVarManager::~CVarManager()
{
}
CVarManager::~CVarManager() {}
CVar* CVarManager::registerCVar(std::unique_ptr<CVar>&& cvar)
{
CVar* CVarManager::registerCVar(std::unique_ptr<CVar>&& cvar) {
std::string tmp(cvar->name());
athena::utility::tolower(tmp);
if (m_cvars.find(tmp) != m_cvars.end())
@ -44,8 +40,7 @@ CVar* CVarManager::registerCVar(std::unique_ptr<CVar>&& cvar)
return ret;
}
CVar* CVarManager::findCVar(std::string_view name)
{
CVar* CVarManager::findCVar(std::string_view name) {
std::string lower(name);
athena::utility::tolower(lower);
auto search = m_cvars.find(lower);
@ -55,8 +50,7 @@ CVar* CVarManager::findCVar(std::string_view name)
return search->second.get();
}
std::vector<CVar*> CVarManager::archivedCVars() const
{
std::vector<CVar*> CVarManager::archivedCVars() const {
std::vector<CVar*> ret;
for (const auto& pair : m_cvars)
if (pair.second->isArchive())
@ -65,8 +59,7 @@ std::vector<CVar*> CVarManager::archivedCVars() const
return ret;
}
std::vector<CVar*> CVarManager::cvars(CVar::EFlags filter) const
{
std::vector<CVar*> CVarManager::cvars(CVar::EFlags filter) const {
std::vector<CVar*> ret;
for (const auto& pair : m_cvars)
if (filter == CVar::EFlags::None || (pair.second->flags() & filter) != 0)
@ -75,16 +68,14 @@ std::vector<CVar*> CVarManager::cvars(CVar::EFlags filter) const
return ret;
}
void CVarManager::deserialize(CVar* cvar)
{
void CVarManager::deserialize(CVar* cvar) {
if (!cvar)
return;
/* First let's check for a deferred value */
std::string lowName = cvar->name().data();
athena::utility::tolower(lowName);
if (m_deferedCVars.find(lowName) != m_deferedCVars.end())
{
if (m_deferedCVars.find(lowName) != m_deferedCVars.end()) {
std::string val = m_deferedCVars[lowName];
m_deferedCVars.erase(lowName);
if (cvar->fromLiteralToType(val))
@ -96,14 +87,15 @@ void CVarManager::deserialize(CVar* cvar)
return;
#if _WIN32
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toWideLiteral();
hecl::SystemString filename =
hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toWideLiteral();
#else
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toLiteral();
hecl::SystemString filename =
hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toLiteral();
#endif
hecl::Sstat st;
if (m_useBinary)
{
if (m_useBinary) {
CVarContainer container;
filename += _SYS_STR(".bin");
if (hecl::Stat(filename.c_str(), &st) || !S_ISREG(st.st_mode))
@ -112,18 +104,14 @@ void CVarManager::deserialize(CVar* cvar)
if (reader.isOpen())
container.read(reader);
if (container.cvars.size() > 0)
{
auto serialized = std::find_if(container.cvars.begin(),
container.cvars.end(),
if (container.cvars.size() > 0) {
auto serialized = std::find_if(container.cvars.begin(), container.cvars.end(),
[&cvar](const DNACVAR::CVar& c) { return c.m_name == cvar->name(); });
if (serialized != container.cvars.end())
{
if (serialized != container.cvars.end()) {
DNACVAR::CVar& tmp = *serialized;
if (cvar->m_value != tmp.m_value)
{
if (cvar->m_value != tmp.m_value) {
cvar->unlock();
cvar->fromLiteralToType(tmp.m_value, true);
cvar->m_wasDeserialized = true;
@ -131,29 +119,22 @@ void CVarManager::deserialize(CVar* cvar)
}
}
}
}
else
{
} else {
filename += _SYS_STR(".yaml");
if (hecl::Stat(filename.c_str(), &st) || !S_ISREG(st.st_mode))
return;
athena::io::FileReader reader(filename);
if (reader.isOpen())
{
if (reader.isOpen()) {
athena::io::YAMLDocReader docReader;
if (docReader.parse(&reader))
{
if (docReader.parse(&reader)) {
std::unique_ptr<athena::io::YAMLNode> root = docReader.releaseRootNode();
auto serialized = std::find_if(root->m_mapChildren.begin(),
root->m_mapChildren.end(),
auto serialized = std::find_if(root->m_mapChildren.begin(), root->m_mapChildren.end(),
[&cvar](const auto& c) { return c.first == cvar->name(); });
if (serialized != root->m_mapChildren.end())
{
if (serialized != root->m_mapChildren.end()) {
const std::unique_ptr<athena::io::YAMLNode>& tmp = serialized->second;
if (cvar->m_value != tmp->m_scalarString)
{
if (cvar->m_value != tmp->m_scalarString) {
cvar->unlock();
cvar->fromLiteralToType(tmp->m_scalarString, true);
cvar->m_wasDeserialized = true;
@ -165,20 +146,20 @@ void CVarManager::deserialize(CVar* cvar)
}
}
void CVarManager::serialize()
{
void CVarManager::serialize() {
#if _WIN32
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toWideLiteral();
hecl::SystemString filename =
hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toWideLiteral();
#else
hecl::SystemString filename = hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toLiteral();
hecl::SystemString filename =
hecl::SystemString(m_store.getStoreRoot()) + _SYS_STR('/') + com_configfile->toLiteral();
#endif
if (m_useBinary)
{
if (m_useBinary) {
CVarContainer container;
for (const auto& pair : m_cvars)
if (pair.second->isArchive() || (pair.second->isInternalArchivable() &&
pair.second->wasDeserialized() && !pair.second->hasDefaultValue()))
if (pair.second->isArchive() ||
(pair.second->isInternalArchivable() && pair.second->wasDeserialized() && !pair.second->hasDefaultValue()))
container.cvars.push_back(*pair.second);
container.cvarCount = atUint32(container.cvars.size());
@ -186,9 +167,7 @@ void CVarManager::serialize()
athena::io::FileWriter writer(filename);
if (writer.isOpen())
container.write(writer);
}
else
{
} else {
filename += _SYS_STR(".yaml");
athena::io::FileReader r(filename);
@ -197,8 +176,8 @@ void CVarManager::serialize()
docWriter.setStyle(athena::io::YAMLNodeStyle::Block);
for (const auto& pair : m_cvars)
if (pair.second->isArchive() || (pair.second->isInternalArchivable() &&
pair.second->wasDeserialized() && !pair.second->hasDefaultValue()))
if (pair.second->isArchive() ||
(pair.second->isInternalArchivable() && pair.second->wasDeserialized() && !pair.second->hasDefaultValue()))
docWriter.writeString(pair.second->name().data(), pair.second->toLiteral());
athena::io::FileWriter w(filename);
@ -207,32 +186,24 @@ void CVarManager::serialize()
}
}
CVarManager* CVarManager::instance()
{
return m_instance;
}
CVarManager* CVarManager::instance() { return m_instance; }
void CVarManager::list(Console* con, const std::vector<std::string>& /*args*/)
{
for (const auto& cvar : m_cvars)
{
void CVarManager::list(Console* con, const std::vector<std::string>& /*args*/) {
for (const auto& cvar : m_cvars) {
if (!cvar.second->isHidden())
con->report(Console::Level::Info, "%s: %s", cvar.second->name().data(), cvar.second->help().c_str());
}
}
void CVarManager::setCVar(Console* con, const std::vector<std::string> &args)
{
if (args.size() < 2)
{
void CVarManager::setCVar(Console* con, const std::vector<std::string>& args) {
if (args.size() < 2) {
con->report(Console::Level::Info, "Usage setCvar <cvar> <value>");
return;
}
std::string cvName = args[0];
athena::utility::tolower(cvName);
if (m_cvars.find(cvName) == m_cvars.end())
{
if (m_cvars.find(cvName) == m_cvars.end()) {
con->report(Console::Level::Error, "CVar '%s' does not exist", args[0].c_str());
return;
}
@ -254,18 +225,15 @@ void CVarManager::setCVar(Console* con, const std::vector<std::string> &args)
con->report(Console::Level::Info, "Set '%s' from '%s' to '%s'", cv->name().data(), oldVal.c_str(), value.c_str());
}
void CVarManager::getCVar(Console* con, const std::vector<std::string> &args)
{
if (args.empty())
{
void CVarManager::getCVar(Console* con, const std::vector<std::string>& args) {
if (args.empty()) {
con->report(Console::Level::Info, "Usage getCVar <cvar>");
return;
}
std::string cvName = args[0];
athena::utility::tolower(cvName);
if (m_cvars.find(cvName) == m_cvars.end())
{
if (m_cvars.find(cvName) == m_cvars.end()) {
con->report(Console::Level::Error, "CVar '%s' does not exist", args[0].c_str());
return;
}
@ -274,21 +242,17 @@ void CVarManager::getCVar(Console* con, const std::vector<std::string> &args)
con->report(Console::Level::Info, "'%s' = '%s'", cv->name().data(), cv->value().c_str());
}
void CVarManager::setDeveloperMode(bool v, bool setDeserialized)
{
void CVarManager::setDeveloperMode(bool v, bool setDeserialized) {
com_developer->unlock();
com_developer->fromBoolean(v);
if (setDeserialized)
com_developer->m_wasDeserialized = true;
com_developer->lock();
com_developer->setModified();
}
bool CVarManager::restartRequired() const
{
for (const auto& cv : m_cvars)
{
bool CVarManager::restartRequired() const {
for (const auto& cv : m_cvars) {
if (cv.second->isModified() && cv.second->modificationRequiresRestart())
return true;
}
@ -296,32 +260,25 @@ bool CVarManager::restartRequired() const
return false;
}
void CVarManager::parseCommandLine(const std::vector<SystemString>& args)
{
void CVarManager::parseCommandLine(const std::vector<SystemString>& args) {
bool oldDeveloper = suppressDeveloper();
std::string developerName = com_developer->name().data();
athena::utility::tolower(developerName);
for (const SystemString& arg : args)
{
if (arg[0] == _SYS_STR('+'))
{
for (const SystemString& arg : args) {
if (arg[0] == _SYS_STR('+')) {
std::string tmp = SystemUTF8Conv(arg).c_str();
std::smatch matches;
if (std::regex_match(tmp, matches, cmdLineRegex))
{
if (std::regex_match(tmp, matches, cmdLineRegex)) {
std::string cvarName = matches[1].str();
std::string cvarValue = matches[2].str();
if (CVar* cv = findCVar(cvarName))
{
if (CVar* cv = findCVar(cvarName)) {
cv->fromLiteralToType(cvarValue);
athena::utility::tolower(cvarName);
if (developerName == cvarName)
/* Make sure we're not overriding developer mode when we restore */
oldDeveloper = com_developer->toBoolean();
}
else
{
} else {
/* Unable to find an existing CVar, let's defer for the time being 8 */
athena::utility::tolower(cvarName);
m_deferedCVars[cvarName] = cvarValue;
@ -333,8 +290,7 @@ void CVarManager::parseCommandLine(const std::vector<SystemString>& args)
restoreDeveloper(oldDeveloper);
}
bool CVarManager::suppressDeveloper()
{
bool CVarManager::suppressDeveloper() {
bool oldDeveloper = com_developer->toBoolean();
CVarUnlocker unlock(com_developer);
com_developer->fromBoolean(true);
@ -342,10 +298,9 @@ bool CVarManager::suppressDeveloper()
return oldDeveloper;
}
void CVarManager::restoreDeveloper(bool oldDeveloper)
{
void CVarManager::restoreDeveloper(bool oldDeveloper) {
CVarUnlocker unlock(com_developer);
com_developer->fromBoolean(oldDeveloper);
}
}
} // namespace hecl

View File

@ -13,14 +13,12 @@
#define HECL_MULTIPROCESSOR 1
namespace hecl
{
namespace hecl {
static logvisor::Module CP_Log("hecl::ClientProcess");
ThreadLocalPtr<ClientProcess::Worker> ClientProcess::ThreadWorker;
static int GetCPUCount()
{
static int GetCPUCount() {
#if _WIN32
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
@ -30,13 +28,10 @@ static int GetCPUCount()
#endif
}
void ClientProcess::BufferTransaction::run(blender::Token& btok)
{
void ClientProcess::BufferTransaction::run(blender::Token& btok) {
athena::io::FileReader r(m_path.getAbsolutePath(), 32 * 1024, false);
if (r.hasError())
{
CP_Log.report(logvisor::Fatal, _SYS_STR("unable to background-buffer '%s'"),
m_path.getAbsolutePath().data());
if (r.hasError()) {
CP_Log.report(logvisor::Fatal, _SYS_STR("unable to background-buffer '%s'"), m_path.getAbsolutePath().data());
return;
}
if (m_offset)
@ -45,8 +40,7 @@ void ClientProcess::BufferTransaction::run(blender::Token& btok)
m_complete = true;
}
void ClientProcess::CookTransaction::run(blender::Token& btok)
{
void ClientProcess::CookTransaction::run(blender::Token& btok) {
m_dataSpec->setThreadProject();
m_returnResult = m_parent.syncCook(m_path, m_dataSpec, btok, m_force, m_fast);
std::unique_lock<std::mutex> lk(m_parent.m_mutex);
@ -55,20 +49,16 @@ void ClientProcess::CookTransaction::run(blender::Token& btok)
m_complete = true;
}
void ClientProcess::LambdaTransaction::run(blender::Token& btok)
{
void ClientProcess::LambdaTransaction::run(blender::Token& btok) {
m_func(btok);
m_complete = true;
}
ClientProcess::Worker::Worker(ClientProcess& proc, int idx)
: m_proc(proc), m_idx(idx)
{
ClientProcess::Worker::Worker(ClientProcess& proc, int idx) : m_proc(proc), m_idx(idx) {
m_thr = std::thread(std::bind(&Worker::proc, this));
}
void ClientProcess::Worker::proc()
{
void ClientProcess::Worker::proc() {
ClientProcess::ThreadWorker.reset(this);
char thrName[64];
@ -76,15 +66,12 @@ void ClientProcess::Worker::proc()
logvisor::RegisterThreadName(thrName);
std::unique_lock<std::mutex> lk(m_proc.m_mutex);
while (m_proc.m_running)
{
if (!m_didInit)
{
while (m_proc.m_running) {
if (!m_didInit) {
m_proc.m_initCv.notify_one();
m_didInit = true;
}
while (m_proc.m_running && m_proc.m_pendingQueue.size())
{
while (m_proc.m_running && m_proc.m_pendingQueue.size()) {
std::shared_ptr<Transaction> trans = std::move(m_proc.m_pendingQueue.front());
++m_proc.m_inProgress;
m_proc.m_pendingQueue.pop_front();
@ -103,27 +90,23 @@ void ClientProcess::Worker::proc()
m_blendTok.shutdown();
}
ClientProcess::ClientProcess(const MultiProgressPrinter* progPrinter)
: m_progPrinter(progPrinter)
{
ClientProcess::ClientProcess(const MultiProgressPrinter* progPrinter) : m_progPrinter(progPrinter) {
#if HECL_MULTIPROCESSOR
const int cpuCount = GetCPUCount();
#else
constexpr int cpuCount = 1;
#endif
m_workers.reserve(cpuCount);
for (int i=0 ; i<cpuCount ; ++i)
{
for (int i = 0; i < cpuCount; ++i) {
std::unique_lock<std::mutex> lk(m_mutex);
m_workers.emplace_back(*this, m_workers.size());
m_initCv.wait(lk);
}
}
std::shared_ptr<const ClientProcess::BufferTransaction>
ClientProcess::addBufferTransaction(const ProjectPath& path, void* target,
size_t maxLen, size_t offset)
{
std::shared_ptr<const ClientProcess::BufferTransaction> ClientProcess::addBufferTransaction(const ProjectPath& path,
void* target, size_t maxLen,
size_t offset) {
std::unique_lock<std::mutex> lk(m_mutex);
auto ret = std::make_shared<BufferTransaction>(*this, path, target, maxLen, offset);
m_pendingQueue.emplace_back(ret);
@ -131,10 +114,9 @@ ClientProcess::addBufferTransaction(const ProjectPath& path, void* target,
return ret;
}
std::shared_ptr<const ClientProcess::CookTransaction>
ClientProcess::addCookTransaction(const hecl::ProjectPath& path, bool force,
bool fast, Database::IDataSpec* spec)
{
std::shared_ptr<const ClientProcess::CookTransaction> ClientProcess::addCookTransaction(const hecl::ProjectPath& path,
bool force, bool fast,
Database::IDataSpec* spec) {
std::unique_lock<std::mutex> lk(m_mutex);
auto ret = std::make_shared<CookTransaction>(*this, path, force, fast, spec);
m_pendingQueue.emplace_back(ret);
@ -145,8 +127,7 @@ ClientProcess::addCookTransaction(const hecl::ProjectPath& path, bool force,
}
std::shared_ptr<const ClientProcess::LambdaTransaction>
ClientProcess::addLambdaTransaction(std::function<void(blender::Token&)>&& func)
{
ClientProcess::addLambdaTransaction(std::function<void(blender::Token&)>&& func) {
std::unique_lock<std::mutex> lk(m_mutex);
auto ret = std::make_shared<LambdaTransaction>(*this, std::move(func));
m_pendingQueue.emplace_back(ret);
@ -154,23 +135,17 @@ ClientProcess::addLambdaTransaction(std::function<void(blender::Token&)>&& func)
return ret;
}
bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, blender::Token& btok,
bool force, bool fast)
{
if (spec->canCook(path, btok))
{
bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec* spec, blender::Token& btok, bool force,
bool fast) {
if (spec->canCook(path, btok)) {
const Database::DataSpecEntry* specEnt = spec->overrideDataSpec(path, spec->getDataSpecEntry(), btok);
if (specEnt)
{
if (specEnt) {
hecl::ProjectPath cooked = path.getCookedPath(*specEnt);
if (fast)
cooked = cooked.getWithExtension(_SYS_STR(".fast"));
cooked.makeDirChain(false);
if (force || cooked.getPathType() == ProjectPath::Type::None ||
path.getModtime() > cooked.getModtime())
{
if (m_progPrinter)
{
if (force || cooked.getPathType() == ProjectPath::Type::None || path.getModtime() > cooked.getModtime()) {
if (m_progPrinter) {
hecl::SystemString str;
if (path.getAuxInfo().empty())
str = hecl::SysFormat(_SYS_STR("Cooking %s"), path.getRelativePath().data());
@ -178,20 +153,15 @@ bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec*
str = hecl::SysFormat(_SYS_STR("Cooking %s|%s"), path.getRelativePath().data(), path.getAuxInfo().data());
m_progPrinter->print(str.c_str(), nullptr, -1.f, hecl::ClientProcess::GetThreadWorkerIdx());
m_progPrinter->flush();
}
else
{
} else {
if (path.getAuxInfo().empty())
LogModule.report(logvisor::Info, _SYS_STR("Cooking %s"),
path.getRelativePath().data());
LogModule.report(logvisor::Info, _SYS_STR("Cooking %s"), path.getRelativePath().data());
else
LogModule.report(logvisor::Info, _SYS_STR("Cooking %s|%s"),
path.getRelativePath().data(),
LogModule.report(logvisor::Info, _SYS_STR("Cooking %s|%s"), path.getRelativePath().data(),
path.getAuxInfo().data());
}
spec->doCook(path, cooked, false, btok, [](const SystemChar*) {});
if (m_progPrinter)
{
if (m_progPrinter) {
hecl::SystemString str;
if (path.getAuxInfo().empty())
str = hecl::SysFormat(_SYS_STR("Cooked %s"), path.getRelativePath().data());
@ -207,21 +177,18 @@ bool ClientProcess::syncCook(const hecl::ProjectPath& path, Database::IDataSpec*
return false;
}
void ClientProcess::swapCompletedQueue(std::list<std::shared_ptr<Transaction>>& queue)
{
void ClientProcess::swapCompletedQueue(std::list<std::shared_ptr<Transaction>>& queue) {
std::unique_lock<std::mutex> lk(m_mutex);
queue.swap(m_completedQueue);
}
void ClientProcess::waitUntilComplete()
{
void ClientProcess::waitUntilComplete() {
std::unique_lock<std::mutex> lk(m_mutex);
while (isBusy())
m_waitCv.wait(lk);
}
void ClientProcess::shutdown()
{
void ClientProcess::shutdown() {
if (!m_running)
return;
std::unique_lock<std::mutex> lk(m_mutex);
@ -234,4 +201,4 @@ void ClientProcess::shutdown()
worker.m_thr.join();
}
}
} // namespace hecl

View File

@ -14,36 +14,33 @@ extern pD3DCompile D3DCompilePROC;
#include <memory>
#endif
namespace hecl
{
namespace hecl {
logvisor::Module Log("hecl::Compilers");
namespace PlatformType
{
namespace PlatformType {
const char* OpenGL::Name = "OpenGL";
const char* Vulkan::Name = "Vulkan";
const char* D3D11::Name = "D3D11";
const char* Metal::Name = "Metal";
const char* NX::Name = "NX";
}
} // namespace PlatformType
namespace PipelineStage
{
namespace PipelineStage {
const char* Null::Name = "Null";
const char* Vertex::Name = "Vertex";
const char* Fragment::Name = "Fragment";
const char* Geometry::Name = "Geometry";
const char* Control::Name = "Control";
const char* Evaluation::Name = "Evaluation";
}
} // namespace PipelineStage
template<typename P> struct ShaderCompiler {};
template <typename P>
struct ShaderCompiler {};
template<> struct ShaderCompiler<PlatformType::OpenGL>
{
template<typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text)
{
template <>
struct ShaderCompiler<PlatformType::OpenGL> {
template <typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text) {
std::string str = "#version 330\n";
str += BOO_GLSL_BINDING_HEAD;
str += text;
@ -53,28 +50,20 @@ template<> struct ShaderCompiler<PlatformType::OpenGL>
}
};
template<> struct ShaderCompiler<PlatformType::Vulkan>
{
static constexpr EShLanguage ShaderTypes[] =
{
EShLangVertex, /* Invalid */
EShLangVertex,
EShLangFragment,
EShLangGeometry,
EShLangTessControl,
EShLangTessEvaluation
};
template <>
struct ShaderCompiler<PlatformType::Vulkan> {
static constexpr EShLanguage ShaderTypes[] = {EShLangVertex, /* Invalid */
EShLangVertex, EShLangFragment, EShLangGeometry,
EShLangTessControl, EShLangTessEvaluation};
template<typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text)
{
template <typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text) {
EShLanguage lang = ShaderTypes[int(S::Enum)];
const EShMessages messages = EShMessages(EShMsgSpvRules | EShMsgVulkanRules);
glslang::TShader shader(lang);
const char* strings[] = { "#version 330\n", BOO_GLSL_BINDING_HEAD, text.data() };
const char* strings[] = {"#version 330\n", BOO_GLSL_BINDING_HEAD, text.data()};
shader.setStrings(strings, 3);
if (!shader.parse(&glslang::DefaultTBuiltInResource, 110, false, messages))
{
if (!shader.parse(&glslang::DefaultTBuiltInResource, 110, false, messages)) {
printf("%s\n", text.data());
Log.report(logvisor::Fatal, "unable to compile shader\n%s", shader.getInfoLog());
return {};
@ -82,8 +71,7 @@ template<> struct ShaderCompiler<PlatformType::Vulkan>
glslang::TProgram prog;
prog.addShader(&shader);
if (!prog.link(messages))
{
if (!prog.link(messages)) {
Log.report(logvisor::Fatal, "unable to link shader program\n%s", prog.getInfoLog());
return {};
}
@ -97,36 +85,25 @@ template<> struct ShaderCompiler<PlatformType::Vulkan>
};
#if _WIN32
static const char* D3DShaderTypes[] =
{
nullptr,
"vs_5_0",
"ps_5_0",
"gs_5_0",
"hs_5_0",
"ds_5_0"
};
template<> struct ShaderCompiler<PlatformType::D3D11>
{
static const char* D3DShaderTypes[] = {nullptr, "vs_5_0", "ps_5_0", "gs_5_0", "hs_5_0", "ds_5_0"};
template <>
struct ShaderCompiler<PlatformType::D3D11> {
#if _DEBUG && 0
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_DEBUG | D3DCOMPILE_OPTIMIZATION_LEVEL0
#else
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3
#endif
template<typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text)
{
template <typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text) {
ComPtr<ID3DBlob> errBlob;
ComPtr<ID3DBlob> blobOut;
if (FAILED(D3DCompilePROC(text.data(), text.size(), "Boo HLSL Source", nullptr, nullptr, "main",
D3DShaderTypes[int(S::Enum)], BOO_D3DCOMPILE_FLAG, 0, &blobOut, &errBlob)))
{
D3DShaderTypes[int(S::Enum)], BOO_D3DCOMPILE_FLAG, 0, &blobOut, &errBlob))) {
printf("%s\n", text.data());
Log.report(logvisor::Fatal, "error compiling shader: %s", errBlob->GetBufferPointer());
return {};
}
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(blobOut->GetBufferSize()),
blobOut->GetBufferSize());
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(blobOut->GetBufferSize()), blobOut->GetBufferSize());
memcpy(ret.first.get(), blobOut->GetBufferPointer(), blobOut->GetBufferSize());
return ret;
}
@ -134,21 +111,19 @@ template<> struct ShaderCompiler<PlatformType::D3D11>
#endif
#if __APPLE__
template<> struct ShaderCompiler<PlatformType::Metal>
{
template <>
struct ShaderCompiler<PlatformType::Metal> {
static bool m_didCompilerSearch;
static bool m_hasCompiler;
static bool SearchForCompiler()
{
static bool SearchForCompiler() {
m_didCompilerSearch = true;
const char* no_metal_compiler = getenv("HECL_NO_METAL_COMPILER");
if (no_metal_compiler && atoi(no_metal_compiler))
return false;
pid_t pid = fork();
if (!pid)
{
if (!pid) {
execlp("xcrun", "xcrun", "-sdk", "macosx", "metal", NULL);
/* xcrun returns 72 if metal command not found;
* emulate that if xcrun not found */
@ -162,27 +137,24 @@ template<> struct ShaderCompiler<PlatformType::Metal>
return WEXITSTATUS(status) == 1;
}
template<typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text)
{
template <typename S>
static std::pair<StageBinaryData, size_t> Compile(std::string_view text) {
if (!m_didCompilerSearch)
m_hasCompiler = SearchForCompiler();
std::string str = "#include <metal_stdlib>\n"
std::string str =
"#include <metal_stdlib>\n"
"using namespace metal;\n";
str += text;
std::pair<StageBinaryData, size_t> ret;
if (!m_hasCompiler)
{
if (!m_hasCompiler) {
/* First byte unset to indicate source data */
ret.first = MakeStageBinaryData(str.size() + 2);
ret.first.get()[0] = 0;
ret.second = str.size() + 2;
memcpy(&ret.first.get()[1], str.data(), str.size() + 1);
}
else
{
} else {
int compilerOut[2];
int compilerIn[2];
pipe(compilerOut);
@ -195,8 +167,7 @@ template<> struct ShaderCompiler<PlatformType::Metal>
/* Pipe source write to compiler */
pid_t compilerPid = fork();
if (!compilerPid)
{
if (!compilerPid) {
dup2(compilerIn[0], STDIN_FILENO);
dup2(compilerOut[1], STDOUT_FILENO);
@ -215,8 +186,7 @@ template<> struct ShaderCompiler<PlatformType::Metal>
/* Pipe compiler to linker */
pid_t linkerPid = fork();
if (!linkerPid)
{
if (!linkerPid) {
dup2(compilerOut[0], STDIN_FILENO);
close(compilerOut[0]);
@ -232,11 +202,9 @@ template<> struct ShaderCompiler<PlatformType::Metal>
/* Stream in source */
const char* inPtr = str.data();
size_t inRem = str.size();
while (inRem)
{
while (inRem) {
ssize_t writeRes = write(compilerIn[1], inPtr, inRem);
if (writeRes < 0)
{
if (writeRes < 0) {
fprintf(stderr, "write fail %s\n", strerror(errno));
break;
}
@ -247,30 +215,26 @@ template<> struct ShaderCompiler<PlatformType::Metal>
/* Wait for completion */
int compilerStat, linkerStat;
while (waitpid(compilerPid, &compilerStat, 0) < 0)
{
while (waitpid(compilerPid, &compilerStat, 0) < 0) {
if (errno == EINTR)
continue;
Log.report(logvisor::Fatal, "waitpid fail %s", strerror(errno));
return {};
}
if (WEXITSTATUS(compilerStat))
{
if (WEXITSTATUS(compilerStat)) {
Log.report(logvisor::Fatal, "compile fail");
return {};
}
while (waitpid(linkerPid, &linkerStat, 0) < 0)
{
while (waitpid(linkerPid, &linkerStat, 0) < 0) {
if (errno == EINTR)
continue;
Log.report(logvisor::Fatal, "waitpid fail %s", strerror(errno));
return {};
}
if (WEXITSTATUS(linkerStat))
{
if (WEXITSTATUS(linkerStat)) {
Log.report(logvisor::Fatal, "link fail");
return {};
}
@ -296,11 +260,10 @@ bool ShaderCompiler<PlatformType::Metal>::m_hasCompiler = false;
#endif
#if HECL_NOUVEAU_NX
template<> struct ShaderCompiler<PlatformType::NX>
{
template<typename S>
static std::pair<std::shared_ptr<uint8_t[]>, size_t> Compile(std::string_view text)
{
template <>
struct ShaderCompiler<PlatformType::NX> {
template <typename S>
static std::pair<std::shared_ptr<uint8_t[]>, size_t> Compile(std::string_view text) {
std::string str = "#version 330\n";
str += BOO_GLSL_BINDING_HEAD;
str += text;
@ -311,17 +274,16 @@ template<> struct ShaderCompiler<PlatformType::NX>
};
#endif
template<typename P, typename S>
std::pair<StageBinaryData, size_t> CompileShader(std::string_view text)
{
template <typename P, typename S>
std::pair<StageBinaryData, size_t> CompileShader(std::string_view text) {
return ShaderCompiler<P>::template Compile<S>(text);
}
#define SPECIALIZE_COMPILE_SHADER(P) \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Vertex>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Fragment>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Geometry>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Control>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Evaluation>(std::string_view text);
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Vertex>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Fragment>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Geometry>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Control>(std::string_view text); \
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Evaluation>(std::string_view text);
SPECIALIZE_COMPILE_SHADER(PlatformType::OpenGL)
SPECIALIZE_COMPILE_SHADER(PlatformType::Vulkan)
#if _WIN32
@ -334,4 +296,4 @@ SPECIALIZE_COMPILE_SHADER(PlatformType::Metal)
SPECIALIZE_COMPILE_SHADER(PlatformType::NX)
#endif
}
} // namespace hecl

View File

@ -4,45 +4,46 @@
#include "hecl/hecl.hpp"
#include "athena/Utility.hpp"
namespace hecl
{
namespace hecl {
Console* Console::m_instance = nullptr;
Console::Console(CVarManager* cvarMgr)
: m_cvarMgr(cvarMgr)
, m_overwrite(false)
, m_cursorAtEnd(false)
{
Console::Console(CVarManager* cvarMgr) : m_cvarMgr(cvarMgr), m_overwrite(false), m_cursorAtEnd(false) {
m_instance = this;
registerCommand("help", "Prints information about a given function", "<command>", std::bind(&Console::help, this, std::placeholders::_1, std::placeholders::_2));
registerCommand("listCommands", "Prints a list of all available Commands", "", std::bind(&Console::listCommands, this, std::placeholders::_1, std::placeholders::_2));
registerCommand("listCVars", "Lists all available CVars", "", std::bind(&CVarManager::list, m_cvarMgr, std::placeholders::_1, std::placeholders::_2));
registerCommand("setCVar", "Sets a given Console Variable to the specified value", "<cvar> <value>", std::bind(&CVarManager::setCVar, m_cvarMgr, std::placeholders::_1, std::placeholders::_2));
registerCommand("getCVar", "Prints the value stored in the specified Console Variable", "<cvar>", std::bind(&CVarManager::getCVar, m_cvarMgr, std::placeholders::_1, std::placeholders::_2));
m_conSpeed = cvarMgr->findOrMakeCVar("con_speed", "Speed at which the console opens and closes, calculated as pixels per second", 1.f,
hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive);
m_conHeight = cvarMgr->findOrMakeCVar("con_height", "Maximum absolute height of the console, height is calculated from the top of the window, expects values ranged from [0.f,1.f]", 0.5f,
hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive);
registerCommand("help", "Prints information about a given function", "<command>",
std::bind(&Console::help, this, std::placeholders::_1, std::placeholders::_2));
registerCommand("listCommands", "Prints a list of all available Commands", "",
std::bind(&Console::listCommands, this, std::placeholders::_1, std::placeholders::_2));
registerCommand("listCVars", "Lists all available CVars", "",
std::bind(&CVarManager::list, m_cvarMgr, std::placeholders::_1, std::placeholders::_2));
registerCommand("setCVar", "Sets a given Console Variable to the specified value", "<cvar> <value>",
std::bind(&CVarManager::setCVar, m_cvarMgr, std::placeholders::_1, std::placeholders::_2));
registerCommand("getCVar", "Prints the value stored in the specified Console Variable", "<cvar>",
std::bind(&CVarManager::getCVar, m_cvarMgr, std::placeholders::_1, std::placeholders::_2));
m_conSpeed = cvarMgr->findOrMakeCVar("con_speed",
"Speed at which the console opens and closes, calculated as pixels per second",
1.f, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive);
m_conHeight = cvarMgr->findOrMakeCVar("con_height",
"Maximum absolute height of the console, height is calculated from the top of "
"the window, expects values ranged from [0.f,1.f]",
0.5f, hecl::CVar::EFlags::System | hecl::CVar::EFlags::Archive);
}
void Console::registerCommand(std::string_view name, std::string_view helpText, std::string_view usage, const std::function<void(Console*, const std::vector<std::string> &)>&& func, SConsoleCommand::ECommandFlags cmdFlags)
{
void Console::registerCommand(std::string_view name, std::string_view helpText, std::string_view usage,
const std::function<void(Console*, const std::vector<std::string>&)>&& func,
SConsoleCommand::ECommandFlags cmdFlags) {
std::string lowName = name.data();
athena::utility::tolower(lowName);
if (m_commands.find(lowName) == m_commands.end())
m_commands[lowName] = SConsoleCommand{name.data(), helpText.data(), usage.data(), std::move(func), cmdFlags};
}
void Console::unregisterCommand(std::string_view name)
{
void Console::unregisterCommand(std::string_view name) {
std::string lowName = name.data();
athena::utility::tolower(lowName);
if (m_commands.find(lowName) != m_commands.end())
m_commands.erase(m_commands.find(lowName));
}
void Console::executeString(const std::string& str)
{
void Console::executeString(const std::string& str) {
if (str.empty())
return;
@ -52,8 +53,7 @@ void Console::executeString(const std::string& str)
if (commands.empty())
return;
for (std::string command : commands)
{
for (std::string command : commands) {
command = athena::utility::trim(command);
std::vector<std::string> tmpArgs = athena::utility::split(command, ' ');
if (tmpArgs.empty())
@ -64,36 +64,28 @@ void Console::executeString(const std::string& str)
bool isInLiteral = false;
std::string curLiteral;
int depth = 0;
for (std::string arg : tmpArgs)
{
if ((arg.front() == '\'' || arg.front() == '"'))
{
for (std::string arg : tmpArgs) {
if ((arg.front() == '\'' || arg.front() == '"')) {
++depth;
isInLiteral = true;
curLiteral += arg;
}
else if ((arg.back() == '\'' || arg.back() == '"') && isInLiteral)
{
} else if ((arg.back() == '\'' || arg.back() == '"') && isInLiteral) {
--depth;
curLiteral += arg;
args.push_back(curLiteral);
if (depth <= 0)
{
if (depth <= 0) {
depth = 0;
isInLiteral = false;
curLiteral.clear();
}
}
else if (isInLiteral)
} else if (isInLiteral)
curLiteral += arg;
else
args.push_back(arg);
}
if (isInLiteral)
{
if ((curLiteral.back() != '\'' && curLiteral.back() != '"') || depth > 1)
{
if (isInLiteral) {
if ((curLiteral.back() != '\'' && curLiteral.back() != '"') || depth > 1) {
report(Level::Warning, "Unterminated string literal");
return;
}
@ -105,47 +97,38 @@ void Console::executeString(const std::string& str)
std::string lowComName = commandName;
athena::utility::tolower(lowComName);
if (m_commands.find(lowComName) != m_commands.end())
{
if (m_commands.find(lowComName) != m_commands.end()) {
const SConsoleCommand& cmd = m_commands[lowComName];
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Developer) && !com_developer->toBoolean())
{
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Developer) && !com_developer->toBoolean()) {
report(Level::Error, "This command can only be executed in developer mode", commandName.c_str());
return;
}
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Cheat) && !com_enableCheats->toBoolean())
{
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Cheat) && !com_enableCheats->toBoolean()) {
report(Level::Error, "This command can only be executed with cheats enabled", commandName.c_str());
return;
}
m_commands[lowComName].m_func(this, args);
}
else if (const CVar* cv = m_cvarMgr->findCVar(commandName))
{
} else if (const CVar* cv = m_cvarMgr->findCVar(commandName)) {
args.insert(args.begin(), commandName);
if (args.size() > 1)
m_cvarMgr->setCVar(this, args);
else
m_cvarMgr->getCVar(this, args);
}
else
} else
report(Level::Error, "Command '%s' is not valid!", commandName.c_str());
}
}
void Console::help(Console* /*con*/, const std::vector<std::string>& args)
{
if (args.empty())
{
void Console::help(Console* /*con*/, const std::vector<std::string>& args) {
if (args.empty()) {
report(Level::Info, "Expected usage: help <command>");
return;
}
std::string cmd = args.front();
athena::utility::tolower(cmd);
auto it = m_commands.find(cmd);
if (it == m_commands.end())
{
if (it == m_commands.end()) {
report(Level::Error, "No such command '%s'", args.front().c_str());
return;
}
@ -155,66 +138,55 @@ void Console::help(Console* /*con*/, const std::vector<std::string>& args)
report(Level::Info, "Usage: %s %s", it->second.m_displayName.c_str(), it->second.m_usage.c_str());
}
void Console::listCommands(Console* /*con*/, const std::vector<std::string>& /*args*/)
{
void Console::listCommands(Console* /*con*/, const std::vector<std::string>& /*args*/) {
for (const auto& comPair : m_commands)
report(Level::Info, "'%s': %s", comPair.second.m_displayName.c_str(), comPair.second.m_helpString.c_str());
}
bool Console::commandExists(std::string_view cmd)
{
bool Console::commandExists(std::string_view cmd) {
std::string cmdName = cmd.data();
athena::utility::tolower(cmdName);
return m_commands.find(cmdName) != m_commands.end();
}
void Console::report(Level level, const char* fmt, va_list list)
{
void Console::report(Level level, const char* fmt, va_list list) {
char tmp[2048];
vsnprintf(tmp, 2048, fmt, list);
std::vector<std::string> lines = athena::utility::split(tmp, '\n');
for (const std::string& line : lines)
{
for (const std::string& line : lines) {
std::string v = athena::utility::sprintf("%s", line.c_str());
m_log.emplace_back(v, level);
}
printf("%s\n", tmp);
}
void Console::report(Level level, const char* fmt, ...)
{
void Console::report(Level level, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
report(level, fmt, ap);
va_end(ap);
}
void Console::proc()
{
if (m_conHeight->isModified())
{
void Console::proc() {
if (m_conHeight->isModified()) {
m_cachedConHeight = m_conHeight->toFloat();
m_conHeight->clearModified();
}
if (m_conSpeed->isModified())
{
if (m_conSpeed->isModified()) {
m_cachedConSpeed = m_conSpeed->toFloat();
m_conSpeed->clearModified();
}
if (m_state == State::Opened)
{
if (m_state == State::Opened) {
printf("\r%s ", m_commandString.c_str());
fflush(stdout);
}
else if (m_state == State::Opening)
} else if (m_state == State::Opening)
m_state = State::Opened;
else if (m_state == State::Closing)
m_state = State::Closed;
if (m_cursorPosition > int(m_commandString.size() - 1))
m_cursorPosition = int(m_commandString.size() - 1);
if (m_cursorPosition < -1)
@ -226,61 +198,46 @@ void Console::proc()
m_logOffset = 0;
}
void Console::draw(boo::IGraphicsCommandQueue* /*gfxQ*/)
{
}
void Console::draw(boo::IGraphicsCommandQueue* /*gfxQ*/) {}
void Console::handleCharCode(unsigned long chr, boo::EModifierKey /*mod*/, bool /*repeat*/)
{
if (chr == U'`' || chr == U'~')
{
void Console::handleCharCode(unsigned long chr, boo::EModifierKey /*mod*/, bool /*repeat*/) {
if (chr == U'`' || chr == U'~') {
if (m_state == State::Closed || m_state == State::Closing)
m_state = State::Opening;
else
m_state = State::Closing;
}
if (m_state == State::Opened)
{
if (!m_commandString.empty() && m_cursorPosition + 1 < int(m_commandString.size()))
{
if (m_state == State::Opened) {
if (!m_commandString.empty() && m_cursorPosition + 1 < int(m_commandString.size())) {
if (m_overwrite)
m_commandString[unsigned(m_cursorPosition + 1)] = char(chr);
else
m_commandString.insert(m_commandString.begin() + m_cursorPosition + 1, char(chr));
}
else
} else
m_commandString += char(chr);
++m_cursorPosition;
}
}
void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, bool /*repeat*/)
{
void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, bool /*repeat*/) {
if (m_state != Opened)
return;
switch (sp)
{
switch (sp) {
case boo::ESpecialKey::Insert:
m_overwrite ^= 1;
break;
case boo::ESpecialKey::Backspace:
{
if (!m_commandString.empty())
{
if (int(mod & boo::EModifierKey::Ctrl) != 0)
{
case boo::ESpecialKey::Backspace: {
if (!m_commandString.empty()) {
if (int(mod & boo::EModifierKey::Ctrl) != 0) {
size_t index = m_commandString.rfind(' ', size_t(m_cursorPosition - 1));
if (index == std::string::npos)
{
if (index == std::string::npos) {
m_commandString.clear();
m_cursorPosition = -1;
}
else
{
} else {
m_commandString.erase(index, (index - m_commandString.size()));
m_cursorPosition = int(index);
}
@ -294,16 +251,13 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
}
break;
}
case boo::ESpecialKey::Delete:
{
if (!m_commandString.empty())
{
case boo::ESpecialKey::Delete: {
if (!m_commandString.empty()) {
// Don't try to delete if the cursor is at the end of the line
if ((m_cursorPosition + 1) >= int(m_commandString.size()))
break;
if (int(mod & boo::EModifierKey::Ctrl) != 0)
{
if (int(mod & boo::EModifierKey::Ctrl) != 0) {
size_t index = m_commandString.find_first_of(' ', size_t(m_cursorPosition + 1));
if (index != std::string::npos)
m_commandString.erase(size_t(m_cursorPosition + 1), index + 1);
@ -315,20 +269,17 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
}
break;
}
case boo::ESpecialKey::PgUp:
{
case boo::ESpecialKey::PgUp: {
if (m_logOffset < int(m_log.size() - m_maxLines) - 1)
m_logOffset++;
break;
}
case boo::ESpecialKey::PgDown:
{
case boo::ESpecialKey::PgDown: {
if (m_logOffset > 0)
m_logOffset--;
break;
}
case boo::ESpecialKey::Enter:
{
case boo::ESpecialKey::Enter: {
printf("\n");
executeString(m_commandString);
m_cursorPosition = -1;
@ -338,8 +289,7 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
m_cursorTime = 0.f;
break;
}
case boo::ESpecialKey::Left:
{
case boo::ESpecialKey::Left: {
if (m_cursorPosition < 0)
break;
@ -352,13 +302,11 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
m_cursorTime = 0.f;
break;
}
case boo::ESpecialKey::Right:
{
case boo::ESpecialKey::Right: {
if (m_cursorPosition >= int(m_commandString.size() - 1))
break;
if (int(mod & boo::EModifierKey::Ctrl) != 0)
{
if (int(mod & boo::EModifierKey::Ctrl) != 0) {
if (m_commandString[size_t(m_cursorPosition)] == ' ')
m_cursorPosition++;
@ -367,8 +315,7 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
m_cursorPosition = int(m_commandString.size() - 1);
else
m_cursorPosition = int(tmpPos);
}
else
} else
m_cursorPosition++;
m_showCursor = true;
@ -376,8 +323,7 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
break;
}
case boo::ESpecialKey::Up:
{
case boo::ESpecialKey::Up: {
if (m_commandHistory.size() == 0)
break;
@ -390,17 +336,13 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
m_cursorPosition = int(m_commandString.size() - 1);
break;
}
case boo::ESpecialKey::Down:
{
case boo::ESpecialKey::Down: {
if (m_commandHistory.empty())
break;
m_currentCommand--;
if (m_currentCommand >= 0)
{
if (m_currentCommand >= 0) {
m_commandString = m_commandHistory[size_t(m_currentCommand)];
}
else if (m_currentCommand <= -1)
{
} else if (m_currentCommand <= -1) {
m_currentCommand = -1;
m_commandString.clear();
}
@ -418,60 +360,51 @@ void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, b
}
}
void Console::handleSpecialKeyUp(boo::ESpecialKey /*sp*/, boo::EModifierKey /*mod*/)
{
}
void Console::handleSpecialKeyUp(boo::ESpecialKey /*sp*/, boo::EModifierKey /*mod*/) {}
void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const char *format, va_list ap)
{
void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const char* format, va_list ap) {
char tmp[2048];
vsnprintf(tmp, 2048, format, ap);
std::vector<std::string> lines = athena::utility::split(tmp, '\n');
for (const std::string& line : lines)
{
for (const std::string& line : lines) {
std::string v = athena::utility::sprintf("[%s] %s", modName, line.c_str());
m_con->m_log.emplace_back(v, Console::Level(severity));
}
}
void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const wchar_t* format, va_list ap)
{
void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity, const wchar_t* format,
va_list ap) {
wchar_t tmp[2048];
vswprintf(tmp, 2048, format, ap);
std::vector<std::string> lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n');
for (const std::string& line : lines)
{
for (const std::string& line : lines) {
std::string v = athena::utility::sprintf("[%s] %s", modName, line.c_str());
m_con->m_log.emplace_back(v, Console::Level(severity));
}
}
void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, const char* format, va_list ap)
{
void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file,
unsigned linenum, const char* format, va_list ap) {
char tmp[2048];
vsnprintf(tmp, 2048, format, ap);
std::string v = athena::utility::sprintf("[%s] %s %s:%i", modName, tmp, file, linenum);
m_con->m_log.emplace_back(v, Console::Level(severity));
}
void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum, const wchar_t* format, va_list ap)
{
void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file,
unsigned linenum, const wchar_t* format, va_list ap) {
wchar_t tmp[2048];
vswprintf(tmp, 2048, format, ap);
std::vector<std::string> lines = athena::utility::split(athena::utility::wideToUtf8(tmp), '\n');
for (const std::string& line : lines)
{
for (const std::string& line : lines) {
std::string v = athena::utility::sprintf("[%s] %s %s:%i", modName, line.c_str(), file, linenum);
m_con->m_log.emplace_back(v, Console::Level(severity));
}
}
void Console::dumpLog()
{
for (const auto& l : m_log)
{
switch(l.second)
{
void Console::dumpLog() {
for (const auto& l : m_log) {
switch (l.second) {
case Level::Info:
printf("%s\n", l.first.c_str());
break;
@ -488,13 +421,7 @@ void Console::dumpLog()
}
}
void Console::RegisterLogger(Console* con)
{
logvisor::MainLoggers.emplace_back(new LogVisorAdapter(con));
}
void Console::RegisterLogger(Console* con) { logvisor::MainLoggers.emplace_back(new LogVisorAdapter(con)); }
Console* Console::instance()
{
return m_instance;
}
}
Console* Console::instance() { return m_instance; }
} // namespace hecl

View File

@ -12,14 +12,11 @@
#define BOLD "\x1b[1m"
#define NORMAL "\x1b[0m"
namespace hecl::Frontend
{
namespace hecl::Frontend {
std::string Diagnostics::sourceDiagString(const SourceLocation& l, bool ansi) const
{
std::string Diagnostics::sourceDiagString(const SourceLocation& l, bool ansi) const {
std::string::const_iterator it = m_source.begin();
for (int i=1 ; i<l.line ; ++i)
{
for (int i = 1; i < l.line; ++i) {
while (*it != '\n' && it != m_source.end())
++it;
if (*it == '\n')
@ -32,7 +29,7 @@ std::string Diagnostics::sourceDiagString(const SourceLocation& l, bool ansi) co
std::string retval(begin, end);
retval += '\n';
for (int i=1 ; i<l.col ; ++i)
for (int i = 1; i < l.col; ++i)
retval += ' ';
if (ansi)
retval += GREEN "^" NORMAL;
@ -41,8 +38,7 @@ std::string Diagnostics::sourceDiagString(const SourceLocation& l, bool ansi) co
return retval;
}
void Diagnostics::reportScannerErr(const SourceLocation& l, const char* fmt, ...)
{
void Diagnostics::reportScannerErr(const SourceLocation& l, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
char* result = nullptr;
@ -55,56 +51,54 @@ void Diagnostics::reportScannerErr(const SourceLocation& l, const char* fmt, ...
#endif
va_end(ap);
if (logvisor::XtermColor)
LogModule.report(logvisor::Fatal, CYAN "[Scanner]" NORMAL " %s " YELLOW "@%d:%d " NORMAL "\n%s\n%s",
LogModule.report(logvisor::Fatal, CYAN "[Scanner]" NORMAL " %s " YELLOW "@%d:%d " NORMAL "\n%s\n%s", m_name.c_str(),
l.line, l.col, result, sourceDiagString(l, true).c_str());
else
LogModule.report(logvisor::Fatal, "[Scanner] %s @%d:%d\n%s\n%s", m_name.c_str(), l.line, l.col, result,
sourceDiagString(l, false).c_str());
free(result);
}
void Diagnostics::reportParserErr(const SourceLocation& l, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
char* result = nullptr;
#ifdef _WIN32
int length = _vscprintf(fmt, ap);
result = (char*)malloc(length);
vsnprintf(result, length, fmt, ap);
#else
vasprintf(&result, fmt, ap);
#endif
va_end(ap);
if (logvisor::XtermColor)
LogModule.report(logvisor::Fatal, CYAN "[Parser]" NORMAL " %s " YELLOW "@%d:%d " NORMAL "\n%s\n%s", m_name.c_str(),
l.line, l.col, result, sourceDiagString(l, true).c_str());
else
LogModule.report(logvisor::Fatal, "[Parser] %s @%d:%d\n%s\n%s", m_name.c_str(), l.line, l.col, result,
sourceDiagString(l, false).c_str());
free(result);
}
void Diagnostics::reportBackendErr(const SourceLocation& l, const char* fmt, ...) {
va_list ap;
va_start(ap, fmt);
char* result = nullptr;
#ifdef _WIN32
int length = _vscprintf(fmt, ap);
result = (char*)malloc(length);
vsnprintf(result, length, fmt, ap);
#else
vasprintf(&result, fmt, ap);
#endif
va_end(ap);
if (logvisor::XtermColor)
LogModule.report(logvisor::Fatal, CYAN "[%s]" NORMAL " %s " YELLOW "@%d:%d " NORMAL "\n%s\n%s", m_backend.c_str(),
m_name.c_str(), l.line, l.col, result, sourceDiagString(l, true).c_str());
else
LogModule.report(logvisor::Fatal, "[Scanner] %s @%d:%d\n%s\n%s",
m_name.c_str(), l.line, l.col, result, sourceDiagString(l, false).c_str());
LogModule.report(logvisor::Fatal, "[%s] %s @%d:%d\n%s\n%s", m_backend.c_str(), m_name.c_str(), l.line, l.col,
result, sourceDiagString(l, false).c_str());
free(result);
}
void Diagnostics::reportParserErr(const SourceLocation& l, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
char* result = nullptr;
#ifdef _WIN32
int length = _vscprintf(fmt, ap);
result = (char*)malloc(length);
vsnprintf(result, length, fmt, ap);
#else
vasprintf(&result, fmt, ap);
#endif
va_end(ap);
if (logvisor::XtermColor)
LogModule.report(logvisor::Fatal, CYAN "[Parser]" NORMAL " %s " YELLOW "@%d:%d " NORMAL "\n%s\n%s",
m_name.c_str(), l.line, l.col, result, sourceDiagString(l, true).c_str());
else
LogModule.report(logvisor::Fatal, "[Parser] %s @%d:%d\n%s\n%s",
m_name.c_str(), l.line, l.col, result, sourceDiagString(l, false).c_str());
free(result);
}
void Diagnostics::reportBackendErr(const SourceLocation& l, const char* fmt, ...)
{
va_list ap;
va_start(ap, fmt);
char* result = nullptr;
#ifdef _WIN32
int length = _vscprintf(fmt, ap);
result = (char*)malloc(length);
vsnprintf(result, length, fmt, ap);
#else
vasprintf(&result, fmt, ap);
#endif
va_end(ap);
if (logvisor::XtermColor)
LogModule.report(logvisor::Fatal, CYAN "[%s]" NORMAL " %s " YELLOW "@%d:%d " NORMAL "\n%s\n%s",
m_backend.c_str(), m_name.c_str(), l.line, l.col, result, sourceDiagString(l, true).c_str());
else
LogModule.report(logvisor::Fatal, "[%s] %s @%d:%d\n%s\n%s",
m_backend.c_str(), m_name.c_str(), l.line, l.col, result, sourceDiagString(l, false).c_str());
free(result);
}
}
} // namespace hecl::Frontend

View File

@ -1,12 +1,9 @@
#include "hecl/Frontend.hpp"
namespace hecl::Frontend
{
namespace hecl::Frontend {
int IR::Instruction::getChildCount() const
{
switch (m_op)
{
int IR::Instruction::getChildCount() const {
switch (m_op) {
case OpType::Call:
return m_call.m_argInstIdxs.size();
case OpType::Arithmetic:
@ -19,10 +16,8 @@ int IR::Instruction::getChildCount() const
return -1;
}
const IR::Instruction& IR::Instruction::getChildInst(const IR& ir, size_t idx) const
{
switch (m_op)
{
const IR::Instruction& IR::Instruction::getChildInst(const IR& ir, size_t idx) const {
switch (m_op) {
case OpType::Call:
return ir.m_instructions.at(m_call.m_argInstIdxs.at(idx));
case OpType::Arithmetic:
@ -39,21 +34,19 @@ const IR::Instruction& IR::Instruction::getChildInst(const IR& ir, size_t idx) c
return *this;
}
const atVec4f& IR::Instruction::getImmVec() const
{
const atVec4f& IR::Instruction::getImmVec() const {
if (m_op != OpType::LoadImm)
LogModule.report(logvisor::Fatal, "invalid op type");
return m_loadImm.m_immVec;
}
template <class Op>
void IR::Instruction::Enumerate(typename Op::StreamT& s)
{
void IR::Instruction::Enumerate(typename Op::StreamT& s) {
Do<Op>({"op"}, m_op, s);
Do<Op>({"target"}, m_target, s);
switch (m_op)
{
default: break;
switch (m_op) {
default:
break;
case OpType::Call:
Do<Op>({"call"}, m_call, s);
break;
@ -69,10 +62,8 @@ void IR::Instruction::Enumerate(typename Op::StreamT& s)
}
}
atInt8 IR::swizzleCompIdx(char aChar)
{
switch (aChar)
{
atInt8 IR::swizzleCompIdx(char aChar) {
switch (aChar) {
case 'x':
case 'r':
return 0;
@ -91,50 +82,40 @@ atInt8 IR::swizzleCompIdx(char aChar)
return -1;
}
int IR::addInstruction(const IRNode& n, IR::RegID target)
{
int IR::addInstruction(const IRNode& n, IR::RegID target) {
if (n.kind == IRNode::Kind::None)
return -1;
switch (n.kind)
{
case IRNode::Kind::Call:
{
if (!n.str.compare("vec3") && n.children.size() >= 3)
{
switch (n.kind) {
case IRNode::Kind::Call: {
if (!n.str.compare("vec3") && n.children.size() >= 3) {
atVec4f vec = {};
auto it = n.children.cbegin();
int i;
athena::simd_floats f;
for (i=0 ; i<3 ; ++i, ++it)
{
for (i = 0; i < 3; ++i, ++it) {
if (it->kind != IRNode::Kind::Imm)
break;
f[i] = it->val;
}
vec.simd.copy_from(f);
if (i == 3)
{
if (i == 3) {
m_instructions.emplace_back(OpType::LoadImm, target, n.loc);
Instruction::LoadImm& inst = m_instructions.back().m_loadImm;
inst.m_immVec = vec;
return m_instructions.size() - 1;
}
}
else if (!n.str.compare("vec4") && n.children.size() >= 4)
{
} else if (!n.str.compare("vec4") && n.children.size() >= 4) {
atVec4f vec = {};
auto it = n.children.cbegin();
int i;
athena::simd_floats f;
for (i=0 ; i<4 ; ++i, ++it)
{
for (i = 0; i < 4; ++i, ++it) {
if (it->kind != IRNode::Kind::Imm)
break;
f[i] = it->val;
}
vec.simd.copy_from(f);
if (i == 4)
{
if (i == 4) {
m_instructions.emplace_back(OpType::LoadImm, target, n.loc);
Instruction::LoadImm& inst = m_instructions.back().m_loadImm;
inst.m_immVec = vec;
@ -154,15 +135,13 @@ int IR::addInstruction(const IRNode& n, IR::RegID target)
inst.m_argInstIdxs = argInstIdxs;
return m_instructions.size() - 1;
}
case IRNode::Kind::Imm:
{
case IRNode::Kind::Imm: {
m_instructions.emplace_back(OpType::LoadImm, target, n.loc);
Instruction::LoadImm& inst = m_instructions.back().m_loadImm;
inst.m_immVec.simd = athena::simd<float>(n.val);
return m_instructions.size() - 1;
}
case IRNode::Kind::Binop:
{
case IRNode::Kind::Binop: {
atUint16 left = addInstruction(*n.left, target);
atUint16 right = addInstruction(*n.right, target + 1);
m_instructions.emplace_back(OpType::Arithmetic, target, n.loc);
@ -172,12 +151,11 @@ int IR::addInstruction(const IRNode& n, IR::RegID target)
inst.m_instIdxs[1] = right;
return m_instructions.size() - 1;
}
case IRNode::Kind::Swizzle:
{
case IRNode::Kind::Swizzle: {
atUint16 left = addInstruction(*n.left, target);
m_instructions.emplace_back(OpType::Swizzle, target, n.loc);
Instruction::Swizzle& inst = m_instructions.back().m_swizzle;
for (int i=0 ; i<n.str.size() && i<4 ; ++i)
for (int i = 0; i < n.str.size() && i < 4; ++i)
inst.m_idxs[i] = swizzleCompIdx(n.str[i]);
inst.m_instIdx = left;
return m_instructions.size() - 1;
@ -188,32 +166,26 @@ int IR::addInstruction(const IRNode& n, IR::RegID target)
}
template <>
void IR::Enumerate<BigDNA::Read>(typename Read::StreamT& reader)
{
void IR::Enumerate<BigDNA::Read>(typename Read::StreamT& reader) {
m_hash = reader.readUint64Big();
m_regCount = reader.readUint16Big();
atUint16 instCount = reader.readUint16Big();
m_instructions.clear();
m_instructions.reserve(instCount);
for (atUint16 i=0 ; i<instCount ; ++i)
for (atUint16 i = 0; i < instCount; ++i)
m_instructions.emplace_back(reader);
/* Pre-resolve blending mode */
const IR::Instruction& rootCall = m_instructions.back();
m_doAlpha = false;
if (!rootCall.m_call.m_name.compare("HECLOpaque"))
{
if (!rootCall.m_call.m_name.compare("HECLOpaque")) {
m_blendSrc = boo::BlendFactor::One;
m_blendDst = boo::BlendFactor::Zero;
}
else if (!rootCall.m_call.m_name.compare("HECLAlpha"))
{
} else if (!rootCall.m_call.m_name.compare("HECLAlpha")) {
m_blendSrc = boo::BlendFactor::SrcAlpha;
m_blendDst = boo::BlendFactor::InvSrcAlpha;
m_doAlpha = true;
}
else if (!rootCall.m_call.m_name.compare("HECLAdditive"))
{
} else if (!rootCall.m_call.m_name.compare("HECLAdditive")) {
m_blendSrc = boo::BlendFactor::SrcAlpha;
m_blendDst = boo::BlendFactor::One;
m_doAlpha = true;
@ -221,8 +193,7 @@ void IR::Enumerate<BigDNA::Read>(typename Read::StreamT& reader)
}
template <>
void IR::Enumerate<BigDNA::Write>(typename Write::StreamT& writer)
{
void IR::Enumerate<BigDNA::Write>(typename Write::StreamT& writer) {
writer.writeUint64Big(m_hash);
writer.writeUint16Big(m_regCount);
writer.writeUint16Big(m_instructions.size());
@ -231,15 +202,13 @@ void IR::Enumerate<BigDNA::Write>(typename Write::StreamT& writer)
}
template <>
void IR::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& sz)
{
void IR::Enumerate<BigDNA::BinarySize>(typename BinarySize::StreamT& sz) {
sz += 12;
for (const Instruction& inst : m_instructions)
inst.binarySize(sz);
}
IR Frontend::compileSource(std::string_view source, std::string_view diagName)
{
IR Frontend::compileSource(std::string_view source, std::string_view diagName) {
m_diag.reset(diagName, source);
m_parser.reset(source);
auto insts = m_parser.parse();
@ -253,4 +222,4 @@ IR Frontend::compileSource(std::string_view source, std::string_view diagName)
return ir;
}
}
} // namespace hecl::Frontend

View File

@ -3,8 +3,7 @@
/* Syntatical token parsing system */
namespace hecl::Frontend
{
namespace hecl::Frontend {
/*
* hecl = { lf } call { lf { lf } call } { lf } .
@ -15,10 +14,9 @@ namespace hecl::Frontend
* value = ( call [ "." ident ] )
* | [ "-" ] number
* .
*/
*/
std::string IRNode::rep(int n, std::string_view s)
{
std::string IRNode::rep(int n, std::string_view s) {
std::string buf;
buf.reserve(n * s.size());
for (int i = 0; i < n; i++)
@ -26,24 +24,19 @@ std::string IRNode::rep(int n, std::string_view s)
return buf;
}
std::string IRNode::fmt(int level, bool stripUVAnims) const
{
std::string IRNode::fmt(int level, bool stripUVAnims) const {
std::string buf;
auto indent = rep(level, "\t"sv);
switch (kind)
{
switch (kind) {
case Kind::Call:
if (stripUVAnims && (str == "Texture" || str == "TextureN") && children.size() >= 2)
{
if (stripUVAnims && (str == "Texture" || str == "TextureN") && children.size() >= 2) {
auto it = children.begin();
IRNode& uvNode = const_cast<IRNode&>(*++it);
if (uvNode.str != "UV" && uvNode.str != "Normal" && uvNode.str != "View")
{
if (uvNode.str != "UV" && uvNode.str != "Normal" && uvNode.str != "View") {
std::string replacementName(str);
if (uvNode.str.back() == 'N' && replacementName.back() != 'N')
replacementName += 'N';
IRNode replacementNode(Kind::Call, std::move(replacementName),
std::move(uvNode.children), loc);
IRNode replacementNode(Kind::Call, std::move(replacementName), std::move(uvNode.children), loc);
auto ret = replacementNode.fmt(level, false);
uvNode.children = std::move(replacementNode.children);
return ret;
@ -51,11 +44,9 @@ std::string IRNode::fmt(int level, bool stripUVAnims) const
}
buf.append(indent);
buf.append("Call "sv).append(str);
if (!children.empty())
{
if (!children.empty()) {
buf.append(" {\n"sv);
for (const IRNode& n : children)
{
for (const IRNode& n : children) {
buf.append(n.fmt(level + 1, stripUVAnims));
buf.append("\n"sv);
}
@ -87,26 +78,21 @@ std::string IRNode::fmt(int level, bool stripUVAnims) const
return buf;
}
std::string IRNode::describe() const
{
std::string IRNode::describe() const {
std::vector<std::string> l;
l.push_back("kind="s + KindToStr(kind).data());
if (!str.empty())
l.push_back("str="s + str);
if (kind == Kind::Binop)
{
if (kind == Kind::Binop) {
l.push_back("op="s + OpToStr(op).data());
l.push_back("left="s + left->toString());
l.push_back("right="s + right->toString());
}
if (kind == Kind::Swizzle)
l.push_back("node="s + left->toString());
if (kind == Kind::Call)
{
if (kind == Kind::Call) {
std::string str = "children=["s;
for (auto it = children.begin(); it != children.end(); ++it)
{
for (auto it = children.begin(); it != children.end(); ++it) {
str += it->toString();
if (&*it != &children.back())
str += ';';
@ -116,8 +102,7 @@ std::string IRNode::describe() const
}
std::string str = "IRNode["s;
for (auto it = l.begin(); it != l.end(); ++it)
{
for (auto it = l.begin(); it != l.end(); ++it) {
str += *it;
if (&*it != &l.back())
str += ';';
@ -126,28 +111,24 @@ std::string IRNode::describe() const
return str;
}
void Parser::check(Token::Kind expected)
{
void Parser::check(Token::Kind expected) {
if (sym == expected)
scan();
else
error("expected %s, was %s", Token::KindToStr(expected).data(), Token::KindToStr(sym).data());
}
IRNode Parser::call()
{
IRNode Parser::call() {
check(Token::Kind::Ident);
std::string name = t.str;
std::list<IRNode> args;
check(Token::Kind::Lpar);
if (sym == Token::Kind::Lpar || sym == Token::Kind::Ident ||
sym == Token::Kind::Number || sym == Token::Kind::Minus)
{
if (sym == Token::Kind::Lpar || sym == Token::Kind::Ident || sym == Token::Kind::Number ||
sym == Token::Kind::Minus) {
args.push_back(expr());
while (sym == Token::Kind::Comma)
{
while (sym == Token::Kind::Comma) {
scan();
args.push_back(expr());
}
@ -160,21 +141,17 @@ IRNode Parser::call()
return IRNode(IRNode::Kind::Call, std::move(name), std::move(args), t.loc);
}
bool Parser::imm(const IRNode& a, const IRNode& b)
{
bool Parser::imm(const IRNode& a, const IRNode& b) {
return a.kind == IRNode::Kind::Imm && b.kind == IRNode::Kind::Imm;
}
IRNode Parser::expr()
{
IRNode Parser::expr() {
IRNode node = sum();
while (sym == Token::Kind::Plus || sym == Token::Kind::Minus)
{
while (sym == Token::Kind::Plus || sym == Token::Kind::Minus) {
scan();
Token::Kind op = t.kind;
IRNode right = sum();
switch (op)
{
switch (op) {
case Token::Kind::Plus:
if (imm(node, right)) // constant folding
return IRNode(IRNode::Kind::Imm, node.val + right.val, t.loc);
@ -194,16 +171,13 @@ IRNode Parser::expr()
return node;
}
IRNode Parser::sum()
{
IRNode Parser::sum() {
IRNode node = factor();
while (sym == Token::Kind::Times || sym == Token::Kind::Div)
{
while (sym == Token::Kind::Times || sym == Token::Kind::Div) {
scan();
Token::Kind op = t.kind;
IRNode right = factor();
switch (op)
{
switch (op) {
case Token::Kind::Times:
if (imm(node, right)) // constant folding
node = IRNode(IRNode::Kind::Imm, node.val * right.val, t.loc);
@ -223,10 +197,8 @@ IRNode Parser::sum()
return node;
}
IRNode Parser::factor()
{
if (sym == Token::Kind::Lpar)
{
IRNode Parser::factor() {
if (sym == Token::Kind::Lpar) {
scan();
IRNode node = expr();
check(Token::Kind::Rpar);
@ -235,47 +207,37 @@ IRNode Parser::factor()
return value();
}
IRNode Parser::value()
{
if (sym == Token::Kind::Number || sym == Token::Kind::Minus)
{
IRNode Parser::value() {
if (sym == Token::Kind::Number || sym == Token::Kind::Minus) {
scan();
bool neg = false;
if (t.kind == Token::Kind::Minus)
{
if (t.kind == Token::Kind::Minus) {
neg = true;
check(Token::Kind::Number);
}
float val = strtof(((neg ? "-"s : ""s) + t.str).c_str(), nullptr);
return IRNode(IRNode::Kind::Imm, val, t.loc);
}
else if (sym == Token::Kind::Ident)
{
} else if (sym == Token::Kind::Ident) {
IRNode call = Parser::call();
if (sym == Token::Kind::Period)
{
if (sym == Token::Kind::Period) {
scan();
check(Token::Kind::Ident);
return IRNode(IRNode::Kind::Swizzle, std::string(t.str), std::move(call), t.loc);
}
return call;
}
else
{
} else {
error("expected number|call, was %s", Token::KindToStr(sym).data());
return IRNode();
}
}
std::list<IRNode> Parser::parse()
{
std::list<IRNode> Parser::parse() {
std::list<IRNode> result;
scan();
while (sym == Token::Kind::Lf)
scan();
result.push_back(call());
while (sym == Token::Kind::Lf)
{
while (sym == Token::Kind::Lf) {
while (sym == Token::Kind::Lf)
scan();
if (sym != Token::Kind::Eof)
@ -292,4 +254,4 @@ std::list<IRNode> Parser::parse()
return result;
}
}
} // namespace hecl::Frontend

View File

@ -1,42 +1,34 @@
#include "hecl/Frontend.hpp"
namespace hecl::Frontend
{
namespace hecl::Frontend {
int Scanner::_read()
{
int Scanner::_read() {
if (m_sourceIt == m_source.end())
return -1;
return *m_sourceIt++;
}
bool Scanner::read()
{
bool Scanner::read() {
if (ch == EOF)
return false;
if (ch == LF)
{
if (ch == LF) {
lastLine = std::move(currentLine);
currentLine = std::string();
}
int c = _read();
ch = char(c);
if (ch == LF)
{
if (ch == LF) {
loc.line++;
lfcol = loc.col;
loc.col = 0;
}
else if (c != EOF)
{
} else if (c != EOF) {
currentLine += ch;
loc.col++;
}
return c != EOF;
}
Token Scanner::next()
{
Token Scanner::next() {
if (ch == EOF)
return Token(Token::Kind::Eof, loc);
@ -47,12 +39,9 @@ Token Scanner::next()
read();
// skip comments and newlines
while (c != EOF && (c == COMMENT || isspace(c)))
{
if (c == COMMENT)
{
while (c != LF && c != EOF)
{
while (c != EOF && (c == COMMENT || isspace(c))) {
if (c == COMMENT) {
while (c != LF && c != EOF) {
tline = loc.line;
tcol = loc.col;
tlfcol = lfcol;
@ -60,8 +49,7 @@ Token Scanner::next()
read();
}
}
while (c != EOF && isspace(c))
{
while (c != EOF && isspace(c)) {
if (c == LF)
return Token(Token::Kind::Lf, {tline - 1, tlfcol + 1});
tline = loc.line;
@ -80,21 +68,17 @@ Token Scanner::next()
return Token(Token::Kind::Eof, {tline, tcol});
// ident or number
if (isDigit(c))
{
if (isDigit(c)) {
std::string buf;
buf += c;
while (isDigit(ch))
{
while (isDigit(ch)) {
buf += ch;
read();
}
if (ch == '.')
{ // float
if (ch == '.') { // float
buf += ch;
read();
while (isDigit(ch))
{
while (isDigit(ch)) {
buf += ch;
read();
}
@ -102,12 +86,10 @@ Token Scanner::next()
return Token(Token::Kind::Number, std::move(buf), {tline, tcol});
}
if (isStartIdent(c))
{
if (isStartIdent(c)) {
std::string buf;
buf += c;
while (isMidIdent(ch))
{
while (isMidIdent(ch)) {
buf += ch;
read();
}
@ -119,4 +101,4 @@ Token Scanner::next()
return Token(Token::Kind::None, {tline, tcol});
}
}
} // namespace hecl::Frontend

View File

@ -32,14 +32,12 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
namespace hecl
{
namespace hecl {
static logvisor::Module Log("hecl::HumanizeNumber");
static const int maxscale = 7;
std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int scale, HNFlags flags)
{
std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int scale, HNFlags flags) {
const char *prefixes, *sep;
int i, r, remainder, s1, s2, sign;
int divisordeccut;
@ -91,7 +89,7 @@ std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int
}
}
#define SCALE2PREFIX(scale) (&prefixes[(scale) * 3])
#define SCALE2PREFIX(scale) (&prefixes[(scale)*3])
if (quotient < 0) {
sign = -1;
@ -111,9 +109,7 @@ std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int
/* Check if enough room for `x y' + suffix */
if (len < baselen)
Log.report(logvisor::Fatal,
"buffer size %" PRISize "insufficient for minimum size %" PRISize,
len, baselen);
Log.report(logvisor::Fatal, "buffer size %" PRISize "insufficient for minimum size %" PRISize, len, baselen);
std::string ret(len, '\0');
len += 1;
@ -127,9 +123,7 @@ std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int
* If there will be an overflow by the rounding below,
* divide once more.
*/
for (i = 0;
(quotient >= max || (quotient == max - 1 &&
remainder >= divisordeccut)) && i < maxscale; i++) {
for (i = 0; (quotient >= max || (quotient == max - 1 && remainder >= divisordeccut)) && i < maxscale; i++) {
remainder = quotient % divisor;
quotient /= divisor;
}
@ -145,20 +139,17 @@ std::string HumanizeNumber(int64_t quotient, size_t len, const char* suffix, int
* XXX - should we make sure there is enough space for the decimal
* place and if not, don't do HN_DECIMAL?
*/
if (((quotient == 9 && remainder < divisordeccut) || quotient < 9) &&
i > 0 && (flags & HNFlags::Decimal) != HNFlags::None) {
s1 = (int)quotient + ((remainder * 10 + divisor / 2) /
divisor / 10);
if (((quotient == 9 && remainder < divisordeccut) || quotient < 9) && i > 0 &&
(flags & HNFlags::Decimal) != HNFlags::None) {
s1 = (int)quotient + ((remainder * 10 + divisor / 2) / divisor / 10);
s2 = ((remainder * 10 + divisor / 2) / divisor) % 10;
r = snprintf(&ret[0], len, "%d%s%d%s%s%s",
sign * s1, localeconv()->decimal_point, s2,
sep, SCALE2PREFIX(i), suffix);
r = snprintf(&ret[0], len, "%d%s%d%s%s%s", sign * s1, localeconv()->decimal_point, s2, sep, SCALE2PREFIX(i),
suffix);
} else
r = snprintf(&ret[0], len, "%" PRId64 "%s%s%s",
sign * (quotient + (remainder + divisor / 2) / divisor),
sep, SCALE2PREFIX(i), suffix);
r = snprintf(&ret[0], len, "%" PRId64 "%s%s%s", sign * (quotient + (remainder + divisor / 2) / divisor), sep,
SCALE2PREFIX(i), suffix);
return ret;
}
}
} // namespace hecl

View File

@ -7,14 +7,12 @@
#define SHOW_CURSOR "\033[?25h"
#if _WIN32
#define FOREGROUND_WHITE FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE
#define FOREGROUND_WHITE FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
#endif
namespace hecl
{
namespace hecl {
void MultiProgressPrinter::ThreadStat::print(const TermInfo& tinfo) const
{
void MultiProgressPrinter::ThreadStat::print(const TermInfo& tinfo) const {
bool blocks = m_factor >= 0.f;
float factor = std::max(0.f, std::min(1.f, m_factor));
int iFactor = factor * 100.f;
@ -30,58 +28,49 @@ void MultiProgressPrinter::ThreadStat::print(const TermInfo& tinfo) const
else
half = messageLen;
if (half - messageLen < submessageLen-2)
if (half - messageLen < submessageLen - 2)
submessageLen = 0;
if (submessageLen)
{
if (messageLen > half-submessageLen-1)
hecl::Printf(_SYS_STR(" %.*s... %s "), half-submessageLen-4, m_message.c_str(), m_submessage.c_str());
else
{
if (submessageLen) {
if (messageLen > half - submessageLen - 1)
hecl::Printf(_SYS_STR(" %.*s... %s "), half - submessageLen - 4, m_message.c_str(), m_submessage.c_str());
else {
hecl::Printf(_SYS_STR(" %s"), m_message.c_str());
for (int i=half-messageLen-submessageLen-1 ; i>=0 ; --i)
for (int i = half - messageLen - submessageLen - 1; i >= 0; --i)
hecl::Printf(_SYS_STR(" "));
hecl::Printf(_SYS_STR("%s "), m_submessage.c_str());
}
}
else
{
} else {
if (messageLen > half)
hecl::Printf(_SYS_STR(" %.*s... "), half-3, m_message.c_str());
else
{
hecl::Printf(_SYS_STR(" %.*s... "), half - 3, m_message.c_str());
else {
hecl::Printf(_SYS_STR(" %s"), m_message.c_str());
for (int i=half-messageLen ; i>=0 ; --i)
for (int i = half - messageLen; i >= 0; --i)
hecl::Printf(_SYS_STR(" "));
}
}
if (blocks)
{
if (blocks) {
int rightHalf = tinfo.width - half - 4;
int blocks = rightHalf - 7;
int filled = blocks * factor;
int rem = blocks - filled;
if (tinfo.xtermColor)
{
if (tinfo.xtermColor) {
hecl::Printf(_SYS_STR("" BOLD "%3d%% ["), iFactor);
for (int b=0 ; b<filled ; ++b)
for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#"));
for (int b=0 ; b<rem ; ++b)
for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("]" NORMAL ""));
}
else
{
} else {
#if _WIN32
SetConsoleTextAttribute(tinfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
#endif
hecl::Printf(_SYS_STR("%3d%% ["), iFactor);
for (int b=0 ; b<filled ; ++b)
for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#"));
for (int b=0 ; b<rem ; ++b)
for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("]"));
#if _WIN32
@ -91,8 +80,7 @@ void MultiProgressPrinter::ThreadStat::print(const TermInfo& tinfo) const
}
}
void MultiProgressPrinter::DrawIndeterminateBar()
{
void MultiProgressPrinter::DrawIndeterminateBar() {
int half = m_termInfo.width - 2;
int blocks = half - 2;
@ -106,26 +94,23 @@ void MultiProgressPrinter::DrawIndeterminateBar()
int pre = absCounter;
int rem = blocks - pre - 1;
if (m_termInfo.xtermColor)
{
if (m_termInfo.xtermColor) {
hecl::Printf(_SYS_STR("" BOLD " ["));
for (int b=0 ; b<pre ; ++b)
for (int b = 0; b < pre; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("#"));
for (int b=0 ; b<rem ; ++b)
for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("]" NORMAL ""));
}
else
{
} else {
#if _WIN32
SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
#endif
hecl::Printf(_SYS_STR(" ["));
for (int b=0 ; b<pre ; ++b)
for (int b = 0; b < pre; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("#"));
for (int b=0 ; b<rem ; ++b)
for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("]"));
#if _WIN32
@ -134,17 +119,13 @@ void MultiProgressPrinter::DrawIndeterminateBar()
}
}
void MultiProgressPrinter::MoveCursorUp(int n)
{
if (n)
{
if (m_termInfo.xtermColor)
{
void MultiProgressPrinter::MoveCursorUp(int n) {
if (n) {
if (m_termInfo.xtermColor) {
hecl::Printf(_SYS_STR("" PREV_LINE ""), n);
}
#if _WIN32
else
{
else {
CONSOLE_SCREEN_BUFFER_INFO consoleInfo;
GetConsoleScreenBufferInfo(m_termInfo.console, &consoleInfo);
consoleInfo.dwCursorPosition.X = 0;
@ -152,19 +133,15 @@ void MultiProgressPrinter::MoveCursorUp(int n)
SetConsoleCursorPosition(m_termInfo.console, consoleInfo.dwCursorPosition);
}
#endif
}
else
{
} else {
hecl::Printf(_SYS_STR("\r"));
}
}
void MultiProgressPrinter::DoPrint()
{
void MultiProgressPrinter::DoPrint() {
auto logLk = logvisor::LockLog();
uint64_t logCounter = logvisor::GetLogCounter();
if (logCounter != m_lastLogCounter)
{
if (logCounter != m_lastLogCounter) {
m_curThreadLines = 0;
m_lastLogCounter = logCounter;
}
@ -177,18 +154,14 @@ void MultiProgressPrinter::DoPrint()
if (m_termInfo.xtermColor)
hecl::Printf(_SYS_STR("" HIDE_CURSOR ""));
if (m_dirty)
{
if (m_dirty) {
m_termInfo.width = (hecl::GuiMode ? 120 : std::max(80, hecl::ConsoleWidth(&m_termInfo.truncate)));
MoveCursorUp(m_curThreadLines + m_curProgLines);
m_curThreadLines = m_curProgLines = 0;
if (m_newLineAfter)
{
for (const ThreadStat& stat : m_threadStats)
{
if (stat.m_active)
{
if (m_newLineAfter) {
for (const ThreadStat& stat : m_threadStats) {
if (stat.m_active) {
stat.print(m_termInfo);
hecl::Printf(_SYS_STR("\n"));
++m_curThreadLines;
@ -199,14 +172,11 @@ void MultiProgressPrinter::DoPrint()
#ifndef _WIN32
&& m_termInfo.xtermColor
#endif
)
{
) {
DrawIndeterminateBar();
hecl::Printf(_SYS_STR("\n"));
++m_curProgLines;
}
else if (m_mainFactor >= 0.f)
{
} else if (m_mainFactor >= 0.f) {
float factor = std::max(0.0f, std::min(1.0f, m_mainFactor));
int iFactor = factor * 100.0;
int half = m_termInfo.width - 2;
@ -215,24 +185,21 @@ void MultiProgressPrinter::DoPrint()
int filled = blocks * factor;
int rem = blocks - filled;
if (m_termInfo.xtermColor)
{
if (m_termInfo.xtermColor) {
hecl::Printf(_SYS_STR("" BOLD " %3d%% ["), iFactor);
for (int b=0 ; b<filled ; ++b)
for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#"));
for (int b=0 ; b<rem ; ++b)
for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("]" NORMAL ""));
}
else
{
} else {
#if _WIN32
SetConsoleTextAttribute(m_termInfo.console, FOREGROUND_INTENSITY | FOREGROUND_WHITE);
#endif
hecl::Printf(_SYS_STR(" %3d%% ["), iFactor);
for (int b=0 ; b<filled ; ++b)
for (int b = 0; b < filled; ++b)
hecl::Printf(_SYS_STR("#"));
for (int b=0 ; b<rem ; ++b)
for (int b = 0; b < rem; ++b)
hecl::Printf(_SYS_STR("-"));
hecl::Printf(_SYS_STR("]"));
#if _WIN32
@ -243,21 +210,17 @@ void MultiProgressPrinter::DoPrint()
hecl::Printf(_SYS_STR("\n"));
++m_curProgLines;
}
}
else if (m_latestThread != -1)
{
} else if (m_latestThread != -1) {
const ThreadStat& stat = m_threadStats[m_latestThread];
stat.print(m_termInfo);
hecl::Printf(_SYS_STR("\r"));
}
m_dirty = false;
}
else if (m_mainIndeterminate
} else if (m_mainIndeterminate
#ifndef _WIN32
&& m_termInfo.xtermColor
#endif
)
{
) {
m_termInfo.width = (hecl::GuiMode ? 120 : std::max(80, hecl::ConsoleWidth()));
MoveCursorUp(m_curProgLines);
m_curProgLines = 0;
@ -276,10 +239,8 @@ void MultiProgressPrinter::DoPrint()
#endif
}
void MultiProgressPrinter::LogProc()
{
while (m_running)
{
void MultiProgressPrinter::LogProc() {
while (m_running) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
if (!m_dirty && !m_mainIndeterminate)
continue;
@ -288,10 +249,8 @@ void MultiProgressPrinter::LogProc()
}
}
MultiProgressPrinter::MultiProgressPrinter(bool activate)
{
if (activate)
{
MultiProgressPrinter::MultiProgressPrinter(bool activate) {
if (activate) {
/* Xterm check */
#if _WIN32
m_newLineAfter = true;
@ -302,8 +261,7 @@ MultiProgressPrinter::MultiProgressPrinter(bool activate)
#else
m_newLineAfter = false;
const char* term = getenv("TERM");
if (term && !strncmp(term, "xterm", 5))
{
if (term && !strncmp(term, "xterm", 5)) {
m_termInfo.xtermColor = true;
m_newLineAfter = true;
}
@ -314,17 +272,14 @@ MultiProgressPrinter::MultiProgressPrinter(bool activate)
}
}
MultiProgressPrinter::~MultiProgressPrinter()
{
MultiProgressPrinter::~MultiProgressPrinter() {
m_running = false;
if (m_logThread.joinable())
m_logThread.join();
}
void MultiProgressPrinter::print(const hecl::SystemChar* message,
const hecl::SystemChar* submessage,
float factor, int threadIdx) const
{
void MultiProgressPrinter::print(const hecl::SystemChar* message, const hecl::SystemChar* submessage, float factor,
int threadIdx) const {
if (!m_running)
return;
std::lock_guard<std::mutex> lk(m_logLock);
@ -347,8 +302,7 @@ void MultiProgressPrinter::print(const hecl::SystemChar* message,
m_dirty = true;
}
void MultiProgressPrinter::setMainFactor(float factor) const
{
void MultiProgressPrinter::setMainFactor(float factor) const {
if (!m_running)
return;
std::lock_guard<std::mutex> lk(m_logLock);
@ -357,20 +311,17 @@ void MultiProgressPrinter::setMainFactor(float factor) const
m_mainFactor = factor;
}
void MultiProgressPrinter::setMainIndeterminate(bool indeterminate) const
{
void MultiProgressPrinter::setMainIndeterminate(bool indeterminate) const {
if (!m_running)
return;
std::lock_guard<std::mutex> lk(m_logLock);
if (m_mainIndeterminate != indeterminate)
{
if (m_mainIndeterminate != indeterminate) {
m_mainIndeterminate = indeterminate;
m_dirty = true;
}
}
void MultiProgressPrinter::startNewLine() const
{
void MultiProgressPrinter::startNewLine() const {
if (!m_running)
return;
std::lock_guard<std::mutex> lk(m_logLock);
@ -383,10 +334,9 @@ void MultiProgressPrinter::startNewLine() const
hecl::Printf(_SYS_STR("\n"));
}
void MultiProgressPrinter::flush() const
{
void MultiProgressPrinter::flush() const {
std::lock_guard<std::mutex> lk(m_logLock);
const_cast<MultiProgressPrinter&>(*this).DoPrint();
}
}
} // namespace hecl

View File

@ -2,22 +2,19 @@
#include "athena/FileReader.hpp"
#include <zlib.h>
namespace hecl
{
namespace hecl {
#if HECL_RUNTIME
PipelineConverterBase* conv = nullptr;
class ShaderCacheZipStream : public athena::io::IStreamReader
{
class ShaderCacheZipStream : public athena::io::IStreamReader {
std::unique_ptr<uint8_t[]> m_compBuf;
athena::io::FileReader m_reader;
z_stream m_zstrm = {};
public:
explicit ShaderCacheZipStream(const hecl::SystemChar* path)
: m_reader(path)
{
explicit ShaderCacheZipStream(const hecl::SystemChar* path) : m_reader(path) {
if (m_reader.hasError())
return;
if (m_reader.readUint32Big() != SBIG('SHAD'))
@ -27,20 +24,14 @@ public:
m_zstrm.avail_in = 0;
inflateInit(&m_zstrm);
}
~ShaderCacheZipStream()
{
inflateEnd(&m_zstrm);
}
~ShaderCacheZipStream() { inflateEnd(&m_zstrm); }
operator bool() const { return m_compBuf.operator bool(); }
atUint64 readUBytesToBuf(void *buf, atUint64 len)
{
atUint64 readUBytesToBuf(void* buf, atUint64 len) {
m_zstrm.next_out = (Bytef*)buf;
m_zstrm.avail_out = len;
m_zstrm.total_out = 0;
while (m_zstrm.avail_out != 0)
{
if (m_zstrm.avail_in == 0)
{
while (m_zstrm.avail_out != 0) {
if (m_zstrm.avail_in == 0) {
atUint64 readSz = m_reader.readUBytesToBuf(m_compBuf.get(), 4096);
m_zstrm.avail_in = readSz;
m_zstrm.next_in = m_compBuf.get();
@ -52,27 +43,23 @@ public:
return m_zstrm.total_out;
}
void seek(atInt64, athena::SeekOrigin) {}
atUint64 position() const {return 0;}
atUint64 length() const {return 0;}
atUint64 position() const { return 0; }
atUint64 length() const { return 0; }
};
template<typename P, typename S>
void StageConverter<P, S>::loadFromStream(FactoryCtx& ctx, ShaderCacheZipStream& r)
{
template <typename P, typename S>
void StageConverter<P, S>::loadFromStream(FactoryCtx& ctx, ShaderCacheZipStream& r) {
uint32_t count = r.readUint32Big();
for (uint32_t i = 0; i < count; ++i)
{
for (uint32_t i = 0; i < count; ++i) {
uint64_t hash = r.readUint64Big();
uint32_t size = r.readUint32Big();
StageBinaryData data = MakeStageBinaryData(size);
r.readUBytesToBuf(data.get(), size);
m_stageCache.insert(std::make_pair(hash,
Do<StageTargetTp>(ctx, StageBinary<P, S>(data, size))));
m_stageCache.insert(std::make_pair(hash, Do<StageTargetTp>(ctx, StageBinary<P, S>(data, size))));
}
}
static boo::AdditionalPipelineInfo ReadAdditionalInfo(ShaderCacheZipStream& r)
{
static boo::AdditionalPipelineInfo ReadAdditionalInfo(ShaderCacheZipStream& r) {
boo::AdditionalPipelineInfo additionalInfo;
additionalInfo.srcFac = boo::BlendFactor(r.readUint32Big());
additionalInfo.dstFac = boo::BlendFactor(r.readUint32Big());
@ -88,14 +75,12 @@ static boo::AdditionalPipelineInfo ReadAdditionalInfo(ShaderCacheZipStream& r)
return additionalInfo;
}
static std::vector<boo::VertexElementDescriptor> ReadVertexFormat(ShaderCacheZipStream& r)
{
static std::vector<boo::VertexElementDescriptor> ReadVertexFormat(ShaderCacheZipStream& r) {
std::vector<boo::VertexElementDescriptor> ret;
uint32_t count = r.readUint32Big();
ret.reserve(count);
for (int i = 0; i < count; ++i)
{
for (int i = 0; i < count; ++i) {
ret.emplace_back();
ret.back().semantic = boo::VertexSemantic(r.readUint32Big());
ret.back().semanticIdx = int(r.readUint32Big());
@ -104,9 +89,8 @@ static std::vector<boo::VertexElementDescriptor> ReadVertexFormat(ShaderCacheZip
return ret;
}
template<typename P>
bool PipelineConverter<P>::loadFromFile(FactoryCtx& ctx, const hecl::SystemChar* path)
{
template <typename P>
bool PipelineConverter<P>::loadFromFile(FactoryCtx& ctx, const hecl::SystemChar* path) {
ShaderCacheZipStream r(path);
if (!r)
return false;
@ -118,8 +102,7 @@ bool PipelineConverter<P>::loadFromFile(FactoryCtx& ctx, const hecl::SystemChar*
m_evaluationConverter.loadFromStream(ctx, r);
uint32_t count = r.readUint32Big();
for (uint32_t i = 0; i < count; ++i)
{
for (uint32_t i = 0; i < count; ++i) {
uint64_t hash = r.readUint64Big();
StageRuntimeObject<P, PipelineStage::Vertex> vertex;
StageRuntimeObject<P, PipelineStage::Fragment> fragment;
@ -140,9 +123,10 @@ bool PipelineConverter<P>::loadFromFile(FactoryCtx& ctx, const hecl::SystemChar*
boo::AdditionalPipelineInfo additionalInfo = ReadAdditionalInfo(r);
std::vector<boo::VertexElementDescriptor> vtxFmt = ReadVertexFormat(r);
m_pipelineCache.insert(std::make_pair(hash, FinalPipeline<P>(*this, ctx,
StageCollection<StageRuntimeObject<P, PipelineStage::Null>>
(vertex, fragment, geometry, control, evaluation, additionalInfo,
m_pipelineCache.insert(
std::make_pair(hash, FinalPipeline<P>(*this, ctx,
StageCollection<StageRuntimeObject<P, PipelineStage::Null>>(
vertex, fragment, geometry, control, evaluation, additionalInfo,
boo::VertexFormatInfo(vtxFmt.size(), vtxFmt.data())))));
}
@ -150,11 +134,11 @@ bool PipelineConverter<P>::loadFromFile(FactoryCtx& ctx, const hecl::SystemChar*
}
#define SPECIALIZE_STAGE_CONVERTER(P) \
template class StageConverter<P, PipelineStage::Vertex>; \
template class StageConverter<P, PipelineStage::Fragment>; \
template class StageConverter<P, PipelineStage::Geometry>; \
template class StageConverter<P, PipelineStage::Control>; \
template class StageConverter<P, PipelineStage::Evaluation>;
template class StageConverter<P, PipelineStage::Vertex>; \
template class StageConverter<P, PipelineStage::Fragment>; \
template class StageConverter<P, PipelineStage::Geometry>; \
template class StageConverter<P, PipelineStage::Control>; \
template class StageConverter<P, PipelineStage::Evaluation>;
#if BOO_HAS_GL
template class PipelineConverter<PlatformType::OpenGL>;
@ -179,4 +163,4 @@ SPECIALIZE_STAGE_CONVERTER(PlatformType::NX)
#endif
}
} // namespace hecl

View File

@ -14,8 +14,7 @@
#include "hecl/ClientProcess.hpp"
#include "hecl/MultiProgressPrinter.hpp"
namespace hecl::Database
{
namespace hecl::Database {
logvisor::Module LogModule("hecl::Database");
static const hecl::FourCC HECLfcc("HECL");
@ -24,17 +23,12 @@ static const hecl::FourCC HECLfcc("HECL");
* Project::ConfigFile
**********************************************/
static inline bool CheckNewLineAdvance(std::string::const_iterator& it)
{
if (*it == '\n')
{
static inline bool CheckNewLineAdvance(std::string::const_iterator& it) {
if (*it == '\n') {
it += 1;
return true;
}
else if (*it == '\r')
{
if (*(it+1) == '\n')
{
} else if (*it == '\r') {
if (*(it + 1) == '\n') {
it += 2;
return true;
}
@ -44,14 +38,11 @@ static inline bool CheckNewLineAdvance(std::string::const_iterator& it)
return false;
}
Project::ConfigFile::ConfigFile(const Project& project, SystemStringView name,
SystemStringView subdir)
{
Project::ConfigFile::ConfigFile(const Project& project, SystemStringView name, SystemStringView subdir) {
m_filepath = SystemString(project.m_rootPath.getAbsolutePath()) + subdir.data() + name.data();
}
std::vector<std::string>& Project::ConfigFile::lockAndRead()
{
std::vector<std::string>& Project::ConfigFile::lockAndRead() {
if (m_lockedFile)
return m_lines;
@ -68,13 +59,11 @@ std::vector<std::string>& Project::ConfigFile::lockAndRead()
std::string::const_iterator end = mainString.begin();
m_lines.clear();
while (end != mainString.end())
{
while (end != mainString.end()) {
std::string::const_iterator origEnd = end;
if (*end == '\0')
break;
else if (CheckNewLineAdvance(end))
{
else if (CheckNewLineAdvance(end)) {
if (begin != origEnd)
m_lines.push_back(std::string(begin, origEnd));
begin = end;
@ -88,26 +77,19 @@ std::vector<std::string>& Project::ConfigFile::lockAndRead()
return m_lines;
}
void Project::ConfigFile::addLine(std::string_view line)
{
void Project::ConfigFile::addLine(std::string_view line) {
if (!checkForLine(line))
m_lines.emplace_back(line);
}
void Project::ConfigFile::removeLine(std::string_view refLine)
{
if (!m_lockedFile)
{
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__,
"Project::ConfigFile::lockAndRead not yet called");
void Project::ConfigFile::removeLine(std::string_view refLine) {
if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
return;
}
for (auto it = m_lines.begin();
it != m_lines.end();)
{
if (!(*it).compare(refLine))
{
for (auto it = m_lines.begin(); it != m_lines.end();) {
if (!(*it).compare(refLine)) {
it = m_lines.erase(it);
continue;
}
@ -115,12 +97,9 @@ void Project::ConfigFile::removeLine(std::string_view refLine)
}
}
bool Project::ConfigFile::checkForLine(std::string_view refLine)
{
if (!m_lockedFile)
{
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__,
"Project::ConfigFile::lockAndRead not yet called");
bool Project::ConfigFile::checkForLine(std::string_view refLine) {
if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
return false;
}
@ -130,12 +109,9 @@ bool Project::ConfigFile::checkForLine(std::string_view refLine)
return false;
}
void Project::ConfigFile::unlockAndDiscard()
{
if (!m_lockedFile)
{
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__,
"Project::ConfigFile::lockAndRead not yet called");
void Project::ConfigFile::unlockAndDiscard() {
if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
return;
}
@ -144,27 +120,21 @@ void Project::ConfigFile::unlockAndDiscard()
m_lockedFile = NULL;
}
bool Project::ConfigFile::unlockAndCommit()
{
if (!m_lockedFile)
{
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__,
"Project::ConfigFile::lockAndRead not yet called");
bool Project::ConfigFile::unlockAndCommit() {
if (!m_lockedFile) {
LogModule.reportSource(logvisor::Fatal, __FILE__, __LINE__, "Project::ConfigFile::lockAndRead not yet called");
return false;
}
SystemString newPath = m_filepath + _SYS_STR(".part");
FILE* newFile = hecl::Fopen(newPath.c_str(), _SYS_STR("w"), FileLockType::Write);
bool fail = false;
for (const std::string& line : m_lines)
{
if (fwrite(line.c_str(), 1, line.size(), newFile) != line.size())
{
for (const std::string& line : m_lines) {
if (fwrite(line.c_str(), 1, line.size(), newFile) != line.size()) {
fail = true;
break;
}
if (fwrite("\n", 1, 1, newFile) != 1)
{
if (fwrite("\n", 1, 1, newFile) != 1) {
fail = true;
break;
}
@ -173,17 +143,14 @@ bool Project::ConfigFile::unlockAndCommit()
fclose(newFile);
fclose(m_lockedFile);
m_lockedFile = NULL;
if (fail)
{
if (fail) {
#if HECL_UCS2
_wunlink(newPath.c_str());
#else
unlink(newPath.c_str());
#endif
return false;
}
else
{
} else {
#if HECL_UCS2
//_wrename(newPath.c_str(), m_filepath.c_str());
MoveFileExW(newPath.c_str(), m_filepath.c_str(), MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH);
@ -199,24 +166,21 @@ bool Project::ConfigFile::unlockAndCommit()
**********************************************/
Project::Project(const ProjectRootPath& rootPath)
: m_rootPath(rootPath),
m_workRoot(*this, _SYS_STR("")),
m_dotPath(m_workRoot, _SYS_STR(".hecl")),
m_cookedRoot(m_dotPath, _SYS_STR("cooked")),
m_specs(*this, _SYS_STR("specs")),
m_paths(*this, _SYS_STR("paths")),
m_groups(*this, _SYS_STR("groups"))
{
: m_rootPath(rootPath)
, m_workRoot(*this, _SYS_STR(""))
, m_dotPath(m_workRoot, _SYS_STR(".hecl"))
, m_cookedRoot(m_dotPath, _SYS_STR("cooked"))
, m_specs(*this, _SYS_STR("specs"))
, m_paths(*this, _SYS_STR("paths"))
, m_groups(*this, _SYS_STR("groups")) {
/* Stat for existing project directory (must already exist) */
Sstat myStat;
if (hecl::Stat(m_rootPath.getAbsolutePath().data(), &myStat))
{
if (hecl::Stat(m_rootPath.getAbsolutePath().data(), &myStat)) {
LogModule.report(logvisor::Error, _SYS_STR("unable to stat %s"), m_rootPath.getAbsolutePath().data());
return;
}
if (!S_ISDIR(myStat.st_mode))
{
if (!S_ISDIR(myStat.st_mode)) {
LogModule.report(logvisor::Error, _SYS_STR("provided path must be a directory; '%s' isn't"),
m_rootPath.getAbsolutePath().data());
return;
@ -229,23 +193,19 @@ Project::Project(const ProjectRootPath& rootPath)
/* Ensure beacon is valid or created */
ProjectPath beaconPath(m_dotPath, _SYS_STR("beacon"));
FILE* bf = hecl::Fopen(beaconPath.getAbsolutePath().data(), _SYS_STR("a+b"));
struct BeaconStruct
{
struct BeaconStruct {
hecl::FourCC magic;
uint32_t version;
} beacon;
#define DATA_VERSION 1
if (fread(&beacon, 1, sizeof(beacon), bf) != sizeof(beacon))
{
if (fread(&beacon, 1, sizeof(beacon), bf) != sizeof(beacon)) {
fseek(bf, 0, SEEK_SET);
beacon.magic = HECLfcc;
beacon.version = SBig(DATA_VERSION);
fwrite(&beacon, 1, sizeof(beacon), bf);
}
fclose(bf);
if (beacon.magic != HECLfcc ||
SBig(beacon.version) != DATA_VERSION)
{
if (beacon.magic != HECLfcc || SBig(beacon.version) != DATA_VERSION) {
LogModule.report(logvisor::Fatal, "incompatible project version");
return;
}
@ -255,8 +215,7 @@ Project::Project(const ProjectRootPath& rootPath)
m_valid = true;
}
const ProjectPath& Project::getProjectCookedPath(const DataSpecEntry& spec) const
{
const ProjectPath& Project::getProjectCookedPath(const DataSpecEntry& spec) const {
for (const ProjectDataSpec& sp : m_compiledSpecs)
if (&sp.spec == &spec)
return sp.cookedPath;
@ -264,60 +223,48 @@ const ProjectPath& Project::getProjectCookedPath(const DataSpecEntry& spec) cons
return m_cookedRoot;
}
bool Project::addPaths(const std::vector<ProjectPath>& paths)
{
bool Project::addPaths(const std::vector<ProjectPath>& paths) {
m_paths.lockAndRead();
for (const ProjectPath& path : paths)
m_paths.addLine(path.getRelativePathUTF8());
return m_paths.unlockAndCommit();
}
bool Project::removePaths(const std::vector<ProjectPath>& paths, bool recursive)
{
bool Project::removePaths(const std::vector<ProjectPath>& paths, bool recursive) {
std::vector<std::string>& existingPaths = m_paths.lockAndRead();
if (recursive)
{
for (const ProjectPath& path : paths)
{
if (recursive) {
for (const ProjectPath& path : paths) {
auto recursiveBase = path.getRelativePathUTF8();
for (auto it = existingPaths.begin();
it != existingPaths.end();)
{
if (!(*it).compare(0, recursiveBase.size(), recursiveBase))
{
for (auto it = existingPaths.begin(); it != existingPaths.end();) {
if (!(*it).compare(0, recursiveBase.size(), recursiveBase)) {
it = existingPaths.erase(it);
continue;
}
++it;
}
}
}
else
} else
for (const ProjectPath& path : paths)
m_paths.removeLine(path.getRelativePathUTF8());
return m_paths.unlockAndCommit();
}
bool Project::addGroup(const hecl::ProjectPath& path)
{
bool Project::addGroup(const hecl::ProjectPath& path) {
m_groups.lockAndRead();
m_groups.addLine(path.getRelativePathUTF8());
return m_groups.unlockAndCommit();
}
bool Project::removeGroup(const ProjectPath& path)
{
bool Project::removeGroup(const ProjectPath& path) {
m_groups.lockAndRead();
m_groups.removeLine(path.getRelativePathUTF8());
return m_groups.unlockAndCommit();
}
void Project::rescanDataSpecs()
{
void Project::rescanDataSpecs() {
m_compiledSpecs.clear();
m_specs.lockAndRead();
for (const DataSpecEntry* spec : DATA_SPEC_REGISTRY)
{
for (const DataSpecEntry* spec : DATA_SPEC_REGISTRY) {
hecl::SystemString specStr(spec->m_name);
SystemUTF8Conv specUTF8(specStr);
m_compiledSpecs.push_back({*spec, ProjectPath(m_cookedRoot, hecl::SystemString(spec->m_name) + _SYS_STR(".spec")),
@ -326,11 +273,9 @@ void Project::rescanDataSpecs()
m_specs.unlockAndDiscard();
}
bool Project::enableDataSpecs(const std::vector<SystemString>& specs)
{
bool Project::enableDataSpecs(const std::vector<SystemString>& specs) {
m_specs.lockAndRead();
for (const SystemString& spec : specs)
{
for (const SystemString& spec : specs) {
SystemUTF8Conv specView(spec);
m_specs.addLine(specView.str());
}
@ -339,11 +284,9 @@ bool Project::enableDataSpecs(const std::vector<SystemString>& specs)
return result;
}
bool Project::disableDataSpecs(const std::vector<SystemString>& specs)
{
bool Project::disableDataSpecs(const std::vector<SystemString>& specs) {
m_specs.lockAndRead();
for (const SystemString& spec : specs)
{
for (const SystemString& spec : specs) {
SystemUTF8Conv specView(spec);
m_specs.removeLine(specView.str());
}
@ -352,26 +295,30 @@ bool Project::disableDataSpecs(const std::vector<SystemString>& specs)
return result;
}
class CookProgress
{
class CookProgress {
const hecl::MultiProgressPrinter& m_progPrinter;
const SystemChar* m_dir = nullptr;
const SystemChar* m_file = nullptr;
float m_prog = 0.f;
public:
CookProgress(const hecl::MultiProgressPrinter& progPrinter) : m_progPrinter(progPrinter) {}
void changeDir(const SystemChar* dir) {m_dir = dir; m_progPrinter.startNewLine();}
void changeFile(const SystemChar* file, float prog) {m_file = file; m_prog = prog;}
void reportFile(const DataSpecEntry* specEnt)
{
void changeDir(const SystemChar* dir) {
m_dir = dir;
m_progPrinter.startNewLine();
}
void changeFile(const SystemChar* file, float prog) {
m_file = file;
m_prog = prog;
}
void reportFile(const DataSpecEntry* specEnt) {
SystemString submsg(m_file);
submsg += _SYS_STR(" (");
submsg += specEnt->m_name.data();
submsg += _SYS_STR(')');
m_progPrinter.print(m_dir, submsg.c_str(), m_prog);
}
void reportFile(const DataSpecEntry* specEnt, const SystemChar* extra)
{
void reportFile(const DataSpecEntry* specEnt, const SystemChar* extra) {
SystemString submsg(m_file);
submsg += _SYS_STR(" (");
submsg += specEnt->m_name.data();
@ -380,59 +327,42 @@ public:
submsg += _SYS_STR(')');
m_progPrinter.print(m_dir, submsg.c_str(), m_prog);
}
void reportDirComplete()
{
m_progPrinter.print(m_dir, nullptr, 1.f);
}
void reportDirComplete() { m_progPrinter.print(m_dir, nullptr, 1.f); }
};
static void VisitFile(const ProjectPath& path, bool force, bool fast,
std::vector<std::unique_ptr<IDataSpec>>& specInsts,
CookProgress& progress, ClientProcess* cp, int cookPass)
{
for (auto& spec : specInsts)
{
if (spec->canCook(path, hecl::blender::SharedBlenderToken, cookPass))
{
if (cp)
{
std::vector<std::unique_ptr<IDataSpec>>& specInsts, CookProgress& progress, ClientProcess* cp,
int cookPass) {
for (auto& spec : specInsts) {
if (spec->canCook(path, hecl::blender::SharedBlenderToken, cookPass)) {
if (cp) {
cp->addCookTransaction(path, force, fast, spec.get());
}
else
{
const DataSpecEntry* override = spec->overrideDataSpec(path, spec->getDataSpecEntry(),
hecl::blender::SharedBlenderToken);
} else {
const DataSpecEntry* override =
spec->overrideDataSpec(path, spec->getDataSpecEntry(), hecl::blender::SharedBlenderToken);
if (!override)
continue;
ProjectPath cooked = path.getCookedPath(*override);
if (fast)
cooked = cooked.getWithExtension(_SYS_STR(".fast"));
if (force || cooked.getPathType() == ProjectPath::Type::None ||
path.getModtime() > cooked.getModtime())
{
if (force || cooked.getPathType() == ProjectPath::Type::None || path.getModtime() > cooked.getModtime()) {
progress.reportFile(override);
spec->doCook(path, cooked, fast, hecl::blender::SharedBlenderToken,
[&](const SystemChar* extra)
{
progress.reportFile(override, extra);
});
[&](const SystemChar* extra) { progress.reportFile(override, extra); });
}
}
}
}
}
static void VisitDirectory(const ProjectPath& dir,
bool recursive, bool force, bool fast,
std::vector<std::unique_ptr<IDataSpec>>& specInsts,
CookProgress& progress, ClientProcess* cp, int cookPass)
{
static void VisitDirectory(const ProjectPath& dir, bool recursive, bool force, bool fast,
std::vector<std::unique_ptr<IDataSpec>>& specInsts, CookProgress& progress,
ClientProcess* cp, int cookPass) {
if (dir.getLastComponent().size() > 1 && dir.getLastComponent()[0] == _SYS_STR('.'))
return;
if (hecl::ProjectPath(dir, _SYS_STR("!project.yaml")).isFile() &&
hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).isFile())
{
hecl::ProjectPath(dir, _SYS_STR("!pool.yaml")).isFile()) {
/* Handle AudioGroup case */
VisitFile(dir, force, fast, specInsts, progress, cp, cookPass);
return;
@ -451,50 +381,39 @@ static void VisitDirectory(const ProjectPath& dir,
int progNum = 0;
float progDenom = childFileCount;
progress.changeDir(dir.getLastComponent().data());
for (auto& child : children)
{
if (child.second.getPathType() == ProjectPath::Type::File)
{
progress.changeFile(child.first.c_str(), progNum++/progDenom);
for (auto& child : children) {
if (child.second.getPathType() == ProjectPath::Type::File) {
progress.changeFile(child.first.c_str(), progNum++ / progDenom);
VisitFile(child.second, force, fast, specInsts, progress, cp, cookPass);
}
}
progress.reportDirComplete();
/* Pass 3: child directories */
if (recursive)
{
for (auto& child : children)
{
switch (child.second.getPathType())
{
case ProjectPath::Type::Directory:
{
if (recursive) {
for (auto& child : children) {
switch (child.second.getPathType()) {
case ProjectPath::Type::Directory: {
VisitDirectory(child.second, recursive, force, fast, specInsts, progress, cp, cookPass);
break;
}
default: break;
default:
break;
}
}
}
}
bool Project::cookPath(const ProjectPath& path, const hecl::MultiProgressPrinter& progress,
bool recursive, bool force, bool fast, const DataSpecEntry* spec,
ClientProcess* cp, int cookPass)
{
bool Project::cookPath(const ProjectPath& path, const hecl::MultiProgressPrinter& progress, bool recursive, bool force,
bool fast, const DataSpecEntry* spec, ClientProcess* cp, int cookPass) {
/* Construct DataSpec instances for cooking */
if (spec)
{
if (m_cookSpecs.size() != 1 || m_cookSpecs[0]->getDataSpecEntry() != spec)
{
if (spec) {
if (m_cookSpecs.size() != 1 || m_cookSpecs[0]->getDataSpecEntry() != spec) {
m_cookSpecs.clear();
if (spec->m_factory)
m_cookSpecs.push_back(spec->m_factory(*this, DataSpecTool::Cook));
}
}
else if (m_cookSpecs.empty())
{
} else if (m_cookSpecs.empty()) {
m_cookSpecs.reserve(m_compiledSpecs.size());
for (const ProjectDataSpec& spec : m_compiledSpecs)
if (spec.active && spec.spec.m_factory)
@ -503,50 +422,39 @@ bool Project::cookPath(const ProjectPath& path, const hecl::MultiProgressPrinter
/* Iterate complete directory/file/glob list */
CookProgress cookProg(progress);
switch (path.getPathType())
{
switch (path.getPathType()) {
case ProjectPath::Type::File:
case ProjectPath::Type::Glob:
{
case ProjectPath::Type::Glob: {
cookProg.changeFile(path.getLastComponent().data(), 0.f);
VisitFile(path, force, fast, m_cookSpecs, cookProg, cp, cookPass);
break;
}
case ProjectPath::Type::Directory:
{
case ProjectPath::Type::Directory: {
VisitDirectory(path, recursive, force, fast, m_cookSpecs, cookProg, cp, cookPass);
break;
}
default: break;
default:
break;
}
return true;
}
bool Project::packagePath(const ProjectPath& path, const hecl::MultiProgressPrinter& progress,
bool fast, const DataSpecEntry* spec, ClientProcess* cp)
{
bool Project::packagePath(const ProjectPath& path, const hecl::MultiProgressPrinter& progress, bool fast,
const DataSpecEntry* spec, ClientProcess* cp) {
/* Construct DataSpec instance for packaging */
const DataSpecEntry* specEntry = nullptr;
if (spec)
{
if (spec) {
if (spec->m_factory)
specEntry = spec;
}
else
{
} else {
bool foundPC = false;
for (const ProjectDataSpec& spec : m_compiledSpecs)
{
if (spec.active && spec.spec.m_factory)
{
if (hecl::StringUtils::EndsWith(spec.spec.m_name, _SYS_STR("-PC")))
{
for (const ProjectDataSpec& spec : m_compiledSpecs) {
if (spec.active && spec.spec.m_factory) {
if (hecl::StringUtils::EndsWith(spec.spec.m_name, _SYS_STR("-PC"))) {
foundPC = true;
specEntry = &spec.spec;
}
else if (!foundPC)
{
} else if (!foundPC) {
specEntry = &spec.spec;
}
}
@ -559,8 +467,7 @@ bool Project::packagePath(const ProjectPath& path, const hecl::MultiProgressPrin
if (!m_lastPackageSpec || m_lastPackageSpec->getDataSpecEntry() != specEntry)
m_lastPackageSpec = specEntry->m_factory(*this, DataSpecTool::Package);
if (m_lastPackageSpec->canPackage(path))
{
if (m_lastPackageSpec->canPackage(path)) {
m_lastPackageSpec->doPackage(path, specEntry, fast, hecl::blender::SharedBlenderToken, progress, cp);
return true;
}
@ -568,38 +475,24 @@ bool Project::packagePath(const ProjectPath& path, const hecl::MultiProgressPrin
return false;
}
void Project::interruptCook()
{
void Project::interruptCook() {
if (m_lastPackageSpec)
m_lastPackageSpec->interruptCook();
}
bool Project::cleanPath(const ProjectPath& path, bool recursive)
{
return false;
}
bool Project::cleanPath(const ProjectPath& path, bool recursive) { return false; }
PackageDepsgraph Project::buildPackageDepsgraph(const ProjectPath& path)
{
return PackageDepsgraph();
}
PackageDepsgraph Project::buildPackageDepsgraph(const ProjectPath& path) { return PackageDepsgraph(); }
void Project::addBridgePathToCache(uint64_t id, const ProjectPath& path)
{
m_bridgePathCache[id] = path;
}
void Project::addBridgePathToCache(uint64_t id, const ProjectPath& path) { m_bridgePathCache[id] = path; }
void Project::clearBridgePathCache()
{
m_bridgePathCache.clear();
}
void Project::clearBridgePathCache() { m_bridgePathCache.clear(); }
const ProjectPath* Project::lookupBridgePath(uint64_t id) const
{
const ProjectPath* Project::lookupBridgePath(uint64_t id) const {
auto search = m_bridgePathCache.find(id);
if (search == m_bridgePathCache.cend())
return nullptr;
return &search->second;
}
}
} // namespace hecl::Database

View File

@ -2,27 +2,22 @@
#include "hecl/Database.hpp"
#include <regex>
namespace hecl
{
static const SystemRegex regPATHCOMP(_SYS_STR("[/\\\\]*([^/\\\\]+)"), SystemRegex::ECMAScript|SystemRegex::optimize);
static const SystemRegex regDRIVELETTER(_SYS_STR("^([^/]*)/"), SystemRegex::ECMAScript|SystemRegex::optimize);
namespace hecl {
static const SystemRegex regPATHCOMP(_SYS_STR("[/\\\\]*([^/\\\\]+)"), SystemRegex::ECMAScript | SystemRegex::optimize);
static const SystemRegex regDRIVELETTER(_SYS_STR("^([^/]*)/"), SystemRegex::ECMAScript | SystemRegex::optimize);
static SystemString CanonRelPath(SystemStringView path)
{
static SystemString CanonRelPath(SystemStringView path) {
/* Tokenize Path */
std::vector<SystemString> comps;
hecl::SystemRegexMatch matches;
SystemString in(path);
SanitizePath(in);
for (; std::regex_search(in, matches, regPATHCOMP) ; in = matches.suffix().str())
{
for (; std::regex_search(in, matches, regPATHCOMP); in = matches.suffix().str()) {
hecl::SystemRegexMatch::const_reference match = matches[1];
if (!match.compare(_SYS_STR(".")))
continue;
else if (!match.compare(_SYS_STR("..")))
{
if (comps.empty())
{
else if (!match.compare(_SYS_STR(".."))) {
if (comps.empty()) {
/* Unable to resolve outside project */
LogModule.report(logvisor::Fatal, _SYS_STR("Unable to resolve outside project root in %s"), path.data());
return _SYS_STR(".");
@ -34,14 +29,11 @@ static SystemString CanonRelPath(SystemStringView path)
}
/* Emit relative path */
if (comps.size())
{
if (comps.size()) {
auto it = comps.begin();
SystemString retval = *it;
for (++it ; it != comps.end() ; ++it)
{
if ((*it).size())
{
for (++it; it != comps.end(); ++it) {
if ((*it).size()) {
retval += _SYS_STR('/');
retval += *it;
}
@ -51,26 +43,22 @@ static SystemString CanonRelPath(SystemStringView path)
return _SYS_STR(".");
}
static SystemString CanonRelPath(SystemStringView path, const ProjectRootPath& projectRoot)
{
static SystemString CanonRelPath(SystemStringView path, const ProjectRootPath& projectRoot) {
/* Absolute paths not allowed; attempt to make project-relative */
if (IsAbsolute(path))
return CanonRelPath(projectRoot.getProjectRelativeFromAbsolute(path));
return CanonRelPath(path);
}
void ProjectPath::assign(Database::Project& project, SystemStringView path)
{
void ProjectPath::assign(Database::Project& project, SystemStringView path) {
m_proj = &project;
SystemString usePath;
size_t pipeFind = path.rfind(_SYS_STR('|'));
if (pipeFind != SystemString::npos)
{
if (pipeFind != SystemString::npos) {
m_auxInfo.assign(path.cbegin() + pipeFind + 1, path.cend());
usePath.assign(path.cbegin(), path.cbegin() + pipeFind);
}
else
} else
usePath = path;
m_relPath = CanonRelPath(usePath, project.getProjectRootPath());
@ -82,25 +70,21 @@ void ProjectPath::assign(Database::Project& project, SystemStringView path)
}
#if HECL_UCS2
void ProjectPath::assign(Database::Project& project, std::string_view path)
{
void ProjectPath::assign(Database::Project& project, std::string_view path) {
std::wstring wpath = UTF8ToWide(path);
assign(project, wpath);
}
#endif
void ProjectPath::assign(const ProjectPath& parentPath, SystemStringView path)
{
void ProjectPath::assign(const ProjectPath& parentPath, SystemStringView path) {
m_proj = parentPath.m_proj;
SystemString usePath;
size_t pipeFind = path.rfind(_SYS_STR('|'));
if (pipeFind != SystemString::npos)
{
if (pipeFind != SystemString::npos) {
m_auxInfo.assign(path.cbegin() + pipeFind + 1, path.cend());
usePath.assign(path.cbegin(), path.cbegin() + pipeFind);
}
else
} else
usePath = path;
m_relPath = CanonRelPath(parentPath.m_relPath + _SYS_STR('/') + usePath);
@ -112,37 +96,31 @@ void ProjectPath::assign(const ProjectPath& parentPath, SystemStringView path)
}
#if HECL_UCS2
void ProjectPath::assign(const ProjectPath& parentPath, std::string_view path)
{
void ProjectPath::assign(const ProjectPath& parentPath, std::string_view path) {
std::wstring wpath = UTF8ToWide(path);
assign(parentPath, wpath);
}
#endif
ProjectPath ProjectPath::getWithExtension(const SystemChar* ext, bool replace) const
{
ProjectPath ProjectPath::getWithExtension(const SystemChar* ext, bool replace) const {
ProjectPath pp(*this);
if (replace)
{
if (replace) {
auto relIt = pp.m_relPath.end();
if (relIt != pp.m_relPath.begin())
--relIt;
auto absIt = pp.m_absPath.end();
if (absIt != pp.m_absPath.begin())
--absIt;
while (relIt != pp.m_relPath.begin() && *relIt != _SYS_STR('.') && *relIt != _SYS_STR('/'))
{
while (relIt != pp.m_relPath.begin() && *relIt != _SYS_STR('.') && *relIt != _SYS_STR('/')) {
--relIt;
--absIt;
}
if (*relIt == _SYS_STR('.') && relIt != pp.m_relPath.begin())
{
if (*relIt == _SYS_STR('.') && relIt != pp.m_relPath.begin()) {
pp.m_relPath.resize(relIt - pp.m_relPath.begin());
pp.m_absPath.resize(absIt - pp.m_absPath.begin());
}
}
if (ext)
{
if (ext) {
pp.m_relPath += ext;
pp.m_absPath += ext;
}
@ -151,8 +129,7 @@ ProjectPath ProjectPath::getWithExtension(const SystemChar* ext, bool replace) c
return pp;
}
ProjectPath ProjectPath::getCookedPath(const Database::DataSpecEntry& spec) const
{
ProjectPath ProjectPath::getCookedPath(const Database::DataSpecEntry& spec) const {
ProjectPath woExt = getWithExtension(nullptr, true);
ProjectPath ret(m_proj->getProjectCookedPath(spec), woExt.getRelativePath());
@ -162,8 +139,7 @@ ProjectPath ProjectPath::getCookedPath(const Database::DataSpecEntry& spec) cons
return ret;
}
ProjectPath::Type ProjectPath::getPathType() const
{
ProjectPath::Type ProjectPath::getPathType() const {
if (m_absPath.find(_SYS_STR('*')) != SystemString::npos)
return Type::Glob;
Sstat theStat;
@ -176,38 +152,27 @@ ProjectPath::Type ProjectPath::getPathType() const
return Type::None;
}
Time ProjectPath::getModtime() const
{
Time ProjectPath::getModtime() const {
Sstat theStat;
time_t latestTime = 0;
if (m_absPath.find(_SYS_STR('*')) != SystemString::npos)
{
if (m_absPath.find(_SYS_STR('*')) != SystemString::npos) {
std::vector<ProjectPath> globResults;
getGlobResults(globResults);
for (ProjectPath& path : globResults)
{
if (!hecl::Stat(path.getAbsolutePath().data(), &theStat))
{
for (ProjectPath& path : globResults) {
if (!hecl::Stat(path.getAbsolutePath().data(), &theStat)) {
if (S_ISREG(theStat.st_mode) && theStat.st_mtime > latestTime)
latestTime = theStat.st_mtime;
}
}
return Time(latestTime);
}
if (!hecl::Stat(m_absPath.c_str(), &theStat))
{
if (S_ISREG(theStat.st_mode))
{
if (!hecl::Stat(m_absPath.c_str(), &theStat)) {
if (S_ISREG(theStat.st_mode)) {
return Time(theStat.st_mtime);
}
else if (S_ISDIR(theStat.st_mode))
{
hecl::DirectoryEnumerator de(m_absPath, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted,
false, false, true);
for (const hecl::DirectoryEnumerator::Entry& ent : de)
{
if (!hecl::Stat(ent.m_path.c_str(), &theStat))
{
} else if (S_ISDIR(theStat.st_mode)) {
hecl::DirectoryEnumerator de(m_absPath, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const hecl::DirectoryEnumerator::Entry& ent : de) {
if (!hecl::Stat(ent.m_path.c_str(), &theStat)) {
if (S_ISREG(theStat.st_mode) && theStat.st_mtime > latestTime)
latestTime = theStat.st_mtime;
}
@ -219,19 +184,14 @@ Time ProjectPath::getModtime() const
return Time();
}
static void _recursiveGlob(Database::Project& proj,
std::vector<ProjectPath>& outPaths,
const SystemString& remPath,
const SystemString& itStr,
bool needSlash)
{
static void _recursiveGlob(Database::Project& proj, std::vector<ProjectPath>& outPaths, const SystemString& remPath,
const SystemString& itStr, bool needSlash) {
SystemRegexMatch matches;
if (!std::regex_search(remPath, matches, regPATHCOMP))
return;
const SystemString& comp = matches[1];
if (comp.find(_SYS_STR('*')) == SystemString::npos)
{
if (comp.find(_SYS_STR('*')) == SystemString::npos) {
SystemString nextItStr = itStr;
if (needSlash)
nextItStr += _SYS_STR('/');
@ -251,12 +211,9 @@ static void _recursiveGlob(Database::Project& proj,
/* Compile component into regex */
SystemRegex regComp(comp, SystemRegex::ECMAScript);
hecl::DirectoryEnumerator de(itStr, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted,
false, false, true);
for (const hecl::DirectoryEnumerator::Entry& ent : de)
{
if (std::regex_match(ent.m_name, regComp))
{
hecl::DirectoryEnumerator de(itStr, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const hecl::DirectoryEnumerator::Entry& ent : de) {
if (std::regex_match(ent.m_name, regComp)) {
SystemString nextItStr = itStr;
if (needSlash)
nextItStr += '/';
@ -274,40 +231,31 @@ static void _recursiveGlob(Database::Project& proj,
}
}
void ProjectPath::getDirChildren(std::map<SystemString, ProjectPath>& outPaths) const
{
hecl::DirectoryEnumerator de(m_absPath, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted,
false, false, true);
void ProjectPath::getDirChildren(std::map<SystemString, ProjectPath>& outPaths) const {
hecl::DirectoryEnumerator de(m_absPath, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const hecl::DirectoryEnumerator::Entry& ent : de)
outPaths[ent.m_name] = ProjectPath(*this, ent.m_name);
}
hecl::DirectoryEnumerator ProjectPath::enumerateDir() const
{
return hecl::DirectoryEnumerator(m_absPath, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted,
false, false, true);
hecl::DirectoryEnumerator ProjectPath::enumerateDir() const {
return hecl::DirectoryEnumerator(m_absPath, hecl::DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
}
void ProjectPath::getGlobResults(std::vector<ProjectPath>& outPaths) const
{
void ProjectPath::getGlobResults(std::vector<ProjectPath>& outPaths) const {
auto rootPath = m_proj->getProjectRootPath().getAbsolutePath();
_recursiveGlob(*m_proj, outPaths, m_relPath, rootPath.data(), rootPath.back() != _SYS_STR('/'));
}
ProjectRootPath SearchForProject(SystemStringView path)
{
ProjectRootPath SearchForProject(SystemStringView path) {
ProjectRootPath testRoot(path);
auto begin = testRoot.getAbsolutePath().begin();
auto end = testRoot.getAbsolutePath().end();
while (begin != end)
{
while (begin != end) {
SystemString testPath(begin, end);
SystemString testIndexPath = testPath + _SYS_STR("/.hecl/beacon");
Sstat theStat;
if (!hecl::Stat(testIndexPath.c_str(), &theStat))
{
if (S_ISREG(theStat.st_mode))
{
if (!hecl::Stat(testIndexPath.c_str(), &theStat)) {
if (S_ISREG(theStat.st_mode)) {
FILE* fp = hecl::Fopen(testIndexPath.c_str(), _SYS_STR("rb"));
if (!fp)
continue;
@ -323,7 +271,7 @@ ProjectRootPath SearchForProject(SystemStringView path)
}
}
while (begin != end && *(end-1) != _SYS_STR('/') && *(end-1) != _SYS_STR('\\'))
while (begin != end && *(end - 1) != _SYS_STR('/') && *(end - 1) != _SYS_STR('\\'))
--end;
if (begin != end)
--end;
@ -331,20 +279,16 @@ ProjectRootPath SearchForProject(SystemStringView path)
return ProjectRootPath();
}
ProjectRootPath SearchForProject(SystemStringView path, SystemString& subpathOut)
{
ProjectRootPath SearchForProject(SystemStringView path, SystemString& subpathOut) {
ProjectRootPath testRoot(path);
auto begin = testRoot.getAbsolutePath().begin();
auto end = testRoot.getAbsolutePath().end();
while (begin != end)
{
while (begin != end) {
SystemString testPath(begin, end);
SystemString testIndexPath = testPath + _SYS_STR("/.hecl/beacon");
Sstat theStat;
if (!hecl::Stat(testIndexPath.c_str(), &theStat))
{
if (S_ISREG(theStat.st_mode))
{
if (!hecl::Stat(testIndexPath.c_str(), &theStat)) {
if (S_ISREG(theStat.st_mode)) {
FILE* fp = hecl::Fopen(testIndexPath.c_str(), _SYS_STR("rb"));
if (!fp)
continue;
@ -366,7 +310,7 @@ ProjectRootPath SearchForProject(SystemStringView path, SystemString& subpathOut
}
}
while (begin != end && *(end-1) != _SYS_STR('/') && *(end-1) != _SYS_STR('\\'))
while (begin != end && *(end - 1) != _SYS_STR('/') && *(end - 1) != _SYS_STR('\\'))
--end;
if (begin != end)
--end;
@ -374,4 +318,4 @@ ProjectRootPath SearchForProject(SystemStringView path, SystemString& subpathOut
return ProjectRootPath();
}
}
} // namespace hecl

View File

@ -8,13 +8,10 @@
using namespace Windows::Storage;
#endif
namespace hecl::Runtime
{
namespace hecl::Runtime {
static logvisor::Module Log("FileStoreManager");
FileStoreManager::FileStoreManager(SystemStringView domain)
: m_domain(domain)
{
FileStoreManager::FileStoreManager(SystemStringView domain) : m_domain(domain) {
#if _WIN32
#if !WINDOWS_STORE
WCHAR home[MAX_PATH];
@ -23,7 +20,7 @@ FileStoreManager::FileStoreManager(SystemStringView domain)
SystemString path(home);
#else
StorageFolder^ cacheFolder = ApplicationData::Current->LocalCacheFolder;
StorageFolder ^ cacheFolder = ApplicationData::Current->LocalCacheFolder;
SystemString path(cacheFolder->Path->Data());
#endif
path += _SYS_STR("/.heclrun");
@ -50,4 +47,4 @@ FileStoreManager::FileStoreManager(SystemStringView domain)
#endif
}
}
} // namespace hecl::Runtime

View File

@ -2,13 +2,10 @@
#include "hecl/Runtime.hpp"
#include <athena/MemoryReader.hpp>
namespace hecl::Runtime
{
namespace hecl::Runtime {
static logvisor::Module HMDL_Log("HMDL");
HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx,
const void* metaData, const void* vbo, const void* ibo)
{
HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx, const void* metaData, const void* vbo, const void* ibo) {
HMDLMeta meta;
{
athena::io::MemoryReader r((atUint8*)metaData, HECL_HMDL_META_SZ);
@ -27,20 +24,17 @@ HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx,
m_vtxFmtData[1].semantic = boo::VertexSemantic::Normal3;
size_t e = 2;
for (size_t i=0 ; i<meta.colorCount ; ++i, ++e)
{
for (size_t i = 0; i < meta.colorCount; ++i, ++e) {
m_vtxFmtData[e].semantic = boo::VertexSemantic::ColorUNorm;
m_vtxFmtData[e].semanticIdx = i;
}
for (size_t i=0 ; i<meta.uvCount ; ++i, ++e)
{
for (size_t i = 0; i < meta.uvCount; ++i, ++e) {
m_vtxFmtData[e].semantic = boo::VertexSemantic::UV2;
m_vtxFmtData[e].semanticIdx = i;
}
for (size_t i=0 ; i<meta.weightCount ; ++i, ++e)
{
for (size_t i = 0; i < meta.weightCount; ++i, ++e) {
m_vtxFmtData[e].semantic = boo::VertexSemantic::Weight;
m_vtxFmtData[e].semanticIdx = i;
}
@ -48,4 +42,4 @@ HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx,
m_vtxFmt = boo::VertexFormatInfo(elemCount, m_vtxFmtData.get());
}
}
} // namespace hecl::Runtime

View File

@ -7,15 +7,12 @@
#define PATH_SEP '/'
#endif
namespace hecl
{
namespace hecl {
/* Used to extract alternate steam install directories from libraryfolders.vdf */
static const std::regex regSteamPath(R"(^\s+\"[0-9]+\"\s+\"(.*)\")",
std::regex::ECMAScript|std::regex::optimize);
static const std::regex regSteamPath(R"(^\s+\"[0-9]+\"\s+\"(.*)\")", std::regex::ECMAScript | std::regex::optimize);
hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name)
{
hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name) {
hecl::SystemString steamInstallDir;
hecl::Sstat theStat;
@ -23,17 +20,16 @@ hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name)
#if !WINDOWS_STORE
HKEY hkey;
hecl::SystemChar _steamInstallDir[MAX_PATH] = {0};
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _SYS_STR("Software\\Valve\\Steam"),
0, KEY_QUERY_VALUE, &hkey) != ERROR_SUCCESS)
{
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _SYS_STR("Software\\Valve\\Steam"),
0, KEY_QUERY_VALUE | KEY_WOW64_32KEY, &hkey) != ERROR_SUCCESS)
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _SYS_STR("Software\\Valve\\Steam"), 0, KEY_QUERY_VALUE, &hkey) !=
ERROR_SUCCESS) {
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, _SYS_STR("Software\\Valve\\Steam"), 0, KEY_QUERY_VALUE | KEY_WOW64_32KEY,
&hkey) != ERROR_SUCCESS)
return {};
}
DWORD size = MAX_PATH;
if (RegQueryValueEx(hkey, _SYS_STR("InstallPath"), nullptr, nullptr,
(LPBYTE)_steamInstallDir, &size) == ERROR_SUCCESS)
if (RegQueryValueEx(hkey, _SYS_STR("InstallPath"), nullptr, nullptr, (LPBYTE)_steamInstallDir, &size) ==
ERROR_SUCCESS)
steamInstallDir = _steamInstallDir;
RegCloseKey(hkey);
@ -52,8 +48,7 @@ hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name)
#else
steamInstallDir = getenv("HOME");
steamInstallDir += "/.local/share/Steam";
if (hecl::Stat(steamInstallDir.c_str(), &theStat) || !S_ISDIR(theStat.st_mode))
{
if (hecl::Stat(steamInstallDir.c_str(), &theStat) || !S_ISDIR(theStat.st_mode)) {
steamInstallDir = getenv("HOME");
steamInstallDir += "/.steam/steam";
if (hecl::Stat(steamInstallDir.c_str(), &theStat) || !S_ISDIR(theStat.st_mode))
@ -77,16 +72,14 @@ hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name)
return {};
hecl::FSeek(fp, 0, SEEK_END);
int64_t fileLen = hecl::FTell(fp);
if (fileLen <= 0)
{
if (fileLen <= 0) {
fclose(fp);
return {};
}
hecl::FSeek(fp, 0, SEEK_SET);
std::string fileBuf;
fileBuf.resize(fileLen);
if (fread(&fileBuf[0], 1, fileLen, fp) != fileLen)
{
if (fread(&fileBuf[0], 1, fileLen, fp) != fileLen) {
fclose(fp);
return {};
}
@ -95,12 +88,11 @@ hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name)
std::smatch dirMatch;
auto begin = fileBuf.cbegin();
auto end = fileBuf.cend();
while (std::regex_search(begin, end, dirMatch, regSteamPath))
{
while (std::regex_search(begin, end, dirMatch, regSteamPath)) {
std::string match = dirMatch[1].str();
hecl::SystemStringConv otherInstallDir(match);
hecl::SystemString otherAppPath = hecl::SystemString(otherInstallDir.sys_str()) + PATH_SEP +
_SYS_STR("steamapps") + PATH_SEP + appPath;
hecl::SystemString otherAppPath =
hecl::SystemString(otherInstallDir.sys_str()) + PATH_SEP + _SYS_STR("steamapps") + PATH_SEP + appPath;
if (!hecl::Stat(otherAppPath.c_str(), &theStat) && S_ISDIR(theStat.st_mode))
return otherAppPath;
begin = dirMatch.suffix().first;
@ -109,4 +101,4 @@ hecl::SystemString FindCommonSteamApp(const hecl::SystemChar* name)
return {};
}
}
} // namespace hecl

View File

@ -1,20 +1,16 @@
#include <utf8proc.h>
#include "hecl/hecl.hpp"
namespace hecl
{
namespace hecl {
static logvisor::Module Log("hecl-wsconv");
std::string WideToUTF8(std::wstring_view src)
{
std::string WideToUTF8(std::wstring_view src) {
std::string retval;
retval.reserve(src.length());
for (wchar_t ch : src)
{
for (wchar_t ch : src) {
utf8proc_uint8_t mb[4];
utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb);
if (c < 0)
{
if (c < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while encoding");
return retval;
}
@ -23,16 +19,13 @@ std::string WideToUTF8(std::wstring_view src)
return retval;
}
std::string Char16ToUTF8(std::u16string_view src)
{
std::string Char16ToUTF8(std::u16string_view src) {
std::string retval;
retval.reserve(src.length());
for (char16_t ch : src)
{
for (char16_t ch : src) {
utf8proc_uint8_t mb[4];
utf8proc_ssize_t c = utf8proc_encode_char(utf8proc_int32_t(ch), mb);
if (c < 0)
{
if (c < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while encoding");
return retval;
}
@ -41,17 +34,14 @@ std::string Char16ToUTF8(std::u16string_view src)
return retval;
}
std::wstring UTF8ToWide(std::string_view src)
{
std::wstring UTF8ToWide(std::string_view src) {
std::wstring retval;
retval.reserve(src.length());
const utf8proc_uint8_t* buf = reinterpret_cast<const utf8proc_uint8_t*>(src.data());
while (*buf)
{
while (*buf) {
utf8proc_int32_t wc;
utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc);
if (len < 0)
{
if (len < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while decoding");
return retval;
}
@ -61,17 +51,14 @@ std::wstring UTF8ToWide(std::string_view src)
return retval;
}
std::u16string UTF8ToChar16(std::string_view src)
{
std::u16string UTF8ToChar16(std::string_view src) {
std::u16string retval;
retval.reserve(src.length());
const utf8proc_uint8_t* buf = reinterpret_cast<const utf8proc_uint8_t*>(src.data());
while (*buf)
{
while (*buf) {
utf8proc_int32_t wc;
utf8proc_ssize_t len = utf8proc_iterate(buf, -1, &wc);
if (len < 0)
{
if (len < 0) {
Log.report(logvisor::Warning, "invalid UTF-8 character while decoding");
return retval;
}
@ -81,4 +68,4 @@ std::u16string UTF8ToChar16(std::string_view src)
return retval;
}
}
} // namespace hecl

View File

@ -20,18 +20,17 @@
#include <sys/wait.h>
#endif
namespace hecl
{
namespace hecl {
unsigned VerbosityLevel = 0;
bool GuiMode = false;
logvisor::Module LogModule("hecl");
static const std::string Illegals {"<>?\"|"};
static const std::string Illegals{"<>?\"|"};
#if __GNUC__
__attribute__((__format__ (__printf__, 1, 2)))
__attribute__((__format__(__printf__, 1, 2)))
#endif
SystemString SysFormat(const SystemChar* format, ...)
{
SystemString
SysFormat(const SystemChar* format, ...) {
SystemChar resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
@ -45,10 +44,10 @@ SystemString SysFormat(const SystemChar* format, ...)
}
#if __GNUC__
__attribute__((__format__ (__printf__, 1, 2)))
__attribute__((__format__(__printf__, 1, 2)))
#endif
std::string Format(const char* format, ...)
{
std::string
Format(const char* format, ...) {
char resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
@ -57,8 +56,7 @@ std::string Format(const char* format, ...)
return std::string(resultBuf, printSz);
}
std::wstring WideFormat(const wchar_t* format, ...)
{
std::wstring WideFormat(const wchar_t* format, ...) {
wchar_t resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
@ -67,8 +65,7 @@ std::wstring WideFormat(const wchar_t* format, ...)
return std::wstring(resultBuf, printSz);
}
std::u16string Char16Format(const wchar_t* format, ...)
{
std::u16string Char16Format(const wchar_t* format, ...) {
wchar_t resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
@ -76,13 +73,12 @@ std::u16string Char16Format(const wchar_t* format, ...)
va_end(va);
std::u16string res;
res.reserve(printSz);
for (size_t i=0 ; i<printSz ; ++i)
for (size_t i = 0; i < printSz; ++i)
res.push_back(resultBuf[i]);
return res;
}
void SanitizePath(std::string& path)
{
void SanitizePath(std::string& path) {
if (path.empty())
return;
path.erase(std::remove(path.begin(), path.end(), '\n'), path.end());
@ -91,19 +87,16 @@ void SanitizePath(std::string& path)
bool ic = false;
std::transform(path.begin(), path.end(), path.begin(), [&](const char a) -> char {
++p1;
if (Illegals.find_first_of(a) != std::string::npos)
{
if (Illegals.find_first_of(a) != std::string::npos) {
ic = false;
return '_';
}
if (ic)
{
if (ic) {
ic = false;
return a;
}
if (a == '\\' && (p1 == path.end() || *p1 != '\\'))
{
if (a == '\\' && (p1 == path.end() || *p1 != '\\')) {
ic = true;
return '/';
}
@ -113,10 +106,9 @@ void SanitizePath(std::string& path)
path.pop_back();
}
static const std::wstring WIllegals {L"<>?\"|"};
static const std::wstring WIllegals{L"<>?\"|"};
void SanitizePath(std::wstring& path)
{
void SanitizePath(std::wstring& path) {
if (path.empty())
return;
path.erase(std::remove(path.begin(), path.end(), L'\n'), path.end());
@ -125,19 +117,16 @@ void SanitizePath(std::wstring& path)
bool ic = false;
std::transform(path.begin(), path.end(), path.begin(), [&](const wchar_t a) -> wchar_t {
++p1;
if (WIllegals.find_first_of(a) != std::wstring::npos)
{
if (WIllegals.find_first_of(a) != std::wstring::npos) {
ic = false;
return L'_';
}
if (ic)
{
if (ic) {
ic = false;
return a;
}
if (a == L'\\' && (p1 == path.end() || *p1 != L'\\'))
{
if (a == L'\\' && (p1 == path.end() || *p1 != L'\\')) {
ic = true;
return L'/';
}
@ -147,31 +136,27 @@ void SanitizePath(std::wstring& path)
path.pop_back();
}
SystemString GetcwdStr()
{
SystemString GetcwdStr() {
/* http://stackoverflow.com/a/2869667 */
//const size_t ChunkSize=255;
//const int MaxChunks=10240; // 2550 KiBs of current path are more than enough
// const size_t ChunkSize=255;
// const int MaxChunks=10240; // 2550 KiBs of current path are more than enough
SystemChar stackBuffer[255]; // Stack buffer for the "normal" case
if (Getcwd(stackBuffer, 255) != nullptr)
return SystemString(stackBuffer);
if (errno != ERANGE)
{
if (errno != ERANGE) {
// It's not ERANGE, so we don't know how to handle it
LogModule.report(logvisor::Fatal, "Cannot determine the current path.");
// Of course you may choose a different error reporting method
}
// Ok, the stack buffer isn't long enough; fallback to heap allocation
for (int chunks=2 ; chunks<10240 ; chunks++)
{
for (int chunks = 2; chunks < 10240; chunks++) {
// With boost use scoped_ptr; in C++0x, use unique_ptr
// If you want to be less C++ but more efficient you may want to use realloc
std::unique_ptr<SystemChar[]> cwd(new SystemChar[255*chunks]);
if (Getcwd(cwd.get(), 255*chunks) != nullptr)
std::unique_ptr<SystemChar[]> cwd(new SystemChar[255 * chunks]);
if (Getcwd(cwd.get(), 255 * chunks) != nullptr)
return SystemString(cwd.get());
if (errno != ERANGE)
{
if (errno != ERANGE) {
// It's not ERANGE, so we don't know how to handle it
LogModule.report(logvisor::Fatal, "Cannot determine the current path.");
// Of course you may choose a different error reporting method
@ -184,8 +169,7 @@ SystemString GetcwdStr()
static std::mutex PathsMutex;
static std::unordered_map<std::thread::id, ProjectPath> PathsInProgress;
bool ResourceLock::InProgress(const ProjectPath& path)
{
bool ResourceLock::InProgress(const ProjectPath& path) {
std::unique_lock<std::mutex> lk(PathsMutex);
for (const auto& p : PathsInProgress)
if (p.second == path)
@ -193,8 +177,7 @@ bool ResourceLock::InProgress(const ProjectPath& path)
return false;
}
bool ResourceLock::SetThreadRes(const ProjectPath& path)
{
bool ResourceLock::SetThreadRes(const ProjectPath& path) {
std::unique_lock<std::mutex> lk(PathsMutex);
if (PathsInProgress.find(std::this_thread::get_id()) != PathsInProgress.cend())
LogModule.report(logvisor::Fatal, "multiple resource locks on thread");
@ -207,20 +190,17 @@ bool ResourceLock::SetThreadRes(const ProjectPath& path)
return true;
}
void ResourceLock::ClearThreadRes()
{
void ResourceLock::ClearThreadRes() {
std::unique_lock<std::mutex> lk(PathsMutex);
PathsInProgress.erase(std::this_thread::get_id());
}
bool IsPathPNG(const hecl::ProjectPath& path)
{
bool IsPathPNG(const hecl::ProjectPath& path) {
FILE* fp = hecl::Fopen(path.getAbsolutePath().data(), _SYS_STR("rb"));
if (!fp)
return false;
uint32_t buf = 0;
if (fread(&buf, 1, 4, fp) != 4)
{
if (fread(&buf, 1, 4, fp) != 4) {
fclose(fp);
return false;
}
@ -231,8 +211,7 @@ bool IsPathPNG(const hecl::ProjectPath& path)
return false;
}
bool IsPathBlend(const hecl::ProjectPath& path)
{
bool IsPathBlend(const hecl::ProjectPath& path) {
auto lastCompExt = path.getLastComponentExt();
if (lastCompExt.empty() || hecl::StrCmp(lastCompExt.data(), _SYS_STR("blend")))
return false;
@ -240,8 +219,7 @@ bool IsPathBlend(const hecl::ProjectPath& path)
if (!fp)
return false;
uint32_t buf = 0;
if (fread(&buf, 1, 4, fp) != 4)
{
if (fread(&buf, 1, 4, fp) != 4) {
fclose(fp);
return false;
}
@ -252,22 +230,19 @@ bool IsPathBlend(const hecl::ProjectPath& path)
return false;
}
bool IsPathYAML(const hecl::ProjectPath& path)
{
bool IsPathYAML(const hecl::ProjectPath& path) {
if (!hecl::StrCmp(path.getLastComponent().data(), _SYS_STR("!catalog.yaml")))
return false; /* !catalog.yaml is exempt from general use */
auto lastCompExt = path.getLastComponentExt();
if (lastCompExt.empty())
return false;
if (!hecl::StrCmp(lastCompExt.data(), _SYS_STR("yaml")) ||
!hecl::StrCmp(lastCompExt.data(), _SYS_STR("yml")))
if (!hecl::StrCmp(lastCompExt.data(), _SYS_STR("yaml")) || !hecl::StrCmp(lastCompExt.data(), _SYS_STR("yml")))
return true;
return false;
}
hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
bool sizeSort, bool reverse, bool noHidden)
{
hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode, bool sizeSort, bool reverse,
bool noHidden) {
hecl::Sstat theStat;
if (hecl::Stat(path.data(), &theStat) || !S_ISDIR(theStat.st_mode))
return;
@ -279,11 +254,9 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
HANDLE dir = FindFirstFileW(wc.c_str(), &d);
if (dir == INVALID_HANDLE_VALUE)
return;
switch (mode)
{
switch (mode) {
case Mode::Native:
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -308,17 +281,15 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
} while (FindNextFileW(dir, &d));
break;
case Mode::DirsThenFilesSorted:
case Mode::DirsSorted:
{
case Mode::DirsSorted: {
std::map<hecl::SystemString, Entry, CaseInsensitiveCompare> sort;
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
continue;
hecl::SystemString fp(path);
fp +=_SYS_STR('/');
fp += _SYS_STR('/');
fp += d.cFileName;
hecl::Sstat st;
if (hecl::Stat(fp.c_str(), &st) || !S_ISDIR(st.st_mode))
@ -327,7 +298,7 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
} while (FindNextFileW(dir, &d));
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -338,16 +309,13 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
FindClose(dir);
dir = FindFirstFileW(wc.c_str(), &d);
}
case Mode::FilesSorted:
{
case Mode::FilesSorted: {
if (mode == Mode::FilesSorted)
m_entries.clear();
if (sizeSort)
{
if (sizeSort) {
std::multimap<size_t, Entry> sort;
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -362,17 +330,14 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
} while (FindNextFileW(dir, &d));
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
m_entries.push_back(std::move(e.second));
}
else
{
} else {
std::map<hecl::SystemString, Entry, CaseInsensitiveCompare> sort;
do
{
do {
if (!wcscmp(d.cFileName, _SYS_STR(".")) || !wcscmp(d.cFileName, _SYS_STR("..")))
continue;
if (noHidden && (d.cFileName[0] == L'.' || (d.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) != 0))
@ -387,7 +352,7 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
} while (FindNextFileW(dir, &d));
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -405,11 +370,9 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
if (!dir)
return;
const dirent* d;
switch (mode)
{
switch (mode) {
case Mode::Native:
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -434,11 +397,9 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
}
break;
case Mode::DirsThenFilesSorted:
case Mode::DirsSorted:
{
case Mode::DirsSorted: {
std::map<hecl::SystemString, Entry, CaseInsensitiveCompare> sort;
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -453,7 +414,7 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
}
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -463,16 +424,13 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
break;
rewinddir(dir);
}
case Mode::FilesSorted:
{
case Mode::FilesSorted: {
if (mode == Mode::FilesSorted)
m_entries.clear();
if (sizeSort)
{
if (sizeSort) {
std::multimap<size_t, Entry> sort;
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -487,17 +445,14 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
}
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
m_entries.push_back(std::move(e.second));
}
else
{
} else {
std::map<hecl::SystemString, Entry, CaseInsensitiveCompare> sort;
while ((d = readdir(dir)))
{
while ((d = readdir(dir))) {
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
if (noHidden && d->d_name[0] == '.')
@ -512,7 +467,7 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
}
if (reverse)
for (auto it=sort.crbegin() ; it != sort.crend() ; ++it)
for (auto it = sort.crbegin(); it != sort.crend(); ++it)
m_entries.push_back(std::move(it->second));
else
for (auto& e : sort)
@ -529,9 +484,7 @@ hecl::DirectoryEnumerator::DirectoryEnumerator(SystemStringView path, Mode mode,
#define FILE_MAXDIR 768
static std::pair<hecl::SystemString, std::string>
NameFromPath(hecl::SystemStringView path)
{
static std::pair<hecl::SystemString, std::string> NameFromPath(hecl::SystemStringView path) {
hecl::SystemUTF8Conv utf8(path);
if (utf8.str().size() == 1 && utf8.str()[0] == '/')
return {hecl::SystemString(path), "/"};
@ -542,8 +495,7 @@ NameFromPath(hecl::SystemStringView path)
return {hecl::SystemString(path), std::string(utf8.str())};
}
std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
{
std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations() {
std::vector<std::pair<hecl::SystemString, std::string>> ret;
#ifdef WIN32
#if !WINDOWS_STORE
@ -556,10 +508,8 @@ std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
tmp = GetLogicalDrives();
for (i = 0; i < 26; i++)
{
if ((tmp >> i) & 1)
{
for (i = 0; i < 26; i++) {
if ((tmp >> i) & 1) {
wline[0] = L'A' + i;
wline[1] = L':';
wline[2] = L'/';
@ -567,11 +517,9 @@ std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
name = nullptr;
/* Flee from horrible win querying hover floppy drives! */
if (i > 1)
{
if (i > 1) {
/* Try to get volume label as well... */
if (GetVolumeInformationW(wline, wline + 4, FILE_MAXDIR - 4, nullptr, nullptr, nullptr, nullptr, 0))
{
if (GetVolumeInformationW(wline, wline + 4, FILE_MAXDIR - 4, nullptr, nullptr, nullptr, nullptr, 0)) {
size_t labelLen = wcslen(wline + 4);
_snwprintf(wline + 4 + labelLen, FILE_MAXDIR - 4 - labelLen, L" (%.2s)", wline);
name = wline + 4;
@ -604,8 +552,7 @@ std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
hecl::Sstat theStat;
const char* home = getenv("HOME");
if (home)
{
if (home) {
ret.push_back(NameFromPath(home));
std::string desktop(home);
desktop += "/Desktop";
@ -621,15 +568,14 @@ std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
CFURLEnumeratorResult result = kCFURLEnumeratorSuccess;
CFURLEnumeratorRef volEnum = CFURLEnumeratorCreateForMountedVolumes(NULL, kCFURLEnumeratorSkipInvisibles, NULL);
while (result != kCFURLEnumeratorEnd)
{
while (result != kCFURLEnumeratorEnd) {
char defPath[1024];
result = CFURLEnumeratorGetNextURL(volEnum, &cfURL, NULL);
if (result != kCFURLEnumeratorSuccess)
continue;
CFURLGetFileSystemRepresentation(cfURL, false, (UInt8 *)defPath, 1024);
CFURLGetFileSystemRepresentation(cfURL, false, (UInt8*)defPath, 1024);
ret.push_back(NameFromPath(defPath));
}
@ -641,8 +587,7 @@ std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
hecl::Sstat theStat;
const char* home = getenv("HOME");
if (home)
{
if (home) {
ret.push_back(NameFromPath(home));
std::string desktop(home);
desktop += "/Desktop";
@ -654,13 +599,11 @@ std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
bool found = false;
#ifdef __linux__
/* Loop over mount points */
struct mntent *mnt;
struct mntent* mnt;
FILE* fp = setmntent(MOUNTED, "r");
if (fp)
{
while ((mnt = getmntent(fp)))
{
if (fp) {
while ((mnt = getmntent(fp))) {
if (strlen(mnt->mnt_fsname) < 4 || strncmp(mnt->mnt_fsname, "/dev", 4))
continue;
@ -684,16 +627,13 @@ std::vector<std::pair<hecl::SystemString, std::string>> GetSystemLocations()
return ret;
}
std::wstring Char16ToWide(std::u16string_view src)
{
return std::wstring(src.begin(), src.end());
}
std::wstring Char16ToWide(std::u16string_view src) { return std::wstring(src.begin(), src.end()); }
/* recursive mkdir */
#if _WIN32
int RecursiveMakeDir(const SystemChar* dir) {
SystemChar tmp[1024];
SystemChar *p = nullptr;
SystemChar* p = nullptr;
Sstat sb;
size_t len;
@ -705,13 +645,13 @@ int RecursiveMakeDir(const SystemChar* dir) {
}
/* remove trailing slash */
if(tmp[len - 1] == '/' || tmp[len - 1] == '\\') {
if (tmp[len - 1] == '/' || tmp[len - 1] == '\\') {
tmp[len - 1] = 0;
}
/* recursive mkdir */
for(p = tmp + 1; *p; p++) {
if(*p == '/' || *p == '\\') {
for (p = tmp + 1; *p; p++) {
if (*p == '/' || *p == '\\') {
*p = 0;
/* test path */
if (Stat(tmp, &sb) != 0) {
@ -741,7 +681,7 @@ int RecursiveMakeDir(const SystemChar* dir) {
#else
int RecursiveMakeDir(const SystemChar* dir) {
SystemChar tmp[1024];
SystemChar *p = nullptr;
SystemChar* p = nullptr;
Sstat sb;
size_t len;
@ -753,13 +693,13 @@ int RecursiveMakeDir(const SystemChar* dir) {
}
/* remove trailing slash */
if(tmp[len - 1] == '/') {
if (tmp[len - 1] == '/') {
tmp[len - 1] = 0;
}
/* recursive mkdir */
for(p = tmp + 1; *p; p++) {
if(*p == '/') {
for (p = tmp + 1; *p; p++) {
if (*p == '/') {
*p = 0;
/* test path */
if (Stat(tmp, &sb) != 0) {
@ -788,8 +728,7 @@ int RecursiveMakeDir(const SystemChar* dir) {
}
#endif
const SystemChar* GetTmpDir()
{
const SystemChar* GetTmpDir() {
#ifdef _WIN32
#if WINDOWS_STORE
wchar_t* TMPDIR = nullptr;
@ -807,33 +746,27 @@ const SystemChar* GetTmpDir()
}
#if !WINDOWS_STORE
int RunProcess(const SystemChar* path, const SystemChar* const args[])
{
int RunProcess(const SystemChar* path, const SystemChar* const args[]) {
#ifdef _WIN32
SECURITY_ATTRIBUTES sattrs = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
HANDLE consoleOutReadTmp, consoleOutWrite, consoleErrWrite, consoleOutRead;
if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 0))
{
if (!CreatePipe(&consoleOutReadTmp, &consoleOutWrite, &sattrs, 0)) {
LogModule.report(logvisor::Fatal, "Error with CreatePipe");
return -1;
}
if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite,
GetCurrentProcess(), &consoleErrWrite, 0,
TRUE,DUPLICATE_SAME_ACCESS))
{
if (!DuplicateHandle(GetCurrentProcess(), consoleOutWrite, GetCurrentProcess(), &consoleErrWrite, 0, TRUE,
DUPLICATE_SAME_ACCESS)) {
LogModule.report(logvisor::Fatal, "Error with DuplicateHandle");
CloseHandle(consoleOutReadTmp);
CloseHandle(consoleOutWrite);
return -1;
}
if (!DuplicateHandle(GetCurrentProcess(), consoleOutReadTmp,
GetCurrentProcess(),
if (!DuplicateHandle(GetCurrentProcess(), consoleOutReadTmp, GetCurrentProcess(),
&consoleOutRead, // Address of new handle.
0, FALSE, // Make it uninheritable.
DUPLICATE_SAME_ACCESS))
{
DUPLICATE_SAME_ACCESS)) {
LogModule.report(logvisor::Fatal, "Error with DupliateHandle");
CloseHandle(consoleOutReadTmp);
CloseHandle(consoleOutWrite);
@ -845,27 +778,26 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[])
hecl::SystemString cmdLine;
const SystemChar* const* arg = &args[1];
while (*arg)
{
while (*arg) {
cmdLine += _SYS_STR(" \"");
cmdLine += *arg++;
cmdLine += _SYS_STR('"');
}
STARTUPINFO sinfo = {sizeof(STARTUPINFO)};
HANDLE nulHandle = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE,
&sattrs, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE nulHandle = CreateFileW(L"nul", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sattrs, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
sinfo.dwFlags = STARTF_USESTDHANDLES;
sinfo.hStdInput = nulHandle;
sinfo.hStdError = consoleErrWrite;
sinfo.hStdOutput = consoleOutWrite;
PROCESS_INFORMATION pinfo = {};
if (!CreateProcessW(path, (LPWSTR)cmdLine.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo, &pinfo))
{
if (!CreateProcessW(path, (LPWSTR)cmdLine.c_str(), NULL, NULL, TRUE, NORMAL_PRIORITY_CLASS, NULL, NULL, &sinfo,
&pinfo)) {
LPWSTR messageBuffer = nullptr;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL);
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL,
GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&messageBuffer, 0, NULL);
LogModule.report(logvisor::Error, L"unable to launch process from %s: %s", path, messageBuffer);
LocalFree(messageBuffer);
@ -881,17 +813,13 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[])
CloseHandle(consoleOutWrite);
bool consoleThreadRunning = true;
auto consoleThread = std::thread([=, &consoleThreadRunning]()
{
auto consoleThread = std::thread([=, &consoleThreadRunning]() {
CHAR lpBuffer[256];
DWORD nBytesRead;
DWORD nCharsWritten;
while (consoleThreadRunning)
{
if (!ReadFile(consoleOutRead, lpBuffer, sizeof(lpBuffer),
&nBytesRead, NULL) || !nBytesRead)
{
while (consoleThreadRunning) {
if (!ReadFile(consoleOutRead, lpBuffer, sizeof(lpBuffer), &nBytesRead, NULL) || !nBytesRead) {
DWORD err = GetLastError();
if (err == ERROR_BROKEN_PIPE)
break; // pipe done - normal exit path.
@ -901,10 +829,8 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[])
// Display the character read on the screen.
auto lk = logvisor::LockLog();
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer,
nBytesRead, &nCharsWritten, NULL))
{
//LogModule.report(logvisor::Error, "Error with WriteConsole: %08X", GetLastError());
if (!WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), lpBuffer, nBytesRead, &nCharsWritten, NULL)) {
// LogModule.report(logvisor::Error, "Error with WriteConsole: %08X", GetLastError());
}
}
@ -925,9 +851,8 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[])
return ret;
#else
pid_t pid = fork();
if (!pid)
{
execvp(path, (char * const *)args);
if (!pid) {
execvp(path, (char* const*)args);
exit(1);
}
int ret;
@ -940,4 +865,4 @@ int RunProcess(const SystemChar* path, const SystemChar* const args[])
}
#endif
}
} // namespace hecl

View File

@ -5,28 +5,26 @@
#include "hecl/winsupport.hpp"
/*
* The memmem() function finds the start of the first occurrence of the
* substring 'needle' of length 'nlen' in the memory area 'haystack' of
* length 'hlen'.
*
* The return value is a pointer to the beginning of the sub-string, or
* NULL if the substring is not found.
*/
void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
{
* The memmem() function finds the start of the first occurrence of the
* substring 'needle' of length 'nlen' in the memory area 'haystack' of
* length 'hlen'.
*
* The return value is a pointer to the beginning of the sub-string, or
* NULL if the substring is not found.
*/
void* memmem(const void* haystack, size_t hlen, const void* needle, size_t nlen) {
int needle_first;
const uint8_t *p = static_cast<const uint8_t*>(haystack);
const uint8_t* p = static_cast<const uint8_t*>(haystack);
size_t plen = hlen;
if (!nlen)
return NULL;
needle_first = *(unsigned char *)needle;
needle_first = *(unsigned char*)needle;
while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1))))
{
while (plen >= nlen && (p = static_cast<const uint8_t*>(memchr(p, needle_first, plen - nlen + 1)))) {
if (!memcmp(p, needle, nlen))
return (void *)p;
return (void*)p;
p++;
plen = hlen - (p - static_cast<const uint8_t*>(haystack));
@ -35,8 +33,7 @@ void *memmem(const void *haystack, size_t hlen, const void *needle, size_t nlen)
return NULL;
}
int asprintf(char** buf, const char* format, ...)
{
int asprintf(char** buf, const char* format, ...) {
va_list ap;
va_start(ap, format);
int len = vsnprintf(nullptr, 0, format, ap);

View File

@ -11,27 +11,21 @@ static logvisor::Module Log("shaderc");
extern pD3DCompile D3DCompilePROC;
pD3DCompile D3DCompilePROC = nullptr;
static bool FindBestD3DCompile()
{
static bool FindBestD3DCompile() {
HMODULE d3dCompilelib = LoadLibraryW(L"D3DCompiler_47.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_46.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_45.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_44.dll");
if (!d3dCompilelib)
{
if (!d3dCompilelib) {
d3dCompilelib = LoadLibraryW(L"D3DCompiler_43.dll");
}
}
}
}
if (d3dCompilelib)
{
if (d3dCompilelib) {
D3DCompilePROC = (pD3DCompile)GetProcAddress(d3dCompilelib, "D3DCompile");
return D3DCompilePROC != nullptr;
}
@ -47,56 +41,39 @@ int main(int argc, const hecl::SystemChar** argv)
logvisor::RegisterStandardExceptions();
#if _WIN32
if (!FindBestD3DCompile())
{
if (!FindBestD3DCompile()) {
Log.report(logvisor::Info, "Unable to find D3DCompiler dll");
return 1;
}
#endif
if (argc == 1)
{
if (argc == 1) {
Log.report(logvisor::Info, "Usage: shaderc -o <out-base> [-D definevar=defineval]... <in-files>...");
return 0;
}
hecl::SystemString outPath;
hecl::shaderc::Compiler c;
for (int i = 1; i < argc; ++i)
{
if (argv[i][0] == '-')
{
if (argv[i][1] == 'o')
{
if (argv[i][2])
{
for (int i = 1; i < argc; ++i) {
if (argv[i][0] == '-') {
if (argv[i][1] == 'o') {
if (argv[i][2]) {
outPath = &argv[i][2];
}
else if (i + 1 < argc)
{
} else if (i + 1 < argc) {
++i;
outPath = argv[i];
}
else
{
} else {
Log.report(logvisor::Error, "Invalid -o argument");
return 1;
}
}
else if (argv[i][1] == 'D')
{
} else if (argv[i][1] == 'D') {
const hecl::SystemChar* define;
if (argv[i][2])
{
if (argv[i][2]) {
define = &argv[i][2];
}
else if (i + 1 < argc)
{
} else if (i + 1 < argc) {
++i;
define = argv[i];
}
else
{
} else {
Log.report(logvisor::Error, "Invalid -D argument");
return 1;
}
@ -106,21 +83,16 @@ int main(int argc, const hecl::SystemChar** argv)
c.addDefine(std::string(defineU8, equals - defineU8), equals + 1);
else
c.addDefine(defineU8, "");
}
else
{
} else {
Log.report(logvisor::Error, "Unrecognized flag option '%c'", argv[i][1]);
return 1;
}
}
else
{
} else {
c.addInputFile(argv[i]);
}
}
if (outPath.empty())
{
if (outPath.empty()) {
Log.report(logvisor::Error, "-o option is required");
return 1;
}
@ -132,8 +104,7 @@ int main(int argc, const hecl::SystemChar** argv)
else
baseName = outPath;
if (!glslang::InitializeProcess())
{
if (!glslang::InitializeProcess()) {
Log.report(logvisor::Error, "Unable to initialize glslang");
return 1;
}
@ -146,8 +117,7 @@ int main(int argc, const hecl::SystemChar** argv)
{
hecl::SystemString headerPath = outPath + _SYS_STR(".hpp");
athena::io::FileWriter w(headerPath);
if (w.hasError())
{
if (w.hasError()) {
Log.report(logvisor::Error, _SYS_STR("Error opening '%s' for writing"), headerPath.c_str());
return 1;
}
@ -157,8 +127,7 @@ int main(int argc, const hecl::SystemChar** argv)
{
hecl::SystemString impPath = outPath + _SYS_STR(".cpp");
athena::io::FileWriter w(impPath);
if (w.hasError())
{
if (w.hasError()) {
Log.report(logvisor::Error, _SYS_STR("Error opening '%s' for writing"), impPath.c_str());
return 1;
}

View File

@ -13,17 +13,16 @@
using namespace std::literals;
namespace hecl::shaderc
{
namespace hecl::shaderc {
static logvisor::Module Log("shaderc");
static constexpr std::regex::flag_type RegexFlags = std::regex::ECMAScript|std::regex::optimize;
static constexpr std::regex::flag_type RegexFlags = std::regex::ECMAScript | std::regex::optimize;
#if __GNUC__
__attribute__((__format__ (__printf__, 1, 2)))
__attribute__((__format__(__printf__, 1, 2)))
#endif
static std::string Format(const char* format, ...)
{
static std::string
Format(const char* format, ...) {
char resultBuf[FORMAT_BUF_SZ];
va_list va;
va_start(va, format);
@ -32,11 +31,9 @@ static std::string Format(const char* format, ...)
return std::string(resultBuf, printSz);
}
const std::string* Compiler::getFileContents(SystemStringView path)
{
const std::string* Compiler::getFileContents(SystemStringView path) {
auto search = m_fileContents.find(path.data());
if (search == m_fileContents.end())
{
if (search == m_fileContents.end()) {
athena::io::FileReader r(path);
if (r.hasError())
return nullptr;
@ -47,88 +44,76 @@ const std::string* Compiler::getFileContents(SystemStringView path)
return &search->second;
}
void Compiler::addInputFile(SystemStringView file)
{
void Compiler::addInputFile(SystemStringView file) {
if (std::find(m_inputFiles.begin(), m_inputFiles.end(), file) == m_inputFiles.end())
m_inputFiles.emplace_back(file);
}
void Compiler::addDefine(std::string_view var, std::string_view val)
{
m_defines[var.data()] = val;
}
void Compiler::addDefine(std::string_view var, std::string_view val) { m_defines[var.data()] = val; }
static const char* ShaderHeaderTemplate =
"class Shader_%s : public hecl::GeneralShader\n"
"{\n"
"public:\n"
" static const boo::VertexFormatInfo VtxFmt;\n"
" static const boo::AdditionalPipelineInfo PipelineInfo;\n"
" static constexpr bool HasHash = true;\n"
" static constexpr uint64_t Hash() { return 0x%016llX; }\n"
"};\n\n";
"class Shader_%s : public hecl::GeneralShader\n"
"{\n"
"public:\n"
" static const boo::VertexFormatInfo VtxFmt;\n"
" static const boo::AdditionalPipelineInfo PipelineInfo;\n"
" static constexpr bool HasHash = true;\n"
" static constexpr uint64_t Hash() { return 0x%016llX; }\n"
"};\n\n";
static const char* StageObjectHeaderTemplate =
"template<typename P, typename S>\n"
"class StageObject_%s : public hecl::StageBinary<P, S>\n"
"{\n"
" static const hecl::StageBinary<P, S> Prototype;\n"
"public:\n"
" StageObject_%s(hecl::StageConverter<P, S>& conv, hecl::FactoryCtx& ctx, const Shader_%s& in)\n"
" : hecl::StageBinary<P, S>(Prototype) {}\n"
"};\n"
"STAGEOBJECT_PROTOTYPE_DECLARATIONS(StageObject_%s)\n\n";
"template<typename P, typename S>\n"
"class StageObject_%s : public hecl::StageBinary<P, S>\n"
"{\n"
" static const hecl::StageBinary<P, S> Prototype;\n"
"public:\n"
" StageObject_%s(hecl::StageConverter<P, S>& conv, hecl::FactoryCtx& ctx, const Shader_%s& in)\n"
" : hecl::StageBinary<P, S>(Prototype) {}\n"
"};\n"
"STAGEOBJECT_PROTOTYPE_DECLARATIONS(StageObject_%s)\n\n";
static const char* StageObjectImplTemplate =
"template<>\n"
"const hecl::StageBinary<hecl::PlatformType::%s, hecl::PipelineStage::%s>\n"
"StageObject_%s<hecl::PlatformType::%s, hecl::PipelineStage::%s>::Prototype = \n"
"{%s_%s_%s_data, sizeof(%s_%s_%s_data)};\n\n";
"template<>\n"
"const hecl::StageBinary<hecl::PlatformType::%s, hecl::PipelineStage::%s>\n"
"StageObject_%s<hecl::PlatformType::%s, hecl::PipelineStage::%s>::Prototype = \n"
"{%s_%s_%s_data, sizeof(%s_%s_%s_data)};\n\n";
struct CompileSubStageAction
{
template<typename P, typename S>
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut)
{
implOut += Format(StageObjectImplTemplate, P::Name, S::Name, name.c_str(), P::Name, S::Name,
basename.c_str(), P::Name, S::Name, basename.c_str(), P::Name, S::Name);
struct CompileSubStageAction {
template <typename P, typename S>
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut) {
implOut += Format(StageObjectImplTemplate, P::Name, S::Name, name.c_str(), P::Name, S::Name, basename.c_str(),
P::Name, S::Name, basename.c_str(), P::Name, S::Name);
return true;
}
};
struct CompileStageAction
{
template<typename P, typename S>
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut)
{
struct CompileStageAction {
template <typename P, typename S>
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut) {
std::pair<StageBinaryData, size_t> data = CompileShader<P, S>(stage);
if (data.second == 0)
return false;
implOut += Format("static const uint8_t %s_%s_%s_data[] = {\n", name.c_str(), P::Name, S::Name);
for (size_t i = 0; i < data.second; )
{
for (size_t i = 0; i < data.second;) {
implOut += " ";
for (int j = 0; j < 10 && i < data.second ; ++i, ++j)
for (int j = 0; j < 10 && i < data.second; ++i, ++j)
implOut += Format("0x%02X, ", data.first.get()[i]);
implOut += "\n";
}
implOut += "};\n\n";
implOut += Format(StageObjectImplTemplate, P::Name, S::Name, name.c_str(), P::Name, S::Name,
name.c_str(), P::Name, S::Name, name.c_str(), P::Name, S::Name);
implOut += Format(StageObjectImplTemplate, P::Name, S::Name, name.c_str(), P::Name, S::Name, name.c_str(), P::Name,
S::Name, name.c_str(), P::Name, S::Name);
return true;
}
};
template<typename Action, typename P>
bool Compiler::StageAction(StageType type,
const std::string& name, const std::string& basename, const std::string& stage,
std::string& implOut)
{
switch (type)
{
template <typename Action, typename P>
bool Compiler::StageAction(StageType type, const std::string& name, const std::string& basename,
const std::string& stage, std::string& implOut) {
switch (type) {
case StageType::Vertex:
return Action::template Do<P, PipelineStage::Vertex>(name, basename, stage, implOut);
case StageType::Fragment:
@ -148,20 +133,16 @@ bool Compiler::StageAction(StageType type,
static const std::regex regWord(R"((\w+))", RegexFlags);
template<typename Action>
bool Compiler::StageAction(const std::string& platforms, StageType type,
const std::string& name, const std::string& basename, const std::string& stage,
std::string& implOut)
{
template <typename Action>
bool Compiler::StageAction(const std::string& platforms, StageType type, const std::string& name,
const std::string& basename, const std::string& stage, std::string& implOut) {
std::smatch match;
auto begin = platforms.cbegin();
auto end = platforms.cend();
while (std::regex_search(begin, end, match, regWord))
{
while (std::regex_search(begin, end, match, regWord)) {
std::string plat = match[1].str();
std::transform(plat.begin(), plat.end(), plat.begin(), ::tolower);
if (plat == "glsl")
{
if (plat == "glsl") {
if (!StageAction<Action, PlatformType::OpenGL>(type, name, basename, stage, implOut) ||
!StageAction<Action, PlatformType::Vulkan>(type, name, basename, stage, implOut)
#if HECL_NOUVEAU_NX
@ -169,40 +150,28 @@ bool Compiler::StageAction(const std::string& platforms, StageType type,
#endif
)
return false;
}
else if (plat == "opengl")
{
} else if (plat == "opengl") {
if (!StageAction<Action, PlatformType::OpenGL>(type, name, basename, stage, implOut))
return false;
}
else if (plat == "vulkan")
{
} else if (plat == "vulkan") {
if (!StageAction<Action, PlatformType::Vulkan>(type, name, basename, stage, implOut))
return false;
}
else if (plat == "nx")
{
} else if (plat == "nx") {
#if HECL_NOUVEAU_NX
if (!StageAction<Action, PlatformType::NX>(type, name, basename, stage, implOut))
return false;
#endif
}
else if (plat == "d3d11" || plat == "hlsl")
{
} else if (plat == "d3d11" || plat == "hlsl") {
#if _WIN32
if (!StageAction<Action, PlatformType::D3D11>(type, name, basename, stage, implOut))
return false;
#endif
}
else if (plat == "metal")
{
} else if (plat == "metal") {
#if __APPLE__
if (!StageAction<Action, PlatformType::Metal>(type, name, basename, stage, implOut))
return false;
#endif
}
else
{
} else {
Log.report(logvisor::Error, "Unknown platform '%s'", plat.c_str());
return false;
}
@ -237,17 +206,14 @@ static const std::regex regGeometry(R"(#\s*geometry\s+(.*))", RegexFlags);
static const std::regex regControl(R"(#\s*control\s+(.*))", RegexFlags);
static const std::regex regEvaluation(R"(#\s*evaluation\s+(.*))", RegexFlags);
bool Compiler::includeFile(SystemStringView file, std::string& out, int depth)
{
if (depth > 32)
{
bool Compiler::includeFile(SystemStringView file, std::string& out, int depth) {
if (depth > 32) {
Log.report(logvisor::Error, _SYS_STR("Too many levels of includes (>32) at '%s'"), file.data());
return false;
}
const std::string* data = getFileContents(file);
if (!data)
{
if (!data) {
Log.report(logvisor::Error, _SYS_STR("Unable to access '%s'"), file.data());
return false;
}
@ -262,8 +228,7 @@ bool Compiler::includeFile(SystemStringView file, std::string& out, int depth)
auto begin = sdata.cbegin();
auto end = sdata.cend();
while (begin != end)
{
while (begin != end) {
std::string::const_iterator nextBegin;
auto findPos = sdata.find('\n', begin - sdata.begin());
if (findPos == std::string::npos)
@ -272,11 +237,9 @@ bool Compiler::includeFile(SystemStringView file, std::string& out, int depth)
nextBegin = sdata.begin() + findPos + 1;
std::smatch subMatch;
if (std::regex_search(begin, nextBegin, subMatch, regInclude))
{
if (std::regex_search(begin, nextBegin, subMatch, regInclude)) {
std::string path = subMatch[1].str();
if (path.empty())
{
if (path.empty()) {
Log.report(logvisor::Error, _SYS_STR("Empty path provided to include in '%s'"), file.data());
return false;
}
@ -286,9 +249,7 @@ bool Compiler::includeFile(SystemStringView file, std::string& out, int depth)
pathStr = directory + _SYS_STR('/') + pathStr;
if (!includeFile(pathStr, out, depth + 1))
return false;
}
else
{
} else {
out.insert(out.end(), begin, nextBegin);
}
@ -297,10 +258,8 @@ bool Compiler::includeFile(SystemStringView file, std::string& out, int depth)
return true;
}
static std::string_view BlendFactorToStr(boo::BlendFactor fac)
{
switch (fac)
{
static std::string_view BlendFactorToStr(boo::BlendFactor fac) {
switch (fac) {
case boo::BlendFactor::Zero:
default:
return "boo::BlendFactor::Zero"sv;
@ -331,8 +290,7 @@ static std::string_view BlendFactorToStr(boo::BlendFactor fac)
}
}
static bool StrToBlendFactor(std::string str, boo::BlendFactor& fac)
{
static bool StrToBlendFactor(std::string str, boo::BlendFactor& fac) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "zero")
fac = boo::BlendFactor::Zero;
@ -360,18 +318,15 @@ static bool StrToBlendFactor(std::string str, boo::BlendFactor& fac)
fac = boo::BlendFactor::InvSrcColor1;
else if (str == "subtract")
fac = boo::BlendFactor::Subtract;
else
{
else {
Log.report(logvisor::Error, "Unrecognized blend mode '%s'", str.c_str());
return false;
}
return true;
}
static std::string_view PrimitiveToStr(boo::Primitive prim)
{
switch (prim)
{
static std::string_view PrimitiveToStr(boo::Primitive prim) {
switch (prim) {
case boo::Primitive::Triangles:
default:
return "boo::Primitive::Triangles"sv;
@ -382,8 +337,7 @@ static std::string_view PrimitiveToStr(boo::Primitive prim)
}
}
static bool StrToPrimitive(std::string str, boo::Primitive& prim)
{
static bool StrToPrimitive(std::string str, boo::Primitive& prim) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "triangles")
prim = boo::Primitive::Triangles;
@ -391,18 +345,15 @@ static bool StrToPrimitive(std::string str, boo::Primitive& prim)
prim = boo::Primitive::TriStrips;
else if (str == "patches")
prim = boo::Primitive::Patches;
else
{
else {
Log.report(logvisor::Error, "Unrecognized primitive '%s'", str.c_str());
return false;
}
return true;
}
static std::string_view ZTestToStr(boo::ZTest ztest)
{
switch (ztest)
{
static std::string_view ZTestToStr(boo::ZTest ztest) {
switch (ztest) {
case boo::ZTest::None:
default:
return "boo::ZTest::None"sv;
@ -417,8 +368,7 @@ static std::string_view ZTestToStr(boo::ZTest ztest)
}
}
static bool StrToZTest(std::string str, boo::ZTest& ztest)
{
static bool StrToZTest(std::string str, boo::ZTest& ztest) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "none")
ztest = boo::ZTest::None;
@ -430,18 +380,15 @@ static bool StrToZTest(std::string str, boo::ZTest& ztest)
ztest = boo::ZTest::GEqual;
else if (str == "equal")
ztest = boo::ZTest::Equal;
else
{
else {
Log.report(logvisor::Error, "Unrecognized ztest '%s'", str.c_str());
return false;
}
return true;
}
static std::string_view CullModeToStr(boo::CullMode cull)
{
switch (cull)
{
static std::string_view CullModeToStr(boo::CullMode cull) {
switch (cull) {
case boo::CullMode::None:
default:
return "boo::CullMode::None"sv;
@ -452,8 +399,7 @@ static std::string_view CullModeToStr(boo::CullMode cull)
}
}
static bool StrToCullMode(std::string str, boo::CullMode& cull)
{
static bool StrToCullMode(std::string str, boo::CullMode& cull) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (str == "none")
cull = boo::CullMode::None;
@ -461,21 +407,16 @@ static bool StrToCullMode(std::string str, boo::CullMode& cull)
cull = boo::CullMode::Backface;
else if (str == "frontface")
cull = boo::CullMode::Frontface;
else
{
else {
Log.report(logvisor::Error, "Unrecognized cull mode '%s'", str.c_str());
return false;
}
return true;
}
static std::string_view BoolToStr(bool b)
{
return b ? "true"sv : "false"sv;
}
static std::string_view BoolToStr(bool b) { return b ? "true"sv : "false"sv; }
static bool StrToBool(std::string str, bool& b)
{
static bool StrToBool(std::string str, bool& b) {
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
if (strtol(str.c_str(), nullptr, 0))
b = true;
@ -483,16 +424,14 @@ static bool StrToBool(std::string str, bool& b)
b = true;
else if (str == "false")
b = false;
else
{
else {
Log.report(logvisor::Error, "Unrecognized bool '%s'", str.c_str());
return false;
}
return true;
}
bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std::pair<std::string, std::string>& out)
{
bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std::pair<std::string, std::string>& out) {
std::string includesPass;
if (!includeFile(file, includesPass))
return false;
@ -509,22 +448,18 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
std::unordered_map<std::string, std::pair<std::bitset<6>, std::set<std::string>>> shaderStageUses;
std::unordered_map<std::string, std::string> shaderBases;
auto _DoCompile = [&]()
{
auto _DoCompile = [&]() {
if (stageBegin == includesPass.end())
return true;
if (shaderName.empty())
{
if (shaderName.empty()) {
Log.report(logvisor::Error, "`#shader <name>` must be issued before stages");
return false;
}
std::string stage(stageBegin, stageEnd);
for (const auto& define : m_defines)
{
for (const auto& define : m_defines) {
std::string::size_type pos = 0;
while ((pos = stage.find(define.first, pos)) != std::string::npos)
{
while ((pos = stage.find(define.first, pos)) != std::string::npos) {
stage = std::string(stage.begin(), stage.begin() + pos) + define.second +
std::string(stage.begin() + pos + define.first.size(), stage.end());
}
@ -533,12 +468,10 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
std::pair<std::bitset<6>, std::set<std::string>>& uses = shaderStageUses[shaderName];
uses.first.set(size_t(stageType));
uses.second.insert(stagePlatforms);
return StageAction<CompileStageAction>(stagePlatforms, stageType, shaderName,
shaderBase, stage, out.second);
return StageAction<CompileStageAction>(stagePlatforms, stageType, shaderName, shaderBase, stage, out.second);
};
auto DoCompile = [&](std::string platform, StageType type,
std::string::const_iterator end, std::string::const_iterator begin)
{
auto DoCompile = [&](std::string platform, StageType type, std::string::const_iterator end,
std::string::const_iterator begin) {
stageEnd = end;
bool ret = _DoCompile();
stagePlatforms = std::move(platform);
@ -546,33 +479,28 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
stageBegin = begin;
return ret;
};
auto DoShader = [&]()
{
auto DoShader = [&]() {
if (shaderBase.empty() && shaderStageUses.find(shaderName) == shaderStageUses.cend())
return true;
std::pair<std::bitset<6>, std::set<std::string>>& uses = shaderStageUses[shaderName];
if (uses.first.test(5))
return true;
out.first += Format(ShaderHeaderTemplate, shaderName.c_str(),
XXH64(shaderName.c_str(), shaderName.size(), 0));
out.first += Format(StageObjectHeaderTemplate, shaderName.c_str(), shaderName.c_str(),
shaderName.c_str(), shaderName.c_str());
out.first += Format(ShaderHeaderTemplate, shaderName.c_str(), XXH64(shaderName.c_str(), shaderName.size(), 0));
out.first += Format(StageObjectHeaderTemplate, shaderName.c_str(), shaderName.c_str(), shaderName.c_str(),
shaderName.c_str());
if (!shaderBase.empty())
{
if (!shaderBase.empty()) {
shaderBases[shaderName] = shaderBase;
for (int i = 0; i < 5; ++i)
{
for (int i = 0; i < 5; ++i) {
if (uses.first.test(size_t(i)))
continue;
std::string useBase = shaderBase;
std::unordered_map<std::string, std::pair<std::bitset<6>, std::set<std::string>>>::const_iterator
baseUses = shaderStageUses.find(useBase);
while (baseUses == shaderStageUses.cend() || !baseUses->second.first.test(size_t(i)))
{
std::unordered_map<std::string, std::pair<std::bitset<6>, std::set<std::string>>>::const_iterator baseUses =
shaderStageUses.find(useBase);
while (baseUses == shaderStageUses.cend() || !baseUses->second.first.test(size_t(i))) {
auto search = shaderBases.find(useBase);
if (search == shaderBases.cend())
break;
@ -581,21 +509,17 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
}
if (baseUses == shaderStageUses.cend() || !baseUses->second.first.test(size_t(i)))
continue;
for (const std::string& basePlatforms : baseUses->second.second)
{
StageAction<CompileSubStageAction>(basePlatforms, StageType(i), shaderName,
useBase, {}, out.second);
for (const std::string& basePlatforms : baseUses->second.second) {
StageAction<CompileSubStageAction>(basePlatforms, StageType(i), shaderName, useBase, {}, out.second);
}
}
shaderBase.clear();
}
out.second += Format("static const boo::VertexElementDescriptor %s_vtxfmtelems[] = {\n", shaderName.c_str());
for (const auto& attr : shaderAttributes)
{
for (const auto& attr : shaderAttributes) {
const char* fmt;
switch (attr.first & boo::VertexSemantic::SemanticMask)
{
switch (attr.first & boo::VertexSemantic::SemanticMask) {
case boo::VertexSemantic::Position3:
fmt = "{boo::VertexSemantic::Position3%s, %d},\n";
break;
@ -631,34 +555,44 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
break;
}
out.second += Format(fmt,
(attr.first & boo::VertexSemantic::Instanced) != boo::VertexSemantic::None ?
" | boo::VertexSemantic::Instanced" : "", attr.second);
(attr.first & boo::VertexSemantic::Instanced) != boo::VertexSemantic::None
? " | boo::VertexSemantic::Instanced"
: "",
attr.second);
}
out.second += "};\n";
out.second += Format("const boo::VertexFormatInfo Shader_%s::VtxFmt = { %s_vtxfmtelems };\n\n",
shaderName.c_str(), shaderName.c_str());
out.second += Format("const boo::VertexFormatInfo Shader_%s::VtxFmt = { %s_vtxfmtelems };\n\n", shaderName.c_str(),
shaderName.c_str());
out.second += Format("const boo::AdditionalPipelineInfo Shader_%s::PipelineInfo = {\n", shaderName.c_str());
out.second += BlendFactorToStr(shaderInfo.srcFac); out.second += ", ";
out.second += BlendFactorToStr(shaderInfo.dstFac); out.second += ", ";
out.second += PrimitiveToStr(shaderInfo.prim); out.second += ", ";
out.second += ZTestToStr(shaderInfo.depthTest); out.second += ",\n";
out.second += BoolToStr(shaderInfo.depthWrite); out.second += ", ";
out.second += BoolToStr(shaderInfo.colorWrite); out.second += ", ";
out.second += BoolToStr(shaderInfo.alphaWrite); out.second += ", ";
out.second += CullModeToStr(shaderInfo.culling); out.second += ", ";
out.second += BlendFactorToStr(shaderInfo.srcFac);
out.second += ", ";
out.second += BlendFactorToStr(shaderInfo.dstFac);
out.second += ", ";
out.second += PrimitiveToStr(shaderInfo.prim);
out.second += ", ";
out.second += ZTestToStr(shaderInfo.depthTest);
out.second += ",\n";
out.second += BoolToStr(shaderInfo.depthWrite);
out.second += ", ";
out.second += BoolToStr(shaderInfo.colorWrite);
out.second += ", ";
out.second += BoolToStr(shaderInfo.alphaWrite);
out.second += ", ";
out.second += CullModeToStr(shaderInfo.culling);
out.second += ", ";
out.second += Format("%d, ", shaderInfo.patchSize);
out.second += BoolToStr(shaderInfo.overwriteAlpha); out.second += ", ";
out.second += BoolToStr(shaderInfo.depthAttachment); out.second += ", ";
out.second += BoolToStr(shaderInfo.overwriteAlpha);
out.second += ", ";
out.second += BoolToStr(shaderInfo.depthAttachment);
out.second += ", ";
out.second += "};\n\n";
uses.first.set(5);
return true;
};
auto AddAttribute = [&](std::string semantic, std::string idx, bool inst)
{
if (shaderAttributesReset)
{
auto AddAttribute = [&](std::string semantic, std::string idx, bool inst) {
if (shaderAttributesReset) {
shaderAttributes.clear();
shaderAttributesReset = false;
}
@ -685,8 +619,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::Weight | orsem, idxNum));
else if (semantic == "modelview")
shaderAttributes.push_back(std::make_pair(boo::VertexSemantic::ModelView | orsem, idxNum));
else
{
else {
Log.report(logvisor::Error, "Unrecognized vertex semantic '%s'", semantic.c_str());
return false;
}
@ -696,8 +629,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
auto begin = includesPass.cbegin();
auto end = includesPass.cend();
std::string* defineContinue = nullptr;
while (begin != end)
{
while (begin != end) {
std::string::const_iterator nextBegin;
auto findPos = includesPass.find('\n', begin - includesPass.cbegin());
if (findPos == std::string::npos)
@ -706,8 +638,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
nextBegin = includesPass.cbegin() + findPos + 1;
std::smatch subMatch;
if (defineContinue)
{
if (defineContinue) {
std::string extraLine;
if (findPos == std::string::npos)
extraLine = std::string(begin, end);
@ -720,143 +651,95 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
defineContinue->pop_back();
else
defineContinue = nullptr;
}
else if (std::regex_search(begin, nextBegin, subMatch, regDefine))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regDefine)) {
std::string& defOut = m_defines[subMatch[1].str()];
defOut = subMatch[2].str();
if (!defOut.empty() && defOut.back() == '\r')
defOut.pop_back();
if (!defOut.empty() && defOut.back() == '\\')
{
if (!defOut.empty() && defOut.back() == '\\') {
defOut.pop_back();
defineContinue = &defOut;
}
}
else if (std::regex_search(begin, nextBegin, subMatch, regShaderEx))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regShaderEx)) {
stageEnd = begin;
if (!_DoCompile() || !DoShader())
return false;
shaderName = subMatch[1].str();
shaderBase = subMatch[2].str();
shaderAttributesReset = true;
//shaderAttributes.clear();
//shaderInfo = boo::AdditionalPipelineInfo();
}
else if (std::regex_search(begin, nextBegin, subMatch, regShader))
{
// shaderAttributes.clear();
// shaderInfo = boo::AdditionalPipelineInfo();
} else if (std::regex_search(begin, nextBegin, subMatch, regShader)) {
stageEnd = begin;
if (!_DoCompile() || !DoShader())
return false;
shaderName = subMatch[1].str();
shaderAttributesReset = true;
//shaderAttributes.clear();
//shaderInfo = boo::AdditionalPipelineInfo();
}
else if (std::regex_search(begin, nextBegin, subMatch, regAttributeEx))
{
// shaderAttributes.clear();
// shaderInfo = boo::AdditionalPipelineInfo();
} else if (std::regex_search(begin, nextBegin, subMatch, regAttributeEx)) {
if (!AddAttribute(subMatch[1].str(), subMatch[2].str(), false))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regAttribute))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regAttribute)) {
if (!AddAttribute(subMatch[1].str(), "0", false))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regInstAttributeEx))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regInstAttributeEx)) {
if (!AddAttribute(subMatch[1].str(), subMatch[2].str(), true))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regInstAttribute))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regInstAttribute)) {
if (!AddAttribute(subMatch[1].str(), "0", true))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regSrcFac))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regSrcFac)) {
if (!StrToBlendFactor(subMatch[1].str(), shaderInfo.srcFac))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regDstFac))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regDstFac)) {
if (!StrToBlendFactor(subMatch[1].str(), shaderInfo.dstFac))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regPrim))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regPrim)) {
if (!StrToPrimitive(subMatch[1].str(), shaderInfo.prim))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regZTest))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regZTest)) {
if (!StrToZTest(subMatch[1].str(), shaderInfo.depthTest))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regDepthWrite))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regDepthWrite)) {
if (!StrToBool(subMatch[1].str(), shaderInfo.depthWrite))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regColorWrite))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regColorWrite)) {
if (!StrToBool(subMatch[1].str(), shaderInfo.colorWrite))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regAlphaWrite))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regAlphaWrite)) {
if (!StrToBool(subMatch[1].str(), shaderInfo.alphaWrite))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regCulling))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regCulling)) {
if (!StrToCullMode(subMatch[1].str(), shaderInfo.culling))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regPatchSize))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regPatchSize)) {
auto str = subMatch[1].str();
char* endptr;
shaderInfo.patchSize = uint32_t(strtoul(str.c_str(), &endptr, 0));
if (endptr == str.c_str())
{
if (endptr == str.c_str()) {
Log.report(logvisor::Error, "Non-unsigned-integer value for #patchsize directive");
return false;
}
}
else if (std::regex_search(begin, nextBegin, subMatch, regOverwriteAlpha))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regOverwriteAlpha)) {
if (!StrToBool(subMatch[1].str(), shaderInfo.overwriteAlpha))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regDepthAttachment))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regDepthAttachment)) {
if (!StrToBool(subMatch[1].str(), shaderInfo.depthAttachment))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regVertex))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regVertex)) {
if (!DoCompile(subMatch[1].str(), StageType::Vertex, begin, nextBegin))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regFragment))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regFragment)) {
if (!DoCompile(subMatch[1].str(), StageType::Fragment, begin, nextBegin))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regGeometry))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regGeometry)) {
if (!DoCompile(subMatch[1].str(), StageType::Geometry, begin, nextBegin))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regControl))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regControl)) {
if (!DoCompile(subMatch[1].str(), StageType::Control, begin, nextBegin))
return false;
}
else if (std::regex_search(begin, nextBegin, subMatch, regEvaluation))
{
} else if (std::regex_search(begin, nextBegin, subMatch, regEvaluation)) {
if (!DoCompile(subMatch[1].str(), StageType::Evaluation, begin, nextBegin))
return false;
}
@ -870,8 +753,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
out.first += "#define UNIVERSAL_PIPELINES_";
out.first += baseName;
for (const auto& shader : shaderStageUses)
{
for (const auto& shader : shaderStageUses) {
out.first += " \\\n";
out.first += "::Shader_";
out.first += shader.first;
@ -881,8 +763,7 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
out.first += "#define STAGES_";
out.first += baseName;
out.first += "(P, S)";
for (const auto& shader : shaderStageUses)
{
for (const auto& shader : shaderStageUses) {
out.first += " \\\n";
out.first += "::StageObject_";
out.first += shader.first;
@ -893,14 +774,11 @@ bool Compiler::compileFile(SystemStringView file, std::string_view baseName, std
return true;
}
bool Compiler::compile(std::string_view baseName, std::pair<std::string, std::string>& out)
{
out =
{
bool Compiler::compile(std::string_view baseName, std::pair<std::string, std::string>& out) {
out = {
"#pragma once\n"
"#include \"hecl/PipelineBase.hpp\"\n\n",
Format("#include \"%s.hpp\"\n\n", baseName.data())
};
Format("#include \"%s.hpp\"\n\n", baseName.data())};
for (const auto& file : m_inputFiles)
if (!compileFile(file, baseName, out))
@ -909,4 +787,4 @@ bool Compiler::compile(std::string_view baseName, std::pair<std::string, std::st
return true;
}
}
} // namespace hecl::shaderc

View File

@ -4,38 +4,28 @@
#include <vector>
#include <unordered_map>
namespace hecl::shaderc
{
namespace hecl::shaderc {
class Compiler
{
enum class StageType
{
Vertex,
Fragment,
Geometry,
Control,
Evaluation
};
class Compiler {
enum class StageType { Vertex, Fragment, Geometry, Control, Evaluation };
std::vector<SystemString> m_inputFiles;
std::unordered_map<SystemString, std::string> m_fileContents;
const std::string* getFileContents(SystemStringView path);
std::unordered_map<std::string, std::string> m_defines;
template<typename Action, typename P>
static bool StageAction(StageType type,
const std::string& name, const std::string& basename, const std::string& stage,
std::string& implOut);
template<typename Action>
static bool StageAction(const std::string& platforms, StageType type,
const std::string& name, const std::string& basename, const std::string& stage,
std::string& implOut);
template <typename Action, typename P>
static bool StageAction(StageType type, const std::string& name, const std::string& basename,
const std::string& stage, std::string& implOut);
template <typename Action>
static bool StageAction(const std::string& platforms, StageType type, const std::string& name,
const std::string& basename, const std::string& stage, std::string& implOut);
bool includeFile(SystemStringView file, std::string& out, int depth = 0);
bool compileFile(SystemStringView file, std::string_view baseName, std::pair<std::string, std::string>& out);
public:
void addInputFile(SystemStringView file);
void addDefine(std::string_view var, std::string_view val);
bool compile(std::string_view baseName, std::pair<std::string, std::string>& out);
};
}
} // namespace hecl::shaderc

View File

@ -14,44 +14,32 @@
using namespace std::literals;
struct HECLWindowCallback : boo::IWindowCallback
{
struct HECLWindowCallback : boo::IWindowCallback {
bool m_sizeDirty = false;
boo::SWindowRect m_latestSize;
virtual ~HECLWindowCallback();
void resized(const boo::SWindowRect& rect, bool /*sync*/)
{
void resized(const boo::SWindowRect& rect, bool /*sync*/) {
m_sizeDirty = true;
m_latestSize = rect;
}
bool m_destroyed = false;
void destroyed()
{
m_destroyed = true;
}
void destroyed() { m_destroyed = true; }
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat)
{
void charKeyDown(unsigned long charCode, boo::EModifierKey mods, bool isRepeat) {
hecl::Console::instance()->handleCharCode(charCode, mods, isRepeat);
}
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat)
{
void specialKeyDown(boo::ESpecialKey key, boo::EModifierKey mods, bool isRepeat) {
hecl::Console::instance()->handleSpecialKeyDown(key, mods, isRepeat);
}
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods)
{
void specialKeyUp(boo::ESpecialKey key, boo::EModifierKey mods) {
hecl::Console::instance()->hecl::Console::handleSpecialKeyUp(key, mods);
}
};
HECLWindowCallback::~HECLWindowCallback()
{
HECLWindowCallback::~HECLWindowCallback() {}
}
struct HECLApplicationCallback : boo::IApplicationCallback
{
struct HECLApplicationCallback : boo::IApplicationCallback {
HECLWindowCallback m_windowCb;
hecl::Runtime::FileStoreManager m_fileStoreMgr;
hecl::CVarManager m_cvarManager;
@ -60,18 +48,15 @@ struct HECLApplicationCallback : boo::IApplicationCallback
bool m_running = true;
HECLApplicationCallback()
: m_fileStoreMgr(_SYS_STR("heclTest")),
m_cvarManager(m_fileStoreMgr),
m_console(&m_cvarManager)
{
m_console.registerCommand("quit"sv, "Quits application"sv, "",
: m_fileStoreMgr(_SYS_STR("heclTest")), m_cvarManager(m_fileStoreMgr), m_console(&m_cvarManager) {
m_console.registerCommand(
"quit"sv, "Quits application"sv, "",
std::bind(&HECLApplicationCallback::quit, this, std::placeholders::_1, std::placeholders::_2));
}
virtual ~HECLApplicationCallback();
int appMain(boo::IApplication* app)
{
int appMain(boo::IApplication* app) {
hecl::VerbosityLevel = 2;
/* Setup boo window */
@ -83,13 +68,11 @@ struct HECLApplicationCallback : boo::IApplicationCallback
boo::ObjToken<boo::IShaderPipeline> pipeline, pipeline2;
boo::ObjToken<boo::IShaderDataBinding> binding, binding2;
struct VertexUBO
{
struct VertexUBO {
float modelview[4][4] = {};
float modelviewInv[4][4] = {};
float projection[4][4] = {};
VertexUBO()
{
VertexUBO() {
modelview[0][0] = 1.0;
modelview[1][1] = 1.0;
modelview[2][2] = 1.0;
@ -108,9 +91,8 @@ struct HECLApplicationCallback : boo::IApplicationCallback
/* Make ramp texture */
using Pixel = uint8_t[4];
static Pixel tex[256][256];
for (int i=0 ; i<256 ; ++i)
for (int j=0 ; j<256 ; ++j)
{
for (int i = 0; i < 256; ++i)
for (int j = 0; j < 256; ++j) {
tex[i][j][0] = uint8_t(i);
tex[i][j][1] = uint8_t(j);
tex[i][j][2] = 0;
@ -126,15 +108,14 @@ struct HECLApplicationCallback : boo::IApplicationCallback
/* Compile HECL shader */
static std::string testShader = "HECLOpaque(Texture(0, UV(0)))";
//static std::string testShader = "HECLOpaque(vec3(1.0,1.0,1.0),1.0)";
// static std::string testShader = "HECLOpaque(vec3(1.0,1.0,1.0),1.0)";
hecl::Backend::ShaderTag testShaderTag(testShader, 0, 1, 0, 0, boo::Primitive::TriStrips,
hecl::Backend::ReflectionType::None, false, false, false, false);
hecl::Frontend::Frontend FE;
hecl::Frontend::IR ir = FE.compileSource(testShader, "booTest");
hecl::HECLIR irObj(ir, testShaderTag, 0);
gfxF->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx)
{
gfxF->commitTransaction([&](boo::IGraphicsDataFactory::Context& ctx) {
pipeline = conv->convert(ctx, irObj);
pipeline2 = conv->convert(ctx, Shader_test{});
@ -159,28 +140,25 @@ struct HECLApplicationCallback : boo::IApplicationCallback
testMeta.write(testMetaWriter);
/* Make Tri-strip VBO */
struct Vert
{
struct Vert {
float pos[3];
float norm[3];
float uv[2];
};
static const Vert quad[4] =
{
{{0.5,0.5},{},{1.0,1.0}},
{{-0.5,0.5},{},{0.0,1.0}},
{{0.5,-0.5},{},{1.0,0.0}},
{{-0.5,-0.5},{},{0.0,0.0}}
};
static const Vert quad[4] = {{{0.5, 0.5}, {}, {1.0, 1.0}},
{{-0.5, 0.5}, {}, {0.0, 1.0}},
{{0.5, -0.5}, {}, {1.0, 0.0}},
{{-0.5, -0.5}, {}, {0.0, 0.0}}};
/* Now simple IBO */
static const uint32_t ibo[4] = {0,1,2,3};
static const uint32_t ibo[4] = {0, 1, 2, 3};
/* Construct quad mesh against boo factory */
hecl::Runtime::HMDLData testData(ctx, testMetaBuf, quad, ibo);
boo::ObjToken<boo::ITexture> texture =
ctx.newStaticTexture(256, 256, 1, boo::TextureFormat::RGBA8, boo::TextureClampMode::Repeat, tex, 256*256*4).get();
boo::ObjToken<boo::ITexture> texture = ctx.newStaticTexture(256, 256, 1, boo::TextureFormat::RGBA8,
boo::TextureClampMode::Repeat, tex, 256 * 256 * 4)
.get();
/* Make vertex uniform buffer */
vubo = ctx.newDynamicBuffer(boo::BufferUse::Uniform, sizeof(VertexUBO), 1).get();
@ -191,26 +169,21 @@ struct HECLApplicationCallback : boo::IApplicationCallback
return true;
} BooTrace);
m_mainWindow->showWindow();
m_windowCb.m_latestSize = m_mainWindow->getWindowFrame();
boo::IGraphicsCommandQueue* gfxQ = m_mainWindow->getCommandQueue();
size_t frameIdx = 0;
while (m_running)
{
while (m_running) {
m_mainWindow->waitForRetrace();
if (m_windowCb.m_destroyed)
{
if (m_windowCb.m_destroyed) {
m_running = false;
break;
}
if (m_windowCb.m_sizeDirty)
{
gfxQ->resizeRenderTexture(renderTex,
size_t(m_windowCb.m_latestSize.size[0]),
if (m_windowCb.m_sizeDirty) {
gfxQ->resizeRenderTexture(renderTex, size_t(m_windowCb.m_latestSize.size[0]),
size_t(m_windowCb.m_latestSize.size[1]));
m_windowCb.m_sizeDirty = false;
}
@ -244,21 +217,13 @@ struct HECLApplicationCallback : boo::IApplicationCallback
gfxQ->stopRenderer();
return 0;
}
void appQuitting(boo::IApplication* /*app*/)
{
m_running = false;
}
void appQuitting(boo::IApplication* /*app*/) { m_running = false; }
void quit(hecl::Console* /*con*/, const std::vector<std::string>& /*args*/)
{
m_running = false;
}
void quit(hecl::Console* /*con*/, const std::vector<std::string>& /*args*/) { m_running = false; }
};
void AthenaExcHandler(athena::error::Level level,
const char* file, const char* /*function*/,
int line, const char* fmt, ...)
{
void AthenaExcHandler(athena::error::Level level, const char* file, const char* /*function*/, int line, const char* fmt,
...) {
static logvisor::Module Log("heclTest::AthenaExcHandler");
va_list ap;
va_start(ap, fmt);
@ -277,30 +242,27 @@ int main(int argc, const boo::SystemChar** argv)
logvisor::RegisterStandardExceptions();
logvisor::RegisterConsoleLogger();
HECLApplicationCallback appCb;
int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto,
appCb, _SYS_STR("heclTest"), _SYS_STR("HECL Test"), argc, argv);
int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, appCb, _SYS_STR("heclTest"),
_SYS_STR("HECL Test"), argc, argv);
printf("IM DYING!!\n");
return ret;
}
#else
using namespace Windows::ApplicationModel::Core;
[Platform::MTAThread]
int WINAPIV main(Platform::Array<Platform::String^>^ params)
{
[Platform::MTAThread] int WINAPIV main(Platform::Array<Platform::String ^> ^ params) {
logvisor::RegisterStandardExceptions();
logvisor::RegisterConsoleLogger();
HECLApplicationCallback appCb;
boo::ViewProvider^ viewProvider =
ref new boo::ViewProvider(appCb, _SYS_STR("heclTest"), _SYS_STR("HECL Test"), _SYS_STR("heclTest"), params, false);
boo::ViewProvider ^ viewProvider = ref new boo::ViewProvider(appCb, _SYS_STR("heclTest"), _SYS_STR("HECL Test"),
_SYS_STR("heclTest"), params, false);
CoreApplication::Run(viewProvider);
return 0;
}
#endif
#if _WIN32 && !WINDOWS_STORE
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
{
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) {
int argc = 0;
const boo::SystemChar** argv;
if (lpCmdLine[0])
@ -309,15 +271,12 @@ int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int)
GetModuleFileNameW(nullptr, selfPath, 1024);
static const boo::SystemChar* booArgv[32] = {};
booArgv[0] = selfPath;
for (int i=0 ; i<argc ; ++i)
booArgv[i+1] = argv[i];
for (int i = 0; i < argc; ++i)
booArgv[i + 1] = argv[i];
logvisor::CreateWin32Console();
return wmain(argc + 1, booArgv);
}
#endif
HECLApplicationCallback::~HECLApplicationCallback()
{
}
HECLApplicationCallback::~HECLApplicationCallback() {}