2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-08 11:44:55 +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

@@ -5,7 +5,7 @@
#include <string_view>
#include <vector>
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
//#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
#include <xxhash/xxhash.h>
#include "hecl.hpp"
@@ -87,213 +87,213 @@ struct TextureInfo {
enum class ReflectionType { None, Simple, Indirect };
/**
* @brief Hash subclass for identifying shaders and their metadata
*/
class ShaderTag : public Hash {
union {
uint64_t m_meta = 0;
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;
};
};
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;
}
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) {}
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; }
std::vector<boo::VertexElementDescriptor> vertexFormat() const {
std::vector<boo::VertexElementDescriptor> ret;
size_t elemCount = 2 + m_colorCount + m_uvCount + m_weightCount;
ret.resize(elemCount);
ret[0].semantic = boo::VertexSemantic::Position3;
ret[1].semantic = boo::VertexSemantic::Normal3;
size_t e = 2;
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) {
ret[e].semantic = boo::VertexSemantic::UV2;
ret[e].semanticIdx = i;
}
for (size_t i = 0; i < m_weightCount; ++i, ++e) {
ret[e].semantic = boo::VertexSemantic::Weight;
ret[e].semanticIdx = i;
}
return ret;
}
boo::AdditionalPipelineInfo additionalInfo(const ExtensionSlot& ext,
std::pair<BlendFactor, BlendFactor> blendFactors) const;
};
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) {}
};
struct ExtensionSlot {
const char* shaderMacro = 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;
bool diffuseOnly = false;
constexpr ExtensionSlot(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, bool diffuseOnly = false) noexcept
: texCount(texCount)
, texs(texs)
, srcFactor(srcFactor)
, dstFactor(dstFactor)
, depthTest(depthTest)
, cullMode(cullMode)
, noDepthWrite(noDepthWrite)
, noColorWrite(noColorWrite)
, noAlphaWrite(noAlphaWrite)
, noAlphaOverwrite(noAlphaOverwrite)
, noReflection(noReflection)
, forceAlphaTest(forceAlphaTest)
, diffuseOnly(diffuseOnly) {}
mutable uint64_t m_hash = 0;
void calculateHash() const {
XXH64_state_t st;
XXH64_reset(&st, 0);
XXH64_update(&st, shaderMacro, strlen(shaderMacro));
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 {
if (m_hash == 0)
calculateHash();
return m_hash;
}
};
inline boo::AdditionalPipelineInfo ShaderTag::additionalInfo(const ExtensionSlot& ext,
std::pair<BlendFactor, BlendFactor> blendFactors) const {
boo::ZTest zTest;
switch (ext.depthTest) {
case hecl::Backend::ZTest::Original:
default:
zTest = getDepthTest() ? boo::ZTest::LEqual : boo::ZTest::None;
break;
case hecl::Backend::ZTest::None:
zTest = boo::ZTest::None;
break;
case hecl::Backend::ZTest::LEqual:
zTest = boo::ZTest::LEqual;
break;
case hecl::Backend::ZTest::Greater:
zTest = boo::ZTest::Greater;
break;
case hecl::Backend::ZTest::Equal:
zTest = boo::ZTest::Equal;
break;
case hecl::Backend::ZTest::GEqual:
zTest = boo::ZTest::GEqual;
break;
}
BlendFactor srcFactor = m_alphaTest ? BlendFactor::One : blendFactors.first;
BlendFactor dstFactor = m_alphaTest ? BlendFactor::Zero : blendFactors.second;
return {boo::BlendFactor((ext.srcFactor == BlendFactor::Original) ? srcFactor : ext.srcFactor),
boo::BlendFactor((ext.dstFactor == BlendFactor::Original) ? dstFactor : 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};
}
///**
// * @brief Hash subclass for identifying shaders and their metadata
// */
//class ShaderTag : public Hash {
// union {
// uint64_t m_meta = 0;
// 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;
// };
// };
//
//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;
// }
// 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) {}
// 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; }
//
// std::vector<boo::VertexElementDescriptor> vertexFormat() const {
// std::vector<boo::VertexElementDescriptor> ret;
// size_t elemCount = 2 + m_colorCount + m_uvCount + m_weightCount;
// ret.resize(elemCount);
//
// ret[0].semantic = boo::VertexSemantic::Position3;
// ret[1].semantic = boo::VertexSemantic::Normal3;
// size_t e = 2;
//
// 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) {
// ret[e].semantic = boo::VertexSemantic::UV2;
// ret[e].semanticIdx = i;
// }
//
// for (size_t i = 0; i < m_weightCount; ++i, ++e) {
// ret[e].semantic = boo::VertexSemantic::Weight;
// ret[e].semanticIdx = i;
// }
//
// return ret;
// }
//
// boo::AdditionalPipelineInfo additionalInfo(const ExtensionSlot& ext,
// std::pair<BlendFactor, BlendFactor> blendFactors) const;
//};
//
//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) {}
//};
//
//struct ExtensionSlot {
// const char* shaderMacro = 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;
// bool diffuseOnly = false;
//
// constexpr ExtensionSlot(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, bool diffuseOnly = false) noexcept
// : texCount(texCount)
// , texs(texs)
// , srcFactor(srcFactor)
// , dstFactor(dstFactor)
// , depthTest(depthTest)
// , cullMode(cullMode)
// , noDepthWrite(noDepthWrite)
// , noColorWrite(noColorWrite)
// , noAlphaWrite(noAlphaWrite)
// , noAlphaOverwrite(noAlphaOverwrite)
// , noReflection(noReflection)
// , forceAlphaTest(forceAlphaTest)
// , diffuseOnly(diffuseOnly) {}
//
// mutable uint64_t m_hash = 0;
// void calculateHash() const {
// XXH64_state_t st;
// XXH64_reset(&st, 0);
// XXH64_update(&st, shaderMacro, strlen(shaderMacro));
// 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 {
// if (m_hash == 0)
// calculateHash();
// return m_hash;
// }
//};
//
//inline boo::AdditionalPipelineInfo ShaderTag::additionalInfo(const ExtensionSlot& ext,
// std::pair<BlendFactor, BlendFactor> blendFactors) const {
// boo::ZTest zTest;
// switch (ext.depthTest) {
// case hecl::Backend::ZTest::Original:
// default:
// zTest = getDepthTest() ? boo::ZTest::LEqual : boo::ZTest::None;
// break;
// case hecl::Backend::ZTest::None:
// zTest = boo::ZTest::None;
// break;
// case hecl::Backend::ZTest::LEqual:
// zTest = boo::ZTest::LEqual;
// break;
// case hecl::Backend::ZTest::Greater:
// zTest = boo::ZTest::Greater;
// break;
// case hecl::Backend::ZTest::Equal:
// zTest = boo::ZTest::Equal;
// break;
// case hecl::Backend::ZTest::GEqual:
// zTest = boo::ZTest::GEqual;
// break;
// }
//
// BlendFactor srcFactor = m_alphaTest ? BlendFactor::One : blendFactors.first;
// BlendFactor dstFactor = m_alphaTest ? BlendFactor::Zero : blendFactors.second;
// return {boo::BlendFactor((ext.srcFactor == BlendFactor::Original) ? srcFactor : ext.srcFactor),
// boo::BlendFactor((ext.dstFactor == BlendFactor::Original) ? dstFactor : 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};
//}
//
} // 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
//
//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

@@ -98,10 +98,6 @@ public:
void proc();
void list(class Console* con, const std::vector<std::string>& args);
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 setCheatsEnabled(bool v, bool setDeserialized = false);
bool restartRequired() const;

View File

@@ -1,96 +0,0 @@
#pragma once
#include <cstddef>
#include <memory>
#include <utility>
#include <boo/graphicsdev/D3D.hpp>
#include <boo/graphicsdev/GL.hpp>
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
#include <boo/graphicsdev/Metal.hpp>
#include <boo/graphicsdev/Vulkan.hpp>
namespace hecl {
namespace PlatformType {
using PlatformEnum = boo::IGraphicsDataFactory::Platform;
struct Null {};
struct OpenGL {
static constexpr PlatformEnum Enum = PlatformEnum::OpenGL;
static constexpr char Name[] = "OpenGL";
#if BOO_HAS_GL
using Context = boo::GLDataFactory::Context;
#endif
};
struct D3D11 {
static constexpr PlatformEnum Enum = PlatformEnum::D3D11;
static constexpr char Name[] = "D3D11";
#if _WIN32
using Context = boo::D3D11DataFactory::Context;
#endif
};
struct Metal {
static constexpr PlatformEnum Enum = PlatformEnum::Metal;
static constexpr char Name[] = "Metal";
#if BOO_HAS_METAL
using Context = boo::MetalDataFactory::Context;
#endif
};
struct Vulkan {
static constexpr PlatformEnum Enum = PlatformEnum::Vulkan;
static constexpr char Name[] = "Vulkan";
#if BOO_HAS_VULKAN
using Context = boo::VulkanDataFactory::Context;
#endif
};
struct NX {
static constexpr PlatformEnum Enum = PlatformEnum::NX;
static constexpr char Name[] = "NX";
#if BOO_HAS_NX
using Context = boo::NXDataFactory::Context;
#endif
};
} // namespace PlatformType
namespace PipelineStage {
using StageEnum = boo::PipelineStage;
struct Null {
static constexpr StageEnum Enum = StageEnum::Null;
static constexpr char Name[] = "Null";
};
struct Vertex {
static constexpr StageEnum Enum = StageEnum::Vertex;
static constexpr char Name[] = "Vertex";
};
struct Fragment {
static constexpr StageEnum Enum = StageEnum::Fragment;
static constexpr char Name[] = "Fragment";
};
struct Geometry {
static constexpr StageEnum Enum = StageEnum::Geometry;
static constexpr char Name[] = "Geometry";
};
struct Control {
static constexpr StageEnum Enum = StageEnum::Control;
static constexpr char Name[] = "Control";
};
struct Evaluation {
static constexpr StageEnum Enum = StageEnum::Evaluation;
static constexpr char Name[] = "Evaluation";
};
} // namespace PipelineStage
#ifdef _LIBCPP_VERSION
using StageBinaryData = std::shared_ptr<uint8_t>;
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[]>;
inline StageBinaryData MakeStageBinaryData(size_t sz) { return StageBinaryData(new uint8_t[sz]); }
#endif
template <typename P, typename S>
std::pair<StageBinaryData, size_t> CompileShader(std::string_view text);
} // namespace hecl

View File

@@ -1,107 +0,0 @@
#pragma once
#include <functional>
#include <string>
#include <unordered_map>
#include <vector>
#include <boo/System.hpp>
#include <logvisor/logvisor.hpp>
namespace boo {
class IWindow;
enum class EModifierKey;
enum class ESpecialKey;
struct IGraphicsCommandQueue;
} // namespace boo
namespace hecl {
class CVarManager;
class CVar;
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;
std::function<void(class Console*, const std::vector<std::string>&)> m_func;
ECommandFlags m_flags;
};
ENABLE_BITWISE_ENUM(SConsoleCommand::ECommandFlags)
class Console {
friend class LogVisorAdapter;
struct LogVisorAdapter : logvisor::ILogger {
Console* m_con;
LogVisorAdapter(Console* con) : logvisor::ILogger(log_typeid(LogVisorAdapter)), m_con(con) {}
~LogVisorAdapter() override = default;
void report(const char* modName, logvisor::Level severity, fmt::string_view format, fmt::format_args args) override;
void reportSource(const char* modName, logvisor::Level severity, const char* file, unsigned linenum,
fmt::string_view format, fmt::format_args args) override;
};
public:
static Console* m_instance;
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 class State { Closed, Closing, Opened, Opening };
private:
CVarManager* m_cvarMgr = nullptr;
boo::IWindow* m_window = nullptr;
std::unordered_map<std::string, SConsoleCommand> m_commands;
std::vector<std::pair<std::string, Level>> m_log;
int m_logOffset = 0;
std::string m_commandString;
std::vector<std::string> m_commandHistory;
int m_cursorPosition = -1;
int m_currentCommand = -1;
size_t m_maxLines = 0;
bool m_overwrite : 1;
bool m_cursorAtEnd : 1;
State m_state = State::Closed;
CVar* m_conSpeed;
CVar* m_conHeight;
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,
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);
void help(Console* con, const std::vector<std::string>& args);
void listCommands(Console* con, const std::vector<std::string>& args);
bool commandExists(std::string_view cmd) const;
void vreport(Level level, fmt::string_view format, fmt::format_args args);
template <typename S, typename... Args, typename Char = fmt::char_t<S>>
void report(Level level, const S& format, Args&&... args) {
vreport(level, fmt::to_string_view<Char>(format),
fmt::basic_format_args<fmt::buffer_context<Char>>(
fmt::make_args_checked<Args...>(format, args...)));
}
void init(boo::IWindow* ctx);
void proc();
void draw(boo::IGraphicsCommandQueue* gfxQ);
void handleCharCode(unsigned long chr, boo::EModifierKey mod, bool repeat);
void handleSpecialKeyDown(boo::ESpecialKey sp, boo::EModifierKey mod, bool repeat);
void handleSpecialKeyUp(boo::ESpecialKey sp, boo::EModifierKey mod);
void dumpLog();
static Console* instance();
static void RegisterLogger(Console* con);
bool isOpen() const { return m_state == State::Opened; }
};
} // namespace hecl

View File

@@ -1,506 +0,0 @@
#pragma once
#include <cassert>
#include <cstdint>
#include <memory>
#include <type_traits>
#include <unordered_map>
#include "hecl/hecl.hpp"
#include "hecl/PipelineBase.hpp"
#include <boo/BooObject.hpp>
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
/* CMake-curated rep classes for the application */
#include "ApplicationReps.hpp"
namespace hecl {
#if HECL_RUNTIME
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) {
m_stage = static_cast<typename P::Context&>(ctx).newShaderStage(in.data(), in.size(), S::Enum);
}
boo::ObjToken<boo::IShaderStage> stage() const { return m_stage; }
};
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) {
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);
}
boo::ObjToken<boo::IShaderPipeline> pipeline() const { return m_pipeline; }
};
#endif
template <typename... Args>
struct pack {};
struct null_t {};
template <typename P>
struct ShaderDB {};
#define STAGE_COLLECTION_SPECIALIZATIONS(T, P) StageCollection<T<P, PipelineStage::Null>>,
#define PIPELINE_RUNTIME_SPECIALIZATIONS(P) \
STAGE_COLLECTION_SPECIALIZATIONS(StageSourceText, P) STAGE_COLLECTION_SPECIALIZATIONS(StageBinary, P) \
STAGE_COLLECTION_SPECIALIZATIONS(StageRuntimeObject, P) FinalPipeline<P>,
#define PIPELINE_OFFLINE_SPECIALIZATIONS(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)
#define SPECIALIZE_RUNTIME_AVAILABLE_STAGE(P, S) \
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>; \
};
#define SPECIALIZE_OFFLINE_STAGE(P, S) \
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)
#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)
#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)
#if HECL_RUNTIME
#if BOO_HAS_GL
SPECIALIZE_RUNTIME_AVAILABLE_PLATFORM(hecl::PlatformType::OpenGL)
#else
SPECIALIZE_RUNTIME_UNAVAILABLE_PLATFORM(hecl::PlatformType::OpenGL)
#endif
#if BOO_HAS_VULKAN
SPECIALIZE_RUNTIME_AVAILABLE_PLATFORM(hecl::PlatformType::Vulkan)
#else
SPECIALIZE_RUNTIME_UNAVAILABLE_PLATFORM(hecl::PlatformType::Vulkan)
#endif
#if _WIN32
SPECIALIZE_RUNTIME_AVAILABLE_PLATFORM(hecl::PlatformType::D3D11)
#else
SPECIALIZE_RUNTIME_UNAVAILABLE_PLATFORM(hecl::PlatformType::D3D11)
#endif
#if BOO_HAS_METAL
SPECIALIZE_RUNTIME_AVAILABLE_PLATFORM(hecl::PlatformType::Metal)
#else
SPECIALIZE_RUNTIME_UNAVAILABLE_PLATFORM(hecl::PlatformType::Metal)
#endif
#if BOO_HAS_NX
SPECIALIZE_RUNTIME_AVAILABLE_PLATFORM(hecl::PlatformType::NX)
#else
SPECIALIZE_RUNTIME_UNAVAILABLE_PLATFORM(hecl::PlatformType::NX)
#endif
#else
SPECIALIZE_OFFLINE_PLATFORM(hecl::PlatformType::OpenGL)
SPECIALIZE_OFFLINE_PLATFORM(hecl::PlatformType::Vulkan)
SPECIALIZE_OFFLINE_PLATFORM(hecl::PlatformType::D3D11)
SPECIALIZE_OFFLINE_PLATFORM(hecl::PlatformType::Metal)
SPECIALIZE_OFFLINE_PLATFORM(hecl::PlatformType::NX)
#endif
class ShaderCacheZipStream;
template <typename P, typename S>
class StageConverter {
friend class PipelineConverter<P>;
#if HECL_RUNTIME
using StageTargetTp = StageRuntimeObject<P, S>;
#else
using StageTargetTp = StageBinary<P, S>;
#endif
std::unordered_map<uint64_t, StageTargetTp> m_stageCache;
#if 0 /* Horrible compiler memory explosion - DO NOT USE! */
template <typename ToTp, typename FromTp>
static constexpr bool is_stage_constructible_v =
std::is_constructible<ToTp, StageConverter<P, S>&, FactoryCtx&, FromTp>::value;
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>
struct _is_eventually_constructible
: std::conditional_t<is_stage_constructible_v<FinalTp, OriginTp>,
std::true_type,
std::conditional_t<is_stage_constructible_v<ToTp, OriginTp>,
is_eventually_constructible<FinalTp, ToTp, AllStageTypes>,
_is_eventually_constructible<FinalTp, OriginTp, T, Targs...>>> {};
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>
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, AllStageTypes>::value;
template<typename FinalTp, typename OriginTp, typename ToTp, typename T, typename... Targs>
struct _next_type { using type = std::conditional_t<is_stage_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, AllStageTypes>::type;
template<class ToTp, class FromTp>
std::enable_if_t<!is_stage_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_stage_constructible_v<ToTp, FromTp>, ToTp>
_Do(FactoryCtx& ctx, const FromTp& in)
{
return ToTp(*this, ctx, in);
}
#endif
using StageTypes = typename ShaderDB<P>::template StageDB<S>::StageTypes;
template <typename ToTp, typename FromTp>
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>
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) {
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) {
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) {
using NextTp = next_type_t<FromTp>;
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) {
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) {
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) {
return StageRuntimeObject<P, S>(*this, ctx, in);
}
template <class ToTp, class FromTp>
ToTp Do(FactoryCtx& ctx, const FromTp& in) {
return _Do<ToTp, FromTp>(ctx, in);
}
public:
#if HECL_RUNTIME
void loadFromStream(FactoryCtx& ctx, ShaderCacheZipStream& r);
#endif
template <class FromTp>
StageTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
if constexpr (FromTp::HasStageHash) {
uint64_t hash = in.template StageHash<S>();
auto search = m_stageCache.find(hash);
if (search != m_stageCache.end())
return search->second;
return m_stageCache.insert(std::make_pair(hash, Do<StageTargetTp>(ctx, in))).first->second;
}
return Do<StageTargetTp>(ctx, in);
}
};
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>
boo::ObjToken<boo::IShaderPipeline> convert(FactoryCtx& ctx, const FromTp& in);
template <class FromTp>
boo::ObjToken<boo::IShaderPipeline> convert(const FromTp& in);
#endif
};
template <typename P>
class PipelineConverter : public PipelineConverterBase {
#if HECL_RUNTIME
using PipelineTargetTp = FinalPipeline<P>;
#else
using PipelineTargetTp = StageCollection<StageBinary<P>>;
#endif
std::unordered_map<uint64_t, PipelineTargetTp> m_pipelineCache;
StageConverter<P, PipelineStage::Vertex> m_vertexConverter;
StageConverter<P, PipelineStage::Fragment> m_fragmentConverter;
StageConverter<P, PipelineStage::Geometry> m_geometryConverter;
StageConverter<P, PipelineStage::Control> m_controlConverter;
StageConverter<P, PipelineStage::Evaluation> m_evaluationConverter;
using PipelineTypes = typename ShaderDB<P>::PipelineTypes;
template <typename ToTp, typename FromTp>
static constexpr bool is_pipeline_constructible_v =
std::is_constructible<ToTp, PipelineConverter<P>&, FactoryCtx&, FromTp>::value;
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>
struct _is_eventually_constructible
: 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>
struct _is_eventually_constructible<FinalTp, OriginTp, ToTp, null_t> : std::false_type {};
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>
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) {
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) {
return ToTp(*this, ctx, 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");
return _Do<ToTp, FromTp>(ctx, in);
}
public:
PipelineConverter(boo::IGraphicsDataFactory* gfxF) : PipelineConverterBase(gfxF, P::Enum) {}
#if HECL_RUNTIME
bool loadFromFile(FactoryCtx& ctx, const char* path);
#endif
template <class FromTp>
PipelineTargetTp convert(FactoryCtx& ctx, const FromTp& in) {
if constexpr (FromTp::HasHash) {
uint64_t hash = in.Hash();
auto search = m_pipelineCache.find(hash);
if (search != m_pipelineCache.end())
return search->second;
return m_pipelineCache.insert(std::make_pair(hash, Do<PipelineTargetTp>(ctx, in))).first->second;
}
return Do<PipelineTargetTp>(ctx, in);
}
StageConverter<P, PipelineStage::Vertex>& getVertexConverter() { return m_vertexConverter; }
StageConverter<P, PipelineStage::Fragment>& getFragmentConverter() { return m_fragmentConverter; }
StageConverter<P, PipelineStage::Geometry>& getGeometryConverter() { return m_geometryConverter; }
StageConverter<P, PipelineStage::Control>& getControlConverter() { return m_controlConverter; }
StageConverter<P, PipelineStage::Evaluation>& getEvaluationConverter() { return m_evaluationConverter; }
};
#if HECL_RUNTIME
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) {
#if BOO_HAS_GL
case boo::IGraphicsDataFactory::Platform::OpenGL:
return static_cast<PipelineConverter<PlatformType::OpenGL>&>(*this).convert(ctx, in).pipeline();
#endif
#if BOO_HAS_VULKAN
case boo::IGraphicsDataFactory::Platform::Vulkan:
return static_cast<PipelineConverter<PlatformType::Vulkan>&>(*this).convert(ctx, in).pipeline();
#endif
#if _WIN32
case boo::IGraphicsDataFactory::Platform::D3D11:
return static_cast<PipelineConverter<PlatformType::D3D11>&>(*this).convert(ctx, in).pipeline();
#endif
#if BOO_HAS_METAL
case boo::IGraphicsDataFactory::Platform::Metal:
return static_cast<PipelineConverter<PlatformType::Metal>&>(*this).convert(ctx, in).pipeline();
#endif
#if BOO_HAS_NX
case boo::IGraphicsDataFactory::Platform::NX:
return static_cast<PipelineConverter<PlatformType::NX>&>(*this).convert(ctx, in).pipeline();
#endif
default:
return {};
}
}
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) {
ret = convert(ctx, in);
return true;
} BooTrace);
return ret;
}
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);
#endif
#if BOO_HAS_VULKAN
case boo::IGraphicsDataFactory::Platform::Vulkan:
return std::make_unique<PipelineConverter<PlatformType::Vulkan>>(gfxF);
#endif
#if _WIN32
case boo::IGraphicsDataFactory::Platform::D3D11:
return std::make_unique<PipelineConverter<PlatformType::D3D11>>(gfxF);
#endif
#if BOO_HAS_METAL
case boo::IGraphicsDataFactory::Platform::Metal:
setenv("HECL_NO_METAL_COMPILER", "1", 1);
return std::make_unique<PipelineConverter<PlatformType::Metal>>(gfxF);
#endif
#if BOO_HAS_NX
case boo::IGraphicsDataFactory::Platform::NX:
return std::make_unique<PipelineConverter<PlatformType::NX>>(gfxF);
#endif
default:
return {};
}
}
extern PipelineConverterBase* conv;
#endif
} // namespace hecl

View File

@@ -1,222 +0,0 @@
#pragma once
#include <cstddef>
#include <cstdint>
#include <string_view>
#include <type_traits>
#include <vector>
#include "hecl/Compilers.hpp"
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
#include <xxhash/xxhash.h>
#define HECL_RUNTIME 1
namespace hecl {
using AdditionalPipelineInfo = boo::AdditionalPipelineInfo;
enum class StageTargetType { SourceText, Binary, Runtime };
enum class PipelineTargetType {
StageSourceTextCollection,
StageBinaryCollection,
StageRuntimeCollection,
FinalPipeline
};
template <typename P, typename S>
class StageConverter;
template <typename P>
class PipelineConverter;
#if HECL_RUNTIME
using FactoryCtx = boo::IGraphicsDataFactory::Context;
#else
struct FactoryCtx {};
#endif
template <typename P, typename S>
class StageRep {
public:
using Platform = P;
using Stage = S;
};
template <typename P>
class PipelineRep {
public:
using Platform = P;
};
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> {
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)) {}
std::string_view text() const { return m_text; }
};
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(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) {}
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>
class FinalPipeline;
template <class 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>,
std::is_base_of<StageRep<typename T::Platform, PipelineStage::Evaluation>, T>>;
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> {
using base = PipelineRep<P>;
friend class FinalPipeline<P>;
static_assert(__IsStageSubclass_v<T<P, PipelineStage::Vertex>>,
"Stage Collection may only be specialized with StageRep subclasses");
T<P, PipelineStage::Vertex> m_vertex;
T<P, PipelineStage::Fragment> m_fragment;
T<P, PipelineStage::Geometry> m_geometry;
T<P, PipelineStage::Control> m_control;
T<P, PipelineStage::Evaluation> m_evaluation;
AdditionalPipelineInfo m_additionalInfo;
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...>>>
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();
m_hash ^= m_geometry.Hash();
m_hash ^= m_control.Hash();
m_hash ^= m_evaluation.Hash();
m_hash ^= XXH64(&m_additionalInfo, sizeof(m_additionalInfo), 0);
}
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) {
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) {
m_vertex = conv.getVertexConverter().convert(ctx, in);
m_fragment = conv.getFragmentConverter().convert(ctx, in);
if (in.HasTessellation) {
m_control = conv.getControlConverter().convert(ctx, in);
m_evaluation = conv.getEvaluationConverter().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::is_same<P, PlatformType::Metal>>>* = 0) {
if (in.HasTessellation) {
m_control = conv.getControlConverter().convert(ctx, in);
m_evaluation = conv.getEvaluationConverter().convert(ctx, in);
} else {
m_vertex = conv.getVertexConverter().convert(ctx, in);
}
m_fragment = conv.getFragmentConverter().convert(ctx, in);
m_vtxFmt = in.VtxFmt;
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,
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) {}
};
} // 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;
#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)

View File

@@ -1,13 +1,12 @@
#pragma once
#include <cstddef>
#include <memory>
#include <string>
#include <string_view>
#include <boo/BooObject.hpp>
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
//#include <boo/BooObject.hpp>
//#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
namespace hecl {
struct HMDLMeta;
namespace Runtime {
@@ -28,27 +27,27 @@ public:
std::string_view getStoreRoot() const { return m_storeRoot; }
};
/**
* @brief Integrated reader/constructor/container for HMDL data
*/
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);
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);
}
};
///**
// * @brief Integrated reader/constructor/container for HMDL data
// */
//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);
//
// 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);
// }
//};
} // namespace Runtime
} // namespace hecl

View File

@@ -1,187 +0,0 @@
#pragma once
#include <atomic>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <type_traits>
#include <vector>
#include "hecl/BitVector.hpp"
#include <boo/BooObject.hpp>
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
namespace hecl {
#define HECL_UBUFPOOL_ALLOCATION_BLOCK 262144
/** This class provides a uniform structure for packing instanced uniform-buffer
* data with consistent stride into a vector of 256K 'Buckets'.
*
* This results in a space-efficient way of managing GPU data of things like UI
* widgets. These can potentially have numerous binding instances, so this avoids
* allocating a full GPU buffer object for each. */
template <typename UniformStruct>
class UniformBufferPool {
public:
/* Resolve div_t type using ssize_t as basis */
#if _WIN32
using IndexTp = SSIZE_T;
#else
using IndexTp = ssize_t;
#endif
private:
struct InvalidTp {};
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");
/** Size of single element, rounded up to 256-multiple */
static constexpr IndexTp m_stride = ROUND_UP_256(sizeof(UniformStruct));
static_assert(m_stride <= HECL_UBUFPOOL_ALLOCATION_BLOCK, "Stride too large for uniform pool");
/** Number of rounded elements per 256K bucket */
static constexpr IndexTp m_countPerBucket = HECL_UBUFPOOL_ALLOCATION_BLOCK / m_stride;
/** Buffer size per bucket (ideally 256K) */
static constexpr IndexTp m_sizePerBucket = m_stride * m_countPerBucket;
/** BitVector indicating free allocation blocks */
hecl::llvm::BitVector m_freeBlocks;
/** Efficient way to get bucket and block simultaneously */
DivTp getBucketDiv(IndexTp idx) const { return std::div(idx, m_countPerBucket); }
/** Factory pointer for building additional buffers */
boo::IGraphicsDataFactory* m_factory = nullptr;
/** Private bucket info */
struct Bucket {
boo::ObjToken<boo::IGraphicsBufferD> buffer;
uint8_t* cpuBuffer = nullptr;
std::atomic_size_t useCount = {};
bool dirty = false;
Bucket() = default;
Bucket(const Bucket& other) = delete;
Bucket& operator=(const Bucket& other) = delete;
Bucket(Bucket&& other) = default;
Bucket& operator=(Bucket&& other) = default;
void updateBuffer() {
if (useCount == 0) {
destroy();
return;
}
if (dirty && cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
dirty = false;
}
void increment(UniformBufferPool& pool) {
if (useCount.fetch_add(1) == 0 && !buffer)
buffer = pool.m_factory->newPoolBuffer(boo::BufferUse::Uniform, pool.m_stride, pool.m_countPerBucket BooTrace);
}
void decrement(UniformBufferPool& pool) {
--useCount;
}
void destroy() {
if (cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
buffer.reset();
}
};
std::vector<std::unique_ptr<Bucket>> m_buckets;
public:
/** User block-owning token */
class Token {
friend class UniformBufferPool;
UniformBufferPool* m_pool = nullptr;
IndexTp m_index = -1;
DivTp m_div;
Token(UniformBufferPool* pool) : m_pool(pool) {
auto& freeSpaces = pool->m_freeBlocks;
int idx = freeSpaces.find_first();
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 {
m_index = idx;
}
freeSpaces.reset(m_index);
m_div = pool->getBucketDiv(m_index);
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
bucket.increment(*m_pool);
}
public:
Token() = default;
Token(const Token& other) = delete;
Token& operator=(const Token& other) = delete;
Token& operator=(Token&& other) noexcept {
m_pool = other.m_pool;
m_index = other.m_index;
m_div = other.m_div;
other.m_index = -1;
return *this;
}
Token(Token&& other) noexcept : m_pool(other.m_pool), m_index(other.m_index), m_div(other.m_div) { other.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() {
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
if (!bucket.cpuBuffer)
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
bucket.dirty = true;
return reinterpret_cast<UniformStruct&>(bucket.cpuBuffer[m_div.rem * m_pool->m_stride]);
}
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};
}
explicit operator bool() const { return m_pool != nullptr && m_index != -1; }
};
UniformBufferPool() = default;
UniformBufferPool(const UniformBufferPool& other) = delete;
UniformBufferPool& operator=(const UniformBufferPool& other) = delete;
/** Load dirty buffer data into GPU */
void updateBuffers() {
for (auto& bucket : m_buckets)
bucket->updateBuffer();
}
/** Allocate free block into client-owned Token */
Token allocateBlock(boo::IGraphicsDataFactory* factory) {
m_factory = factory;
return Token(this);
}
void doDestroy() {
for (auto& bucket : m_buckets)
bucket->buffer.reset();
}
};
} // namespace hecl

View File

@@ -1,195 +0,0 @@
#pragma once
#include <atomic>
#include <cassert>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <type_traits>
#include <vector>
#include "hecl/BitVector.hpp"
#include <boo/BooObject.hpp>
#include <boo/graphicsdev/IGraphicsDataFactory.hpp>
namespace hecl {
#define HECL_VBUFPOOL_ALLOCATION_BLOCK 524288
/** This class provides a uniform structure for packing instanced vertex-buffer
* data with consistent stride into a vector of 512K 'Buckets'.
*
* This results in a space-efficient way of managing GPU data of things like UI
* widgets. These can potentially have numerous binding instances, so this avoids
* allocating a full GPU buffer object for each. */
template <typename VertStruct>
class VertexBufferPool {
public:
/* Resolve div_t type using ssize_t as basis */
#if _WIN32
using IndexTp = SSIZE_T;
#else
using IndexTp = ssize_t;
#endif
private:
struct InvalidTp {};
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");
/** Size of single element */
static constexpr IndexTp m_stride = sizeof(VertStruct);
static_assert(m_stride <= HECL_VBUFPOOL_ALLOCATION_BLOCK, "Stride too large for vertex pool");
/** Number of elements per 256K bucket */
static constexpr IndexTp m_countPerBucket = HECL_VBUFPOOL_ALLOCATION_BLOCK / m_stride;
/** Buffer size per bucket (ideally 256K) */
static constexpr IndexTp m_sizePerBucket = m_stride * m_countPerBucket;
/** BitVector indicating free allocation elements */
hecl::llvm::BitVector m_freeElements;
/** Efficient way to get bucket and element simultaneously */
DivTp getBucketDiv(IndexTp idx) const { return std::div(idx, m_countPerBucket); }
/** Factory pointer for building additional buffers */
boo::IGraphicsDataFactory* m_factory = nullptr;
/** Private bucket info */
struct Bucket {
boo::ObjToken<boo::IGraphicsBufferD> buffer;
uint8_t* cpuBuffer = nullptr;
std::atomic_size_t useCount = {};
bool dirty = false;
Bucket() = default;
Bucket(const Bucket& other) = delete;
Bucket& operator=(const Bucket& other) = delete;
Bucket(Bucket&& other) = delete;
Bucket& operator=(Bucket&& other) = delete;
void updateBuffer() {
if (useCount == 0) {
destroy();
return;
}
if (dirty && cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
dirty = false;
}
void increment(VertexBufferPool& pool) {
if (useCount.fetch_add(1) == 0 && !buffer)
buffer = pool.m_factory->newPoolBuffer(boo::BufferUse::Vertex, pool.m_stride, pool.m_countPerBucket BooTrace);
}
void decrement(VertexBufferPool& pool) {
--useCount;
}
void destroy() {
if (cpuBuffer) {
buffer->unmap();
cpuBuffer = nullptr;
}
buffer.reset();
}
};
std::vector<std::unique_ptr<Bucket>> m_buckets;
public:
/** User element-owning 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) {
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) {
pool->m_buckets.push_back(std::make_unique<Bucket>());
m_index = freeSpaces.size();
freeSpaces.resize(freeSpaces.size() + pool->m_countPerBucket, true);
} else {
m_index = idx;
}
freeSpaces.reset(m_index, m_index + count);
m_div = pool->getBucketDiv(m_index);
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) noexcept {
m_pool = other.m_pool;
m_index = other.m_index;
m_count = other.m_count;
m_div = other.m_div;
other.m_index = -1;
return *this;
}
Token(Token&& other) noexcept : 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) {
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() {
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
if (!bucket.cpuBuffer)
bucket.cpuBuffer = reinterpret_cast<uint8_t*>(bucket.buffer->map(m_sizePerBucket));
bucket.dirty = true;
return reinterpret_cast<VertStruct*>(&bucket.cpuBuffer[m_div.rem * m_pool->m_stride]);
}
std::pair<boo::ObjToken<boo::IGraphicsBufferD>, IndexTp> getBufferInfo() const {
Bucket& bucket = *m_pool->m_buckets[m_div.quot];
return {bucket.buffer, m_div.rem};
}
explicit operator bool() const { return m_pool != nullptr && m_index != -1; }
};
VertexBufferPool() = default;
VertexBufferPool(const VertexBufferPool& other) = delete;
VertexBufferPool& operator=(const VertexBufferPool& other) = delete;
/** Load dirty buffer data into GPU */
void updateBuffers() {
for (auto& bucket : m_buckets)
bucket->updateBuffer();
}
/** Allocate free block into client-owned Token */
Token allocateBlock(boo::IGraphicsDataFactory* factory, IndexTp count) {
m_factory = factory;
return Token(this, count);
}
void doDestroy() {
for (auto& bucket : m_buckets)
bucket->buffer.reset();
}
static constexpr IndexTp bucketCapacity() { return m_countPerBucket; }
};
} // namespace hecl

View File

@@ -2,13 +2,13 @@
#ifndef _WIN32
#include <cstdlib>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <dirent.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
#include <unistd.h>
#if __linux__ || __APPLE__
extern "C" int rep_closefrom(int lower);
#define closefrom rep_closefrom
@@ -45,7 +45,6 @@ extern "C" int rep_closefrom(int lower);
#include "athena/Global.hpp"
#include "logvisor/logvisor.hpp"
#include "xxhash/xxhash.h"
#include "FourCC.hpp"
#if defined(__has_feature)

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