2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-08 12:24:56 +00:00

Start wiring up wgpu+winit

This commit is contained in:
2022-01-31 19:06:54 -05:00
parent 5491fd75cf
commit e48435f11e
209 changed files with 24234 additions and 8085 deletions

View File

@@ -20,7 +20,7 @@ endif()
set(HECL_HEADERS
../include/hecl/CVar.hpp
../include/hecl/CVarManager.hpp
../include/hecl/Console.hpp
# ../include/hecl/Console.hpp
../include/hecl/CVarCommons.hpp
../include/hecl/hecl.hpp
../include/hecl/MultiProgressPrinter.hpp
@@ -37,11 +37,9 @@ set(HECL_HEADERS
../include/hecl/ClientProcess.hpp
../include/hecl/BitVector.hpp
../include/hecl/MathExtras.hpp
../include/hecl/UniformBufferPool.hpp
../include/hecl/VertexBufferPool.hpp
../include/hecl/PipelineBase.hpp
../include/hecl/Pipeline.hpp
../include/hecl/Compilers.hpp)
# ../include/hecl/UniformBufferPool.hpp
# ../include/hecl/VertexBufferPool.hpp
)
set(COMMON_SOURCES
hecl.cpp
MultiProgressPrinter.cpp
@@ -51,11 +49,10 @@ set(COMMON_SOURCES
CVar.cpp
CVarCommons.cpp
CVarManager.cpp
Console.cpp
# Console.cpp
ClientProcess.cpp
SteamFinder.cpp
WideStringConvert.cpp
Compilers.cpp)
WideStringConvert.cpp)
if(UNIX)
list(APPEND PLAT_SRCS closefrom.c)
@@ -68,7 +65,7 @@ add_library(hecl-full
${COMMON_SOURCES}
${HECL_HEADERS}
${PLAT_SRCS}
Pipeline.cpp)
${FIND_BLENDER_SOURCES})
target_include_directories(hecl-full PUBLIC ../include)
target_link_libraries(hecl-full PUBLIC ${HECL_APPLICATION_REPS_TARGETS_LIST}
hecl-blender-addon boo athena-core logvisor)
@@ -83,7 +80,7 @@ add_library(hecl-light
${PLAT_SRCS}
${FIND_BLENDER_SOURCES})
target_include_directories(hecl-light PUBLIC ../include)
target_link_libraries(hecl-light PUBLIC ${HECL_APPLICATION_REPS_TARGETS_LIST} boo athena-core logvisor)
target_link_libraries(hecl-light PUBLIC ${HECL_APPLICATION_REPS_TARGETS_LIST} boo athena-core logvisor aurora)
if (WIN32)
# For FindBlender
target_link_libraries(hecl-light PUBLIC Version)

View File

@@ -4,7 +4,6 @@
#include <memory>
#include <regex>
#include "hecl/Console.hpp"
#include "hecl/hecl.hpp"
#include "hecl/Runtime.hpp"
@@ -207,62 +206,6 @@ void CVarManager::serialize() {
CVarManager* CVarManager::instance() { return m_instance; }
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, FMT_STRING("{}: {}"), cvar.second->name(), cvar.second->help());
}
}
void CVarManager::setCVar(Console* con, const std::vector<std::string>& args) {
if (args.size() < 2) {
con->report(Console::Level::Info, FMT_STRING("Usage setCvar <cvar> <value>"));
return;
}
std::string cvName = args[0];
athena::utility::tolower(cvName);
const auto iter = m_cvars.find(cvName);
if (iter == m_cvars.end()) {
con->report(Console::Level::Error, FMT_STRING("CVar '{}' does not exist"), args[0]);
return;
}
const auto& cv = iter->second;
std::string oldVal = cv->value();
std::string value = args[1];
auto it = args.begin() + 2;
for (; it != args.end(); ++it)
value += " " + *it;
/* Check to make sure we're not redundantly assigning the value */
if (cv->value() == value)
return;
if (!cv->fromLiteralToType(value))
con->report(Console::Level::Warning, FMT_STRING("Unable to set cvar '{}' to value '{}'"), cv->name(), value);
else
con->report(Console::Level::Info, FMT_STRING("Set '{}' from '{}' to '{}'"), cv->name(), oldVal, value);
}
void CVarManager::getCVar(Console* con, const std::vector<std::string>& args) {
if (args.empty()) {
con->report(Console::Level::Info, FMT_STRING("Usage getCVar <cvar>"));
return;
}
std::string cvName = args[0];
athena::utility::tolower(cvName);
const auto iter = m_cvars.find(cvName);
if (iter == m_cvars.end()) {
con->report(Console::Level::Error, FMT_STRING("CVar '{}' does not exist"), args[0]);
return;
}
const auto& cv = iter->second;
con->report(Console::Level::Info, FMT_STRING("'{}' = '{}'"), cv->name(), cv->value());
}
void CVarManager::setDeveloperMode(bool v, bool setDeserialized) {
com_developer->unlock();
com_developer->fromBoolean(v);

View File

@@ -1,292 +0,0 @@
#include "hecl/Compilers.hpp"
#include <cstring>
#include <utility>
#include <boo/graphicsdev/GLSLMacros.hpp>
#include <logvisor/logvisor.hpp>
#include <glslang/Public/ShaderLang.h>
#include <StandAlone/ResourceLimits.h>
#include <SPIRV/GlslangToSpv.h>
#include <SPIRV/disassemble.h>
#if _WIN32
#include <d3dcompiler.h>
extern pD3DCompile D3DCompilePROC;
#endif
#if __APPLE__
#include <unistd.h>
#include <memory>
#endif
namespace hecl {
logvisor::Module Log("hecl::Compilers");
template <typename P>
struct ShaderCompiler {};
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;
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(str.size() + 1), str.size() + 1);
memcpy(ret.first.get(), str.data(), ret.second);
return ret;
}
};
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) {
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()};
shader.setStrings(strings, 3);
if (!shader.parse(&glslang::DefaultTBuiltInResource, 110, false, messages)) {
fmt::print(FMT_STRING("{}\n"), text);
Log.report(logvisor::Fatal, FMT_STRING("unable to compile shader\n{}"), shader.getInfoLog());
return {};
}
glslang::TProgram prog;
prog.addShader(&shader);
if (!prog.link(messages)) {
Log.report(logvisor::Fatal, FMT_STRING("unable to link shader program\n{}"), prog.getInfoLog());
return {};
}
std::vector<unsigned int> out;
glslang::GlslangToSpv(*prog.getIntermediate(lang), out);
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(out.size() * 4), out.size() * 4);
memcpy(ret.first.get(), out.data(), ret.second);
return ret;
}
};
#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> {
#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) {
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))) {
fmt::print(FMT_STRING("{}\n"), text);
Log.report(logvisor::Fatal, FMT_STRING("error compiling shader: {}"), (char*)errBlob->GetBufferPointer());
return {};
}
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(blobOut->GetBufferSize()), blobOut->GetBufferSize());
memcpy(ret.first.get(), blobOut->GetBufferPointer(), blobOut->GetBufferSize());
return ret;
}
};
#endif
#if __APPLE__
template <>
struct ShaderCompiler<PlatformType::Metal> {
static bool m_didCompilerSearch;
static bool m_hasCompiler;
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) {
execlp("xcrun", "xcrun", "-sdk", "macosx", "metal", "--version", nullptr);
/* xcrun returns 72 if metal command not found;
* emulate that if xcrun not found */
exit(72);
}
int status, ret;
while ((ret = waitpid(pid, &status, 0)) < 0 && errno == EINTR) {}
if (ret < 0)
return false;
return WEXITSTATUS(status) == 0;
}
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"
"using namespace metal;\n";
str += text;
std::pair<StageBinaryData, size_t> ret;
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 {
int compilerOut[2];
int compilerIn[2];
pipe(compilerOut);
pipe(compilerIn);
pid_t pid = getpid();
const char* tmpdir = getenv("TMPDIR");
std::string libFile = fmt::format(FMT_STRING("{}boo_metal_shader{}.metallib"), tmpdir, pid);
/* Pipe source write to compiler */
pid_t compilerPid = fork();
if (!compilerPid) {
dup2(compilerIn[0], STDIN_FILENO);
dup2(compilerOut[1], STDOUT_FILENO);
close(compilerOut[0]);
close(compilerOut[1]);
close(compilerIn[0]);
close(compilerIn[1]);
execlp("xcrun", "xcrun", "-sdk", "macosx", "metal", "-o", "/dev/stdout", "-Wno-unused-variable",
"-Wno-unused-const-variable", "-Wno-unused-function", "-c", "-x", "metal",
#ifndef NDEBUG
"-gline-tables-only", "-MO",
#endif
"-", nullptr);
fmt::print(stderr, FMT_STRING("execlp fail {}\n"), strerror(errno));
exit(1);
}
close(compilerIn[0]);
close(compilerOut[1]);
/* Pipe compiler to linker */
pid_t linkerPid = fork();
if (!linkerPid) {
dup2(compilerOut[0], STDIN_FILENO);
close(compilerOut[0]);
close(compilerIn[1]);
/* metallib doesn't like outputting to a pipe, so temp file will have to do */
execlp("xcrun", "xcrun", "-sdk", "macosx", "metallib", "-", "-o", libFile.c_str(), nullptr);
fmt::print(stderr, FMT_STRING("execlp fail {}\n"), strerror(errno));
exit(1);
}
close(compilerOut[0]);
/* Stream in source */
const char* inPtr = str.data();
size_t inRem = str.size();
while (inRem) {
ssize_t writeRes = write(compilerIn[1], inPtr, inRem);
if (writeRes < 0) {
fmt::print(stderr, FMT_STRING("write fail {}\n"), strerror(errno));
break;
}
inPtr += writeRes;
inRem -= writeRes;
}
close(compilerIn[1]);
/* Wait for completion */
int compilerStat, linkerStat;
while (waitpid(compilerPid, &compilerStat, 0) < 0) {
if (errno == EINTR)
continue;
Log.report(logvisor::Fatal, FMT_STRING("waitpid fail {}"), strerror(errno));
return {};
}
if (WEXITSTATUS(compilerStat)) {
Log.report(logvisor::Fatal, FMT_STRING("compile fail"));
return {};
}
while (waitpid(linkerPid, &linkerStat, 0) < 0) {
if (errno == EINTR)
continue;
Log.report(logvisor::Fatal, FMT_STRING("waitpid fail {}"), strerror(errno));
return {};
}
if (WEXITSTATUS(linkerStat)) {
Log.report(logvisor::Fatal, FMT_STRING("link fail"));
return {};
}
/* Copy temp file into buffer with first byte set to indicate binary data */
FILE* fin = fopen(libFile.c_str(), "rb");
fseek(fin, 0, SEEK_END);
long libLen = ftell(fin);
fseek(fin, 0, SEEK_SET);
ret.first = MakeStageBinaryData(libLen + 1);
ret.first.get()[0] = 1;
ret.second = libLen + 1;
fread(&ret.first.get()[1], 1, libLen, fin);
fclose(fin);
unlink(libFile.c_str());
}
return ret;
}
};
bool ShaderCompiler<PlatformType::Metal>::m_didCompilerSearch = false;
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) {
std::string str = "#version 330\n";
str += BOO_GLSL_BINDING_HEAD;
str += text;
std::pair<std::shared_ptr<uint8_t[]>, size_t> ret(new uint8_t[str.size() + 1], str.size() + 1);
memcpy(ret.first.get(), str.data(), str.size() + 1);
return ret;
}
};
#endif
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);
SPECIALIZE_COMPILE_SHADER(PlatformType::OpenGL)
SPECIALIZE_COMPILE_SHADER(PlatformType::Vulkan)
#if _WIN32
SPECIALIZE_COMPILE_SHADER(PlatformType::D3D11)
#endif
#if __APPLE__
SPECIALIZE_COMPILE_SHADER(PlatformType::Metal)
#endif
#if HECL_NOUVEAU_NX
SPECIALIZE_COMPILE_SHADER(PlatformType::NX)
#endif
} // namespace hecl

View File

@@ -1,410 +0,0 @@
#include <hecl/Console.hpp>
#include <cstdio>
#include <functional>
#include <string>
#include <vector>
#include "hecl/CVar.hpp"
#include "hecl/CVarManager.hpp"
#include "hecl/hecl.hpp"
#include <athena/Utility.hpp>
#include <boo/IWindow.hpp>
#include <boo/graphicsdev/IGraphicsCommandQueue.hpp>
#include <logvisor/logvisor.hpp>
namespace hecl {
Console* Console::m_instance = nullptr;
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>",
[this](Console* console, const std::vector<std::string>& args) { help(console, args); });
registerCommand("listCommands", "Prints a list of all available Commands", "",
[this](Console* console, const std::vector<std::string>& args) { listCommands(console, args); });
registerCommand("listCVars", "Lists all available CVars", "",
[this](Console* console, const std::vector<std::string>& args) { m_cvarMgr->list(console, args); });
registerCommand(
"setCVar", "Sets a given Console Variable to the specified value", "<cvar> <value>",
[this](Console* console, const std::vector<std::string>& args) { m_cvarMgr->setCVar(console, args); });
registerCommand(
"getCVar", "Prints the value stored in the specified Console Variable", "<cvar>",
[this](Console* console, const std::vector<std::string>& args) { m_cvarMgr->getCVar(console, args); });
}
void Console::registerCommand(std::string_view name, std::string_view helpText, std::string_view usage,
std::function<void(Console*, const std::vector<std::string>&)>&& func,
SConsoleCommand::ECommandFlags cmdFlags) {
std::string lowName{name};
athena::utility::tolower(lowName);
if (m_commands.find(lowName) != m_commands.end()) {
return;
}
m_commands.emplace(std::move(lowName), SConsoleCommand{std::string{name}, std::string{helpText}, std::string{usage},
std::move(func), cmdFlags});
}
void Console::unregisterCommand(std::string_view name) {
std::string lowName{name};
athena::utility::tolower(lowName);
const auto iter = m_commands.find(lowName);
if (iter == m_commands.end()) {
return;
}
m_commands.erase(iter);
}
void Console::executeString(const std::string& str) {
if (str.empty())
return;
/* First let's split semi-colon delimited commands */
std::vector<std::string> commands = athena::utility::split(str, ';');
if (commands.empty())
return;
for (std::string command : commands) {
command = athena::utility::trim(command);
std::vector<std::string> tmpArgs = athena::utility::split(command, ' ');
if (tmpArgs.empty())
continue;
std::vector<std::string> args;
args.reserve(tmpArgs.size());
/* detect string literals */
bool isInLiteral = false;
std::string curLiteral;
int depth = 0;
for (std::string arg : tmpArgs) {
if ((arg.front() == '\'' || arg.front() == '"')) {
++depth;
isInLiteral = true;
curLiteral += arg;
} else if ((arg.back() == '\'' || arg.back() == '"') && isInLiteral) {
--depth;
curLiteral += arg;
args.push_back(curLiteral);
if (depth <= 0) {
depth = 0;
isInLiteral = false;
curLiteral.clear();
}
} else if (isInLiteral) {
curLiteral += arg;
} else {
args.push_back(std::move(arg));
}
}
if (isInLiteral) {
if ((curLiteral.back() != '\'' && curLiteral.back() != '"') || depth > 1) {
report(Level::Warning, FMT_STRING("Unterminated string literal"));
return;
}
args.push_back(std::move(curLiteral));
}
std::string commandName = args[0];
args.erase(args.begin());
std::string lowComName = commandName;
athena::utility::tolower(lowComName);
if (const auto iter = m_commands.find(lowComName); iter != m_commands.end()) {
const SConsoleCommand& cmd = iter->second;
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Developer) && !com_developer->toBoolean()) {
report(Level::Error, FMT_STRING("This command can only be executed in developer mode"), commandName);
return;
}
if (bool(cmd.m_flags & SConsoleCommand::ECommandFlags::Cheat) && !com_enableCheats->toBoolean()) {
report(Level::Error, FMT_STRING("This command can only be executed with cheats enabled"), commandName);
return;
}
cmd.m_func(this, args);
} else if (const CVar* cv = m_cvarMgr->findCVar(commandName)) {
args.insert(args.begin(), std::move(commandName));
if (args.size() > 1)
m_cvarMgr->setCVar(this, args);
else
m_cvarMgr->getCVar(this, args);
} else {
report(Level::Error, FMT_STRING("'{}' is not a valid command or variable!"), commandName);
}
}
}
void Console::help(Console* /*con*/, const std::vector<std::string>& args) {
if (args.empty()) {
report(Level::Info, FMT_STRING("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()) {
report(Level::Error, FMT_STRING("No such command '{}'"), args.front());
return;
}
report(Level::Info, FMT_STRING("{}: {}"), it->second.m_displayName, it->second.m_helpString);
if (!it->second.m_usage.empty())
report(Level::Info, FMT_STRING("Usage: {} {}"), it->second.m_displayName, it->second.m_usage);
}
void Console::listCommands(Console* /*con*/, const std::vector<std::string>& /*args*/) {
for (const auto& comPair : m_commands)
report(Level::Info, FMT_STRING("'{}': {}"), comPair.second.m_displayName, comPair.second.m_helpString);
}
bool Console::commandExists(std::string_view cmd) const {
std::string cmdName{cmd};
athena::utility::tolower(cmdName);
return m_commands.find(cmdName) != m_commands.end();
}
void Console::vreport(Level level, fmt::string_view fmt, fmt::format_args args) {
std::string tmp = fmt::vformat(fmt, args);
std::vector<std::string> lines = athena::utility::split(tmp, '\n');
for (std::string& line : lines) {
m_log.emplace_back(std::move(line), level);
}
fmt::print(FMT_STRING("{}\n"), tmp);
}
void Console::init(boo::IWindow* window) {
m_window = window;
}
void Console::proc() {
if (m_state == State::Opened) {
fmt::print(FMT_STRING("\r{} "), m_commandString);
fflush(stdout);
} else if (m_state == State::Opening)
m_state = State::Opened;
else if (m_state == State::Closing) {
m_state = State::Closed;
m_commandString.clear();
}
if (m_cursorPosition > int(m_commandString.size() - 1))
m_cursorPosition = int(m_commandString.size() - 1);
if (m_cursorPosition < -1)
m_cursorPosition = -1;
if (m_logOffset > int(m_log.size() - 1))
m_logOffset = int(m_log.size() - 1);
if (m_logOffset < 0)
m_logOffset = 0;
}
void Console::draw(boo::IGraphicsCommandQueue* /* gfxQ */) {
}
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_overwrite)
m_commandString[unsigned(m_cursorPosition + 1)] = char(chr);
else
m_commandString.insert(m_commandString.begin() + m_cursorPosition + 1, char(chr));
} else
m_commandString += char(chr);
++m_cursorPosition;
}
}
void Console::handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, bool /*repeat*/) {
if (m_state != State::Opened) {
return;
}
switch (sp) {
case boo::ESpecialKey::Insert:
m_overwrite ^= 1;
break;
case boo::ESpecialKey::Backspace: {
if (!m_commandString.empty()) {
if (True(mod & boo::EModifierKey::Ctrl)) {
size_t index = m_commandString.rfind(' ', size_t(m_cursorPosition - 1));
if (index == std::string::npos) {
m_commandString.clear();
m_cursorPosition = -1;
} else {
m_commandString.erase(index, (index - m_commandString.size()));
m_cursorPosition = int(index);
}
break;
}
if (m_cursorPosition < 0)
break;
m_commandString.erase(size_t(m_cursorPosition), 1);
--m_cursorPosition;
}
break;
}
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 (True(mod & boo::EModifierKey::Ctrl)) {
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);
else
m_commandString.erase(size_t(m_cursorPosition + 1), size_t(m_cursorPosition + 1) - m_commandString.size());
break;
}
m_commandString.erase(size_t(m_cursorPosition + 1), 1);
}
break;
}
case boo::ESpecialKey::PgUp: {
if (m_logOffset < int(m_log.size() - m_maxLines) - 1)
m_logOffset++;
break;
}
case boo::ESpecialKey::PgDown: {
if (m_logOffset > 0)
m_logOffset--;
break;
}
case boo::ESpecialKey::Enter: {
fmt::print(FMT_STRING("\n"));
executeString(m_commandString);
m_cursorPosition = -1;
m_commandHistory.insert(m_commandHistory.begin(), m_commandString);
m_commandString.clear();
m_showCursor = true;
m_cursorTime = 0.f;
break;
}
case boo::ESpecialKey::Left: {
if (m_cursorPosition < 0)
break;
if (True(mod & boo::EModifierKey::Ctrl))
m_cursorPosition = int(m_commandString.rfind(' ', size_t(m_cursorPosition) - 1));
else
m_cursorPosition--;
m_showCursor = true;
m_cursorTime = 0.f;
break;
}
case boo::ESpecialKey::Right: {
if (m_cursorPosition >= int(m_commandString.size() - 1))
break;
if (True(mod & boo::EModifierKey::Ctrl)) {
if (m_commandString[size_t(m_cursorPosition)] == ' ')
m_cursorPosition++;
size_t tmpPos = m_commandString.find(' ', size_t(m_cursorPosition));
if (tmpPos == std::string::npos)
m_cursorPosition = int(m_commandString.size() - 1);
else
m_cursorPosition = int(tmpPos);
} else
m_cursorPosition++;
m_showCursor = true;
m_cursorTime = 0.f;
break;
}
case boo::ESpecialKey::Up: {
if (m_commandHistory.size() == 0)
break;
m_currentCommand++;
if (m_currentCommand > int(m_commandHistory.size() - 1))
m_currentCommand = int(m_commandHistory.size() - 1);
m_commandString = m_commandHistory[size_t(m_currentCommand)];
m_cursorPosition = int(m_commandString.size() - 1);
break;
}
case boo::ESpecialKey::Down: {
if (m_commandHistory.empty())
break;
m_currentCommand--;
if (m_currentCommand >= 0) {
m_commandString = m_commandHistory[size_t(m_currentCommand)];
} else if (m_currentCommand <= -1) {
m_currentCommand = -1;
m_commandString.clear();
}
m_cursorPosition = int(m_commandString.size());
break;
}
case boo::ESpecialKey::Home:
m_cursorPosition = -1;
break;
case boo::ESpecialKey::End:
m_cursorPosition = int(m_commandString.size() - 1);
break;
default:
break;
}
}
void Console::handleSpecialKeyUp(boo::ESpecialKey /*sp*/, boo::EModifierKey /*mod*/) {}
void Console::LogVisorAdapter::report(const char* modName, logvisor::Level severity,
fmt::string_view format, fmt::format_args args) {
auto tmp = fmt::vformat(format, args);
std::vector<std::string> lines = athena::utility::split(tmp, '\n');
for (const std::string& line : lines) {
auto v = fmt::format(FMT_STRING("[{}] {}"), modName, line);
m_con->m_log.emplace_back(std::move(v), Console::Level(severity));
}
}
void Console::LogVisorAdapter::reportSource(const char* modName, logvisor::Level severity, const char* file,
unsigned linenum, fmt::string_view format, fmt::format_args args) {
auto tmp = fmt::vformat(format, args);
auto v = fmt::format(FMT_STRING("[{}] {} {}:{}"), modName, tmp, file, linenum);
m_con->m_log.emplace_back(std::move(v), Console::Level(severity));
}
void Console::dumpLog() {
for (const auto& l : m_log) {
switch (l.second) {
case Level::Info:
fmt::print(FMT_STRING("{}\n"), l.first);
break;
case Level::Warning:
fmt::print(FMT_STRING("[Warning] {}\n"), l.first);
break;
case Level::Error:
fmt::print(FMT_STRING("[ Error ] {}\n"), l.first);
break;
case Level::Fatal:
fmt::print(FMT_STRING("[ Fatal ] {}\n"), l.first);
break;
}
}
}
void Console::RegisterLogger(Console* con) { logvisor::MainLoggers.emplace_back(new LogVisorAdapter(con)); }
Console* Console::instance() { return m_instance; }
} // namespace hecl

View File

@@ -1,167 +0,0 @@
#include "hecl/Pipeline.hpp"
#include <athena/FileReader.hpp>
#include <zlib.h>
namespace hecl {
#if HECL_RUNTIME
PipelineConverterBase* conv = nullptr;
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 char* path) : m_reader(path) {
if (m_reader.hasError())
return;
if (m_reader.readUint32Big() != SBIG('SHAD'))
return;
m_compBuf.reset(new uint8_t[4096]);
m_zstrm.next_in = m_compBuf.get();
m_zstrm.avail_in = 0;
inflateInit(&m_zstrm);
}
~ShaderCacheZipStream() override { inflateEnd(&m_zstrm); }
explicit operator bool() const { return m_compBuf.operator bool(); }
atUint64 readUBytesToBuf(void* buf, atUint64 len) override {
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) {
atUint64 readSz = m_reader.readUBytesToBuf(m_compBuf.get(), 4096);
m_zstrm.avail_in = readSz;
m_zstrm.next_in = m_compBuf.get();
}
int inflateRet = inflate(&m_zstrm, Z_NO_FLUSH);
if (inflateRet != Z_OK)
break;
}
return m_zstrm.total_out;
}
void seek(atInt64, athena::SeekOrigin) override {}
atUint64 position() const override { return 0; }
atUint64 length() const override { return 0; }
};
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) {
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))));
}
}
static boo::AdditionalPipelineInfo ReadAdditionalInfo(ShaderCacheZipStream& r) {
boo::AdditionalPipelineInfo additionalInfo;
additionalInfo.srcFac = boo::BlendFactor(r.readUint32Big());
additionalInfo.dstFac = boo::BlendFactor(r.readUint32Big());
additionalInfo.prim = boo::Primitive(r.readUint32Big());
additionalInfo.depthTest = boo::ZTest(r.readUint32Big());
additionalInfo.depthWrite = r.readBool();
additionalInfo.colorWrite = r.readBool();
additionalInfo.alphaWrite = r.readBool();
additionalInfo.culling = boo::CullMode(r.readUint32Big());
additionalInfo.patchSize = r.readUint32Big();
additionalInfo.overwriteAlpha = r.readBool();
additionalInfo.depthAttachment = r.readBool();
return additionalInfo;
}
static std::vector<boo::VertexElementDescriptor> ReadVertexFormat(ShaderCacheZipStream& r) {
std::vector<boo::VertexElementDescriptor> ret;
uint32_t count = r.readUint32Big();
ret.reserve(count);
for (uint32_t i = 0; i < count; ++i) {
ret.emplace_back();
ret.back().semantic = boo::VertexSemantic(r.readUint32Big());
ret.back().semanticIdx = int(r.readUint32Big());
}
return ret;
}
template <typename P>
bool PipelineConverter<P>::loadFromFile(FactoryCtx& ctx, const char* path) {
ShaderCacheZipStream r(path);
if (!r)
return false;
m_vertexConverter.loadFromStream(ctx, r);
m_fragmentConverter.loadFromStream(ctx, r);
m_geometryConverter.loadFromStream(ctx, r);
m_controlConverter.loadFromStream(ctx, r);
m_evaluationConverter.loadFromStream(ctx, r);
uint32_t count = r.readUint32Big();
for (uint32_t i = 0; i < count; ++i) {
uint64_t hash = r.readUint64Big();
StageRuntimeObject<P, PipelineStage::Vertex> vertex;
StageRuntimeObject<P, PipelineStage::Fragment> fragment;
StageRuntimeObject<P, PipelineStage::Geometry> geometry;
StageRuntimeObject<P, PipelineStage::Control> control;
StageRuntimeObject<P, PipelineStage::Evaluation> evaluation;
if (uint64_t vhash = r.readUint64Big())
vertex = m_vertexConverter.m_stageCache.find(vhash)->second;
if (uint64_t fhash = r.readUint64Big())
fragment = m_fragmentConverter.m_stageCache.find(fhash)->second;
if (uint64_t ghash = r.readUint64Big())
geometry = m_geometryConverter.m_stageCache.find(ghash)->second;
if (uint64_t chash = r.readUint64Big())
control = m_controlConverter.m_stageCache.find(chash)->second;
if (uint64_t ehash = r.readUint64Big())
evaluation = m_evaluationConverter.m_stageCache.find(ehash)->second;
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,
boo::VertexFormatInfo(vtxFmt.size(), vtxFmt.data())))));
}
return true;
}
#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>;
#if BOO_HAS_GL
template class PipelineConverter<PlatformType::OpenGL>;
SPECIALIZE_STAGE_CONVERTER(PlatformType::OpenGL)
#endif
#if BOO_HAS_VULKAN
template class PipelineConverter<PlatformType::Vulkan>;
SPECIALIZE_STAGE_CONVERTER(PlatformType::Vulkan)
#endif
#if _WIN32
template class PipelineConverter<PlatformType::D3D11>;
SPECIALIZE_STAGE_CONVERTER(PlatformType::D3D11)
#endif
#if BOO_HAS_METAL
template class PipelineConverter<PlatformType::Metal>;
SPECIALIZE_STAGE_CONVERTER(PlatformType::Metal)
#endif
#if BOO_HAS_NX
template class PipelineConverter<PlatformType::NX>;
SPECIALIZE_STAGE_CONVERTER(PlatformType::NX)
#endif
#endif
} // namespace hecl

View File

@@ -1,5 +1,4 @@
set(RUNTIME_SOURCES
FileStoreManager.cpp
HMDL_RT.cpp)
FileStoreManager.cpp)
hecl_add_list(Runtime RUNTIME_SOURCES)

View File

@@ -1,48 +0,0 @@
#include "hecl/HMDLMeta.hpp"
#include "hecl/Runtime.hpp"
#include <athena/MemoryReader.hpp>
#include <logvisor/logvisor.hpp>
namespace hecl::Runtime {
static logvisor::Module HMDL_Log("HMDL");
HMDLData::HMDLData(boo::IGraphicsDataFactory::Context& ctx, const void* metaData, const void* vbo, const void* ibo) {
HMDLMeta meta;
{
athena::io::MemoryReader r(metaData, HECL_HMDL_META_SZ);
meta.read(r);
}
if (meta.magic != 'TACO')
HMDL_Log.report(logvisor::Fatal, FMT_STRING("invalid HMDL magic"));
m_vbo = ctx.newStaticBuffer(boo::BufferUse::Vertex, vbo, meta.vertStride, meta.vertCount);
m_ibo = ctx.newStaticBuffer(boo::BufferUse::Index, ibo, 4, meta.indexCount);
const size_t elemCount = 2 + meta.colorCount + meta.uvCount + meta.weightCount;
m_vtxFmtData = std::make_unique<boo::VertexElementDescriptor[]>(elemCount);
m_vtxFmtData[0].semantic = boo::VertexSemantic::Position3;
m_vtxFmtData[1].semantic = boo::VertexSemantic::Normal3;
size_t e = 2;
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) {
m_vtxFmtData[e].semantic = boo::VertexSemantic::UV2;
m_vtxFmtData[e].semanticIdx = i;
}
for (size_t i = 0; i < meta.weightCount; ++i, ++e) {
m_vtxFmtData[e].semantic = boo::VertexSemantic::Weight;
m_vtxFmtData[e].semanticIdx = i;
}
m_vtxFmt = boo::VertexFormatInfo(elemCount, m_vtxFmtData.get());
}
} // namespace hecl::Runtime