Work on MSAA support

This commit is contained in:
Jack Andersen 2018-01-06 19:17:14 -10:00
parent db82ba674b
commit 1dc69c3468
12 changed files with 242 additions and 123 deletions

View File

@ -51,8 +51,7 @@ public:
virtual const std::vector<SystemString>& getArgs() const=0; virtual const std::vector<SystemString>& getArgs() const=0;
/* Constructors/initializers for sub-objects */ /* Constructors/initializers for sub-objects */
virtual std::shared_ptr<IWindow> newWindow(SystemStringView title, uint32_t drawSamples)=0; virtual std::shared_ptr<IWindow> newWindow(SystemStringView title)=0;
}; };
int int
@ -62,6 +61,8 @@ ApplicationRun(IApplication::EPlatformType platform,
SystemStringView friendlyName, SystemStringView friendlyName,
SystemStringView pname, SystemStringView pname,
const std::vector<SystemString>& args, const std::vector<SystemString>& args,
uint32_t samples = 1,
uint32_t anisotropy = 1,
bool singleInstance=true); bool singleInstance=true);
extern IApplication* APP; extern IApplication* APP;
@ -71,6 +72,8 @@ ApplicationRun(IApplication::EPlatformType platform,
SystemStringView uniqueName, SystemStringView uniqueName,
SystemStringView friendlyName, SystemStringView friendlyName,
int argc, const SystemChar** argv, int argc, const SystemChar** argv,
uint32_t samples = 1,
uint32_t anisotropy = 1,
bool singleInstance=true) bool singleInstance=true)
{ {
if (APP) if (APP)
@ -78,7 +81,8 @@ ApplicationRun(IApplication::EPlatformType platform,
std::vector<SystemString> args; std::vector<SystemString> args;
for (int i=1 ; i<argc ; ++i) for (int i=1 ; i<argc ; ++i)
args.push_back(argv[i]); args.push_back(argv[i]);
return ApplicationRun(platform, cb, uniqueName, friendlyName, argv[0], args, singleInstance); return ApplicationRun(platform, cb, uniqueName, friendlyName, argv[0], args,
samples, anisotropy, singleInstance);
} }
} }

View File

@ -11,6 +11,12 @@ namespace boo
{ {
struct BaseGraphicsData; struct BaseGraphicsData;
struct GLContext
{
uint32_t m_sampleCount = 1;
uint32_t m_anisotropy = 1;
};
class GLDataFactory : public IGraphicsDataFactory class GLDataFactory : public IGraphicsDataFactory
{ {
public: public:

View File

@ -45,7 +45,7 @@ public:
ObjToken<IShaderPipeline> newShaderPipeline(const char* vertSource, const char* fragSource, ObjToken<IShaderPipeline> newShaderPipeline(const char* vertSource, const char* fragSource,
std::vector<uint8_t>* vertBlobOut, std::vector<uint8_t>* vertBlobOut,
std::vector<uint8_t>* fragBlobOut, std::vector<uint8_t>* fragBlobOut,
const ObjToken<IVertexFormat>& vtxFmt, unsigned targetSamples, const ObjToken<IVertexFormat>& vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
ZTest depthTest, bool depthWrite, bool colorWrite, ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling); bool alphaWrite, CullMode culling);

View File

@ -66,6 +66,16 @@ protected:
} }
}; };
static inline uint32_t flp2(uint32_t x)
{
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x - (x >> 1);
}
} }
#endif // BOO_INTERNAL_COMMON_HPP #endif // BOO_INTERNAL_COMMON_HPP

View File

@ -36,11 +36,11 @@ class GLDataFactoryImpl : public GLDataFactory, public GraphicsDataFactoryHead
friend struct GLCommandQueue; friend struct GLCommandQueue;
friend class GLDataFactory::Context; friend class GLDataFactory::Context;
IGraphicsContext* m_parent; IGraphicsContext* m_parent;
uint32_t m_drawSamples; GLContext* m_glCtx;
std::unordered_map<uint64_t, std::unique_ptr<GLShareableShader>> m_sharedShaders; std::unordered_map<uint64_t, std::unique_ptr<GLShareableShader>> m_sharedShaders;
public: public:
GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples) GLDataFactoryImpl(IGraphicsContext* parent, GLContext* glCtx)
: m_parent(parent), m_drawSamples(drawSamples) {} : m_parent(parent), m_glCtx(glCtx) {}
Platform platform() const { return Platform::OpenGL; } Platform platform() const { return Platform::OpenGL; }
const SystemChar* platformName() const { return _S("OpenGL"); } const SystemChar* platformName() const { return _S("OpenGL"); }
@ -187,7 +187,7 @@ class GLTextureS : public GraphicsDataNode<ITextureS>
friend class GLDataFactory; friend class GLDataFactory;
GLuint m_tex; GLuint m_tex;
GLTextureS(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height, size_t mips, GLTextureS(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz) TextureFormat fmt, TextureClampMode clampMode, GLint aniso, const void* data, size_t sz)
: GraphicsDataNode<ITextureS>(parent) : GraphicsDataNode<ITextureS>(parent)
{ {
const uint8_t* dataIt = static_cast<const uint8_t*>(data); const uint8_t* dataIt = static_cast<const uint8_t*>(data);
@ -196,12 +196,15 @@ class GLTextureS : public GraphicsDataNode<ITextureS>
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (mips > 1) if (mips > 1)
{ {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mips-1); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, mips-1);
} }
else else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
SetClampMode(GL_TEXTURE_2D, clampMode); SetClampMode(GL_TEXTURE_2D, clampMode);
GLenum intFormat, format; GLenum intFormat, format;
@ -274,7 +277,7 @@ class GLTextureSA : public GraphicsDataNode<ITextureSA>
friend class GLDataFactory; friend class GLDataFactory;
GLuint m_tex; GLuint m_tex;
GLTextureSA(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height, size_t layers, size_t mips, GLTextureSA(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height, size_t layers, size_t mips,
TextureFormat fmt, TextureClampMode clampMode, const void* data, size_t sz) TextureFormat fmt, TextureClampMode clampMode, GLint aniso, const void* data, size_t sz)
: GraphicsDataNode<ITextureSA>(parent) : GraphicsDataNode<ITextureSA>(parent)
{ {
const uint8_t* dataIt = static_cast<const uint8_t*>(data); const uint8_t* dataIt = static_cast<const uint8_t*>(data);
@ -289,6 +292,9 @@ class GLTextureSA : public GraphicsDataNode<ITextureSA>
else else
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
if (GLEW_EXT_texture_filter_anisotropic)
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
SetClampMode(GL_TEXTURE_2D_ARRAY, clampMode); SetClampMode(GL_TEXTURE_2D_ARRAY, clampMode);
GLenum intFormat, format; GLenum intFormat, format;
@ -433,13 +439,13 @@ class GLTextureR : public GraphicsDataNode<ITextureR>
struct GLCommandQueue* m_q; struct GLCommandQueue* m_q;
GLuint m_texs[2] = {}; GLuint m_texs[2] = {};
GLuint m_bindTexs[2][MAX_BIND_TEXS] = {}; GLuint m_bindTexs[2][MAX_BIND_TEXS] = {};
GLuint m_bindFBOs[2][MAX_BIND_TEXS] = {};
GLuint m_fbo = 0; GLuint m_fbo = 0;
size_t m_width = 0; size_t m_width = 0;
size_t m_height = 0; size_t m_height = 0;
size_t m_samples = 0; size_t m_samples = 0;
size_t m_colorBindCount; size_t m_colorBindCount;
size_t m_depthBindCount; size_t m_depthBindCount;
GLenum m_target;
GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples,
TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount); TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount);
public: public:
@ -447,6 +453,8 @@ public:
{ {
glDeleteTextures(2, m_texs); glDeleteTextures(2, m_texs);
glDeleteTextures(MAX_BIND_TEXS * 2, m_bindTexs[0]); glDeleteTextures(MAX_BIND_TEXS * 2, m_bindTexs[0]);
if (m_samples > 1)
glDeleteFramebuffers(MAX_BIND_TEXS * 2, m_bindFBOs[0]);
glDeleteFramebuffers(1, &m_fbo); glDeleteFramebuffers(1, &m_fbo);
} }
@ -467,7 +475,7 @@ public:
void bind(size_t idx, int bindIdx, bool depth) const void bind(size_t idx, int bindIdx, bool depth) const
{ {
glActiveTexture(GL_TEXTURE0 + idx); glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(m_target, m_bindTexs[depth][bindIdx]); glBindTexture(GL_TEXTURE_2D, m_bindTexs[depth][bindIdx]);
} }
void resize(size_t width, size_t height) void resize(size_t width, size_t height)
@ -518,7 +526,9 @@ ObjToken<ITextureS>
GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
TextureClampMode clampMode, const void* data, size_t sz) TextureClampMode clampMode, const void* data, size_t sz)
{ {
return {new GLTextureS(m_data, width, height, mips, fmt, clampMode, data, sz)}; GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent);
return {new GLTextureS(m_data, width, height, mips, fmt, clampMode,
factory.m_glCtx->m_anisotropy, data, sz)};
} }
ObjToken<ITextureSA> ObjToken<ITextureSA>
@ -526,7 +536,9 @@ GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_
TextureFormat fmt, TextureClampMode clampMode, TextureFormat fmt, TextureClampMode clampMode,
const void *data, size_t sz) const void *data, size_t sz)
{ {
return {new GLTextureSA(m_data, width, height, layers, mips, fmt, clampMode, data, sz)}; GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent);
return {new GLTextureSA(m_data, width, height, layers, mips, fmt, clampMode,
factory.m_glCtx->m_anisotropy, data, sz)};
} }
class GLShaderPipeline : public GraphicsDataNode<IShaderPipeline> class GLShaderPipeline : public GraphicsDataNode<IShaderPipeline>
@ -1028,6 +1040,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
Platform platform() const { return IGraphicsDataFactory::Platform::OpenGL; } Platform platform() const { return IGraphicsDataFactory::Platform::OpenGL; }
const SystemChar* platformName() const { return _S("OpenGL"); } const SystemChar* platformName() const { return _S("OpenGL"); }
IGraphicsContext* m_parent = nullptr; IGraphicsContext* m_parent = nullptr;
GLContext* m_glCtx = nullptr;
std::mutex m_mt; std::mutex m_mt;
std::condition_variable m_cv; std::condition_variable m_cv;
@ -1167,8 +1180,31 @@ struct GLCommandQueue : IGraphicsCommandQueue
{ {
glGenFramebuffers(1, &tex->m_fbo); glGenFramebuffers(1, &tex->m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, tex->m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, tex->m_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->m_texs[0], 0); GLenum target = tex->m_samples > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex->m_texs[1], 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tex->m_texs[0], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, target, tex->m_texs[1], 0);
if (tex->m_samples > 1)
{
if (tex->m_colorBindCount)
{
glGenFramebuffers(tex->m_colorBindCount, tex->m_bindFBOs[0]);
for (int i=0 ; i<tex->m_colorBindCount ; ++i)
{
glBindFramebuffer(GL_FRAMEBUFFER, tex->m_bindFBOs[0][i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->m_bindTexs[0][i], 0);
}
}
if (tex->m_depthBindCount)
{
glGenFramebuffers(tex->m_depthBindCount, tex->m_bindFBOs[1]);
for (int i=0 ; i<tex->m_depthBindCount ; ++i)
{
glBindFramebuffer(GL_FRAMEBUFFER, tex->m_bindFBOs[1][i]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex->m_bindTexs[1][i], 0);
}
}
}
} }
static void RenderingWorker(GLCommandQueue* self) static void RenderingWorker(GLCommandQueue* self)
@ -1188,6 +1224,17 @@ struct GLCommandQueue : IGraphicsCommandQueue
Log.report(logvisor::Info, "OpenGL Version: %s", version); Log.report(logvisor::Info, "OpenGL Version: %s", version);
self->m_parent->postInit(); self->m_parent->postInit();
glClearColor(0.f, 0.f, 0.f, 0.f); glClearColor(0.f, 0.f, 0.f, 0.f);
if (GLEW_EXT_texture_filter_anisotropic)
{
GLint maxAniso;
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso);
self->m_glCtx->m_anisotropy = std::min(uint32_t(maxAniso), self->m_glCtx->m_anisotropy);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, maxAniso);
}
GLint maxSamples;
glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
self->m_glCtx->m_sampleCount =
flp2(std::min(uint32_t(maxSamples), std::max(uint32_t(1), self->m_glCtx->m_sampleCount)) - 1);
} }
self->m_initcv.notify_one(); self->m_initcv.notify_one();
while (self->m_running) while (self->m_running)
@ -1229,6 +1276,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf]; std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf];
GLenum currentPrim = GL_TRIANGLES; GLenum currentPrim = GL_TRIANGLES;
const GLShaderDataBinding* curBinding = nullptr; const GLShaderDataBinding* curBinding = nullptr;
GLuint curFBO = 0;
for (const Command& cmd : cmds) for (const Command& cmd : cmds)
{ {
switch (cmd.m_op) switch (cmd.m_op)
@ -1244,10 +1292,8 @@ struct GLCommandQueue : IGraphicsCommandQueue
case Command::Op::SetRenderTarget: case Command::Op::SetRenderTarget:
{ {
const GLTextureR* tex = cmd.target.cast<GLTextureR>(); const GLTextureR* tex = cmd.target.cast<GLTextureR>();
if (!tex) curFBO = (!tex) ? 0 : tex->m_fbo;
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, curFBO);
else
glBindFramebuffer(GL_FRAMEBUFFER, tex->m_fbo);
break; break;
} }
case Command::Op::SetViewport: case Command::Op::SetViewport:
@ -1291,23 +1337,49 @@ struct GLCommandQueue : IGraphicsCommandQueue
break; break;
case Command::Op::ResolveBindTexture: case Command::Op::ResolveBindTexture:
{ {
const SWindowRect& rect = cmd.viewport.rect;
const GLTextureR* tex = cmd.resolveTex.cast<GLTextureR>(); const GLTextureR* tex = cmd.resolveTex.cast<GLTextureR>();
GLenum target = (tex->m_samples > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo);
glActiveTexture(GL_TEXTURE9); if (tex->m_samples <= 1)
if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx])
{ {
glBindTexture(target, tex->m_bindTexs[0][cmd.bindIdx]); glActiveTexture(GL_TEXTURE9);
glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx])
cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], {
cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]); glBindTexture(GL_TEXTURE_2D, tex->m_bindTexs[0][cmd.bindIdx]);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
rect.location[0], rect.location[1],
rect.location[0], rect.location[1],
rect.size[0], rect.size[1]);
}
if (cmd.resolveDepth && tex->m_bindTexs[1][cmd.bindIdx])
{
glBindTexture(GL_TEXTURE_2D, tex->m_bindTexs[1][cmd.bindIdx]);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
rect.location[0], rect.location[1],
rect.location[0], rect.location[1],
rect.size[0], rect.size[1]);
}
} }
if (cmd.resolveDepth && tex->m_bindTexs[1][cmd.bindIdx]) else
{ {
glBindTexture(target, tex->m_bindTexs[1][cmd.bindIdx]); if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx])
glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], {
cmd.viewport.rect.location[0], cmd.viewport.rect.location[1], glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_bindFBOs[0][cmd.bindIdx]);
cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]); glBlitFramebuffer(rect.location[0], rect.location[1],
rect.location[0] + rect.size[0], rect.location[1] + rect.size[1],
rect.location[0], rect.location[1],
rect.location[0] + rect.size[0], rect.location[1] + rect.size[1],
GL_COLOR_BUFFER_BIT, GL_NEAREST);
}
if (cmd.resolveDepth && tex->m_bindTexs[1][cmd.bindIdx])
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_bindFBOs[1][cmd.bindIdx]);
glBlitFramebuffer(rect.location[0], rect.location[1],
rect.location[0] + rect.size[0], rect.location[1] + rect.size[1],
rect.location[0], rect.location[1],
rect.location[0] + rect.size[0], rect.location[1] + rect.size[1],
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
}
} }
if (cmd.clearDepth) if (cmd.clearDepth)
{ {
@ -1315,6 +1387,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
glDepthMask(GL_TRUE); glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT); glClear(GL_DEPTH_BUFFER_BIT);
} }
glBindFramebuffer(GL_FRAMEBUFFER, curFBO);
break; break;
} }
case Command::Op::Present: case Command::Op::Present:
@ -1338,8 +1411,9 @@ struct GLCommandQueue : IGraphicsCommandQueue
} }
} }
GLCommandQueue(IGraphicsContext* parent) GLCommandQueue(IGraphicsContext* parent, GLContext* glCtx)
: m_parent(parent), : m_parent(parent),
m_glCtx(glCtx),
m_initlk(m_initmt), m_initlk(m_initmt),
m_thr(RenderingWorker, this) m_thr(RenderingWorker, this)
{ {
@ -1585,7 +1659,6 @@ GLTextureR::GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue*
if (samples > 1) if (samples > 1)
{ {
m_target = GL_TEXTURE_2D_MULTISAMPLE;
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[0]); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[0]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, width, height, GL_FALSE); glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, width, height, GL_FALSE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]); glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]);
@ -1593,7 +1666,6 @@ GLTextureR::GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue*
} }
else else
{ {
m_target = GL_TEXTURE_2D;
glBindTexture(GL_TEXTURE_2D, m_texs[0]); glBindTexture(GL_TEXTURE_2D, m_texs[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glBindTexture(GL_TEXTURE_2D, m_texs[1]); glBindTexture(GL_TEXTURE_2D, m_texs[1]);
@ -1626,7 +1698,7 @@ GLDataFactory::Context::newRenderTexture(size_t width, size_t height, TextureCla
{ {
GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent); GLDataFactoryImpl& factory = static_cast<GLDataFactoryImpl&>(m_parent);
GLCommandQueue* q = static_cast<GLCommandQueue*>(factory.m_parent->getCommandQueue()); GLCommandQueue* q = static_cast<GLCommandQueue*>(factory.m_parent->getCommandQueue());
ObjToken<ITextureR> retval(new GLTextureR(m_data, q, width, height, factory.m_drawSamples, clampMode, ObjToken<ITextureR> retval(new GLTextureR(m_data, q, width, height, factory.m_glCtx->m_sampleCount, clampMode,
colorBindingCount, depthBindingCount)); colorBindingCount, depthBindingCount));
q->resizeRenderTexture(retval, width, height); q->resizeRenderTexture(retval, width, height);
return retval; return retval;
@ -1653,14 +1725,14 @@ ObjToken<IVertexFormat> GLDataFactory::Context::newVertexFormat
return {new GLVertexFormat(m_data, q, elementCount, elements, baseVert, baseInst)}; return {new GLVertexFormat(m_data, q, elementCount, elements, baseVert, baseInst)};
} }
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent) IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent, GLContext* glCtx)
{ {
return new struct GLCommandQueue(parent); return new struct GLCommandQueue(parent, glCtx);
} }
IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, uint32_t drawSamples) IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, GLContext* glCtx)
{ {
return new class GLDataFactoryImpl(parent, drawSamples); return new class GLDataFactoryImpl(parent, glCtx);
} }
} }

View File

@ -37,15 +37,14 @@ class MetalDataFactoryImpl : public MetalDataFactory, public GraphicsDataFactory
IGraphicsContext* m_parent; IGraphicsContext* m_parent;
std::unordered_map<uint64_t, std::unique_ptr<MetalShareableShader>> m_sharedShaders; std::unordered_map<uint64_t, std::unique_ptr<MetalShareableShader>> m_sharedShaders;
struct MetalContext* m_ctx; struct MetalContext* m_ctx;
uint32_t m_sampleCount;
public: public:
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary; std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
char m_libfile[MAXPATHLEN]; char m_libfile[MAXPATHLEN];
bool m_hasCompiler = false; bool m_hasCompiler = false;
MetalDataFactoryImpl(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount) MetalDataFactoryImpl(IGraphicsContext* parent, MetalContext* ctx)
: m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount) : m_parent(parent), m_ctx(ctx)
{ {
snprintf(m_libfile, MAXPATHLEN, "%sboo_metal_shader.metallib", getenv("TMPDIR")); snprintf(m_libfile, MAXPATHLEN, "%sboo_metal_shader.metallib", getenv("TMPDIR"));
for (auto& arg : APP->getArgs()) for (auto& arg : APP->getArgs())
@ -524,14 +523,28 @@ class MetalTextureR : public GraphicsDataNode<ITextureR>
{ {
desc.pixelFormat = MTLPixelFormatBGRA8Unorm; desc.pixelFormat = MTLPixelFormatBGRA8Unorm;
for (int i=0 ; i<m_colorBindCount ; ++i) for (int i=0 ; i<m_colorBindCount ; ++i)
{
m_colorBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc]; m_colorBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc];
m_blitColor[i] = [MTLRenderPassDescriptor renderPassDescriptor];
m_blitColor[i].colorAttachments[0].texture = m_colorTex;
m_blitColor[i].colorAttachments[0].loadAction = MTLLoadActionLoad;
m_blitColor[i].colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;
m_blitColor[i].colorAttachments[0].resolveTexture = m_colorBindTex[i];
}
} }
if (m_depthBindCount) if (m_depthBindCount)
{ {
desc.pixelFormat = MTLPixelFormatDepth32Float; desc.pixelFormat = MTLPixelFormatDepth32Float;
for (int i=0 ; i<m_depthBindCount ; ++i) for (int i=0 ; i<m_depthBindCount ; ++i)
{
m_depthBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc]; m_depthBindTex[i] = [ctx->m_dev newTextureWithDescriptor:desc];
m_blitDepth[i] = [MTLRenderPassDescriptor renderPassDescriptor];
m_blitDepth[i].depthAttachment.texture = m_colorTex;
m_blitDepth[i].depthAttachment.loadAction = MTLLoadActionLoad;
m_blitDepth[i].depthAttachment.storeAction = MTLStoreActionMultisampleResolve;
m_blitDepth[i].depthAttachment.resolveTexture = m_depthBindTex[i];
}
} }
{ {
@ -609,6 +622,8 @@ public:
MTLRenderPassDescriptor* m_clearDepthPassDesc; MTLRenderPassDescriptor* m_clearDepthPassDesc;
MTLRenderPassDescriptor* m_clearColorPassDesc; MTLRenderPassDescriptor* m_clearColorPassDesc;
MTLRenderPassDescriptor* m_clearBothPassDesc; MTLRenderPassDescriptor* m_clearBothPassDesc;
MTLRenderPassDescriptor* m_blitColor[MAX_BIND_TEXS] = {};
MTLRenderPassDescriptor* m_blitDepth[MAX_BIND_TEXS] = {};
~MetalTextureR() = default; ~MetalTextureR() = default;
void resize(MetalContext* ctx, size_t width, size_t height) void resize(MetalContext* ctx, size_t width, size_t height)
@ -1004,6 +1019,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
IGraphicsContext* m_parent; IGraphicsContext* m_parent;
id<MTLCommandBuffer> m_cmdBuf; id<MTLCommandBuffer> m_cmdBuf;
id<MTLRenderCommandEncoder> m_enc; id<MTLRenderCommandEncoder> m_enc;
id<MTLSamplerState> m_samplers[3];
bool m_running = true; bool m_running = true;
int m_fillBuf = 0; int m_fillBuf = 0;
@ -1015,6 +1031,27 @@ struct MetalCommandQueue : IGraphicsCommandQueue
@autoreleasepool @autoreleasepool
{ {
m_cmdBuf = [ctx->m_q commandBuffer]; m_cmdBuf = [ctx->m_q commandBuffer];
MTLSamplerDescriptor* sampDesc = [MTLSamplerDescriptor new];
sampDesc.rAddressMode = MTLSamplerAddressModeRepeat;
sampDesc.sAddressMode = MTLSamplerAddressModeRepeat;
sampDesc.tAddressMode = MTLSamplerAddressModeRepeat;
sampDesc.minFilter = MTLSamplerMinMagFilterLinear;
sampDesc.magFilter = MTLSamplerMinMagFilterLinear;
sampDesc.mipFilter = MTLSamplerMipFilterLinear;
sampDesc.maxAnisotropy = ctx->m_anisotropy;
sampDesc.borderColor = MTLSamplerBorderColorOpaqueWhite;
m_samplers[0] = [ctx->m_dev newSamplerStateWithDescriptor:sampDesc];
sampDesc.rAddressMode = MTLSamplerAddressModeClampToBorderColor;
sampDesc.sAddressMode = MTLSamplerAddressModeClampToBorderColor;
sampDesc.tAddressMode = MTLSamplerAddressModeClampToBorderColor;
m_samplers[1] = [ctx->m_dev newSamplerStateWithDescriptor:sampDesc];
sampDesc.rAddressMode = MTLSamplerAddressModeClampToEdge;
sampDesc.sAddressMode = MTLSamplerAddressModeClampToEdge;
sampDesc.tAddressMode = MTLSamplerAddressModeClampToEdge;
m_samplers[2] = [ctx->m_dev newSamplerStateWithDescriptor:sampDesc];
} }
} }
@ -1040,6 +1077,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
cbind->bind(m_enc, m_fillBuf); cbind->bind(m_enc, m_fillBuf);
m_boundData = cbind; m_boundData = cbind;
m_currentPrimitive = cbind->m_pipeline.cast<MetalShaderPipeline>()->m_drawPrim; m_currentPrimitive = cbind->m_pipeline.cast<MetalShaderPipeline>()->m_drawPrim;
[m_enc setFragmentSamplerStates:m_samplers withRange:NSMakeRange(0, 3)];
} }
} }
@ -1175,39 +1213,11 @@ struct MetalCommandQueue : IGraphicsCommandQueue
@autoreleasepool @autoreleasepool
{ {
[m_enc endEncoding]; [m_enc endEncoding];
SWindowRect intersectRect = rect.intersect(SWindowRect(0, 0, tex->m_width, tex->m_height));
NSUInteger y = tlOrigin ? intersectRect.location[1] : int(tex->m_height) -
intersectRect.location[1] - intersectRect.size[1];
MTLOrigin origin = {NSUInteger(intersectRect.location[0]), y, 0};
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder];
if (color && tex->m_colorBindTex[bindIdx]) if (color && tex->m_colorBindTex[bindIdx])
{ [[m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_blitColor[bindIdx]] endEncoding];
[blitEnc copyFromTexture:tex->m_colorTex
sourceSlice:0
sourceLevel:0
sourceOrigin:origin
sourceSize:MTLSizeMake(intersectRect.size[0], intersectRect.size[1], 1)
toTexture:tex->m_colorBindTex[bindIdx]
destinationSlice:0
destinationLevel:0
destinationOrigin:origin];
}
if (depth && tex->m_depthBindTex[bindIdx]) if (depth && tex->m_depthBindTex[bindIdx])
{ [[m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_blitDepth[bindIdx]] endEncoding];
[blitEnc copyFromTexture:tex->m_depthTex
sourceSlice:0
sourceLevel:0
sourceOrigin:origin
sourceSize:MTLSizeMake(intersectRect.size[0], intersectRect.size[1], 1)
toTexture:tex->m_depthBindTex[bindIdx]
destinationSlice:0
destinationLevel:0
destinationOrigin:origin];
}
[blitEnc endEncoding];
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:clearDepth ? tex->m_clearDepthPassDesc : tex->m_passDesc]; m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:clearDepth ? tex->m_clearDepthPassDesc : tex->m_passDesc];
[m_enc setFrontFacingWinding:MTLWindingCounterClockwise]; [m_enc setFrontFacingWinding:MTLWindingCounterClockwise];
@ -1225,6 +1235,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
} }
bool m_inProgress = false; bool m_inProgress = false;
std::unordered_map<uintptr_t, MTLRenderPassDescriptor*> m_resolvePasses;
void execute() void execute()
{ {
if (!m_running) if (!m_running)
@ -1297,20 +1308,21 @@ struct MetalCommandQueue : IGraphicsCommandQueue
{ {
MetalTextureR* src = m_needsDisplay.cast<MetalTextureR>(); MetalTextureR* src = m_needsDisplay.cast<MetalTextureR>();
id<MTLTexture> dest = drawable.texture; id<MTLTexture> dest = drawable.texture;
uintptr_t key = uintptr_t(src->m_colorTex) ^ uintptr_t(dest);
auto passSearch = m_resolvePasses.find(key);
if (passSearch == m_resolvePasses.end())
{
MTLRenderPassDescriptor* desc = [MTLRenderPassDescriptor renderPassDescriptor];
desc.colorAttachments[0].texture = src->m_colorTex;
desc.colorAttachments[0].loadAction = MTLLoadActionLoad;
desc.colorAttachments[0].storeAction = MTLStoreActionMultisampleResolve;
desc.colorAttachments[0].resolveTexture = dest;
passSearch = m_resolvePasses.insert(std::make_pair(key, desc)).first;
}
if (src->m_colorTex.width == dest.width && if (src->m_colorTex.width == dest.width &&
src->m_colorTex.height == dest.height) src->m_colorTex.height == dest.height)
{ {
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder]; [[m_cmdBuf renderCommandEncoderWithDescriptor:passSearch->second] endEncoding];
[blitEnc copyFromTexture:src->m_colorTex
sourceSlice:0
sourceLevel:0
sourceOrigin:MTLOriginMake(0, 0, 0)
sourceSize:MTLSizeMake(dest.width, dest.height, 1)
toTexture:dest
destinationSlice:0
destinationLevel:0
destinationOrigin:MTLOriginMake(0, 0, 0)];
[blitEnc endEncoding];
[m_cmdBuf presentDrawable:drawable]; [m_cmdBuf presentDrawable:drawable];
} }
} }
@ -1392,7 +1404,7 @@ MetalDataFactory::Context::newRenderTexture(size_t width, size_t height, Texture
@autoreleasepool @autoreleasepool
{ {
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
return {new MetalTextureR(m_data, factory.m_ctx, width, height, factory.m_sampleCount, return {new MetalTextureR(m_data, factory.m_ctx, width, height, factory.m_ctx->m_sampleCount,
colorBindCount, depthBindCount)}; colorBindCount, depthBindCount)};
} }
} }
@ -1411,7 +1423,7 @@ ObjToken<IShaderPipeline>
MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource, MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char* fragSource,
std::vector<uint8_t>* vertBlobOut, std::vector<uint8_t>* vertBlobOut,
std::vector<uint8_t>* fragBlobOut, std::vector<uint8_t>* fragBlobOut,
const ObjToken<IVertexFormat>& vtxFmt, unsigned targetSamples, const ObjToken<IVertexFormat>& vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
ZTest depthTest, bool depthWrite, bool colorWrite, ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling) bool alphaWrite, CullMode culling)
@ -1420,7 +1432,7 @@ MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char*
{ {
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent); MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MTLCompileOptions* compOpts = [MTLCompileOptions new]; MTLCompileOptions* compOpts = [MTLCompileOptions new];
compOpts.languageVersion = MTLLanguageVersion1_2; compOpts.languageVersion = MTLLanguageVersion1_1;
NSError* err = nullptr; NSError* err = nullptr;
XXH64_state_t hashState; XXH64_state_t hashState;
@ -1541,7 +1553,7 @@ MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char*
} }
return {new MetalShaderPipeline(m_data, factory.m_ctx, std::move(vertShader), std::move(fragShader), return {new MetalShaderPipeline(m_data, factory.m_ctx, std::move(vertShader), std::move(fragShader),
vtxFmt, targetSamples, srcFac, dstFac, prim, depthTest, depthWrite, vtxFmt, factory.m_ctx->m_sampleCount, srcFac, dstFac, prim, depthTest, depthWrite,
colorWrite, alphaWrite, culling)}; colorWrite, alphaWrite, culling)};
} }
} }
@ -1588,9 +1600,9 @@ IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentW
return new struct MetalCommandQueue(ctx, parentWindow, parent); return new struct MetalCommandQueue(ctx, parentWindow, parent);
} }
IGraphicsDataFactory* _NewMetalDataFactory(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount) IGraphicsDataFactory* _NewMetalDataFactory(IGraphicsContext* parent, MetalContext* ctx)
{ {
return new class MetalDataFactoryImpl(parent, ctx, sampleCount); return new class MetalDataFactoryImpl(parent, ctx);
} }
} }

View File

@ -3,7 +3,9 @@
#include "boo/IApplication.hpp" #include "boo/IApplication.hpp"
#include "boo/graphicsdev/Metal.hpp" #include "boo/graphicsdev/Metal.hpp"
#include "boo/graphicsdev/GL.hpp"
#include "CocoaCommon.hpp" #include "CocoaCommon.hpp"
#include "../Common.hpp"
#include "logvisor/logvisor.hpp" #include "logvisor/logvisor.hpp"
@ -31,7 +33,7 @@ namespace boo
static logvisor::Module Log("boo::ApplicationCocoa"); static logvisor::Module Log("boo::ApplicationCocoa");
std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, NSOpenGLContext* lastGLCtx, std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, NSOpenGLContext* lastGLCtx,
MetalContext* metalCtx, uint32_t sampleCount); MetalContext* metalCtx, GLContext* glCtx);
class ApplicationCocoa : public IApplication class ApplicationCocoa : public IApplication
{ {
@ -50,6 +52,7 @@ private:
std::unordered_map<uintptr_t, std::weak_ptr<IWindow>> m_windows; std::unordered_map<uintptr_t, std::weak_ptr<IWindow>> m_windows;
MetalContext m_metalCtx; MetalContext m_metalCtx;
GLContext m_glCtx;
void _deletedWindow(IWindow* window) void _deletedWindow(IWindow* window)
{ {
@ -61,13 +64,20 @@ public:
SystemStringView uniqueName, SystemStringView uniqueName,
SystemStringView friendlyName, SystemStringView friendlyName,
SystemStringView pname, SystemStringView pname,
const std::vector<SystemString>& args) const std::vector<SystemString>& args,
uint32_t samples,
uint32_t anisotropy)
: m_callback(callback), : m_callback(callback),
m_uniqueName(uniqueName), m_uniqueName(uniqueName),
m_friendlyName(friendlyName), m_friendlyName(friendlyName),
m_pname(pname), m_pname(pname),
m_args(args) m_args(args)
{ {
m_metalCtx.m_sampleCount = samples;
m_metalCtx.m_anisotropy = anisotropy;
m_glCtx.m_sampleCount = samples;
m_glCtx.m_anisotropy = anisotropy;
[[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular]; [[NSApplication sharedApplication] setActivationPolicy:NSApplicationActivationPolicyRegular];
/* Delegate (OS X callbacks) */ /* Delegate (OS X callbacks) */
@ -104,6 +114,8 @@ public:
if (m_metalCtx.m_dev) if (m_metalCtx.m_dev)
{ {
m_metalCtx.m_q = [m_metalCtx.m_dev newCommandQueue]; 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"); Log.report(logvisor::Info, "using Metal renderer");
} }
else else
@ -187,9 +199,9 @@ public:
return m_args; return m_args;
} }
std::shared_ptr<IWindow> newWindow(std::string_view title, uint32_t sampleCount) std::shared_ptr<IWindow> newWindow(std::string_view title)
{ {
auto newWindow = _WindowCocoaNew(title, m_lastGLCtx, &m_metalCtx, sampleCount); auto newWindow = _WindowCocoaNew(title, m_lastGLCtx, &m_metalCtx, &m_glCtx);
m_windows[newWindow->getPlatformHandle()] = newWindow; m_windows[newWindow->getPlatformHandle()] = newWindow;
return newWindow; return newWindow;
} }
@ -210,6 +222,8 @@ int ApplicationRun(IApplication::EPlatformType platform,
SystemStringView friendlyName, SystemStringView friendlyName,
SystemStringView pname, SystemStringView pname,
const std::vector<SystemString>& args, const std::vector<SystemString>& args,
uint32_t samples,
uint32_t anisotropy,
bool singleInstance) bool singleInstance)
{ {
std::string thrName = std::string(friendlyName) + " Main Thread"; std::string thrName = std::string(friendlyName) + " Main Thread";
@ -222,7 +236,7 @@ int ApplicationRun(IApplication::EPlatformType platform,
platform != IApplication::EPlatformType::Auto) platform != IApplication::EPlatformType::Auto)
return 1; return 1;
/* Never deallocated to ensure window destructors have access */ /* Never deallocated to ensure window destructors have access */
APP = new ApplicationCocoa(cb, uniqueName, friendlyName, pname, args); APP = new ApplicationCocoa(cb, uniqueName, friendlyName, pname, args, samples, anisotropy);
} }
[NSApp run]; [NSApp run];
ApplicationCocoa* appCocoa = static_cast<ApplicationCocoa*>(APP); ApplicationCocoa* appCocoa = static_cast<ApplicationCocoa*>(APP);

View File

@ -28,6 +28,8 @@ struct MetalContext
CGSize m_size; CGSize m_size;
}; };
std::unordered_map<IWindow*, Window> m_windows; std::unordered_map<IWindow*, Window> m_windows;
uint32_t m_sampleCount = 1;
uint32_t m_anisotropy = 1;
}; };
} }

View File

@ -185,12 +185,11 @@ class GraphicsContextCocoaMetal;
namespace boo namespace boo
{ {
static logvisor::Module Log("boo::WindowCocoa"); static logvisor::Module Log("boo::WindowCocoa");
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent); IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent, GLContext* glCtx);
IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, uint32_t drawSamples); IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, GLContext* glCtx);
IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow, IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentWindow,
IGraphicsContext* parent); IGraphicsContext* parent);
IGraphicsDataFactory* _NewMetalDataFactory(IGraphicsContext* parent, IGraphicsDataFactory* _NewMetalDataFactory(IGraphicsContext* parent, MetalContext* ctx);
MetalContext* ctx, uint32_t sampleCount);
void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx); void _CocoaUpdateLastGLCtx(NSOpenGLContext* lastGLCtx);
class GraphicsContextCocoaGL : public GraphicsContextCocoa class GraphicsContextCocoaGL : public GraphicsContextCocoa
@ -203,14 +202,15 @@ class GraphicsContextCocoaGL : public GraphicsContextCocoa
NSOpenGLContext* m_loadCtx = nullptr; NSOpenGLContext* m_loadCtx = nullptr;
public: public:
NSOpenGLContext* m_lastCtx = nullptr; NSOpenGLContext* m_lastCtx;
GLContext* m_glCtx;
GraphicsContextCocoaGL(EGraphicsAPI api, IWindow* parentWindow, GraphicsContextCocoaGL(EGraphicsAPI api, IWindow* parentWindow,
NSOpenGLContext* lastGLCtx, uint32_t sampleCount) NSOpenGLContext* lastGLCtx, GLContext* glCtx)
: GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow), : GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow),
m_lastCtx(lastGLCtx) m_lastCtx(lastGLCtx), m_glCtx(glCtx)
{ {
m_dataFactory = _NewGLDataFactory(this, sampleCount); m_dataFactory = _NewGLDataFactory(this, glCtx);
} }
~GraphicsContextCocoaGL() ~GraphicsContextCocoaGL()
@ -253,7 +253,7 @@ public:
CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink); CVDisplayLinkCreateWithActiveCGDisplays(&m_dispLink);
CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this); CVDisplayLinkSetOutputCallback(m_dispLink, (CVDisplayLinkOutputCallback)DLCallback, this);
CVDisplayLinkStart(m_dispLink); CVDisplayLinkStart(m_dispLink);
m_commandQueue = _NewGLCommandQueue(this); m_commandQueue = _NewGLCommandQueue(this, m_glCtx);
return true; return true;
} }
@ -318,7 +318,7 @@ public:
IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api, IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow, NSOpenGLContext* lastGLCtx, IWindow* parentWindow, NSOpenGLContext* lastGLCtx,
uint32_t sampleCount) GLContext* glCtx)
{ {
if (api != IGraphicsContext::EGraphicsAPI::OpenGL3_3 && api != IGraphicsContext::EGraphicsAPI::OpenGL4_2) if (api != IGraphicsContext::EGraphicsAPI::OpenGL3_3 && api != IGraphicsContext::EGraphicsAPI::OpenGL4_2)
return NULL; return NULL;
@ -349,7 +349,7 @@ IGraphicsContext* _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI api,
if (api == IGraphicsContext::EGraphicsAPI::OpenGL4_2) if (api == IGraphicsContext::EGraphicsAPI::OpenGL4_2)
return NULL; return NULL;
return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx, sampleCount); return new GraphicsContextCocoaGL(api, parentWindow, lastGLCtx, glCtx);
} }
#if BOO_HAS_METAL #if BOO_HAS_METAL
@ -364,12 +364,11 @@ public:
IWindow* m_parentWindow; IWindow* m_parentWindow;
MetalContext* m_metalCtx; MetalContext* m_metalCtx;
GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow, GraphicsContextCocoaMetal(EGraphicsAPI api, IWindow* parentWindow, MetalContext* metalCtx)
MetalContext* metalCtx, uint32_t sampleCount)
: GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow), : GraphicsContextCocoa(api, EPixelFormat::RGBA8, parentWindow),
m_parentWindow(parentWindow), m_metalCtx(metalCtx) m_parentWindow(parentWindow), m_metalCtx(metalCtx)
{ {
m_dataFactory = _NewMetalDataFactory(this, metalCtx, sampleCount); m_dataFactory = _NewMetalDataFactory(this, metalCtx);
} }
~GraphicsContextCocoaMetal() ~GraphicsContextCocoaMetal()
@ -461,12 +460,11 @@ public:
IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api, IGraphicsContext* _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI api,
IWindow* parentWindow, IWindow* parentWindow,
MetalContext* metalCtx, MetalContext* metalCtx)
uint32_t sampleCount)
{ {
if (api != IGraphicsContext::EGraphicsAPI::Metal) if (api != IGraphicsContext::EGraphicsAPI::Metal)
return nullptr; return nullptr;
return new GraphicsContextCocoaMetal(api, parentWindow, metalCtx, sampleCount); return new GraphicsContextCocoaMetal(api, parentWindow, metalCtx);
} }
#endif #endif
@ -1302,7 +1300,7 @@ class WindowCocoa : public IWindow
public: public:
void setup(std::string_view title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx, uint32_t sampleCount) void setup(std::string_view title, NSOpenGLContext* lastGLCtx, MetalContext* metalCtx, GLContext* glCtx)
{ {
dispatch_sync(dispatch_get_main_queue(), dispatch_sync(dispatch_get_main_queue(),
^{ ^{
@ -1313,12 +1311,12 @@ public:
if (metalCtx->m_dev) if (metalCtx->m_dev)
m_gfxCtx = static_cast<GraphicsContextCocoa*>( m_gfxCtx = static_cast<GraphicsContextCocoa*>(
_GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal, _GraphicsContextCocoaMetalNew(IGraphicsContext::EGraphicsAPI::Metal,
this, metalCtx, sampleCount)); this, metalCtx));
else else
#endif #endif
m_gfxCtx = static_cast<GraphicsContextCocoa*>( m_gfxCtx = static_cast<GraphicsContextCocoa*>(
_GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3, _GraphicsContextCocoaGLNew(IGraphicsContext::EGraphicsAPI::OpenGL3_3,
this, lastGLCtx, sampleCount)); this, lastGLCtx, glCtx));
m_gfxCtx->initializeContext(nullptr); m_gfxCtx->initializeContext(nullptr);
}); });
m_gfxCtx->getMainContextDataFactory(); m_gfxCtx->getMainContextDataFactory();
@ -1591,10 +1589,10 @@ public:
}; };
std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, NSOpenGLContext* lastGLCtx, std::shared_ptr<IWindow> _WindowCocoaNew(SystemStringView title, NSOpenGLContext* lastGLCtx,
MetalContext* metalCtx, uint32_t sampleCount) MetalContext* metalCtx, GLContext* glCtx)
{ {
auto ret = std::make_shared<WindowCocoa>(); auto ret = std::make_shared<WindowCocoa>();
ret->setup(title, lastGLCtx, metalCtx, sampleCount); ret->setup(title, lastGLCtx, metalCtx, glCtx);
return ret; return ret;
} }

View File

@ -35,8 +35,8 @@ IGraphicsDataFactory* _NewD3D12DataFactory(D3D12Context* ctx, IGraphicsContext*
#endif #endif
IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent); IGraphicsCommandQueue* _NewD3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent);
IGraphicsDataFactory* _NewD3D11DataFactory(D3D11Context* ctx, IGraphicsContext* parent, uint32_t sampleCount); IGraphicsDataFactory* _NewD3D11DataFactory(D3D11Context* ctx, IGraphicsContext* parent, uint32_t sampleCount);
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent); IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent, GLContext* glCtx);
IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, uint32_t drawSamples); IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, GLContext* glCtx);
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx, IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx,
VulkanContext::Window* windowCtx, VulkanContext::Window* windowCtx,

View File

@ -110,8 +110,8 @@ extern "C" const size_t MAINICON_NETWM_SZ;
namespace boo namespace boo
{ {
static logvisor::Module Log("boo::WindowXlib"); static logvisor::Module Log("boo::WindowXlib");
IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent); IGraphicsCommandQueue* _NewGLCommandQueue(IGraphicsContext* parent, GLContext* glCtx);
IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, uint32_t drawSamples); IGraphicsDataFactory* _NewGLDataFactory(IGraphicsContext* parent, GLContext* glCtx);
#if BOO_HAS_VULKAN #if BOO_HAS_VULKAN
IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx, IGraphicsCommandQueue* _NewVulkanCommandQueue(VulkanContext* ctx,
VulkanContext::Window* windowCtx, VulkanContext::Window* windowCtx,

View File

@ -458,9 +458,10 @@ struct TestApplicationCallback : IApplicationCallback
static const char* FS = static const char* FS =
"#include <metal_stdlib>\n" "#include <metal_stdlib>\n"
"using namespace metal;\n" "using namespace metal;\n"
"constexpr sampler samp(address::repeat);\n"
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n" "struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
"fragment float4 fmain(VertToFrag d [[ stage_in ]], texture2d<float> tex [[ texture(0) ]])\n" "fragment float4 fmain(VertToFrag d [[ stage_in ]],\n"
" sampler samp [[ sampler(0) ]],\n"
" texture2d<float> tex [[ texture(0) ]])\n"
"{\n" "{\n"
" return tex.sample(samp, d.out_uv);\n" " return tex.sample(samp, d.out_uv);\n"
"}\n"; "}\n";