Commit 9bc86c50 by Alexey Knyazev Committed by Commit Bot

Metal: Implement OES_draw_buffers_indexed

Bug: angleproject:2634 Bug: angleproject:4394 Change-Id: Id6e6c6bdea2b1ff3d974e92e067ed63e1b4e4582 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2465919 Commit-Queue: Alexey Knyazev <lexa.knyazev@gmail.com> Reviewed-by: 's avatarLe Hoang Quyen <le.hoang.q@gmail.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 8b1d1fb6
...@@ -294,7 +294,7 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -294,7 +294,7 @@ class ContextMtl : public ContextImpl, public mtl::Context
void serverWaitEvent(const mtl::SharedEventRef &event, uint64_t value); void serverWaitEvent(const mtl::SharedEventRef &event, uint64_t value);
const mtl::ClearColorValue &getClearColorValue() const; const mtl::ClearColorValue &getClearColorValue() const;
MTLColorWriteMask getColorMask() const; const mtl::WriteMaskArray &getWriteMaskArray() const;
float getClearDepthValue() const; float getClearDepthValue() const;
uint32_t getClearStencilValue() const; uint32_t getClearStencilValue() const;
// Return front facing stencil write mask // Return front facing stencil write mask
...@@ -420,6 +420,7 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -420,6 +420,7 @@ class ContextMtl : public ContextImpl, public mtl::Context
float nearPlane, float nearPlane,
float farPlane); float farPlane);
void updateDepthRange(float nearPlane, float farPlane); void updateDepthRange(float nearPlane, float farPlane);
void updateBlendDescArray(const gl::BlendStateExt &blendStateExt);
void updateScissor(const gl::State &glState); void updateScissor(const gl::State &glState);
void updateCullMode(const gl::State &glState); void updateCullMode(const gl::State &glState);
void updateFrontFace(const gl::State &glState); void updateFrontFace(const gl::State &glState);
...@@ -522,7 +523,8 @@ class ContextMtl : public ContextImpl, public mtl::Context ...@@ -522,7 +523,8 @@ class ContextMtl : public ContextImpl, public mtl::Context
// State // State
mtl::RenderPipelineDesc mRenderPipelineDesc; mtl::RenderPipelineDesc mRenderPipelineDesc;
mtl::DepthStencilDesc mDepthStencilDesc; mtl::DepthStencilDesc mDepthStencilDesc;
mtl::BlendDesc mBlendDesc; mtl::BlendDescArray mBlendDescArray;
mtl::WriteMaskArray mWriteMaskArray;
mtl::ClearColorValue mClearColor; mtl::ClearColorValue mClearColor;
uint32_t mClearStencil = 0; uint32_t mClearStencil = 0;
uint32_t mStencilRefFront = 0; uint32_t mStencilRefFront = 0;
......
...@@ -198,7 +198,13 @@ ContextMtl::~ContextMtl() {} ...@@ -198,7 +198,13 @@ ContextMtl::~ContextMtl() {}
angle::Result ContextMtl::initialize() angle::Result ContextMtl::initialize()
{ {
mBlendDesc.reset(); for (mtl::BlendDesc &blendDesc : mBlendDescArray)
{
blendDesc.reset();
}
mWriteMaskArray.fill(MTLColorWriteMaskAll);
mDepthStencilDesc.reset(); mDepthStencilDesc.reset();
mTriFanIndexBuffer.initialize(this, 0, mtl::kIndexBufferOffsetAlignment, mTriFanIndexBuffer.initialize(this, 0, mtl::kIndexBufferOffsetAlignment,
...@@ -832,7 +838,20 @@ angle::Result ContextMtl::syncState(const gl::Context *context, ...@@ -832,7 +838,20 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
// Initialize incomplete texture set. // Initialize incomplete texture set.
ANGLE_TRY(ensureIncompleteTexturesCreated(context)); ANGLE_TRY(ensureIncompleteTexturesCreated(context));
for (size_t dirtyBit : dirtyBits) // Metal's blend state is set at once, while ANGLE tracks separate dirty
// bits: ENABLED, FUNCS, and EQUATIONS. Merge all three of them to the first one.
constexpr gl::State::DirtyBits checkBlendBitsMask(
angle::Bit<gl::State::DirtyBits::value_type>(gl::State::DIRTY_BIT_BLEND_ENABLED) |
angle::Bit<gl::State::DirtyBits::value_type>(gl::State::DIRTY_BIT_BLEND_FUNCS) |
angle::Bit<gl::State::DirtyBits::value_type>(gl::State::DIRTY_BIT_BLEND_EQUATIONS));
constexpr gl::State::DirtyBits resetBlendBitsMask(
angle::Bit<gl::State::DirtyBits::value_type>(gl::State::DIRTY_BIT_BLEND_FUNCS) |
angle::Bit<gl::State::DirtyBits::value_type>(gl::State::DIRTY_BIT_BLEND_EQUATIONS));
gl::State::DirtyBits mergedDirtyBits = gl::State::DirtyBits(dirtyBits) & ~resetBlendBitsMask;
mergedDirtyBits.set(gl::State::DIRTY_BIT_BLEND_ENABLED, (dirtyBits & checkBlendBitsMask).any());
for (size_t dirtyBit : mergedDirtyBits)
{ {
switch (dirtyBit) switch (dirtyBit)
{ {
...@@ -856,21 +875,19 @@ angle::Result ContextMtl::syncState(const gl::Context *context, ...@@ -856,21 +875,19 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
mDirtyBits.set(DIRTY_BIT_BLEND_COLOR); mDirtyBits.set(DIRTY_BIT_BLEND_COLOR);
break; break;
case gl::State::DIRTY_BIT_BLEND_ENABLED: case gl::State::DIRTY_BIT_BLEND_ENABLED:
mBlendDesc.updateBlendEnabled(glState.getBlendState()); updateBlendDescArray(glState.getBlendStateExt());
invalidateRenderPipeline();
break;
case gl::State::DIRTY_BIT_BLEND_FUNCS:
mBlendDesc.updateBlendFactors(glState.getBlendState());
invalidateRenderPipeline();
break;
case gl::State::DIRTY_BIT_BLEND_EQUATIONS:
mBlendDesc.updateBlendOps(glState.getBlendState());
invalidateRenderPipeline();
break; break;
case gl::State::DIRTY_BIT_COLOR_MASK: case gl::State::DIRTY_BIT_COLOR_MASK:
mBlendDesc.updateWriteMask(glState.getBlendState()); {
const gl::BlendStateExt &blendStateExt = glState.getBlendStateExt();
for (size_t i = 0; i < mBlendDescArray.size(); i++)
{
mBlendDescArray[i].updateWriteMask(blendStateExt.getColorMaskIndexed(i));
mWriteMaskArray[i] = mBlendDescArray[i].writeMask;
}
invalidateRenderPipeline(); invalidateRenderPipeline();
break; break;
}
case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED: case gl::State::DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED:
invalidateRenderPipeline(); invalidateRenderPipeline();
break; break;
...@@ -1299,9 +1316,9 @@ const mtl::ClearColorValue &ContextMtl::getClearColorValue() const ...@@ -1299,9 +1316,9 @@ const mtl::ClearColorValue &ContextMtl::getClearColorValue() const
{ {
return mClearColor; return mClearColor;
} }
MTLColorWriteMask ContextMtl::getColorMask() const const mtl::WriteMaskArray &ContextMtl::getWriteMaskArray() const
{ {
return mBlendDesc.writeMask; return mWriteMaskArray;
} }
float ContextMtl::getClearDepthValue() const float ContextMtl::getClearDepthValue() const
{ {
...@@ -1567,6 +1584,37 @@ void ContextMtl::updateDepthRange(float nearPlane, float farPlane) ...@@ -1567,6 +1584,37 @@ void ContextMtl::updateDepthRange(float nearPlane, float farPlane)
invalidateDriverUniforms(); invalidateDriverUniforms();
} }
void ContextMtl::updateBlendDescArray(const gl::BlendStateExt &blendStateExt)
{
for (size_t i = 0; i < mBlendDescArray.size(); i++)
{
mtl::BlendDesc &blendDesc = mBlendDescArray[i];
if (blendStateExt.mEnabledMask.test(i))
{
blendDesc.blendingEnabled = true;
blendDesc.sourceRGBBlendFactor =
mtl::GetBlendFactor(blendStateExt.getSrcColorIndexed(i));
blendDesc.sourceAlphaBlendFactor =
mtl::GetBlendFactor(blendStateExt.getSrcAlphaIndexed(i));
blendDesc.destinationRGBBlendFactor =
mtl::GetBlendFactor(blendStateExt.getDstColorIndexed(i));
blendDesc.destinationAlphaBlendFactor =
mtl::GetBlendFactor(blendStateExt.getDstAlphaIndexed(i));
blendDesc.rgbBlendOperation = mtl::GetBlendOp(blendStateExt.getEquationColorIndexed(i));
blendDesc.alphaBlendOperation =
mtl::GetBlendOp(blendStateExt.getEquationAlphaIndexed(i));
}
else
{
// Enforce default state when blending is disabled,
blendDesc.reset(blendDesc.writeMask);
}
}
invalidateRenderPipeline();
}
void ContextMtl::updateScissor(const gl::State &glState) void ContextMtl::updateScissor(const gl::State &glState)
{ {
FramebufferMtl *framebufferMtl = mtl::GetImpl(glState.getDrawFramebuffer()); FramebufferMtl *framebufferMtl = mtl::GetImpl(glState.getDrawFramebuffer());
...@@ -2209,7 +2257,7 @@ angle::Result ContextMtl::checkIfPipelineChanged(const gl::Context *context, ...@@ -2209,7 +2257,7 @@ angle::Result ContextMtl::checkIfPipelineChanged(const gl::Context *context,
{ {
const mtl::RenderPassDesc &renderPassDesc = mRenderEncoder.renderPassDesc(); const mtl::RenderPassDesc &renderPassDesc = mRenderEncoder.renderPassDesc();
// Obtain RenderPipelineDesc's output descriptor. // Obtain RenderPipelineDesc's output descriptor.
renderPassDesc.populateRenderPipelineOutputDesc(mBlendDesc, renderPassDesc.populateRenderPipelineOutputDesc(mBlendDescArray,
&mRenderPipelineDesc.outputDescriptor); &mRenderPipelineDesc.outputDescriptor);
if (xfbPass) if (xfbPass)
......
...@@ -626,6 +626,8 @@ void DisplayMtl::initializeExtensions() const ...@@ -626,6 +626,8 @@ void DisplayMtl::initializeExtensions() const
mNativeExtensions.mapBufferRange = true; mNativeExtensions.mapBufferRange = true;
mNativeExtensions.textureStorage = true; mNativeExtensions.textureStorage = true;
mNativeExtensions.drawBuffers = true; mNativeExtensions.drawBuffers = true;
mNativeExtensions.drawBuffersIndexedEXT = true;
mNativeExtensions.drawBuffersIndexedOES = true;
mNativeExtensions.fragDepth = true; mNativeExtensions.fragDepth = true;
mNativeExtensions.framebufferBlitANGLE = true; mNativeExtensions.framebufferBlitANGLE = true;
mNativeExtensions.framebufferMultisample = true; mNativeExtensions.framebufferMultisample = true;
......
...@@ -456,10 +456,10 @@ angle::Result FramebufferMtl::blitWithDraw(const gl::Context *context, ...@@ -456,10 +456,10 @@ angle::Result FramebufferMtl::blitWithDraw(const gl::Context *context,
colorBlitParams.srcLevel = srcColorRt->getLevelIndex(); colorBlitParams.srcLevel = srcColorRt->getLevelIndex();
colorBlitParams.srcLayer = srcColorRt->getLayerIndex(); colorBlitParams.srcLayer = srcColorRt->getLayerIndex();
colorBlitParams.blitColorMask = contextMtl->getColorMask(); colorBlitParams.blitWriteMaskArray = contextMtl->getWriteMaskArray();
colorBlitParams.enabledBuffers = getState().getEnabledDrawBuffers(); colorBlitParams.enabledBuffers = getState().getEnabledDrawBuffers();
colorBlitParams.filter = filter; colorBlitParams.filter = filter;
colorBlitParams.dstLuminance = srcColorRt->getFormat()->actualAngleFormat().isLUMA(); colorBlitParams.dstLuminance = srcColorRt->getFormat()->actualAngleFormat().isLUMA();
ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitColorWithDraw( ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitColorWithDraw(
context, renderEncoder, srcColorRt->getFormat()->actualAngleFormat(), colorBlitParams)); context, renderEncoder, srcColorRt->getFormat()->actualAngleFormat(), colorBlitParams));
...@@ -1042,6 +1042,8 @@ angle::Result FramebufferMtl::clearWithDraw(const gl::Context *context, ...@@ -1042,6 +1042,8 @@ angle::Result FramebufferMtl::clearWithDraw(const gl::Context *context,
continue; continue;
} }
overrideClearOps.clearWriteMaskArray[0] = overrideClearOps.clearWriteMaskArray[drawbuffer];
mtl::RenderCommandEncoder *encoder = mtl::RenderCommandEncoder *encoder =
contextMtl->getRenderTargetCommandEncoder(*renderTarget); contextMtl->getRenderTargetCommandEncoder(*renderTarget);
ANGLE_TRY(display->getUtils().clearWithDraw(context, encoder, overrideClearOps)); ANGLE_TRY(display->getUtils().clearWithDraw(context, encoder, overrideClearOps));
...@@ -1078,8 +1080,8 @@ angle::Result FramebufferMtl::clearImpl(const gl::Context *context, ...@@ -1078,8 +1080,8 @@ angle::Result FramebufferMtl::clearImpl(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
clearOpts.clearColorMask = contextMtl->getColorMask(); clearOpts.clearWriteMaskArray = contextMtl->getWriteMaskArray();
uint32_t stencilMask = contextMtl->getStencilMask(); uint32_t stencilMask = contextMtl->getStencilMask();
if (!contextMtl->getDepthMask()) if (!contextMtl->getDepthMask())
{ {
// Disable depth clearing, since depth write is disable // Disable depth clearing, since depth write is disable
...@@ -1089,8 +1091,18 @@ angle::Result FramebufferMtl::clearImpl(const gl::Context *context, ...@@ -1089,8 +1091,18 @@ angle::Result FramebufferMtl::clearImpl(const gl::Context *context,
// Only clear enabled buffers // Only clear enabled buffers
clearOpts.enabledBuffers = clearColorBuffers; clearOpts.enabledBuffers = clearColorBuffers;
bool allBuffersUnmasked = true;
for (size_t enabledBuffer : clearColorBuffers)
{
if (clearOpts.clearWriteMaskArray[enabledBuffer] != MTLColorWriteMaskAll)
{
allBuffersUnmasked = false;
break;
}
}
if (clearOpts.clearArea == renderArea && if (clearOpts.clearArea == renderArea &&
(!clearOpts.clearColor.valid() || clearOpts.clearColorMask == MTLColorWriteMaskAll) && (!clearOpts.clearColor.valid() || allBuffersUnmasked) &&
(!clearOpts.clearStencil.valid() || (!clearOpts.clearStencil.valid() ||
(stencilMask & mtl::kStencilMaskAll) == mtl::kStencilMaskAll)) (stencilMask & mtl::kStencilMaskAll) == mtl::kStencilMaskAll))
{ {
......
...@@ -32,11 +32,13 @@ namespace mtl ...@@ -32,11 +32,13 @@ namespace mtl
struct ClearRectParams struct ClearRectParams
{ {
ClearRectParams() { clearWriteMaskArray.fill(MTLColorWriteMaskAll); }
Optional<ClearColorValue> clearColor; Optional<ClearColorValue> clearColor;
Optional<float> clearDepth; Optional<float> clearDepth;
Optional<uint32_t> clearStencil; Optional<uint32_t> clearStencil;
MTLColorWriteMask clearColorMask = MTLColorWriteMaskAll; WriteMaskArray clearWriteMaskArray;
const mtl::Format *colorFormat = nullptr; const mtl::Format *colorFormat = nullptr;
gl::Extents dstTextureSize; gl::Extents dstTextureSize;
...@@ -78,7 +80,9 @@ struct BlitParams ...@@ -78,7 +80,9 @@ struct BlitParams
struct ColorBlitParams : public BlitParams struct ColorBlitParams : public BlitParams
{ {
MTLColorWriteMask blitColorMask = MTLColorWriteMaskAll; ColorBlitParams() { blitWriteMaskArray.fill(MTLColorWriteMaskAll); }
WriteMaskArray blitWriteMaskArray;
gl::DrawBufferMask enabledBuffers; gl::DrawBufferMask enabledBuffers;
GLenum filter = GL_NEAREST; GLenum filter = GL_NEAREST;
bool unpackPremultiplyAlpha = false; bool unpackPremultiplyAlpha = false;
......
...@@ -1211,16 +1211,16 @@ id<MTLRenderPipelineState> ClearUtils::getClearRenderPipelineState(const gl::Con ...@@ -1211,16 +1211,16 @@ id<MTLRenderPipelineState> ClearUtils::getClearRenderPipelineState(const gl::Con
{ {
ContextMtl *contextMtl = GetImpl(context); ContextMtl *contextMtl = GetImpl(context);
// The color mask to be applied to every color attachment: // The color mask to be applied to every color attachment:
MTLColorWriteMask globalColorMask = params.clearColorMask; WriteMaskArray clearWriteMaskArray = params.clearWriteMaskArray;
if (!params.clearColor.valid()) if (!params.clearColor.valid())
{ {
globalColorMask = MTLColorWriteMaskNone; clearWriteMaskArray.fill(MTLColorWriteMaskNone);
} }
RenderPipelineDesc pipelineDesc; RenderPipelineDesc pipelineDesc;
const RenderPassDesc &renderPassDesc = cmdEncoder->renderPassDesc(); const RenderPassDesc &renderPassDesc = cmdEncoder->renderPassDesc();
renderPassDesc.populateRenderPipelineOutputDesc(globalColorMask, renderPassDesc.populateRenderPipelineOutputDesc(clearWriteMaskArray,
&pipelineDesc.outputDescriptor); &pipelineDesc.outputDescriptor);
// Disable clear for some outputs that are not enabled // Disable clear for some outputs that are not enabled
...@@ -1404,7 +1404,7 @@ id<MTLRenderPipelineState> ColorBlitUtils::getColorBlitRenderPipelineState( ...@@ -1404,7 +1404,7 @@ id<MTLRenderPipelineState> ColorBlitUtils::getColorBlitRenderPipelineState(
RenderPipelineDesc pipelineDesc; RenderPipelineDesc pipelineDesc;
const RenderPassDesc &renderPassDesc = cmdEncoder->renderPassDesc(); const RenderPassDesc &renderPassDesc = cmdEncoder->renderPassDesc();
renderPassDesc.populateRenderPipelineOutputDesc(params.blitColorMask, renderPassDesc.populateRenderPipelineOutputDesc(params.blitWriteMaskArray,
&pipelineDesc.outputDescriptor); &pipelineDesc.outputDescriptor);
// Disable blit for some outputs that are not enabled // Disable blit for some outputs that are not enabled
......
...@@ -163,10 +163,7 @@ struct BlendDesc ...@@ -163,10 +163,7 @@ struct BlendDesc
void reset(); void reset();
void reset(MTLColorWriteMask writeMask); void reset(MTLColorWriteMask writeMask);
void updateWriteMask(const gl::BlendState &blendState); void updateWriteMask(const uint8_t angleMask);
void updateBlendFactors(const gl::BlendState &blendState);
void updateBlendOps(const gl::BlendState &blendState);
void updateBlendEnabled(const gl::BlendState &blendState);
// Use uint8_t instead of MTLColorWriteMask to compact space // Use uint8_t instead of MTLColorWriteMask to compact space
uint8_t writeMask : 4; uint8_t writeMask : 4;
...@@ -185,6 +182,9 @@ struct BlendDesc ...@@ -185,6 +182,9 @@ struct BlendDesc
bool blendingEnabled : 1; bool blendingEnabled : 1;
}; };
using BlendDescArray = std::array<BlendDesc, kMaxRenderTargets>;
using WriteMaskArray = std::array<uint8_t, kMaxRenderTargets>;
struct alignas(2) RenderPipelineColorAttachmentDesc : public BlendDesc struct alignas(2) RenderPipelineColorAttachmentDesc : public BlendDesc
{ {
bool operator==(const RenderPipelineColorAttachmentDesc &rhs) const; bool operator==(const RenderPipelineColorAttachmentDesc &rhs) const;
...@@ -197,9 +197,9 @@ struct alignas(2) RenderPipelineColorAttachmentDesc : public BlendDesc ...@@ -197,9 +197,9 @@ struct alignas(2) RenderPipelineColorAttachmentDesc : public BlendDesc
void reset(); void reset();
void reset(MTLPixelFormat format); void reset(MTLPixelFormat format);
void reset(MTLPixelFormat format, MTLColorWriteMask writeMask); void reset(MTLPixelFormat format, MTLColorWriteMask writeMask);
void reset(MTLPixelFormat format, const BlendDesc &blendState); void reset(MTLPixelFormat format, const BlendDesc &blendDesc);
void update(const BlendDesc &blendState); void update(const BlendDesc &blendDesc);
// Use uint16_t instead of MTLPixelFormat to compact space // Use uint16_t instead of MTLPixelFormat to compact space
uint16_t pixelFormat : 16; uint16_t pixelFormat : 16;
...@@ -367,10 +367,10 @@ struct RenderPassDesc ...@@ -367,10 +367,10 @@ struct RenderPassDesc
void populateRenderPipelineOutputDesc(RenderPipelineOutputDesc *outDesc) const; void populateRenderPipelineOutputDesc(RenderPipelineOutputDesc *outDesc) const;
// This will populate the RenderPipelineOutputDesc with default blend state and the specified // This will populate the RenderPipelineOutputDesc with default blend state and the specified
// MTLColorWriteMask // MTLColorWriteMask
void populateRenderPipelineOutputDesc(MTLColorWriteMask colorWriteMask, void populateRenderPipelineOutputDesc(const WriteMaskArray &writeMaskArray,
RenderPipelineOutputDesc *outDesc) const; RenderPipelineOutputDesc *outDesc) const;
// This will populate the RenderPipelineOutputDesc with the specified blend state // This will populate the RenderPipelineOutputDesc with the specified blend state
void populateRenderPipelineOutputDesc(const BlendDesc &blendState, void populateRenderPipelineOutputDesc(const BlendDescArray &blendDescArray,
RenderPipelineOutputDesc *outDesc) const; RenderPipelineOutputDesc *outDesc) const;
bool equalIgnoreLoadStoreOptions(const RenderPassDesc &other) const; bool equalIgnoreLoadStoreOptions(const RenderPassDesc &other) const;
......
...@@ -535,44 +535,33 @@ void BlendDesc::reset(MTLColorWriteMask _writeMask) ...@@ -535,44 +535,33 @@ void BlendDesc::reset(MTLColorWriteMask _writeMask)
sourceAlphaBlendFactor = sourceRGBBlendFactor = MTLBlendFactorOne; sourceAlphaBlendFactor = sourceRGBBlendFactor = MTLBlendFactorOne;
} }
void BlendDesc::updateWriteMask(const gl::BlendState &blendState) void BlendDesc::updateWriteMask(const uint8_t angleMask)
{ {
writeMask = MTLColorWriteMaskNone; ASSERT(angleMask == (angleMask & 0xF));
if (blendState.colorMaskRed)
{ // ANGLE's packed color mask is abgr (matches Vulkan & D3D11), while Metal expects rgba.
writeMask |= MTLColorWriteMaskRed; #if defined(__aarch64__)
} // ARM64 can reverse bits in a single instruction
if (blendState.colorMaskGreen) writeMask = __builtin_bitreverse8(angleMask) >> 4;
{ #else
writeMask |= MTLColorWriteMaskGreen; /* On other architectures, Clang generates a polyfill that uses more
} instructions than the following expression optimized for a 4-bit value.
if (blendState.colorMaskBlue)
{ (abgr * 0x41) & 0x14A:
writeMask |= MTLColorWriteMaskBlue; .......abgr +
} .abgr...... &
if (blendState.colorMaskAlpha) 00101001010 =
{ ..b.r..a.g.
writeMask |= MTLColorWriteMaskAlpha;
} (b.r..a.g.) * 0x111:
} b.r..a.g. +
b.r..a.g..... +
void BlendDesc::updateBlendFactors(const gl::BlendState &blendState) b.r..a.g......... =
{ b.r.bargbarg.a.g.
sourceRGBBlendFactor = GetBlendFactor(blendState.sourceBlendRGB); ^^^^
sourceAlphaBlendFactor = GetBlendFactor(blendState.sourceBlendAlpha); */
destinationRGBBlendFactor = GetBlendFactor(blendState.destBlendRGB); writeMask = ((((angleMask * 0x41) & 0x14A) * 0x111) >> 7) & 0xF;
destinationAlphaBlendFactor = GetBlendFactor(blendState.destBlendAlpha); #endif
}
void BlendDesc::updateBlendOps(const gl::BlendState &blendState)
{
rgbBlendOperation = GetBlendOp(blendState.blendEquationRGB);
alphaBlendOperation = GetBlendOp(blendState.blendEquationAlpha);
}
void BlendDesc::updateBlendEnabled(const gl::BlendState &blendState)
{
blendingEnabled = blendState.blend;
} }
// RenderPipelineColorAttachmentDesc implementation // RenderPipelineColorAttachmentDesc implementation
...@@ -603,16 +592,16 @@ void RenderPipelineColorAttachmentDesc::reset(MTLPixelFormat format, MTLColorWri ...@@ -603,16 +592,16 @@ void RenderPipelineColorAttachmentDesc::reset(MTLPixelFormat format, MTLColorWri
BlendDesc::reset(_writeMask); BlendDesc::reset(_writeMask);
} }
void RenderPipelineColorAttachmentDesc::reset(MTLPixelFormat format, const BlendDesc &blendState) void RenderPipelineColorAttachmentDesc::reset(MTLPixelFormat format, const BlendDesc &blendDesc)
{ {
this->pixelFormat = format; this->pixelFormat = format;
BlendDesc::operator=(blendState); BlendDesc::operator=(blendDesc);
} }
void RenderPipelineColorAttachmentDesc::update(const BlendDesc &blendState) void RenderPipelineColorAttachmentDesc::update(const BlendDesc &blendDesc)
{ {
BlendDesc::operator=(blendState); BlendDesc::operator=(blendDesc);
} }
// RenderPipelineOutputDesc implementation // RenderPipelineOutputDesc implementation
...@@ -726,20 +715,24 @@ bool RenderPassAttachmentDesc::operator==(const RenderPassAttachmentDesc &other) ...@@ -726,20 +715,24 @@ bool RenderPassAttachmentDesc::operator==(const RenderPassAttachmentDesc &other)
void RenderPassDesc::populateRenderPipelineOutputDesc(RenderPipelineOutputDesc *outDesc) const void RenderPassDesc::populateRenderPipelineOutputDesc(RenderPipelineOutputDesc *outDesc) const
{ {
populateRenderPipelineOutputDesc(MTLColorWriteMaskAll, outDesc); WriteMaskArray writeMaskArray;
writeMaskArray.fill(MTLColorWriteMaskAll);
populateRenderPipelineOutputDesc(writeMaskArray, outDesc);
} }
void RenderPassDesc::populateRenderPipelineOutputDesc(MTLColorWriteMask colorWriteMask, void RenderPassDesc::populateRenderPipelineOutputDesc(const WriteMaskArray &writeMaskArray,
RenderPipelineOutputDesc *outDesc) const RenderPipelineOutputDesc *outDesc) const
{ {
// Default blend state. // Default blend state with replaced color write masks.
BlendDesc blendState; BlendDescArray blendDescArray;
blendState.reset(colorWriteMask); for (size_t i = 0; i < blendDescArray.size(); i++)
{
populateRenderPipelineOutputDesc(blendState, outDesc); blendDescArray[i].reset(writeMaskArray[i]);
}
populateRenderPipelineOutputDesc(blendDescArray, outDesc);
} }
void RenderPassDesc::populateRenderPipelineOutputDesc(const BlendDesc &blendState, void RenderPassDesc::populateRenderPipelineOutputDesc(const BlendDescArray &blendDescArray,
RenderPipelineOutputDesc *outDesc) const RenderPipelineOutputDesc *outDesc) const
{ {
RenderPipelineOutputDesc &outputDescriptor = *outDesc; RenderPipelineOutputDesc &outputDescriptor = *outDesc;
...@@ -752,16 +745,20 @@ void RenderPassDesc::populateRenderPipelineOutputDesc(const BlendDesc &blendStat ...@@ -752,16 +745,20 @@ void RenderPassDesc::populateRenderPipelineOutputDesc(const BlendDesc &blendStat
if (texture) if (texture)
{ {
// Copy parameters from blend state if (renderPassColorAttachment.blendable)
outputDescriptor.colorAttachments[i].update(blendState); {
if (!renderPassColorAttachment.blendable) // Copy parameters from blend state
outputDescriptor.colorAttachments[i].reset(texture->pixelFormat(),
blendDescArray[i]);
}
else
{ {
// Disable blending if the attachment's render target doesn't support blending. // Disable blending if the attachment's render target doesn't support blending.
outputDescriptor.colorAttachments[i].blendingEnabled = false; // Force default blending state to reduce the number of unique states.
outputDescriptor.colorAttachments[i].reset(texture->pixelFormat(),
blendDescArray[i].writeMask);
} }
outputDescriptor.colorAttachments[i].pixelFormat = texture->pixelFormat();
// Combine the masks. This is useful when the texture is not supposed to have alpha // Combine the masks. This is useful when the texture is not supposed to have alpha
// channel such as GL_RGB8, however, Metal doesn't natively support 24 bit RGB, so // channel such as GL_RGB8, however, Metal doesn't natively support 24 bit RGB, so
// we need to use RGBA texture, and then disable alpha write to this texture // we need to use RGBA texture, and then disable alpha write to this texture
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment