Commit 80d4901a by Le Hoang Quyen Committed by Commit Bot

Metal: Support integer textures.

Bug: angleproject:2634 Bug: angleproject:5154 Change-Id: Iffea26fe2c683557b4fa7c13fddf3523294b47d4 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2433329 Commit-Queue: Le Hoang Quyen <le.hoang.q@gmail.com> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 96714af8
......@@ -297,7 +297,7 @@ class ContextMtl : public ContextImpl, public mtl::Context
void queueEventSignal(const mtl::SharedEventRef &event, uint64_t value);
void serverWaitEvent(const mtl::SharedEventRef &event, uint64_t value);
const MTLClearColor &getClearColorValue() const;
const mtl::ClearColorValue &getClearColorValue() const;
MTLColorWriteMask getColorMask() const;
float getClearDepthValue() const;
uint32_t getClearStencilValue() const;
......@@ -529,7 +529,7 @@ class ContextMtl : public ContextImpl, public mtl::Context
mtl::RenderPipelineDesc mRenderPipelineDesc;
mtl::DepthStencilDesc mDepthStencilDesc;
mtl::BlendDesc mBlendDesc;
MTLClearColor mClearColor;
mtl::ClearColorValue mClearColor;
uint32_t mClearStencil = 0;
uint32_t mStencilRefFront = 0;
uint32_t mStencilRefBack = 0;
......
......@@ -780,10 +780,9 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
// NOTE(hqle): ES 3.0 feature.
break;
case gl::State::DIRTY_BIT_CLEAR_COLOR:
mClearColor.red = glState.getColorClearValue().red;
mClearColor.green = glState.getColorClearValue().green;
mClearColor.blue = glState.getColorClearValue().blue;
mClearColor.alpha = glState.getColorClearValue().alpha;
mClearColor = mtl::ClearColorValue(
glState.getColorClearValue().red, glState.getColorClearValue().green,
glState.getColorClearValue().blue, glState.getColorClearValue().alpha);
break;
case gl::State::DIRTY_BIT_CLEAR_DEPTH:
break;
......@@ -1123,7 +1122,7 @@ void ContextMtl::invalidateRenderPipeline()
mDirtyBits.set(DIRTY_BIT_RENDER_PIPELINE);
}
const MTLClearColor &ContextMtl::getClearColorValue() const
const mtl::ClearColorValue &ContextMtl::getClearColorValue() const
{
return mClearColor;
}
......
......@@ -120,6 +120,7 @@ class FramebufferMtl : public FramebufferImpl
private:
void reset();
bool checkPackedDepthStencilAttachment() const;
angle::Result invalidateImpl(ContextMtl *contextMtl, size_t count, const GLenum *attachments);
angle::Result blitWithDraw(const gl::Context *context,
FramebufferMtl *srcFrameBuffer,
......@@ -161,10 +162,6 @@ class FramebufferMtl : public FramebufferImpl
mtl::RenderCommandEncoder *ensureRenderPassStarted(const gl::Context *context,
const mtl::RenderPassDesc &desc);
void overrideClearColor(const mtl::TextureRef &texture,
MTLClearColor clearColor,
MTLClearColor *colorOut);
angle::Result updateColorRenderTarget(const gl::Context *context, size_t colorIndexGL);
angle::Result updateDepthRenderTarget(const gl::Context *context);
angle::Result updateStencilRenderTarget(const gl::Context *context);
......@@ -185,6 +182,9 @@ class FramebufferMtl : public FramebufferImpl
RenderTargetMtl *mStencilRenderTarget = nullptr;
mtl::RenderPassDesc mRenderPassDesc;
const mtl::Format *mRenderPassFirstColorAttachmentFormat = nullptr;
bool mRenderPassAttachmentsSameColorType = false;
// Flag indicating the render pass start is a clean start or a resume from interruption such
// as by a compute pass.
bool mRenderPassCleanStart = false;
......
......@@ -77,5 +77,6 @@ void RenderTargetMtl::toRenderPassAttachmentDesc(mtl::RenderPassAttachmentDesc *
rpaDescOut->implicitMSTexture = mImplicitMSTexture.lock();
rpaDescOut->level = mLevelIndex;
rpaDescOut->sliceOrDepth = mLayerIndex;
rpaDescOut->blendable = mFormat ? mFormat->getCaps().blendable : false;
}
}
......@@ -546,8 +546,8 @@ angle::Result SurfaceMtl::resolveColorTextureIfNeeded(const gl::Context *context
mColorFormat);
mtl::RenderCommandEncoder *encoder =
contextMtl->getRenderTargetCommandEncoder(mColorManualResolveRenderTarget);
ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitColorWithDraw(context, encoder,
mMSColorTexture));
ANGLE_TRY(contextMtl->getDisplay()->getUtils().blitColorWithDraw(
context, encoder, mColorFormat.actualAngleFormat(), mMSColorTexture));
contextMtl->endEncoding(true);
mColorManualResolveRenderTarget.reset();
}
......
......@@ -1780,7 +1780,8 @@ angle::Result TextureMtl::copySubImageWithDraw(const gl::Context *context,
blitParams.srcYFlipped = framebufferMtl->flipY();
blitParams.dstLuminance = internalFormat.isLUMA();
return displayMtl->getUtils().blitColorWithDraw(context, cmdEncoder, blitParams);
return displayMtl->getUtils().blitColorWithDraw(
context, cmdEncoder, colorReadRT->getFormat()->actualAngleFormat(), blitParams);
}
angle::Result TextureMtl::copySubImageCPU(const gl::Context *context,
......@@ -1937,7 +1938,8 @@ angle::Result TextureMtl::copySubTextureWithDraw(const gl::Context *context,
blitParams.unpackPremultiplyAlpha = unpackPremultiplyAlpha;
blitParams.unpackUnmultiplyAlpha = unpackUnmultiplyAlpha;
return displayMtl->getUtils().blitColorWithDraw(context, cmdEncoder, blitParams);
return displayMtl->getUtils().copyTextureWithDraw(context, cmdEncoder, sourceAngleFormat,
mFormat.actualAngleFormat(), blitParams);
}
angle::Result TextureMtl::copySubTextureCPU(const gl::Context *context,
......
......@@ -156,7 +156,7 @@ constexpr uint32_t kStencilMaskAll = 0xff; // Only 8 bits stencil is supported
constexpr MTLVertexStepFunction kVertexStepFunctionInvalid =
static_cast<MTLVertexStepFunction>(0xff);
constexpr float kEmulatedAlphaValue = 1.0f;
constexpr int kEmulatedAlphaValue = 1;
constexpr size_t kOcclusionQueryResultSize = sizeof(uint64_t);
......@@ -404,11 +404,59 @@ class ImageNativeIndexIterator final
gl::ImageIndexIterator mNativeIndexIte;
};
struct ClearOptions
using ClearColorValueBytes = std::array<uint8_t, 4 * sizeof(float)>;
class ClearColorValue
{
Optional<MTLClearColor> clearColor;
Optional<float> clearDepth;
Optional<uint32_t> clearStencil;
public:
constexpr ClearColorValue()
: mType(PixelType::Float), mRedF(0), mGreenF(0), mBlueF(0), mAlphaF(0)
{}
constexpr ClearColorValue(float r, float g, float b, float a)
: mType(PixelType::Float), mRedF(r), mGreenF(g), mBlueF(b), mAlphaF(a)
{}
constexpr ClearColorValue(int32_t r, int32_t g, int32_t b, int32_t a)
: mType(PixelType::Int), mRedI(r), mGreenI(g), mBlueI(b), mAlphaI(a)
{}
constexpr ClearColorValue(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
: mType(PixelType::UInt), mRedU(r), mGreenU(g), mBlueU(b), mAlphaU(a)
{}
constexpr ClearColorValue(const ClearColorValue &src)
: mType(src.mType), mValueBytes(src.mValueBytes)
{}
MTLClearColor toMTLClearColor() const;
PixelType getType() const { return mType; }
const ClearColorValueBytes &getValueBytes() const { return mValueBytes; }
ClearColorValue &operator=(const ClearColorValue &src);
void setAsFloat(float r, float g, float b, float a);
void setAsInt(int32_t r, int32_t g, int32_t b, int32_t a);
void setAsUInt(uint32_t r, uint32_t g, uint32_t b, uint32_t a);
private:
PixelType mType;
union
{
struct
{
float mRedF, mGreenF, mBlueF, mAlphaF;
};
struct
{
int32_t mRedI, mGreenI, mBlueI, mAlphaI;
};
struct
{
uint32_t mRedU, mGreenU, mBlueU, mAlphaU;
};
ClearColorValueBytes mValueBytes;
};
};
class CommandQueue;
......
......@@ -21,6 +21,58 @@ namespace rx
namespace mtl
{
// ClearColorValue implementation
ClearColorValue &ClearColorValue::operator=(const ClearColorValue &src)
{
mType = src.mType;
mValueBytes = src.mValueBytes;
return *this;
}
void ClearColorValue::setAsFloat(float r, float g, float b, float a)
{
mType = PixelType::Float;
mRedF = r;
mGreenF = g;
mBlueF = b;
mAlphaF = a;
}
void ClearColorValue::setAsInt(int32_t r, int32_t g, int32_t b, int32_t a)
{
mType = PixelType::Int;
mRedI = r;
mGreenI = g;
mBlueI = b;
mAlphaI = a;
}
void ClearColorValue::setAsUInt(uint32_t r, uint32_t g, uint32_t b, uint32_t a)
{
mType = PixelType::UInt;
mRedU = r;
mGreenU = g;
mBlueU = b;
mAlphaU = a;
}
MTLClearColor ClearColorValue::toMTLClearColor() const
{
switch (mType)
{
case PixelType::Int:
return MTLClearColorMake(mRedI, mGreenI, mBlueI, mAlphaI);
case PixelType::UInt:
return MTLClearColorMake(mRedU, mGreenU, mBlueU, mAlphaU);
case PixelType::Float:
return MTLClearColorMake(mRedF, mGreenF, mBlueF, mAlphaF);
default:
UNREACHABLE();
return MTLClearColorMake(0, 0, 0, 0);
}
}
// ImageNativeIndex implementation
ImageNativeIndexIterator ImageNativeIndex::getLayerIterator(GLint layerCount) const
{
......
......@@ -29,10 +29,16 @@ class VisibilityBufferOffsetsMtl;
namespace mtl
{
struct ClearRectParams : public ClearOptions
struct ClearRectParams
{
Optional<ClearColorValue> clearColor;
Optional<float> clearDepth;
Optional<uint32_t> clearStencil;
MTLColorWriteMask clearColorMask = MTLColorWriteMaskAll;
const mtl::Format *colorFormat = nullptr;
gl::Extents dstTextureSize;
// Only clear enabled buffers
......@@ -159,7 +165,9 @@ struct CopyPixelsToBufferParams : CopyPixelsCommonParams
class ClearUtils final : angle::NonCopyable
{
public:
ClearUtils();
ClearUtils() = delete;
ClearUtils(const std::string &fragmentShaderName);
ClearUtils(const ClearUtils &src);
void onDestroy();
......@@ -180,6 +188,8 @@ class ClearUtils final : angle::NonCopyable
RenderCommandEncoder *cmdEncoder,
const ClearRectParams &params);
const std::string mFragmentShaderName;
// Render pipeline cache for clear with draw:
std::array<RenderPipelineCache, kMaxRenderTargets + 1> mClearRenderPipelineCache;
};
......@@ -187,7 +197,9 @@ class ClearUtils final : angle::NonCopyable
class ColorBlitUtils final : angle::NonCopyable
{
public:
ColorBlitUtils();
ColorBlitUtils() = delete;
ColorBlitUtils(const std::string &fragmentShaderName);
ColorBlitUtils(const ColorBlitUtils &src);
void onDestroy();
......@@ -211,6 +223,8 @@ class ColorBlitUtils final : angle::NonCopyable
RenderCommandEncoder *cmdEncoder,
const ColorBlitParams &params);
const std::string mFragmentShaderName;
// Blit with draw pipeline caches:
// First array dimension: number of outputs.
// Second array dimension: source texture type (2d, ms, array, 3d, etc)
......@@ -230,6 +244,7 @@ class DepthStencilBlitUtils final : angle::NonCopyable
angle::Result blitDepthStencilWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const DepthStencilBlitParams &params);
// Blit stencil data using intermediate buffer. This function is used on devices with no
// support for direct stencil write in shader. Thus an intermediate buffer storing copied
// stencil data is needed.
......@@ -431,12 +446,19 @@ class RenderUtils : public Context, angle::NonCopyable
// Blit texture data to current framebuffer
angle::Result blitColorWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const angle::Format &srcAngleFormat,
const ColorBlitParams &params);
// Same as above but blit the whole texture to the whole of current framebuffer.
// This function assumes the framebuffer and the source texture have same size.
angle::Result blitColorWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const angle::Format &srcAngleFormat,
const TextureRef &srcTexture);
angle::Result copyTextureWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const angle::Format &srcAngleFormat,
const angle::Format &dstAngleFormat,
const ColorBlitParams &params);
angle::Result blitDepthStencilWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
......@@ -490,8 +512,11 @@ class RenderUtils : public Context, angle::NonCopyable
const char *function,
unsigned int line) override;
ClearUtils mClearUtils;
ColorBlitUtils mColorBlitUtils;
std::array<ClearUtils, angle::EnumSize<PixelType>()> mClearUtils;
std::array<ColorBlitUtils, angle::EnumSize<PixelType>()> mColorBlitUtils;
ColorBlitUtils mCopyTextureFloatToUIntUtils;
DepthStencilBlitUtils mDepthStencilBlitUtils;
IndexGeneratorUtils mIndexUtils;
VisibilityResultUtils mVisibilityResultUtils;
......
......@@ -535,6 +535,11 @@ StencilBlitViaBufferParams::StencilBlitViaBufferParams(const DepthStencilBlitPar
// RenderUtils implementation
RenderUtils::RenderUtils(DisplayMtl *display)
: Context(display),
mClearUtils(
{ClearUtils("clearIntFS"), ClearUtils("clearUIntFS"), ClearUtils("clearFloatFS")}),
mColorBlitUtils({ColorBlitUtils("blitIntFS"), ColorBlitUtils("blitUIntFS"),
ColorBlitUtils("blitFloatFS")}),
mCopyTextureFloatToUIntUtils("copyTextureFloatToUIntFS"),
mCopyPixelsUtils(
{CopyPixelsUtils("readFromBufferToIntTexture", "writeFromIntTextureToBuffer"),
CopyPixelsUtils("readFromBufferToUIntTexture", "writeFromUIntTextureToBuffer"),
......@@ -550,11 +555,20 @@ angle::Result RenderUtils::initialize()
void RenderUtils::onDestroy()
{
mIndexUtils.onDestroy();
mClearUtils.onDestroy();
mColorBlitUtils.onDestroy();
mDepthStencilBlitUtils.onDestroy();
mIndexUtils.onDestroy();
mVisibilityResultUtils.onDestroy();
mMipmapUtils.onDestroy();
mCopyTextureFloatToUIntUtils.onDestroy();
for (ClearUtils &util : mClearUtils)
{
util.onDestroy();
}
for (ColorBlitUtils &util : mColorBlitUtils)
{
util.onDestroy();
}
for (CopyPixelsUtils &util : mCopyPixelsUtils)
{
util.onDestroy();
......@@ -590,19 +604,31 @@ angle::Result RenderUtils::clearWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const ClearRectParams &params)
{
return mClearUtils.clearWithDraw(context, cmdEncoder, params);
int index = 0;
if (params.clearColor.valid())
{
index = static_cast<int>(params.clearColor.value().getType());
}
else if (params.colorFormat)
{
index = GetPixelTypeIndex(params.colorFormat->actualAngleFormat());
}
return mClearUtils[index].clearWithDraw(context, cmdEncoder, params);
}
// Blit texture data to current framebuffer
angle::Result RenderUtils::blitColorWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const angle::Format &srcAngleFormat,
const ColorBlitParams &params)
{
return mColorBlitUtils.blitColorWithDraw(context, cmdEncoder, params);
int index = GetPixelTypeIndex(srcAngleFormat);
return mColorBlitUtils[index].blitColorWithDraw(context, cmdEncoder, params);
}
angle::Result RenderUtils::blitColorWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const angle::Format &srcAngleFormat,
const TextureRef &srcTexture)
{
if (!srcTexture)
......@@ -618,7 +644,22 @@ angle::Result RenderUtils::blitColorWithDraw(const gl::Context *context,
params.dstRect = params.dstScissorRect = params.srcRect =
gl::Rectangle(0, 0, params.dstTextureSize.width, params.dstTextureSize.height);
return blitColorWithDraw(context, cmdEncoder, params);
return blitColorWithDraw(context, cmdEncoder, srcAngleFormat, params);
}
angle::Result RenderUtils::copyTextureWithDraw(const gl::Context *context,
RenderCommandEncoder *cmdEncoder,
const angle::Format &srcAngleFormat,
const angle::Format &dstAngleFormat,
const ColorBlitParams &params)
{
if (!srcAngleFormat.isInt() && dstAngleFormat.isUint())
{
return mCopyTextureFloatToUIntUtils.blitColorWithDraw(context, cmdEncoder, params);
}
ASSERT(srcAngleFormat.isSint() == dstAngleFormat.isSint() &&
srcAngleFormat.isUint() == dstAngleFormat.isUint());
return blitColorWithDraw(context, cmdEncoder, srcAngleFormat, params);
}
angle::Result RenderUtils::blitDepthStencilWithDraw(const gl::Context *context,
......@@ -705,7 +746,11 @@ angle::Result RenderUtils::packPixelsFromTextureToBuffer(ContextMtl *contextMtl,
}
// ClearUtils implementation
ClearUtils::ClearUtils() = default;
ClearUtils::ClearUtils(const std::string &fragmentShaderName)
: mFragmentShaderName(fragmentShaderName)
{}
ClearUtils::ClearUtils(const ClearUtils &src) : ClearUtils(src.mFragmentShaderName) {}
void ClearUtils::onDestroy()
{
......@@ -736,9 +781,10 @@ void ClearUtils::ensureRenderPipelineStateCacheInitialized(ContextMtl *ctx, uint
type:MTLDataTypeUInt
withName:NUM_COLOR_OUTPUTS_CONSTANT_NAME];
id<MTLFunction> fragmentShader =
[[shaderLib newFunctionWithName:@"clearFloatFS" constantValues:funcConstants
error:&err] ANGLE_MTL_AUTORELEASE];
id<MTLFunction> fragmentShader = [[shaderLib
newFunctionWithName:[NSString stringWithUTF8String:mFragmentShaderName.c_str()]
constantValues:funcConstants
error:&err] ANGLE_MTL_AUTORELEASE];
ASSERT(fragmentShader);
cache.setVertexShader(ctx, vertexShader);
......@@ -840,11 +886,15 @@ void ClearUtils::setupClearWithDraw(const gl::Context *context,
// uniform
ClearParamsUniform uniformParams;
uniformParams.clearColor[0] = static_cast<float>(params.clearColor.value().red);
uniformParams.clearColor[1] = static_cast<float>(params.clearColor.value().green);
uniformParams.clearColor[2] = static_cast<float>(params.clearColor.value().blue);
uniformParams.clearColor[3] = static_cast<float>(params.clearColor.value().alpha);
uniformParams.clearDepth = params.clearDepth.value();
const ClearColorValue &clearValue = params.clearColor.value();
// ClearColorValue is an int, uint, float union so it's safe to use only floats.
// The Shader will do the bit cast based on appropriate format type.
// See shaders/clear.metal (3 variants ClearFloatFS, ClearIntFS and ClearUIntFS each does the
// appropriate bit cast)
ASSERT(sizeof(uniformParams.clearColor) == clearValue.getValueBytes().size());
std::memcpy(uniformParams.clearColor, clearValue.getValueBytes().data(),
clearValue.getValueBytes().size());
uniformParams.clearDepth = params.clearDepth.value();
cmdEncoder->setVertexData(uniformParams, 0);
cmdEncoder->setFragmentData(uniformParams, 0);
......@@ -893,7 +943,12 @@ angle::Result ClearUtils::clearWithDraw(const gl::Context *context,
}
// ColorBlitUtils implementation
ColorBlitUtils::ColorBlitUtils() = default;
ColorBlitUtils::ColorBlitUtils(const std::string &fragmentShaderName)
: mFragmentShaderName(fragmentShaderName)
{}
ColorBlitUtils::ColorBlitUtils(const ColorBlitUtils &src) : ColorBlitUtils(src.mFragmentShaderName)
{}
void ColorBlitUtils::onDestroy()
{
......@@ -952,9 +1007,10 @@ void ColorBlitUtils::ensureRenderPipelineStateCacheInitialized(ContextMtl *ctx,
type:MTLDataTypeInt
withName:SOURCE_TEXTURE_TYPE_CONSTANT_NAME];
id<MTLFunction> fragmentShader =
[[shaderLib newFunctionWithName:@"blitFloatFS" constantValues:funcConstants
error:&err] ANGLE_MTL_AUTORELEASE];
id<MTLFunction> fragmentShader = [[shaderLib
newFunctionWithName:[NSString stringWithUTF8String:mFragmentShaderName.c_str()]
constantValues:funcConstants
error:&err] ANGLE_MTL_AUTORELEASE];
ASSERT(vertexShader);
ASSERT(fragmentShader);
......
......@@ -303,6 +303,9 @@ struct RenderPassAttachmentDesc
MipmapNativeLevel level;
uint32_t sliceOrDepth;
// This attachment is blendable or not.
bool blendable;
MTLLoadAction loadAction;
MTLStoreAction storeAction;
MTLStoreActionOptions storeActionOptions;
......
......@@ -693,6 +693,7 @@ void RenderPassAttachmentDesc::reset()
implicitMSTexture.reset();
level = mtl::kZeroNativeMipLevel;
sliceOrDepth = 0;
blendable = false;
loadAction = MTLLoadActionLoad;
storeAction = MTLStoreActionStore;
storeActionOptions = MTLStoreActionOptionNone;
......@@ -746,6 +747,11 @@ void RenderPassDesc::populateRenderPipelineOutputDesc(const BlendDesc &blendStat
{
// Copy parameters from blend state
outputDescriptor.colorAttachments[i].update(blendState);
if (!renderPassColorAttachment.blendable)
{
// Disable blending if the attachment's render target doesn't support blending.
outputDescriptor.colorAttachments[i].blendingEnabled = false;
}
outputDescriptor.colorAttachments[i].pixelFormat = texture->pixelFormat();
......
......@@ -210,17 +210,18 @@ angle::Result InitializeTextureContentsGPU(const gl::Context *context,
RenderTargetMtl tempRtt;
tempRtt.set(texture, index.getNativeLevel(), sliceOrDepth, textureObjFormat);
MTLClearColor blackColor = {};
int clearAlpha = 0;
if (!textureObjFormat.intendedAngleFormat().alphaBits)
{
// if intended format doesn't have alpha, set it to 1.0.
blackColor.alpha = kEmulatedAlphaValue;
clearAlpha = kEmulatedAlphaValue;
}
RenderCommandEncoder *encoder;
if (channelsToInit == MTLColorWriteMaskAll)
{
// If all channels will be initialized, use clear loadOp.
Optional<MTLClearColor> blackColor = MTLClearColorMake(0, 0, 0, clearAlpha);
encoder = contextMtl->getRenderTargetCommandEncoderWithClear(tempRtt, blackColor);
}
else
......@@ -233,8 +234,23 @@ angle::Result InitializeTextureContentsGPU(const gl::Context *context,
// If there are some channels don't need to be initialized, we must use clearWithDraw.
encoder = contextMtl->getRenderTargetCommandEncoder(tempRtt);
const angle::Format &angleFormat = textureObjFormat.actualAngleFormat();
ClearRectParams clearParams;
clearParams.clearColor = blackColor;
ClearColorValue clearColor;
if (angleFormat.isSint())
{
clearColor.setAsInt(0, 0, 0, clearAlpha);
}
else if (angleFormat.isUint())
{
clearColor.setAsUInt(0, 0, 0, clearAlpha);
}
else
{
clearColor.setAsFloat(0, 0, 0, clearAlpha);
}
clearParams.clearColor = clearColor;
clearParams.dstTextureSize = texture->sizeAt0();
clearParams.enabledBuffers.set(0);
clearParams.clearArea = gl::Rectangle(0, 0, texture->widthAt0(), texture->heightAt0());
......
......@@ -1100,6 +1100,142 @@ TEST_P(ClearTestES3, MaskedClearHeterogeneousAttachments)
verifyStencil(kStencilClearValue, kSize);
}
// Test that clearing multiple attachments of different nature (float, int and uint) in the
// presence of a scissor test works correctly. In the Vulkan backend, this exercises clearWithDraw
// and the relevant internal shaders.
TEST_P(ClearTestES3, ScissoredClearHeterogeneousAttachments)
{
// http://anglebug.com/4855
ANGLE_SKIP_TEST_IF(IsWindows() && IsIntel() && IsVulkan());
// http://anglebug.com/5116
ANGLE_SKIP_TEST_IF(IsWindows() && (IsOpenGL() || IsD3D11()) && IsAMD());
constexpr uint32_t kSize = 16;
constexpr uint32_t kHalfSize = kSize / 2;
constexpr uint32_t kAttachmentCount = 3;
constexpr float kDepthClearValue = 0.256f;
constexpr int32_t kStencilClearValue = 0x1D;
constexpr GLenum kAttachmentFormats[kAttachmentCount] = {
GL_RGBA8,
GL_RGBA8I,
GL_RGBA8UI,
};
constexpr GLenum kDataFormats[kAttachmentCount] = {
GL_RGBA,
GL_RGBA_INTEGER,
GL_RGBA_INTEGER,
};
constexpr GLenum kDataTypes[kAttachmentCount] = {
GL_UNSIGNED_BYTE,
GL_BYTE,
GL_UNSIGNED_BYTE,
};
std::vector<unsigned char> pixelData(kSize * kSize * 4, 0);
glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
GLTexture textures[kAttachmentCount];
GLRenderbuffer depthStencil;
GLenum drawBuffers[kAttachmentCount];
for (uint32_t i = 0; i < kAttachmentCount; ++i)
{
glBindTexture(GL_TEXTURE_2D, textures[i]);
glTexImage2D(GL_TEXTURE_2D, 0, kAttachmentFormats[i], kSize, kSize, 0, kDataFormats[i],
kDataTypes[i], pixelData.data());
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i],
0);
drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
}
glBindRenderbuffer(GL_RENDERBUFFER, depthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, kSize, kSize);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
depthStencil);
glDrawBuffers(kAttachmentCount, drawBuffers);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_EQ(0, 0, 0, 0, 0, 0);
// Enable scissor test
glScissor(0, 0, kHalfSize, kHalfSize);
glEnable(GL_SCISSOR_TEST);
GLColor clearValuef = {25, 50, 75, 100};
angle::Vector4 clearValuefv = clearValuef.toNormalizedVector();
glClearColor(clearValuefv.x(), clearValuefv.y(), clearValuefv.z(), clearValuefv.w());
glClearDepthf(kDepthClearValue);
// clear stencil.
glClearBufferiv(GL_STENCIL, 0, &kStencilClearValue);
// clear float color attachment & depth together
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// clear integer attachment.
int clearValuei[4] = {10, -20, 30, -40};
glClearBufferiv(GL_COLOR, 1, clearValuei);
// clear unsigned integer attachment
uint32_t clearValueui[4] = {50, 60, 70, 80};
glClearBufferuiv(GL_COLOR, 2, clearValueui);
ASSERT_GL_NO_ERROR();
{
glReadBuffer(GL_COLOR_ATTACHMENT0);
ASSERT_GL_NO_ERROR();
GLColor expect = clearValuef;
EXPECT_PIXEL_COLOR_EQ(0, 0, expect);
EXPECT_PIXEL_COLOR_EQ(0, kHalfSize - 1, expect);
EXPECT_PIXEL_COLOR_EQ(kHalfSize - 1, 0, expect);
EXPECT_PIXEL_COLOR_EQ(kHalfSize - 1, kHalfSize - 1, expect);
EXPECT_PIXEL_EQ(kHalfSize + 1, kHalfSize + 1, 0, 0, 0, 0);
}
{
glReadBuffer(GL_COLOR_ATTACHMENT1);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_8I(0, 0, clearValuei[0], clearValuei[1], clearValuei[2], clearValuei[3]);
EXPECT_PIXEL_8I(0, kHalfSize - 1, clearValuei[0], clearValuei[1], clearValuei[2],
clearValuei[3]);
EXPECT_PIXEL_8I(kHalfSize - 1, 0, clearValuei[0], clearValuei[1], clearValuei[2],
clearValuei[3]);
EXPECT_PIXEL_8I(kHalfSize - 1, kHalfSize - 1, clearValuei[0], clearValuei[1],
clearValuei[2], clearValuei[3]);
EXPECT_PIXEL_8I(kHalfSize + 1, kHalfSize + 1, 0, 0, 0, 0);
}
{
glReadBuffer(GL_COLOR_ATTACHMENT2);
ASSERT_GL_NO_ERROR();
EXPECT_PIXEL_8UI(0, 0, clearValueui[0], clearValueui[1], clearValueui[2], clearValueui[3]);
EXPECT_PIXEL_8UI(0, kHalfSize - 1, clearValueui[0], clearValueui[1], clearValueui[2],
clearValueui[3]);
EXPECT_PIXEL_8UI(kHalfSize - 1, 0, clearValueui[0], clearValueui[1], clearValueui[2],
clearValueui[3]);
EXPECT_PIXEL_8UI(kHalfSize - 1, kHalfSize - 1, clearValueui[0], clearValueui[1],
clearValueui[2], clearValueui[3]);
EXPECT_PIXEL_8UI(kHalfSize + 1, kHalfSize + 1, 0, 0, 0, 0);
}
glReadBuffer(GL_COLOR_ATTACHMENT0);
for (uint32_t i = 1; i < kAttachmentCount; ++i)
drawBuffers[i] = GL_NONE;
glDrawBuffers(kAttachmentCount, drawBuffers);
verifyDepth(kDepthClearValue, kHalfSize);
verifyStencil(kStencilClearValue, kHalfSize);
}
// This tests a bug where in a masked clear when calling "ClearBuffer", we would
// mistakenly clear every channel (including the masked-out ones)
TEST_P(ClearTestES3, MaskedClearBufferBug)
......@@ -2140,7 +2276,7 @@ TEST_P(ClearTestES3, ClearBufferfiStencilMask)
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against.
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ClearTest);
ANGLE_INSTANTIATE_TEST_ES3(ClearTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(ClearTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_COMBINE_4(MaskedScissoredClearTest,
MaskedScissoredClearVariationsTestPrint,
testing::Range(0, 3),
......@@ -2155,7 +2291,9 @@ ANGLE_INSTANTIATE_TEST_COMBINE_4(MaskedScissoredClearTest,
ES2_OPENGLES(),
ES3_OPENGLES(),
ES2_VULKAN(),
ES3_VULKAN());
ES3_VULKAN(),
ES2_METAL(),
ES3_METAL());
ANGLE_INSTANTIATE_TEST_COMBINE_4(VulkanClearTest,
MaskedScissoredClearVariationsTestPrint,
testing::Range(0, 3),
......@@ -2166,6 +2304,12 @@ ANGLE_INSTANTIATE_TEST_COMBINE_4(VulkanClearTest,
ES3_VULKAN());
// Not all ANGLE backends support RGB backbuffers
ANGLE_INSTANTIATE_TEST(ClearTestRGB, ES2_D3D11(), ES3_D3D11(), ES2_VULKAN(), ES3_VULKAN());
ANGLE_INSTANTIATE_TEST(ClearTestRGB,
ES2_D3D11(),
ES3_D3D11(),
ES2_VULKAN(),
ES3_VULKAN(),
ES2_METAL(),
ES3_METAL());
} // anonymous namespace
......@@ -2541,6 +2541,6 @@ ANGLE_INSTANTIATE_TEST(CopyTextureTestDest,
ES2_OPENGLES(),
ES2_VULKAN(),
ES2_METAL());
ANGLE_INSTANTIATE_TEST_ES3(CopyTextureTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(CopyTextureTestES3, ES3_METAL());
} // namespace angle
......@@ -301,6 +301,9 @@ TEST_P(DrawBuffersTest, BlendWithGaps)
// Fails on Intel Ubuntu 19.04 Mesa 19.0.2 Vulkan. http://anglebug.com/3616
ANGLE_SKIP_TEST_IF(IsLinux() && IsIntel() && IsVulkan());
// http://anglebug.com/5154
ANGLE_SKIP_TEST_IF(IsOSX() && IsIntel() && IsDesktopOpenGL());
glBindTexture(GL_TEXTURE_2D, mTextures[0]);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[0], 0);
......
......@@ -8116,12 +8116,12 @@ ANGLE_INSTANTIATE_TEST(Texture2DRGTest,
ANGLE_INSTANTIATE_TEST_ES3(Texture2DFloatTestES3);
ANGLE_INSTANTIATE_TEST_ES2(Texture2DFloatTestES2);
ANGLE_INSTANTIATE_TEST_ES3(TextureCubeTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerTestES3);
ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerTestES3);
ANGLE_INSTANTIATE_TEST_ES3(TextureCubeIntegerEdgeTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DIntegerProjectiveOffsetTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture2DArrayIntegerTestES3);
ANGLE_INSTANTIATE_TEST_ES3(Texture3DIntegerTestES3);
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(TextureCubeIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(TextureCubeIntegerEdgeTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DIntegerProjectiveOffsetTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture2DArrayIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES3_AND(Texture3DIntegerTestES3, ES3_METAL());
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(Texture2DDepthTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(PBOCompressedTextureTest);
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(ETC1CompressedTextureTest);
......
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