mirror of https://github.com/AxioDL/metaforce.git
macOS build fixes
This commit is contained in:
parent
61a50aa57e
commit
d395f4a79e
|
@ -1 +1 @@
|
||||||
Subproject commit 592ffa1372a363cc8a5a3c64fee5f4b1f76eb079
|
Subproject commit 65c99ad7697b2a6e1ad1a2212bc8de7b98d7e608
|
|
@ -178,6 +178,8 @@ struct ExtensionSlot
|
||||||
{
|
{
|
||||||
Function lighting;
|
Function lighting;
|
||||||
Function post;
|
Function post;
|
||||||
|
size_t blockCount = 0;
|
||||||
|
const char** blockNames = nullptr;
|
||||||
size_t texCount = 0;
|
size_t texCount = 0;
|
||||||
const Backend::TextureInfo* texs = nullptr;
|
const Backend::TextureInfo* texs = nullptr;
|
||||||
Backend::BlendFactor srcFactor = Backend::BlendFactor::Original;
|
Backend::BlendFactor srcFactor = Backend::BlendFactor::Original;
|
||||||
|
@ -190,7 +192,9 @@ struct ExtensionSlot
|
||||||
bool noAlphaOverwrite = false;
|
bool noAlphaOverwrite = false;
|
||||||
bool noReflection = false;
|
bool noReflection = false;
|
||||||
|
|
||||||
ExtensionSlot(size_t texCount = 0,
|
ExtensionSlot(size_t blockCount = 0,
|
||||||
|
const char** blockNames = nullptr,
|
||||||
|
size_t texCount = 0,
|
||||||
const Backend::TextureInfo* texs = nullptr,
|
const Backend::TextureInfo* texs = nullptr,
|
||||||
Backend::BlendFactor srcFactor = Backend::BlendFactor::Original,
|
Backend::BlendFactor srcFactor = Backend::BlendFactor::Original,
|
||||||
Backend::BlendFactor dstFactor = Backend::BlendFactor::Original,
|
Backend::BlendFactor dstFactor = Backend::BlendFactor::Original,
|
||||||
|
@ -201,8 +205,9 @@ struct ExtensionSlot
|
||||||
bool noAlphaWrite = false,
|
bool noAlphaWrite = false,
|
||||||
bool noAlphaOverwrite = false,
|
bool noAlphaOverwrite = false,
|
||||||
bool noReflection = false)
|
bool noReflection = false)
|
||||||
: texCount(texCount), texs(texs), srcFactor(srcFactor), dstFactor(dstFactor), depthTest(depthTest),
|
: blockCount(blockCount), blockNames(blockNames), texCount(texCount), texs(texs),
|
||||||
cullMode(cullMode), noDepthWrite(noDepthWrite), noColorWrite(noColorWrite), noAlphaWrite(noAlphaWrite),
|
srcFactor(srcFactor), dstFactor(dstFactor), depthTest(depthTest), cullMode(cullMode),
|
||||||
|
noDepthWrite(noDepthWrite), noColorWrite(noColorWrite), noAlphaWrite(noAlphaWrite),
|
||||||
noAlphaOverwrite(noAlphaOverwrite), noReflection(noReflection) {}
|
noAlphaOverwrite(noAlphaOverwrite), noReflection(noReflection) {}
|
||||||
|
|
||||||
mutable uint64_t m_hash = 0;
|
mutable uint64_t m_hash = 0;
|
||||||
|
|
|
@ -14,9 +14,11 @@ struct GLSL : ProgrammableCommon
|
||||||
std::string makeVert(unsigned col, unsigned uv, unsigned w,
|
std::string makeVert(unsigned col, unsigned uv, unsigned w,
|
||||||
unsigned skinSlots, size_t extTexCount,
|
unsigned skinSlots, size_t extTexCount,
|
||||||
const TextureInfo* extTexs, ReflectionType reflectionType) const;
|
const TextureInfo* extTexs, ReflectionType reflectionType) const;
|
||||||
std::string makeFrag(bool alphaTest, ReflectionType reflectionType,
|
std::string makeFrag(size_t blockCount, const char** blockNames,
|
||||||
|
bool alphaTest, ReflectionType reflectionType,
|
||||||
const Function& lighting=Function()) const;
|
const Function& lighting=Function()) const;
|
||||||
std::string makeFrag(bool alphaTest,
|
std::string makeFrag(size_t blockCount, const char** blockNames,
|
||||||
|
bool alphaTest,
|
||||||
ReflectionType reflectionType,
|
ReflectionType reflectionType,
|
||||||
const Function& lighting,
|
const Function& lighting,
|
||||||
const Function& post,
|
const Function& post,
|
||||||
|
|
|
@ -11,9 +11,11 @@ struct HLSL : ProgrammableCommon
|
||||||
std::string makeVert(unsigned col, unsigned uv, unsigned w,
|
std::string makeVert(unsigned col, unsigned uv, unsigned w,
|
||||||
unsigned skinSlots, size_t extTexCount,
|
unsigned skinSlots, size_t extTexCount,
|
||||||
const TextureInfo* extTexs, ReflectionType reflectionType) const;
|
const TextureInfo* extTexs, ReflectionType reflectionType) const;
|
||||||
std::string makeFrag(bool alphaTest, ReflectionType reflectionType,
|
std::string makeFrag(size_t blockCount, const char** blockNames,
|
||||||
|
bool alphaTest, ReflectionType reflectionType,
|
||||||
const Function& lighting=Function()) const;
|
const Function& lighting=Function()) const;
|
||||||
std::string makeFrag(bool alphaTest, ReflectionType reflectionType,
|
std::string makeFrag(size_t blockCount, const char** blockNames,
|
||||||
|
bool alphaTest, ReflectionType reflectionType,
|
||||||
const Function& lighting,
|
const Function& lighting,
|
||||||
const Function& post, size_t extTexCount,
|
const Function& post, size_t extTexCount,
|
||||||
const TextureInfo* extTexs) const;
|
const TextureInfo* extTexs) const;
|
||||||
|
|
|
@ -50,7 +50,21 @@ struct Control { static constexpr StageEnum Enum = StageEnum::Control; static co
|
||||||
struct Evaluation { static constexpr StageEnum Enum = StageEnum::Evaluation; static const char* Name; };
|
struct Evaluation { static constexpr StageEnum Enum = StageEnum::Evaluation; static const char* Name; };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
using StageBinaryData = std::shared_ptr<uint8_t>;
|
||||||
|
static inline StageBinaryData MakeStageBinaryData(size_t sz)
|
||||||
|
{
|
||||||
|
return StageBinaryData(new uint8_t[sz], std::default_delete<uint8_t[]>{});
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
using StageBinaryData = std::shared_ptr<uint8_t[]>;
|
||||||
|
static inline StageBinaryData MakeStageBinaryData(size_t sz)
|
||||||
|
{
|
||||||
|
return StageBinaryData(new uint8_t[sz]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename P, typename S>
|
template<typename P, typename S>
|
||||||
std::pair<std::shared_ptr<uint8_t[]>, size_t> CompileShader(std::string_view text);
|
std::pair<StageBinaryData, size_t> CompileShader(std::string_view text);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,8 +77,8 @@ public:
|
||||||
}
|
}
|
||||||
std::string makeFrag() const
|
std::string makeFrag() const
|
||||||
{
|
{
|
||||||
return m_backend.makeFrag(m_tag.getDepthWrite() &&
|
return m_backend.makeFrag(m_extension.blockCount, m_extension.blockNames,
|
||||||
m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha,
|
m_tag.getDepthWrite() && m_backend.m_blendDst == hecl::Backend::BlendFactor::InvSrcAlpha,
|
||||||
m_tag.getReflectionType(), m_extension.lighting, m_extension.post,
|
m_tag.getReflectionType(), m_extension.lighting, m_extension.post,
|
||||||
m_extension.texCount, m_extension.texs);
|
m_extension.texCount, m_extension.texs);
|
||||||
}
|
}
|
||||||
|
@ -631,6 +631,7 @@ inline std::unique_ptr<PipelineConverterBase> NewPipelineConverter(boo::IGraphic
|
||||||
#endif
|
#endif
|
||||||
#if BOO_HAS_METAL
|
#if BOO_HAS_METAL
|
||||||
case boo::IGraphicsDataFactory::Platform::Metal:
|
case boo::IGraphicsDataFactory::Platform::Metal:
|
||||||
|
setenv("HECL_NO_METAL_COMPILER", "1", 1);
|
||||||
return std::make_unique<PipelineConverter<PlatformType::Metal>>(gfxF);
|
return std::make_unique<PipelineConverter<PlatformType::Metal>>(gfxF);
|
||||||
#endif
|
#endif
|
||||||
#if BOO_HAS_NX
|
#if BOO_HAS_NX
|
||||||
|
|
|
@ -73,7 +73,7 @@ public:
|
||||||
template<typename P, typename S>
|
template<typename P, typename S>
|
||||||
class StageBinary : public StageRep<P, S>
|
class StageBinary : public StageRep<P, S>
|
||||||
{
|
{
|
||||||
std::shared_ptr<uint8_t[]> m_ownedData;
|
StageBinaryData m_ownedData;
|
||||||
const uint8_t* m_data = nullptr;
|
const uint8_t* m_data = nullptr;
|
||||||
size_t m_size = 0;
|
size_t m_size = 0;
|
||||||
uint64_t m_hash = 0;
|
uint64_t m_hash = 0;
|
||||||
|
@ -86,11 +86,11 @@ public:
|
||||||
StageBinary(const uint8_t* data, size_t size)
|
StageBinary(const uint8_t* data, size_t size)
|
||||||
: m_data(data), m_size(size)
|
: m_data(data), m_size(size)
|
||||||
{ m_hash = XXH64(m_data, m_size, 0); }
|
{ m_hash = XXH64(m_data, m_size, 0); }
|
||||||
StageBinary(std::shared_ptr<uint8_t[]> data, size_t size)
|
StageBinary(StageBinaryData data, size_t size)
|
||||||
: m_ownedData(std::move(data)),
|
: m_ownedData(std::move(data)),
|
||||||
m_data(m_ownedData.get()), m_size(size)
|
m_data(m_ownedData.get()), m_size(size)
|
||||||
{ m_hash = XXH64(m_data, m_size, 0); }
|
{ m_hash = XXH64(m_data, m_size, 0); }
|
||||||
explicit StageBinary(std::pair<std::shared_ptr<uint8_t[]>, size_t> data)
|
explicit StageBinary(std::pair<StageBinaryData, size_t> data)
|
||||||
: StageBinary(data.first, data.second) {}
|
: StageBinary(data.first, data.second) {}
|
||||||
StageBinary(StageConverter<P, S>& conv, FactoryCtx& ctx, const StageSourceText<P, S>& in)
|
StageBinary(StageConverter<P, S>& conv, FactoryCtx& ctx, const StageSourceText<P, S>& in)
|
||||||
: StageBinary(CompileShader<P, S>(in.text())) {}
|
: StageBinary(CompileShader<P, S>(in.text())) {}
|
||||||
|
@ -162,7 +162,9 @@ public:
|
||||||
}
|
}
|
||||||
template<typename I>
|
template<typename I>
|
||||||
StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const I& in,
|
StageCollection(PipelineConverter<P>& conv, FactoryCtx& ctx, const I& in,
|
||||||
typename std::enable_if_t<std::is_base_of_v<TessellationShader, I>>* = 0)
|
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_vertex = conv.getVertexConverter().convert(ctx, in);
|
||||||
m_fragment = conv.getFragmentConverter().convert(ctx, in);
|
m_fragment = conv.getFragmentConverter().convert(ctx, in);
|
||||||
|
@ -175,6 +177,20 @@ public:
|
||||||
m_additionalInfo = in.PipelineInfo;
|
m_additionalInfo = in.PipelineInfo;
|
||||||
MakeHash();
|
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)
|
||||||
|
{
|
||||||
|
m_vertex = conv.getVertexConverter().convert(ctx, in);
|
||||||
|
m_fragment = conv.getFragmentConverter().convert(ctx, in);
|
||||||
|
if (in.HasTessellation)
|
||||||
|
m_evaluation = conv.getEvaluationConverter().convert(ctx, in);
|
||||||
|
m_vtxFmt = in.VtxFmt;
|
||||||
|
m_additionalInfo = in.PipelineInfo;
|
||||||
|
MakeHash();
|
||||||
|
}
|
||||||
StageCollection(const T<P, PipelineStage::Vertex>& vertex,
|
StageCollection(const T<P, PipelineStage::Vertex>& vertex,
|
||||||
const T<P, PipelineStage::Fragment>& fragment,
|
const T<P, PipelineStage::Fragment>& fragment,
|
||||||
const T<P, PipelineStage::Geometry>& geometry,
|
const T<P, PipelineStage::Geometry>& geometry,
|
||||||
|
@ -189,7 +205,7 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#ifndef _WIN32
|
||||||
#define _STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, P) \
|
#define _STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, P) \
|
||||||
template <> const hecl::StageBinary<P, hecl::PipelineStage::Vertex> \
|
template <> const hecl::StageBinary<P, hecl::PipelineStage::Vertex> \
|
||||||
T<P, hecl::PipelineStage::Vertex>::Prototype; \
|
T<P, hecl::PipelineStage::Vertex>::Prototype; \
|
||||||
|
@ -201,8 +217,9 @@ template <> const hecl::StageBinary<P, hecl::PipelineStage::Control> \
|
||||||
T<P, hecl::PipelineStage::Control>::Prototype; \
|
T<P, hecl::PipelineStage::Control>::Prototype; \
|
||||||
template <> const hecl::StageBinary<P, hecl::PipelineStage::Evaluation> \
|
template <> const hecl::StageBinary<P, hecl::PipelineStage::Evaluation> \
|
||||||
T<P, hecl::PipelineStage::Evaluation>::Prototype;
|
T<P, hecl::PipelineStage::Evaluation>::Prototype;
|
||||||
#endif
|
#else
|
||||||
#define _STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, P)
|
#define _STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, P)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define STAGEOBJECT_PROTOTYPE_DECLARATIONS(T) \
|
#define STAGEOBJECT_PROTOTYPE_DECLARATIONS(T) \
|
||||||
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::OpenGL) \
|
_STAGEOBJECT_PROTOTYPE_DECLARATIONS(T, hecl::PlatformType::OpenGL) \
|
||||||
|
|
|
@ -220,7 +220,7 @@ std::string GLSL::makeVert(unsigned col, unsigned uv, unsigned w,
|
||||||
return retval + "}\n";
|
return retval + "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GLSL::makeFrag(bool alphaTest,
|
std::string GLSL::makeFrag(size_t blockCount, const char** blockNames, bool alphaTest,
|
||||||
ReflectionType reflectionType, const Function& lighting) const
|
ReflectionType reflectionType, const Function& lighting) const
|
||||||
{
|
{
|
||||||
std::string lightingSrc;
|
std::string lightingSrc;
|
||||||
|
@ -282,7 +282,8 @@ std::string GLSL::makeFrag(bool alphaTest,
|
||||||
return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n";
|
return retval + (alphaTest ? GenerateAlphaTest() : "") + "}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GLSL::makeFrag(bool alphaTest,
|
std::string GLSL::makeFrag(size_t blockCount, const char** blockNames,
|
||||||
|
bool alphaTest,
|
||||||
ReflectionType reflectionType,
|
ReflectionType reflectionType,
|
||||||
const Function& lighting,
|
const Function& lighting,
|
||||||
const Function& post,
|
const Function& post,
|
||||||
|
|
|
@ -214,7 +214,8 @@ std::string HLSL::makeVert(unsigned col, unsigned uv, unsigned w,
|
||||||
"}\n";
|
"}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HLSL::makeFrag(bool alphaTest, ReflectionType reflectionType,
|
std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
|
||||||
|
bool alphaTest, ReflectionType reflectionType,
|
||||||
const Function& lighting) const
|
const Function& lighting) const
|
||||||
{
|
{
|
||||||
std::string lightingSrc;
|
std::string lightingSrc;
|
||||||
|
@ -271,7 +272,8 @@ std::string HLSL::makeFrag(bool alphaTest, ReflectionType reflectionType,
|
||||||
return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n";
|
return retval + (alphaTest ? GenerateAlphaTest() : "") + " return colorOut;\n}\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string HLSL::makeFrag(bool alphaTest, ReflectionType reflectionType,
|
std::string HLSL::makeFrag(size_t blockCount, const char** blockNames,
|
||||||
|
bool alphaTest, ReflectionType reflectionType,
|
||||||
const Function& lighting,
|
const Function& lighting,
|
||||||
const Function& post, size_t extTexCount,
|
const Function& post, size_t extTexCount,
|
||||||
const TextureInfo* extTexs) const
|
const TextureInfo* extTexs) const
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
#include "hecl/Compilers.hpp"
|
#include "hecl/Compilers.hpp"
|
||||||
#include "boo/graphicsdev/GLSLMacros.hpp"
|
#include "boo/graphicsdev/GLSLMacros.hpp"
|
||||||
#include "logvisor/logvisor.hpp"
|
#include "logvisor/logvisor.hpp"
|
||||||
#if BOO_HAS_VULKAN
|
|
||||||
#include <glslang/Public/ShaderLang.h>
|
#include <glslang/Public/ShaderLang.h>
|
||||||
#include <StandAlone/ResourceLimits.h>
|
#include <StandAlone/ResourceLimits.h>
|
||||||
#include <SPIRV/GlslangToSpv.h>
|
#include <SPIRV/GlslangToSpv.h>
|
||||||
#include <SPIRV/disassemble.h>
|
#include <SPIRV/disassemble.h>
|
||||||
#endif
|
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
#include <d3dcompiler.h>
|
#include <d3dcompiler.h>
|
||||||
extern pD3DCompile D3DCompilePROC;
|
extern pD3DCompile D3DCompilePROC;
|
||||||
#endif
|
#endif
|
||||||
|
#if __APPLE__
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <memory>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace hecl
|
namespace hecl
|
||||||
{
|
{
|
||||||
|
@ -40,13 +42,13 @@ template<typename P> struct ShaderCompiler {};
|
||||||
template<> struct ShaderCompiler<PlatformType::OpenGL>
|
template<> struct ShaderCompiler<PlatformType::OpenGL>
|
||||||
{
|
{
|
||||||
template<typename S>
|
template<typename S>
|
||||||
static std::pair<std::shared_ptr<uint8_t[]>, size_t> Compile(std::string_view text)
|
static std::pair<StageBinaryData, size_t> Compile(std::string_view text)
|
||||||
{
|
{
|
||||||
std::string str = "#version 330\n";
|
std::string str = "#version 330\n";
|
||||||
str += BOO_GLSL_BINDING_HEAD;
|
str += BOO_GLSL_BINDING_HEAD;
|
||||||
str += text;
|
str += text;
|
||||||
std::pair<std::shared_ptr<uint8_t[]>, size_t> ret(new uint8_t[str.size() + 1], str.size() + 1);
|
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(str.size() + 1), str.size() + 1);
|
||||||
memcpy(ret.first.get(), str.data(), str.size() + 1);
|
memcpy(ret.first.get(), str.data(), ret.second);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -64,7 +66,7 @@ template<> struct ShaderCompiler<PlatformType::Vulkan>
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename S>
|
template<typename S>
|
||||||
static std::pair<std::shared_ptr<uint8_t[]>, size_t> Compile(std::string_view text)
|
static std::pair<StageBinaryData, size_t> Compile(std::string_view text)
|
||||||
{
|
{
|
||||||
EShLanguage lang = ShaderTypes[int(S::Enum)];
|
EShLanguage lang = ShaderTypes[int(S::Enum)];
|
||||||
const EShMessages messages = EShMessages(EShMsgSpvRules | EShMsgVulkanRules);
|
const EShMessages messages = EShMessages(EShMsgSpvRules | EShMsgVulkanRules);
|
||||||
|
@ -88,7 +90,7 @@ template<> struct ShaderCompiler<PlatformType::Vulkan>
|
||||||
|
|
||||||
std::vector<unsigned int> out;
|
std::vector<unsigned int> out;
|
||||||
glslang::GlslangToSpv(*prog.getIntermediate(lang), out);
|
glslang::GlslangToSpv(*prog.getIntermediate(lang), out);
|
||||||
std::pair<std::shared_ptr<uint8_t[]>, size_t> ret(new uint8_t[out.size() * 4], out.size() * 4);
|
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(out.size() * 4), out.size() * 4);
|
||||||
memcpy(ret.first.get(), out.data(), ret.second);
|
memcpy(ret.first.get(), out.data(), ret.second);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +114,7 @@ template<> struct ShaderCompiler<PlatformType::D3D11>
|
||||||
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3
|
#define BOO_D3DCOMPILE_FLAG D3DCOMPILE_OPTIMIZATION_LEVEL3
|
||||||
#endif
|
#endif
|
||||||
template<typename S>
|
template<typename S>
|
||||||
static std::pair<std::shared_ptr<uint8_t[]>, size_t> Compile(std::string_view text)
|
static std::pair<StageBinaryData, size_t> Compile(std::string_view text)
|
||||||
{
|
{
|
||||||
ComPtr<ID3DBlob> errBlob;
|
ComPtr<ID3DBlob> errBlob;
|
||||||
ComPtr<ID3DBlob> blobOut;
|
ComPtr<ID3DBlob> blobOut;
|
||||||
|
@ -123,13 +125,176 @@ template<> struct ShaderCompiler<PlatformType::D3D11>
|
||||||
Log.report(logvisor::Fatal, "error compiling shader: %s", errBlob->GetBufferPointer());
|
Log.report(logvisor::Fatal, "error compiling shader: %s", errBlob->GetBufferPointer());
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
std::pair<std::shared_ptr<uint8_t[]>, size_t> ret(new uint8_t[blobOut->GetBufferSize()], blobOut->GetBufferSize());
|
std::pair<StageBinaryData, size_t> ret(MakeStageBinaryData(blobOut->GetBufferSize()),
|
||||||
|
blobOut->GetBufferSize());
|
||||||
memcpy(ret.first.get(), blobOut->GetBufferPointer(), blobOut->GetBufferSize());
|
memcpy(ret.first.get(), blobOut->GetBufferPointer(), blobOut->GetBufferSize());
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif
|
#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", NULL);
|
||||||
|
/* 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) == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
char libFile[1024];
|
||||||
|
snprintf(libFile, 1024, "%sboo_metal_shader%d.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", "-", NULL);
|
||||||
|
fprintf(stderr, "execlp fail %s\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, NULL);
|
||||||
|
fprintf(stderr, "execlp fail %s\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)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "write fail %s\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, "waitpid fail %s", strerror(errno));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WEXITSTATUS(compilerStat))
|
||||||
|
{
|
||||||
|
Log.report(logvisor::Fatal, "compile fail");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
while (waitpid(linkerPid, &linkerStat, 0) < 0)
|
||||||
|
{
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
Log.report(logvisor::Fatal, "waitpid fail %s", strerror(errno));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WEXITSTATUS(linkerStat))
|
||||||
|
{
|
||||||
|
Log.report(logvisor::Fatal, "link fail");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy temp file into buffer with first byte set to indicate binary data */
|
||||||
|
FILE* fin = fopen(libFile, "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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
bool ShaderCompiler<PlatformType::Metal>::m_didCompilerSearch = false;
|
||||||
|
bool ShaderCompiler<PlatformType::Metal>::m_hasCompiler = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if HECL_NOUVEAU_NX
|
#if HECL_NOUVEAU_NX
|
||||||
template<> struct ShaderCompiler<PlatformType::NX>
|
template<> struct ShaderCompiler<PlatformType::NX>
|
||||||
{
|
{
|
||||||
|
@ -147,16 +312,16 @@ template<> struct ShaderCompiler<PlatformType::NX>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename P, typename S>
|
template<typename P, typename S>
|
||||||
std::pair<std::shared_ptr<uint8_t[]>, size_t> CompileShader(std::string_view text)
|
std::pair<StageBinaryData, size_t> CompileShader(std::string_view text)
|
||||||
{
|
{
|
||||||
return ShaderCompiler<P>::template Compile<S>(text);
|
return ShaderCompiler<P>::template Compile<S>(text);
|
||||||
}
|
}
|
||||||
#define SPECIALIZE_COMPILE_SHADER(P) \
|
#define SPECIALIZE_COMPILE_SHADER(P) \
|
||||||
template std::pair<std::shared_ptr<uint8_t[]>, size_t> CompileShader<P, PipelineStage::Vertex>(std::string_view text); \
|
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Vertex>(std::string_view text); \
|
||||||
template std::pair<std::shared_ptr<uint8_t[]>, size_t> CompileShader<P, PipelineStage::Fragment>(std::string_view text); \
|
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Fragment>(std::string_view text); \
|
||||||
template std::pair<std::shared_ptr<uint8_t[]>, size_t> CompileShader<P, PipelineStage::Geometry>(std::string_view text); \
|
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Geometry>(std::string_view text); \
|
||||||
template std::pair<std::shared_ptr<uint8_t[]>, size_t> CompileShader<P, PipelineStage::Control>(std::string_view text); \
|
template std::pair<StageBinaryData, size_t> CompileShader<P, PipelineStage::Control>(std::string_view text); \
|
||||||
template std::pair<std::shared_ptr<uint8_t[]>, size_t> CompileShader<P, PipelineStage::Evaluation>(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::OpenGL)
|
||||||
SPECIALIZE_COMPILE_SHADER(PlatformType::Vulkan)
|
SPECIALIZE_COMPILE_SHADER(PlatformType::Vulkan)
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
|
@ -169,127 +334,4 @@ SPECIALIZE_COMPILE_SHADER(PlatformType::Metal)
|
||||||
SPECIALIZE_COMPILE_SHADER(PlatformType::NX)
|
SPECIALIZE_COMPILE_SHADER(PlatformType::NX)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BOO_HAS_METAL
|
|
||||||
static int HasMetalCompiler = -1;
|
|
||||||
|
|
||||||
static void CheckForMetalCompiler()
|
|
||||||
{
|
|
||||||
pid_t pid = fork();
|
|
||||||
if (!pid)
|
|
||||||
{
|
|
||||||
execlp("xcrun", "xcrun", "-sdk", "macosx", "metal", NULL);
|
|
||||||
/* 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)
|
|
||||||
HasMetalCompiler = 0;
|
|
||||||
else
|
|
||||||
HasMetalCompiler = WEXITSTATUS(status) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
std::vector<uint8_t> CompileShader<PlatformType::Metal>(std::string_view text, PipelineStage stage)
|
|
||||||
{
|
|
||||||
if (HasMetalCompiler == -1)
|
|
||||||
CheckForMetalCompiler();
|
|
||||||
|
|
||||||
std::vector<uint8_t> blobOut;
|
|
||||||
if (!HasMetalCompiler)
|
|
||||||
{
|
|
||||||
/* Cache the source if there's no compiler */
|
|
||||||
size_t sourceLen = strlen(source);
|
|
||||||
|
|
||||||
/* First byte unset to indicate source data */
|
|
||||||
blobOut.resize(sourceLen + 2);
|
|
||||||
memcpy(&blobOut[1], source, sourceLen);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Cache the binary otherwise */
|
|
||||||
int compilerOut[2];
|
|
||||||
int compilerIn[2];
|
|
||||||
pipe(compilerOut);
|
|
||||||
pipe(compilerIn);
|
|
||||||
|
|
||||||
/* 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", "-x", "metal", "-", NULL);
|
|
||||||
fprintf(stderr, "execlp fail %s\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", m_libfile, NULL);
|
|
||||||
fprintf(stderr, "execlp fail %s\n", strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
close(compilerOut[0]);
|
|
||||||
|
|
||||||
/* Stream in source */
|
|
||||||
const char* inPtr = source;
|
|
||||||
size_t inRem = strlen(source);
|
|
||||||
while (inRem)
|
|
||||||
{
|
|
||||||
ssize_t writeRes = write(compilerIn[1], inPtr, inRem);
|
|
||||||
if (writeRes < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "write fail %s\n", strerror(errno));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
inPtr += writeRes;
|
|
||||||
inRem -= writeRes;
|
|
||||||
}
|
|
||||||
close(compilerIn[1]);
|
|
||||||
|
|
||||||
/* Wait for completion */
|
|
||||||
int compilerStat, linkerStat;
|
|
||||||
if (waitpid(compilerPid, &compilerStat, 0) < 0 || waitpid(linkerPid, &linkerStat, 0) < 0)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "waitpid fail %s\n", strerror(errno));
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WEXITSTATUS(compilerStat) || WEXITSTATUS(linkerStat))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
/* Copy temp file into buffer with first byte set to indicate binary data */
|
|
||||||
FILE* fin = fopen(m_libfile, "rb");
|
|
||||||
fseek(fin, 0, SEEK_END);
|
|
||||||
long libLen = ftell(fin);
|
|
||||||
fseek(fin, 0, SEEK_SET);
|
|
||||||
blobOut.resize(libLen + 1);
|
|
||||||
blobOut[0] = 1;
|
|
||||||
fread(&blobOut[1], 1, libLen, fin);
|
|
||||||
fclose(fin);
|
|
||||||
}
|
|
||||||
return blobOut;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,9 +64,10 @@ void StageConverter<P, S>::loadFromStream(FactoryCtx& ctx, ShaderCacheZipStream&
|
||||||
{
|
{
|
||||||
uint64_t hash = r.readUint64Big();
|
uint64_t hash = r.readUint64Big();
|
||||||
uint32_t size = r.readUint32Big();
|
uint32_t size = r.readUint32Big();
|
||||||
std::shared_ptr<uint8_t[]> data(new uint8_t[size]);
|
StageBinaryData data = MakeStageBinaryData(size);
|
||||||
r.readUBytesToBuf(data.get(), size);
|
r.readUBytesToBuf(data.get(), size);
|
||||||
m_stageCache.insert(std::make_pair(hash, Do<StageTargetTp>(ctx, StageBinary<P, S>(data, size))));
|
m_stageCache.insert(std::make_pair(hash,
|
||||||
|
Do<StageTargetTp>(ctx, StageBinary<P, S>(data, size))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <memory>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
|
|
||||||
|
@ -100,7 +102,7 @@ struct CompileStageAction
|
||||||
template<typename P, typename S>
|
template<typename P, typename S>
|
||||||
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut)
|
static bool Do(const std::string& name, const std::string& basename, const std::string& stage, std::string& implOut)
|
||||||
{
|
{
|
||||||
std::pair<std::shared_ptr<uint8_t[]>, size_t> data = CompileShader<P, S>(stage);
|
std::pair<StageBinaryData, size_t> data = CompileShader<P, S>(stage);
|
||||||
if (data.second == 0)
|
if (data.second == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -109,7 +111,7 @@ struct CompileStageAction
|
||||||
{
|
{
|
||||||
implOut += " ";
|
implOut += " ";
|
||||||
for (int j = 0; j < 10 && i < data.second ; ++i, ++j)
|
for (int j = 0; j < 10 && i < data.second ; ++i, ++j)
|
||||||
implOut += Format("0x%02X, ", data.first[i]);
|
implOut += Format("0x%02X, ", data.first.get()[i]);
|
||||||
implOut += "\n";
|
implOut += "\n";
|
||||||
}
|
}
|
||||||
implOut += "};\n\n";
|
implOut += "};\n\n";
|
||||||
|
|
Loading…
Reference in New Issue