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

@@ -36,11 +36,11 @@ class GLDataFactoryImpl : public GLDataFactory, public GraphicsDataFactoryHead
friend struct GLCommandQueue;
friend class GLDataFactory::Context;
IGraphicsContext* m_parent;
uint32_t m_drawSamples;
GLContext* m_glCtx;
std::unordered_map<uint64_t, std::unique_ptr<GLShareableShader>> m_sharedShaders;
public:
GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples)
: m_parent(parent), m_drawSamples(drawSamples) {}
GLDataFactoryImpl(IGraphicsContext* parent, GLContext* glCtx)
: m_parent(parent), m_glCtx(glCtx) {}
Platform platform() const { return Platform::OpenGL; }
const SystemChar* platformName() const { return _S("OpenGL"); }
@@ -187,7 +187,7 @@ class GLTextureS : public GraphicsDataNode<ITextureS>
friend class GLDataFactory;
GLuint m_tex;
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)
{
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);
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);
}
else
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);
GLenum intFormat, format;
@@ -274,7 +277,7 @@ class GLTextureSA : public GraphicsDataNode<ITextureSA>
friend class GLDataFactory;
GLuint m_tex;
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)
{
const uint8_t* dataIt = static_cast<const uint8_t*>(data);
@@ -289,6 +292,9 @@ class GLTextureSA : public GraphicsDataNode<ITextureSA>
else
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);
GLenum intFormat, format;
@@ -433,13 +439,13 @@ class GLTextureR : public GraphicsDataNode<ITextureR>
struct GLCommandQueue* m_q;
GLuint m_texs[2] = {};
GLuint m_bindTexs[2][MAX_BIND_TEXS] = {};
GLuint m_bindFBOs[2][MAX_BIND_TEXS] = {};
GLuint m_fbo = 0;
size_t m_width = 0;
size_t m_height = 0;
size_t m_samples = 0;
size_t m_colorBindCount;
size_t m_depthBindCount;
GLenum m_target;
GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples,
TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount);
public:
@@ -447,6 +453,8 @@ public:
{
glDeleteTextures(2, m_texs);
glDeleteTextures(MAX_BIND_TEXS * 2, m_bindTexs[0]);
if (m_samples > 1)
glDeleteFramebuffers(MAX_BIND_TEXS * 2, m_bindFBOs[0]);
glDeleteFramebuffers(1, &m_fbo);
}
@@ -467,7 +475,7 @@ public:
void bind(size_t idx, int bindIdx, bool depth) const
{
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)
@@ -518,7 +526,9 @@ ObjToken<ITextureS>
GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
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>
@@ -526,7 +536,9 @@ GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_
TextureFormat fmt, TextureClampMode clampMode,
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>
@@ -1028,6 +1040,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
Platform platform() const { return IGraphicsDataFactory::Platform::OpenGL; }
const SystemChar* platformName() const { return _S("OpenGL"); }
IGraphicsContext* m_parent = nullptr;
GLContext* m_glCtx = nullptr;
std::mutex m_mt;
std::condition_variable m_cv;
@@ -1167,8 +1180,31 @@ struct GLCommandQueue : IGraphicsCommandQueue
{
glGenFramebuffers(1, &tex->m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, tex->m_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex->m_texs[0], 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex->m_texs[1], 0);
GLenum target = tex->m_samples > 1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
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)
@@ -1188,6 +1224,17 @@ struct GLCommandQueue : IGraphicsCommandQueue
Log.report(logvisor::Info, "OpenGL Version: %s", version);
self->m_parent->postInit();
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();
while (self->m_running)
@@ -1229,6 +1276,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
std::vector<Command>& cmds = self->m_cmdBufs[self->m_drawBuf];
GLenum currentPrim = GL_TRIANGLES;
const GLShaderDataBinding* curBinding = nullptr;
GLuint curFBO = 0;
for (const Command& cmd : cmds)
{
switch (cmd.m_op)
@@ -1244,10 +1292,8 @@ struct GLCommandQueue : IGraphicsCommandQueue
case Command::Op::SetRenderTarget:
{
const GLTextureR* tex = cmd.target.cast<GLTextureR>();
if (!tex)
glBindFramebuffer(GL_FRAMEBUFFER, 0);
else
glBindFramebuffer(GL_FRAMEBUFFER, tex->m_fbo);
curFBO = (!tex) ? 0 : tex->m_fbo;
glBindFramebuffer(GL_FRAMEBUFFER, curFBO);
break;
}
case Command::Op::SetViewport:
@@ -1291,23 +1337,49 @@ struct GLCommandQueue : IGraphicsCommandQueue
break;
case Command::Op::ResolveBindTexture:
{
const SWindowRect& rect = cmd.viewport.rect;
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);
glActiveTexture(GL_TEXTURE9);
if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx])
if (tex->m_samples <= 1)
{
glBindTexture(target, 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],
cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]);
glActiveTexture(GL_TEXTURE9);
if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx])
{
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]);
glCopyTexSubImage2D(target, 0, cmd.viewport.rect.location[0], cmd.viewport.rect.location[1],
cmd.viewport.rect.location[0], cmd.viewport.rect.location[1],
cmd.viewport.rect.size[0], cmd.viewport.rect.size[1]);
if (cmd.resolveColor && tex->m_bindTexs[0][cmd.bindIdx])
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_bindFBOs[0][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_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)
{
@@ -1315,6 +1387,7 @@ struct GLCommandQueue : IGraphicsCommandQueue
glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT);
}
glBindFramebuffer(GL_FRAMEBUFFER, curFBO);
break;
}
case Command::Op::Present:
@@ -1338,8 +1411,9 @@ struct GLCommandQueue : IGraphicsCommandQueue
}
}
GLCommandQueue(IGraphicsContext* parent)
GLCommandQueue(IGraphicsContext* parent, GLContext* glCtx)
: m_parent(parent),
m_glCtx(glCtx),
m_initlk(m_initmt),
m_thr(RenderingWorker, this)
{
@@ -1585,7 +1659,6 @@ GLTextureR::GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue*
if (samples > 1)
{
m_target = GL_TEXTURE_2D_MULTISAMPLE;
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[0]);
glTexImage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, GL_RGBA, width, height, GL_FALSE);
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, m_texs[1]);
@@ -1593,7 +1666,6 @@ GLTextureR::GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue*
}
else
{
m_target = GL_TEXTURE_2D;
glBindTexture(GL_TEXTURE_2D, m_texs[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
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);
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));
q->resizeRenderTexture(retval, width, height);
return retval;
@@ -1653,14 +1725,14 @@ ObjToken<IVertexFormat> GLDataFactory::Context::newVertexFormat
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;
std::unordered_map<uint64_t, std::unique_ptr<MetalShareableShader>> m_sharedShaders;
struct MetalContext* m_ctx;
uint32_t m_sampleCount;
public:
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
char m_libfile[MAXPATHLEN];
bool m_hasCompiler = false;
MetalDataFactoryImpl(IGraphicsContext* parent, MetalContext* ctx, uint32_t sampleCount)
: m_parent(parent), m_ctx(ctx), m_sampleCount(sampleCount)
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())
@@ -524,14 +523,28 @@ class MetalTextureR : public GraphicsDataNode<ITextureR>
{
desc.pixelFormat = MTLPixelFormatBGRA8Unorm;
for (int i=0 ; i<m_colorBindCount ; ++i)
{
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)
{
desc.pixelFormat = MTLPixelFormatDepth32Float;
for (int i=0 ; i<m_depthBindCount ; ++i)
{
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_clearColorPassDesc;
MTLRenderPassDescriptor* m_clearBothPassDesc;
MTLRenderPassDescriptor* m_blitColor[MAX_BIND_TEXS] = {};
MTLRenderPassDescriptor* m_blitDepth[MAX_BIND_TEXS] = {};
~MetalTextureR() = default;
void resize(MetalContext* ctx, size_t width, size_t height)
@@ -1004,6 +1019,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
IGraphicsContext* m_parent;
id<MTLCommandBuffer> m_cmdBuf;
id<MTLRenderCommandEncoder> m_enc;
id<MTLSamplerState> m_samplers[3];
bool m_running = true;
int m_fillBuf = 0;
@@ -1015,6 +1031,27 @@ struct MetalCommandQueue : IGraphicsCommandQueue
@autoreleasepool
{
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);
m_boundData = cbind;
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
{
[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])
{
[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];
}
[[m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_blitColor[bindIdx]] endEncoding];
if (depth && tex->m_depthBindTex[bindIdx])
{
[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];
}
[[m_cmdBuf renderCommandEncoderWithDescriptor:tex->m_blitDepth[bindIdx]] endEncoding];
[blitEnc endEncoding];
m_enc = [m_cmdBuf renderCommandEncoderWithDescriptor:clearDepth ? tex->m_clearDepthPassDesc : tex->m_passDesc];
[m_enc setFrontFacingWinding:MTLWindingCounterClockwise];
@@ -1225,6 +1235,7 @@ struct MetalCommandQueue : IGraphicsCommandQueue
}
bool m_inProgress = false;
std::unordered_map<uintptr_t, MTLRenderPassDescriptor*> m_resolvePasses;
void execute()
{
if (!m_running)
@@ -1297,20 +1308,21 @@ struct MetalCommandQueue : IGraphicsCommandQueue
{
MetalTextureR* src = m_needsDisplay.cast<MetalTextureR>();
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 &&
src->m_colorTex.height == dest.height)
{
id<MTLBlitCommandEncoder> blitEnc = [m_cmdBuf blitCommandEncoder];
[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 renderCommandEncoderWithDescriptor:passSearch->second] endEncoding];
[m_cmdBuf presentDrawable:drawable];
}
}
@@ -1392,7 +1404,7 @@ MetalDataFactory::Context::newRenderTexture(size_t width, size_t height, Texture
@autoreleasepool
{
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)};
}
}
@@ -1411,7 +1423,7 @@ 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, unsigned targetSamples,
const ObjToken<IVertexFormat>& vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling)
@@ -1420,7 +1432,7 @@ MetalDataFactory::Context::newShaderPipeline(const char* vertSource, const char*
{
MetalDataFactoryImpl& factory = static_cast<MetalDataFactoryImpl&>(m_parent);
MTLCompileOptions* compOpts = [MTLCompileOptions new];
compOpts.languageVersion = MTLLanguageVersion1_2;
compOpts.languageVersion = MTLLanguageVersion1_1;
NSError* err = nullptr;
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),
vtxFmt, targetSamples, srcFac, dstFac, prim, depthTest, depthWrite,
vtxFmt, factory.m_ctx->m_sampleCount, srcFac, dstFac, prim, depthTest, depthWrite,
colorWrite, alphaWrite, culling)};
}
}
@@ -1588,9 +1600,9 @@ IGraphicsCommandQueue* _NewMetalCommandQueue(MetalContext* ctx, IWindow* parentW
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);
}
}