mirror of https://github.com/AxioDL/boo.git
macOS API sync
This commit is contained in:
parent
592ffa1372
commit
65c99ad769
|
@ -4,9 +4,9 @@
|
|||
[submodule "logvisor"]
|
||||
path = logvisor
|
||||
url = ../logvisor.git
|
||||
[submodule "lib/graphicsdev/NX/mesa"]
|
||||
[submodule "lib/graphicsdev/nx/mesa"]
|
||||
path = lib/graphicsdev/nx/mesa
|
||||
url = ../mesa.git
|
||||
[submodule "lib/graphicsdev/NX/libdrm_nouveau"]
|
||||
[submodule "lib/graphicsdev/nx/libdrm_nouveau"]
|
||||
path = lib/graphicsdev/nx/libdrm_nouveau
|
||||
url = https://github.com/devkitPro/libdrm_nouveau.git
|
||||
|
|
|
@ -39,7 +39,7 @@ if(TARGET nx_compiler)
|
|||
list(APPEND _BOO_SYS_DEFINES -DHECL_NOUVEAU_NX=1)
|
||||
endif()
|
||||
|
||||
if(NOT GEKKO AND NOT CAFE AND NOT WINDOWS_STORE AND NOT NX)
|
||||
if(NOT GEKKO AND NOT CAFE AND NOT WINDOWS_STORE AND NOT NX AND NOT APPLE)
|
||||
list(APPEND PLAT_SRCS
|
||||
lib/graphicsdev/GL.cpp
|
||||
lib/graphicsdev/glew.c)
|
||||
|
@ -137,7 +137,6 @@ elseif(APPLE)
|
|||
|
||||
find_library(APPKIT_LIBRARY AppKit)
|
||||
find_library(IOKIT_LIBRARY IOKit)
|
||||
find_library(OPENGL_LIBRARY OpenGL)
|
||||
unset(BOO_HAS_METAL CACHE)
|
||||
if (NOT CMAKE_OSX_DEPLOYMENT_TARGET OR CMAKE_OSX_DEPLOYMENT_TARGET VERSION_GREATER 10.11)
|
||||
set(BOO_HAS_METAL ON CACHE BOOL "Metal is available in this OS X version" FORCE)
|
||||
|
@ -151,10 +150,11 @@ elseif(APPLE)
|
|||
find_library(AUDIOTOOLBOX_LIBRARY AudioToolbox)
|
||||
find_library(COREAUDIO_LIBRARY CoreAudio)
|
||||
find_library(COREMIDI_LIBRARY CoreMIDI)
|
||||
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${OPENGL_LIBRARY} ${METAL_LIBRARY}
|
||||
list(APPEND _BOO_SYS_LIBS ${APPKIT_LIBRARY} ${IOKIT_LIBRARY} ${METAL_LIBRARY}
|
||||
${QUARTZCORE_LIBRARY} ${COREVIDEO_LIBRARY} ${AUDIOTOOLBOX_LIBRARY}
|
||||
${COREAUDIO_LIBRARY} ${COREMIDI_LIBRARY})
|
||||
|
||||
add_library(glew lib/graphicsdev/glew.c)
|
||||
elseif(NX)
|
||||
list(APPEND _BOO_SYS_DEFINES -DBOO_HAS_NX=1)
|
||||
list(APPEND PLAT_SRCS
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <memory>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "boo/System.hpp"
|
||||
#include "boo/ThreadLocalPtr.hpp"
|
||||
#include "boo/BooObject.hpp"
|
||||
|
|
|
@ -37,36 +37,15 @@ public:
|
|||
ObjToken<ITextureR> newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
|
||||
size_t colorBindCount, size_t depthBindCount);
|
||||
|
||||
bool bindingNeedsVertexFormat() const { return false; }
|
||||
ObjToken<IVertexFormat> newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||
size_t baseVert = 0, size_t baseInst = 0);
|
||||
ObjToken<IShaderStage> newShaderStage(const uint8_t* data, size_t size, PipelineStage stage);
|
||||
|
||||
ObjToken<IShaderPipeline> newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||
std::vector<uint8_t>* vertBlobOut,
|
||||
std::vector<uint8_t>* fragBlobOut,
|
||||
const ObjToken<IVertexFormat>& vtxFmt,
|
||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||
bool alphaWrite, CullMode culling,
|
||||
bool overwriteAlpha = true,
|
||||
bool depthAttachment = true);
|
||||
|
||||
ObjToken<IShaderPipeline> newTessellationShaderPipeline(
|
||||
const char* computeSource, const char* fragSource,
|
||||
const char* evaluationSource,
|
||||
std::vector<uint8_t>* computeBlobOut,
|
||||
std::vector<uint8_t>* fragBlobOut,
|
||||
std::vector<uint8_t>* evaluationBlobOut,
|
||||
const ObjToken<IVertexFormat>& vtxFmt,
|
||||
BlendFactor srcFac, BlendFactor dstFac, uint32_t patchSize,
|
||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||
bool alphaWrite, CullMode culling,
|
||||
bool overwriteAlpha = true,
|
||||
bool depthAttachment = true);
|
||||
ObjToken<IShaderPipeline> newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
|
||||
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
|
||||
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
|
||||
const AdditionalPipelineInfo& additionalInfo);
|
||||
|
||||
ObjToken<IShaderDataBinding>
|
||||
newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
|
||||
const ObjToken<IVertexFormat>& vtxFormat,
|
||||
const ObjToken<IGraphicsBuffer>& vbo,
|
||||
const ObjToken<IGraphicsBuffer>& instVbo,
|
||||
const ObjToken<IGraphicsBuffer>& ibo,
|
||||
|
@ -76,6 +55,8 @@ public:
|
|||
const int* texBindIdxs, const bool* depthBind,
|
||||
size_t baseVert = 0, size_t baseInst = 0);
|
||||
};
|
||||
|
||||
static std::vector<uint8_t> CompileMetal(const char* source, PipelineStage stage);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <functional>
|
||||
#include <typeindex>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace boo
|
||||
{
|
||||
|
|
|
@ -67,19 +67,11 @@ static logvisor::Module Log("boo::Metal");
|
|||
struct MetalCommandQueue;
|
||||
class MetalDataFactoryImpl;
|
||||
|
||||
struct MetalShareableShader : IShareableShader<MetalDataFactoryImpl, MetalShareableShader>
|
||||
{
|
||||
id<MTLFunction> m_shader;
|
||||
MetalShareableShader(MetalDataFactoryImpl& fac, uint64_t srcKey, uint64_t binKey, id<MTLFunction> s)
|
||||
: IShareableShader(fac, srcKey, binKey), m_shader(s) {}
|
||||
};
|
||||
|
||||
class MetalDataFactoryImpl : public MetalDataFactory, public GraphicsDataFactoryHead
|
||||
{
|
||||
friend struct MetalCommandQueue;
|
||||
friend class MetalDataFactory::Context;
|
||||
IGraphicsContext* m_parent;
|
||||
std::unordered_map<uint64_t, std::unique_ptr<MetalShareableShader>> m_sharedShaders;
|
||||
struct MetalContext* m_ctx;
|
||||
|
||||
bool m_hasTessellation = false;
|
||||
|
@ -88,7 +80,6 @@ class MetalDataFactoryImpl : public MetalDataFactory, public GraphicsDataFactory
|
|||
ObjToken<IShaderPipeline> m_gammaShader;
|
||||
ObjToken<ITextureD> m_gammaLUT;
|
||||
ObjToken<IGraphicsBufferS> m_gammaVBO;
|
||||
ObjToken<IVertexFormat> m_gammaVFMT;
|
||||
ObjToken<IShaderDataBinding> m_gammaBinding;
|
||||
void SetupGammaResources()
|
||||
{
|
||||
|
@ -96,14 +87,20 @@ class MetalDataFactoryImpl : public MetalDataFactory, public GraphicsDataFactory
|
|||
|
||||
commitTransaction([this](IGraphicsDataFactory::Context& ctx)
|
||||
{
|
||||
auto vertexMetal = MetalDataFactory::CompileMetal(GammaVS, PipelineStage::Vertex);
|
||||
auto vertexShader = ctx.newShaderStage(vertexMetal, PipelineStage::Vertex);
|
||||
auto fragmentMetal = MetalDataFactory::CompileMetal(GammaFS, PipelineStage::Fragment);
|
||||
auto fragmentShader = ctx.newShaderStage(fragmentMetal, PipelineStage::Fragment);
|
||||
const VertexElementDescriptor vfmt[] = {
|
||||
{nullptr, nullptr, VertexSemantic::Position4},
|
||||
{nullptr, nullptr, VertexSemantic::UV4}
|
||||
{VertexSemantic::Position4},
|
||||
{VertexSemantic::UV4}
|
||||
};
|
||||
m_gammaVFMT = ctx.newVertexFormat(2, vfmt);
|
||||
m_gammaShader = static_cast<Context&>(ctx).newShaderPipeline(GammaVS, GammaFS,
|
||||
nullptr, nullptr, m_gammaVFMT, BlendFactor::One, BlendFactor::Zero,
|
||||
Primitive::TriStrips, ZTest::None, false, true, false, CullMode::None, true, false);
|
||||
AdditionalPipelineInfo info =
|
||||
{
|
||||
BlendFactor::One, BlendFactor::Zero,
|
||||
Primitive::TriStrips, ZTest::None, false, true, false, CullMode::None
|
||||
};
|
||||
m_gammaShader = ctx.newShaderPipeline(vertexShader, fragmentShader, vfmt, info);
|
||||
m_gammaLUT = ctx.newDynamicTexture(256, 256, TextureFormat::I16, TextureClampMode::ClampToEdge);
|
||||
setDisplayGamma(1.f);
|
||||
const struct Vert {
|
||||
|
@ -117,242 +114,22 @@ class MetalDataFactoryImpl : public MetalDataFactory, public GraphicsDataFactory
|
|||
};
|
||||
m_gammaVBO = ctx.newStaticBuffer(BufferUse::Vertex, verts, 32, 4);
|
||||
ObjToken<ITexture> texs[] = {{}, m_gammaLUT.get()};
|
||||
m_gammaBinding = ctx.newShaderDataBinding(m_gammaShader, m_gammaVFMT, m_gammaVBO.get(), {}, {},
|
||||
m_gammaBinding = ctx.newShaderDataBinding(m_gammaShader, m_gammaVBO.get(), {}, {},
|
||||
0, nullptr, nullptr, 2, texs, nullptr, nullptr);
|
||||
return true;
|
||||
} BooTrace);
|
||||
}
|
||||
|
||||
public:
|
||||
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
|
||||
char m_libfile[MAXPATHLEN];
|
||||
bool m_hasCompiler = false;
|
||||
|
||||
MetalDataFactoryImpl(IGraphicsContext* parent, MetalContext* ctx)
|
||||
: m_parent(parent), m_ctx(ctx)
|
||||
{
|
||||
snprintf(m_libfile, MAXPATHLEN, "%sboo_metal_shader.metallib", getenv("TMPDIR"));
|
||||
for (auto& arg : APP->getArgs())
|
||||
if (arg == "--metal-compile")
|
||||
{
|
||||
m_hasCompiler = CheckForMetalCompiler();
|
||||
break;
|
||||
}
|
||||
}
|
||||
: m_parent(parent), m_ctx(ctx) {}
|
||||
~MetalDataFactoryImpl() = default;
|
||||
|
||||
Platform platform() const { return Platform::Metal; }
|
||||
const char* platformName() const { return "Metal"; }
|
||||
void commitTransaction(const std::function<bool(IGraphicsDataFactory::Context& ctx)>& __BooTraceArgs);
|
||||
ObjToken<IGraphicsBufferD> newPoolBuffer(BufferUse use, size_t stride, size_t count __BooTraceArgs);
|
||||
void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey) { m_sharedShaders.erase(srcKey); }
|
||||
|
||||
static bool 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)
|
||||
return false;
|
||||
return WEXITSTATUS(status) == 1;
|
||||
}
|
||||
|
||||
uint64_t CompileLib(std::vector<uint8_t>& blobOut, const char* source, uint64_t srcKey)
|
||||
{
|
||||
if (!m_hasCompiler)
|
||||
{
|
||||
/* 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 0;
|
||||
}
|
||||
|
||||
if (WEXITSTATUS(compilerStat) || WEXITSTATUS(linkerStat))
|
||||
return 0;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
XXH64_state_t hashState;
|
||||
XXH64_reset(&hashState, 0);
|
||||
XXH64_update(&hashState, blobOut.data(), blobOut.size());
|
||||
uint64_t binKey = XXH64_digest(&hashState);
|
||||
m_sourceToBinary[srcKey] = binKey;
|
||||
return binKey;
|
||||
}
|
||||
|
||||
uint64_t CompileLib(__strong id<MTLLibrary>& libOut, const char* source, uint64_t srcKey,
|
||||
MTLCompileOptions* compOpts, NSError * _Nullable *err)
|
||||
{
|
||||
libOut = [m_ctx->m_dev newLibraryWithSource:@(source)
|
||||
options:compOpts
|
||||
error:err];
|
||||
|
||||
if (srcKey)
|
||||
{
|
||||
XXH64_state_t hashState;
|
||||
XXH64_reset(&hashState, 0);
|
||||
uint8_t zero = 0;
|
||||
XXH64_update(&hashState, &zero, 1);
|
||||
XXH64_update(&hashState, source, strlen(source) + 1);
|
||||
uint64_t binKey = XXH64_digest(&hashState);
|
||||
m_sourceToBinary[srcKey] = binKey;
|
||||
return binKey;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
MetalShareableShader::Token PrepareShaderStage(const char* source, std::vector<uint8_t>* blobOut, NSString* funcName)
|
||||
{
|
||||
MTLCompileOptions* compOpts = [MTLCompileOptions new];
|
||||
compOpts.languageVersion = MTLLanguageVersion1_2;
|
||||
NSError* err = nullptr;
|
||||
|
||||
XXH64_state_t hashState;
|
||||
uint64_t srcHash = 0;
|
||||
uint64_t binHash = 0;
|
||||
XXH64_reset(&hashState, 0);
|
||||
if (source)
|
||||
{
|
||||
XXH64_update(&hashState, source, strlen(source));
|
||||
srcHash = XXH64_digest(&hashState);
|
||||
auto binSearch = m_sourceToBinary.find(srcHash);
|
||||
if (binSearch != m_sourceToBinary.cend())
|
||||
binHash = binSearch->second;
|
||||
}
|
||||
else if (blobOut && !blobOut->empty())
|
||||
{
|
||||
XXH64_update(&hashState, blobOut->data(), blobOut->size());
|
||||
binHash = XXH64_digest(&hashState);
|
||||
}
|
||||
|
||||
if (blobOut && blobOut->empty())
|
||||
binHash = CompileLib(*blobOut, source, srcHash);
|
||||
|
||||
MetalShareableShader::Token shader;
|
||||
auto search = binHash ? m_sharedShaders.find(binHash) : m_sharedShaders.end();
|
||||
if (search != m_sharedShaders.end())
|
||||
{
|
||||
return search->second->lock();
|
||||
}
|
||||
else
|
||||
{
|
||||
id<MTLLibrary> shaderLib;
|
||||
if (blobOut && !blobOut->empty())
|
||||
{
|
||||
if ((*blobOut)[0] == 1)
|
||||
{
|
||||
dispatch_data_t data = dispatch_data_create(blobOut->data() + 1, blobOut->size() - 1, nullptr, nullptr);
|
||||
shaderLib = [m_ctx->m_dev newLibraryWithData:data error:&err];
|
||||
if (!shaderLib)
|
||||
Log.report(logvisor::Fatal, "error loading library: %s", [[err localizedDescription] UTF8String]);
|
||||
}
|
||||
else
|
||||
{
|
||||
CompileLib(shaderLib, (char*)blobOut->data() + 1, 0, compOpts, &err);
|
||||
}
|
||||
}
|
||||
else
|
||||
binHash = CompileLib(shaderLib, source, srcHash, compOpts, &err);
|
||||
|
||||
if (!shaderLib)
|
||||
{
|
||||
printf("%s\n", source);
|
||||
Log.report(logvisor::Fatal, "error compiling shader: %s", [[err localizedDescription] UTF8String]);
|
||||
}
|
||||
id<MTLFunction> func = [shaderLib newFunctionWithName:funcName];
|
||||
|
||||
auto it =
|
||||
m_sharedShaders.emplace(std::make_pair(binHash,
|
||||
std::make_unique<MetalShareableShader>(*this, srcHash, binHash, func))).first;
|
||||
return it->second->lock();
|
||||
}
|
||||
}
|
||||
|
||||
void setDisplayGamma(float gamma)
|
||||
{
|
||||
|
@ -855,15 +632,14 @@ static const MTLVertexFormat SEMANTIC_TYPE_TABLE[] =
|
|||
MTLVertexFormatFloat4
|
||||
};
|
||||
|
||||
struct MetalVertexFormat : GraphicsDataNode<IVertexFormat>
|
||||
struct MetalVertexFormat
|
||||
{
|
||||
size_t m_elementCount;
|
||||
MTLVertexDescriptor* m_vdesc;
|
||||
size_t m_stride = 0;
|
||||
size_t m_instStride = 0;
|
||||
MetalVertexFormat(const ObjToken<BaseGraphicsData>& parent,
|
||||
size_t elementCount, const VertexElementDescriptor* elements)
|
||||
: GraphicsDataNode<IVertexFormat>(parent), m_elementCount(elementCount)
|
||||
MetalVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
|
||||
: m_elementCount(elementCount)
|
||||
{
|
||||
for (size_t i=0 ; i<elementCount ; ++i)
|
||||
{
|
||||
|
@ -909,7 +685,7 @@ struct MetalVertexFormat : GraphicsDataNode<IVertexFormat>
|
|||
}
|
||||
}
|
||||
|
||||
MTLStageInputOutputDescriptor* makeTessellationComputeLayout()
|
||||
MTLStageInputOutputDescriptor* makeTessellationComputeLayout() const
|
||||
{
|
||||
MTLStageInputOutputDescriptor* ret = [MTLStageInputOutputDescriptor stageInputOutputDescriptor];
|
||||
|
||||
|
@ -930,7 +706,7 @@ struct MetalVertexFormat : GraphicsDataNode<IVertexFormat>
|
|||
return ret;
|
||||
}
|
||||
|
||||
MTLVertexDescriptor* makeTessellationVertexLayout()
|
||||
MTLVertexDescriptor* makeTessellationVertexLayout() const
|
||||
{
|
||||
MTLVertexDescriptor* ret = [MTLVertexDescriptor vertexDescriptor];
|
||||
|
||||
|
@ -982,6 +758,56 @@ static const MTLPrimitiveType PRIMITIVE_TABLE[] =
|
|||
|
||||
#define COLOR_WRITE_MASK (MTLColorWriteMaskRed | MTLColorWriteMaskGreen | MTLColorWriteMaskBlue)
|
||||
|
||||
class MetalShaderStage : public GraphicsDataNode<IShaderStage>
|
||||
{
|
||||
friend class MetalDataFactory;
|
||||
id<MTLFunction> m_shader;
|
||||
MetalShaderStage(const boo::ObjToken<BaseGraphicsData>& parent, MetalContext* ctx,
|
||||
const uint8_t* data, size_t size, PipelineStage stage)
|
||||
: GraphicsDataNode<IShaderStage>(parent)
|
||||
{
|
||||
NSError* err = nullptr;
|
||||
|
||||
id<MTLLibrary> shaderLib;
|
||||
if (data[0] == 1)
|
||||
{
|
||||
dispatch_data_t d = dispatch_data_create(data + 1, size - 1, nullptr, nullptr);
|
||||
shaderLib = [ctx->m_dev newLibraryWithData:d error:&err];
|
||||
}
|
||||
else
|
||||
{
|
||||
MTLCompileOptions* compOpts = [MTLCompileOptions new];
|
||||
compOpts.languageVersion = MTLLanguageVersion1_2;
|
||||
shaderLib = [ctx->m_dev newLibraryWithSource:@((const char*)(data + 1))
|
||||
options:compOpts
|
||||
error:&err];
|
||||
if (!shaderLib)
|
||||
printf("%s\n", data + 1);
|
||||
}
|
||||
if (!shaderLib)
|
||||
Log.report(logvisor::Fatal, "error creating library: %s", [[err localizedDescription] UTF8String]);
|
||||
|
||||
NSString* funcName;
|
||||
switch (stage)
|
||||
{
|
||||
case PipelineStage::Vertex:
|
||||
default:
|
||||
funcName = @"vmain"; break;
|
||||
case PipelineStage::Fragment:
|
||||
funcName = @"fmain"; break;
|
||||
case PipelineStage::Geometry:
|
||||
funcName = @"gmain"; break;
|
||||
case PipelineStage::Control:
|
||||
funcName = @"cmain"; break;
|
||||
case PipelineStage::Evaluation:
|
||||
funcName = @"emain"; break;
|
||||
}
|
||||
m_shader = [shaderLib newFunctionWithName:funcName];
|
||||
}
|
||||
public:
|
||||
id<MTLFunction> shader() const { return m_shader; }
|
||||
};
|
||||
|
||||
class MetalShaderPipeline : public GraphicsDataNode<IShaderPipeline>
|
||||
{
|
||||
protected:
|
||||
|
@ -990,17 +816,13 @@ protected:
|
|||
friend struct MetalShaderDataBinding;
|
||||
MTLCullMode m_cullMode = MTLCullModeNone;
|
||||
MTLPrimitiveType m_drawPrim;
|
||||
MetalShareableShader::Token m_vert;
|
||||
MetalShareableShader::Token m_frag;
|
||||
uint32_t m_patchSize;
|
||||
|
||||
MetalShaderPipeline(const ObjToken<BaseGraphicsData>& parent,
|
||||
MetalShareableShader::Token&& vert,
|
||||
MetalShareableShader::Token&& frag)
|
||||
: GraphicsDataNode<IShaderPipeline>(parent),
|
||||
m_vert(std::move(vert)), m_frag(std::move(frag))
|
||||
{}
|
||||
MetalShaderPipeline(const boo::ObjToken<BaseGraphicsData>& parent)
|
||||
: GraphicsDataNode<IShaderPipeline>(parent) {}
|
||||
|
||||
virtual void setupExtraStages(MetalContext* ctx, MTLRenderPipelineDescriptor* desc, MetalVertexFormat& cVtxFmt) {}
|
||||
virtual void setupExtraStages(MetalContext* ctx, MTLRenderPipelineDescriptor* desc,
|
||||
ObjToken<IShaderStage> compute, const MetalVertexFormat& cVtxFmt) {}
|
||||
|
||||
virtual void draw(MetalCommandQueue& q, size_t start, size_t count);
|
||||
virtual void drawIndexed(MetalCommandQueue& q, size_t start, size_t count);
|
||||
|
@ -1008,15 +830,17 @@ protected:
|
|||
virtual void drawInstancesIndexed(MetalCommandQueue& q, size_t start, size_t count, size_t instCount);
|
||||
|
||||
void setup(MetalContext* ctx,
|
||||
const ObjToken<IVertexFormat>& vtxFmt, NSUInteger targetSamples,
|
||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||
bool alphaWrite, bool overwriteAlpha, CullMode culling,
|
||||
bool depthAttachment = true)
|
||||
NSUInteger targetSamples,
|
||||
ObjToken<IShaderStage> vertex,
|
||||
ObjToken<IShaderStage> fragment,
|
||||
ObjToken<IShaderStage> compute,
|
||||
const VertexFormatInfo& vtxFmt,
|
||||
const AdditionalPipelineInfo& info)
|
||||
{
|
||||
m_drawPrim = PRIMITIVE_TABLE[int(prim)];
|
||||
m_drawPrim = PRIMITIVE_TABLE[int(info.prim)];
|
||||
m_patchSize = info.patchSize;
|
||||
|
||||
switch (culling)
|
||||
switch (info.culling)
|
||||
{
|
||||
case CullMode::None:
|
||||
default:
|
||||
|
@ -1031,22 +855,22 @@ protected:
|
|||
}
|
||||
|
||||
MTLRenderPipelineDescriptor* desc = [MTLRenderPipelineDescriptor new];
|
||||
desc.vertexFunction = m_vert.get().m_shader;
|
||||
desc.fragmentFunction = m_frag.get().m_shader;
|
||||
MetalVertexFormat& cVtxFmt = *vtxFmt.cast<MetalVertexFormat>();
|
||||
desc.vertexFunction = vertex.cast<MetalShaderStage>()->shader();
|
||||
desc.fragmentFunction = fragment.cast<MetalShaderStage>()->shader();
|
||||
MetalVertexFormat cVtxFmt(vtxFmt.elementCount, vtxFmt.elements);
|
||||
desc.vertexDescriptor = cVtxFmt.m_vdesc;
|
||||
setupExtraStages(ctx, desc, cVtxFmt);
|
||||
setupExtraStages(ctx, desc, compute, cVtxFmt);
|
||||
desc.sampleCount = targetSamples;
|
||||
desc.colorAttachments[0].pixelFormat = ctx->m_pixelFormat;
|
||||
desc.colorAttachments[0].writeMask = (colorWrite ? COLOR_WRITE_MASK : 0) |
|
||||
(alphaWrite ? MTLColorWriteMaskAlpha : 0);
|
||||
desc.colorAttachments[0].blendingEnabled = dstFac != BlendFactor::Zero;
|
||||
if (srcFac == BlendFactor::Subtract || dstFac == BlendFactor::Subtract)
|
||||
desc.colorAttachments[0].writeMask = (info.colorWrite ? COLOR_WRITE_MASK : 0) |
|
||||
(info.alphaWrite ? MTLColorWriteMaskAlpha : 0);
|
||||
desc.colorAttachments[0].blendingEnabled = info.dstFac != BlendFactor::Zero;
|
||||
if (info.srcFac == BlendFactor::Subtract || info.dstFac == BlendFactor::Subtract)
|
||||
{
|
||||
desc.colorAttachments[0].sourceRGBBlendFactor = MTLBlendFactorSourceAlpha;
|
||||
desc.colorAttachments[0].destinationRGBBlendFactor = MTLBlendFactorOne;
|
||||
desc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationReverseSubtract;
|
||||
if (overwriteAlpha)
|
||||
if (info.overwriteAlpha)
|
||||
{
|
||||
desc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||
desc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero;
|
||||
|
@ -1061,22 +885,22 @@ protected:
|
|||
}
|
||||
else
|
||||
{
|
||||
desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)];
|
||||
desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)];
|
||||
desc.colorAttachments[0].sourceRGBBlendFactor = BLEND_FACTOR_TABLE[int(info.srcFac)];
|
||||
desc.colorAttachments[0].destinationRGBBlendFactor = BLEND_FACTOR_TABLE[int(info.dstFac)];
|
||||
desc.colorAttachments[0].rgbBlendOperation = MTLBlendOperationAdd;
|
||||
if (overwriteAlpha)
|
||||
if (info.overwriteAlpha)
|
||||
{
|
||||
desc.colorAttachments[0].sourceAlphaBlendFactor = MTLBlendFactorOne;
|
||||
desc.colorAttachments[0].destinationAlphaBlendFactor = MTLBlendFactorZero;
|
||||
}
|
||||
else
|
||||
{
|
||||
desc.colorAttachments[0].sourceAlphaBlendFactor = BLEND_FACTOR_TABLE[int(srcFac)];
|
||||
desc.colorAttachments[0].destinationAlphaBlendFactor = BLEND_FACTOR_TABLE[int(dstFac)];
|
||||
desc.colorAttachments[0].sourceAlphaBlendFactor = BLEND_FACTOR_TABLE[int(info.srcFac)];
|
||||
desc.colorAttachments[0].destinationAlphaBlendFactor = BLEND_FACTOR_TABLE[int(info.dstFac)];
|
||||
}
|
||||
desc.colorAttachments[0].alphaBlendOperation = MTLBlendOperationAdd;
|
||||
}
|
||||
desc.depthAttachmentPixelFormat = depthAttachment ? MTLPixelFormatDepth32Float : MTLPixelFormatInvalid;
|
||||
desc.depthAttachmentPixelFormat = info.depthAttachment ? MTLPixelFormatDepth32Float : MTLPixelFormatInvalid;
|
||||
desc.inputPrimitiveTopology = MTLPrimitiveTopologyClassTriangle;
|
||||
NSError* err = nullptr;
|
||||
m_state = [ctx->m_dev newRenderPipelineStateWithDescriptor:desc error:&err];
|
||||
|
@ -1085,7 +909,7 @@ protected:
|
|||
[[err localizedDescription] UTF8String]);
|
||||
|
||||
MTLDepthStencilDescriptor* dsDesc = [MTLDepthStencilDescriptor new];
|
||||
switch (depthTest)
|
||||
switch (info.depthTest)
|
||||
{
|
||||
case ZTest::None:
|
||||
default:
|
||||
|
@ -1105,7 +929,7 @@ protected:
|
|||
break;
|
||||
}
|
||||
|
||||
dsDesc.depthWriteEnabled = depthWrite;
|
||||
dsDesc.depthWriteEnabled = info.depthWrite;
|
||||
m_dsState = [ctx->m_dev newDepthStencilStateWithDescriptor:dsDesc];
|
||||
}
|
||||
|
||||
|
@ -1129,20 +953,12 @@ class MetalTessellationShaderPipeline : public MetalShaderPipeline
|
|||
friend class MetalDataFactory;
|
||||
friend struct MetalCommandQueue;
|
||||
friend struct MetalShaderDataBinding;
|
||||
MetalShareableShader::Token m_compute;
|
||||
uint32_t m_patchSize;
|
||||
|
||||
MetalTessellationShaderPipeline(
|
||||
const ObjToken<BaseGraphicsData>& parent,
|
||||
MetalShareableShader::Token&& compute,
|
||||
MetalShareableShader::Token&& frag,
|
||||
MetalShareableShader::Token&& evaluation,
|
||||
uint32_t patchSize)
|
||||
: MetalShaderPipeline(parent, std::move(evaluation), std::move(frag)),
|
||||
m_compute(std::move(compute)), m_patchSize(patchSize)
|
||||
{}
|
||||
MetalTessellationShaderPipeline(const ObjToken<BaseGraphicsData>& parent)
|
||||
: MetalShaderPipeline(parent) {}
|
||||
|
||||
void setupExtraStages(MetalContext* ctx, MTLRenderPipelineDescriptor* desc, MetalVertexFormat& cVtxFmt)
|
||||
void setupExtraStages(MetalContext* ctx, MTLRenderPipelineDescriptor* desc,
|
||||
ObjToken<IShaderStage> compute, const MetalVertexFormat& cVtxFmt)
|
||||
{
|
||||
desc.maxTessellationFactor = 16;
|
||||
desc.tessellationFactorScaleEnabled = NO;
|
||||
|
@ -1154,7 +970,7 @@ class MetalTessellationShaderPipeline : public MetalShaderPipeline
|
|||
desc.vertexDescriptor = cVtxFmt.makeTessellationVertexLayout();
|
||||
|
||||
MTLComputePipelineDescriptor* compDesc = [MTLComputePipelineDescriptor new];
|
||||
compDesc.computeFunction = m_compute.get().m_shader;
|
||||
compDesc.computeFunction = compute.cast<MetalShaderStage>()->shader();
|
||||
compDesc.stageInputDescriptor = cVtxFmt.makeTessellationComputeLayout();
|
||||
|
||||
NSError* err = nullptr;
|
||||
|
@ -1980,77 +1796,39 @@ MetalDataFactory::Context::newRenderTexture(size_t width, size_t height, Texture
|
|||
}
|
||||
}
|
||||
|
||||
ObjToken<IVertexFormat>
|
||||
MetalDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements,
|
||||
size_t baseVert, size_t baseInst)
|
||||
ObjToken<IShaderStage>
|
||||
MetalDataFactory::Context::newShaderStage(const uint8_t* data, size_t size, PipelineStage stage)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
return {new struct MetalVertexFormat(m_data, elementCount, elements)};
|
||||
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
|
||||
return {new MetalShaderStage(m_data, factory.m_ctx, data, size, stage)};
|
||||
}
|
||||
}
|
||||
|
||||
ObjToken<IShaderPipeline>
|
||||
MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource,
|
||||
std::vector<uint8_t>* vertBlobOut,
|
||||
std::vector<uint8_t>* fragBlobOut,
|
||||
const ObjToken<IVertexFormat>& vtxFmt,
|
||||
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
|
||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||
bool alphaWrite, CullMode culling, bool overwriteAlpha,
|
||||
bool depthAttachment)
|
||||
MetalDataFactory::Context::newShaderPipeline(ObjToken<IShaderStage> vertex, ObjToken<IShaderStage> fragment,
|
||||
ObjToken<IShaderStage> geometry, ObjToken<IShaderStage> control,
|
||||
ObjToken<IShaderStage> evaluation, const VertexFormatInfo& vtxFmt,
|
||||
const AdditionalPipelineInfo& additionalInfo)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
|
||||
|
||||
MetalShareableShader::Token vertShader = factory.PrepareShaderStage(vertSource, vertBlobOut, @"vmain");
|
||||
MetalShareableShader::Token fragShader = factory.PrepareShaderStage(fragSource, fragBlobOut, @"fmain");
|
||||
|
||||
MetalShaderPipeline* ret = new MetalShaderPipeline(m_data, std::move(vertShader), std::move(fragShader));
|
||||
ret->setup(factory.m_ctx, vtxFmt, depthAttachment ? factory.m_ctx->m_sampleCount : 1,
|
||||
srcFac, dstFac, prim, depthTest, depthWrite,
|
||||
colorWrite, alphaWrite, overwriteAlpha, culling, depthAttachment);
|
||||
return {ret};
|
||||
}
|
||||
}
|
||||
|
||||
ObjToken<IShaderPipeline> MetalDataFactory::Context::newTessellationShaderPipeline(
|
||||
const char* computeSource, const char* fragSource,
|
||||
const char* evaluationSource,
|
||||
std::vector<uint8_t>* computeBlobOut,
|
||||
std::vector<uint8_t>* fragBlobOut,
|
||||
std::vector<uint8_t>* evaluationBlobOut,
|
||||
const ObjToken<IVertexFormat>& vtxFmt,
|
||||
BlendFactor srcFac, BlendFactor dstFac, uint32_t patchSize,
|
||||
ZTest depthTest, bool depthWrite, bool colorWrite,
|
||||
bool alphaWrite, CullMode culling,
|
||||
bool overwriteAlpha,
|
||||
bool depthAttachment)
|
||||
{
|
||||
@autoreleasepool
|
||||
{
|
||||
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
|
||||
|
||||
if (!factory.m_hasTessellation)
|
||||
Log.report(logvisor::Fatal, "Device does not support tessellation");
|
||||
|
||||
MetalShareableShader::Token computeShader = factory.PrepareShaderStage(computeSource, computeBlobOut, @"cmain");
|
||||
MetalShareableShader::Token fragShader = factory.PrepareShaderStage(fragSource, fragBlobOut, @"fmain");
|
||||
MetalShareableShader::Token evaluationShader = factory.PrepareShaderStage(evaluationSource, evaluationBlobOut, @"emain");
|
||||
|
||||
MetalTessellationShaderPipeline* ret = new MetalTessellationShaderPipeline(m_data,
|
||||
std::move(computeShader), std::move(fragShader), std::move(evaluationShader), patchSize);
|
||||
ret->setup(factory.m_ctx, vtxFmt, depthAttachment ? factory.m_ctx->m_sampleCount : 1,
|
||||
srcFac, dstFac, Primitive::Patches, depthTest, depthWrite,
|
||||
colorWrite, alphaWrite, overwriteAlpha, culling, depthAttachment);
|
||||
MetalShaderPipeline* ret;
|
||||
if (evaluation)
|
||||
ret = new MetalTessellationShaderPipeline(m_data);
|
||||
else
|
||||
ret = new MetalShaderPipeline(m_data);
|
||||
ret->setup(factory.m_ctx, additionalInfo.depthAttachment ? factory.m_ctx->m_sampleCount : 1,
|
||||
vertex, fragment, evaluation, vtxFmt, additionalInfo);
|
||||
return {ret};
|
||||
}
|
||||
}
|
||||
|
||||
ObjToken<IShaderDataBinding>
|
||||
MetalDataFactory::Context::newShaderDataBinding(const ObjToken<IShaderPipeline>& pipeline,
|
||||
const ObjToken<IVertexFormat>& vtxFormat,
|
||||
const ObjToken<IGraphicsBuffer>& vbo,
|
||||
const ObjToken<IGraphicsBuffer>& instVbo,
|
||||
const ObjToken<IGraphicsBuffer>& ibo,
|
||||
|
@ -2095,6 +1873,14 @@ std::unique_ptr<IGraphicsDataFactory> _NewMetalDataFactory(IGraphicsContext* par
|
|||
return std::make_unique<MetalDataFactoryImpl>(parent, ctx);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> MetalDataFactory::CompileMetal(const char* source, PipelineStage stage)
|
||||
{
|
||||
size_t strSz = strlen(source) + 1;
|
||||
std::vector<uint8_t> ret(strSz + 1);
|
||||
memcpy(ret.data() + 1, source, strSz);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "boo/IApplication.hpp"
|
||||
#include "boo/graphicsdev/Metal.hpp"
|
||||
#include "boo/graphicsdev/GL.hpp"
|
||||
#include "CocoaCommon.hpp"
|
||||
#include "../Common.hpp"
|
||||
|
||||
|
@ -32,8 +31,7 @@ namespace boo
|
|||
{
|
||||
static logvisor::Module Log("boo::ApplicationCocoa");
|
||||
|
||||
std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, NSOpenGLContext* lastGLCtx,
|
||||
MetalContext* metalCtx, GLContext* glCtx);
|
||||
std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, MetalContext* metalCtx);
|
||||
|
||||
class ApplicationCocoa : public IApplication
|
||||
{
|
||||
|
@ -52,7 +50,9 @@ private:
|
|||
std::unordered_map<uintptr_t, std::weak_ptr<IWindow>> m_windows;
|
||||
|
||||
MetalContext m_metalCtx;
|
||||
#if 0
|
||||
GLContext m_glCtx;
|
||||
#endif
|
||||
|
||||
void _deletedWindow(IWindow* window)
|
||||
{
|
||||
|
@ -78,9 +78,11 @@ public:
|
|||
m_metalCtx.m_sampleCount = samples;
|
||||
m_metalCtx.m_anisotropy = anisotropy;
|
||||
m_metalCtx.m_pixelFormat = deepColor ? MTLPixelFormatRGBA16Float : MTLPixelFormatBGRA8Unorm;
|
||||
#if 0
|
||||
m_glCtx.m_sampleCount = samples;
|
||||
m_glCtx.m_anisotropy = anisotropy;
|
||||
m_glCtx.m_deepColor = deepColor;
|
||||
#endif
|
||||
|
||||
[[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular];
|
||||
|
||||
|
@ -104,38 +106,13 @@ public:
|
|||
action:nil keyEquivalent:@""] setSubmenu:appMenu];
|
||||
[[NSApplication sharedApplication] setMainMenu:rootMenu];
|
||||
|
||||
/* Determine which graphics API to use */
|
||||
#if BOO_HAS_METAL
|
||||
bool useGL = false;
|
||||
if (!gfxApi.compare("OpenGL"))
|
||||
useGL = true;
|
||||
for (const SystemString& arg : args)
|
||||
{
|
||||
if (!arg.compare("--gl"))
|
||||
{
|
||||
useGL = true;
|
||||
break;
|
||||
}
|
||||
else if (!arg.compare("--metal"))
|
||||
{
|
||||
useGL = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!useGL)
|
||||
m_metalCtx.m_dev = MTLCreateSystemDefaultDevice();
|
||||
if (m_metalCtx.m_dev)
|
||||
{
|
||||
m_metalCtx.m_q = [m_metalCtx.m_dev newCommandQueue];
|
||||
while (![m_metalCtx.m_dev supportsTextureSampleCount:m_metalCtx.m_sampleCount])
|
||||
m_metalCtx.m_sampleCount = flp2(m_metalCtx.m_sampleCount - 1);
|
||||
Log.report(logvisor::Info, "using Metal renderer");
|
||||
}
|
||||
else
|
||||
Log.report(logvisor::Info, "using OpenGL renderer");
|
||||
#else
|
||||
Log.report(logvisor::Info, "using OpenGL renderer");
|
||||
#endif
|
||||
m_metalCtx.m_dev = MTLCreateSystemDefaultDevice();
|
||||
if (!m_metalCtx.m_dev)
|
||||
Log.report(logvisor::Fatal, "Unable to create metal device");
|
||||
m_metalCtx.m_q = [m_metalCtx.m_dev newCommandQueue];
|
||||
while (![m_metalCtx.m_dev supportsTextureSampleCount:m_metalCtx.m_sampleCount])
|
||||
m_metalCtx.m_sampleCount = flp2(m_metalCtx.m_sampleCount - 1);
|
||||
Log.report(logvisor::Info, "using Metal renderer");
|
||||
}
|
||||
|
||||
EPlatformType getPlatformType() const
|
||||
|
@ -214,19 +191,23 @@ public:
|
|||
|
||||
std::shared_ptr<IWindow> newWindow(std::string_view title)
|
||||
{
|
||||
auto newWindow = _WindowCocoaNew(title, m_lastGLCtx, &m_metalCtx, &m_glCtx);
|
||||
auto newWindow = _WindowCocoaNew(title, &m_metalCtx);
|
||||
m_windows[newWindow->getPlatformHandle()] = newWindow;
|
||||
return newWindow;
|
||||
}
|
||||
|
||||
/* Last GL context */
|
||||
#if 0
|
||||
NSOpenGLContext* m_lastGLCtx = nullptr;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if 0
|
||||
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx)
|
||||
{
|
||||
static_cast<ApplicationCocoa*>(APP)->m_lastGLCtx = lastGLCtx;
|
||||
}
|
||||
#endif
|
||||
|
||||
IApplication* APP = nullptr;
|
||||
int ApplicationRun(IApplication::EPlatformType platform,
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#include "boo/graphicsdev/GL.hpp"
|
||||
#include "boo/graphicsdev/glew.h"
|
||||
#include "boo/graphicsdev/Metal.hpp"
|
||||
#include "CocoaCommon.hpp"
|
||||
#import <AppKit/AppKit.h>
|
||||
|
@ -26,6 +24,7 @@ namespace boo {class WindowCocoa; class GraphicsContextCocoa;}
|
|||
- (void)setTouchBarProvider:(id)provider;
|
||||
@end
|
||||
|
||||
#if 0
|
||||
/* AppKit applies OpenGL much differently than other platforms
|
||||
* the NSOpenGLView class composes together all necessary
|
||||
* OGL context members and provides the necessary event hooks
|
||||
|
@ -95,6 +94,7 @@ static const NSOpenGLPixelFormatAttribute* PF_TABLE[] =
|
|||
PF_RGBAF32_ATTRS,
|
||||
PF_RGBAF32_Z24_ATTRS
|
||||
};
|
||||
#endif
|
||||
|
||||
@interface BooCocoaResponder : NSResponder <NSTextInputClient>
|
||||
{
|
||||
|
@ -155,10 +155,13 @@ public:
|
|||
}
|
||||
virtual BooCocoaResponder* responder() const=0;
|
||||
};
|
||||
#if 0
|
||||
class GraphicsContextCocoaGL;
|
||||
#endif
|
||||
class GraphicsContextCocoaMetal;
|
||||
}
|
||||
|
||||
#if 0
|
||||
@interface GraphicsContextCocoaGLInternal : NSOpenGLView
|
||||
{
|
||||
@public
|
||||
|
@ -166,6 +169,7 @@ class GraphicsContextCocoaMetal;
|
|||
}
|
||||
- (id)initWithBooContext:(boo::GraphicsContextCocoaGL*)bctx;
|
||||
@end
|
||||
#endif
|
||||
|
||||
@interface GraphicsContextCocoaMetalInternal : NSView
|
||||
{
|
||||
|
@ -181,11 +185,14 @@ class GraphicsContextCocoaMetal;
|
|||
namespace boo
|
||||
{
|
||||
static logvisor::Module Log("boo::WindowCocoa");
|
||||
#if 0
|
||||
std::unique_ptr<IGraphicsCommandQueue> _NewGLCommandQueue(IGraphicsContext* parent, GLContext* glCtx);
|
||||
std::unique_ptr<IGraphicsDataFactory> _NewGLDataFactory(IGraphicsContext* parent, GLContext* glCtx);
|
||||
#endif
|
||||
std::unique_ptr<IGraphicsCommandQueue> _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
|
||||
IGraphicsContext* parent);
|
||||
std::unique_ptr<IGraphicsDataFactory> _NewMetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
|
||||
#if 0
|
||||
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
|
||||
|
||||
class GraphicsContextCocoaGL : public GraphicsContextCocoa
|
||||
|
@ -349,6 +356,7 @@ IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
|
|||
|
||||
return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx, glCtx);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BOO_HAS_METAL
|
||||
class GraphicsContextCocoaMetal : public GraphicsContextCocoa
|
||||
|
@ -1147,6 +1155,7 @@ static boo::ESpecialKey translateKeycode(short code)
|
|||
|
||||
@end
|
||||
|
||||
#if 0
|
||||
@implementation GraphicsContextCocoaGLInternal
|
||||
- (id)initWithBooContext:(boo::GraphicsContextCocoaGL*)bctx
|
||||
{
|
||||
|
@ -1203,6 +1212,7 @@ static boo::ESpecialKey translateKeycode(short code)
|
|||
}
|
||||
|
||||
@end
|
||||
#endif
|
||||
|
||||
#if BOO_HAS_METAL
|
||||
@implementation GraphicsContextCocoaMetalInternal
|
||||
|
@ -1299,23 +1309,16 @@ class WindowCocoa : public IWindow
|
|||
|
||||
public:
|
||||
|
||||
void setup(std::string_view title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx, GLContext* glCtx)
|
||||
void setup(std::string_view title, MetalContext* metalCtx)
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
std::shared_ptr<boo::WindowCocoa> windowPtr =
|
||||
std::static_pointer_cast<boo::WindowCocoa>(shared_from_this());
|
||||
m_nsWindow = [[WindowCocoaInternal alloc] initWithBooWindow:windowPtr title:title];
|
||||
#if BOO_HAS_METAL
|
||||
if (metalCtx->m_dev)
|
||||
m_gfxCtx = static_cast<GraphicsContextCocoa*>(
|
||||
_GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal,
|
||||
this, metalCtx));
|
||||
else
|
||||
#endif
|
||||
m_gfxCtx = static_cast<GraphicsContextCocoa*>(
|
||||
_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3,
|
||||
this, lastGLCtx, glCtx));
|
||||
m_gfxCtx = static_cast<GraphicsContextCocoa*>(
|
||||
_GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal,
|
||||
this, metalCtx));
|
||||
m_gfxCtx->initializeContext(nullptr);
|
||||
});
|
||||
m_gfxCtx->getMainContextDataFactory();
|
||||
|
@ -1587,11 +1590,10 @@ public:
|
|||
|
||||
};
|
||||
|
||||
std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, NSOpenGLContext* lastGLCtx,
|
||||
MetalContext* metalCtx, GLContext* glCtx)
|
||||
std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, MetalContext* metalCtx)
|
||||
{
|
||||
auto ret = std::make_shared<WindowCocoa>();
|
||||
ret->setup(title, lastGLCtx, metalCtx, glCtx);
|
||||
ret->setup(title, metalCtx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue