Commit bccb0d56 by Geoff Lang Committed by Commit Bot

Add messages for framebuffer completeness errors.

This also creates a common code path for all framebuffer completeness errors (FramebufferStatus::Incomplete) which helps for adding a debug breakpoint. Bug: angleproject:5949 Change-Id: Ib102dbf86e020777e56c6dc6b78dda8ebdba2127 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2888110 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent e354ff1a
...@@ -6447,7 +6447,7 @@ GLenum Context::checkFramebufferStatus(GLenum target) ...@@ -6447,7 +6447,7 @@ GLenum Context::checkFramebufferStatus(GLenum target)
{ {
Framebuffer *framebuffer = mState.getTargetFramebuffer(target); Framebuffer *framebuffer = mState.getTargetFramebuffer(target);
ASSERT(framebuffer); ASSERT(framebuffer);
return framebuffer->checkStatus(this); return framebuffer->checkStatus(this).status;
} }
void Context::compileShader(ShaderProgramID shader) void Context::compileShader(ShaderProgramID shader)
......
...@@ -143,6 +143,41 @@ MSG kFragDataBindingIndexOutOfRange = "Fragment output color index must be zero ...@@ -143,6 +143,41 @@ MSG kFragDataBindingIndexOutOfRange = "Fragment output color index must be zero
MSG kFragmentInputTypeNotFloatingPoint = "Fragment input type is not a floating point scalar or vector."; MSG kFragmentInputTypeNotFloatingPoint = "Fragment input type is not a floating point scalar or vector.";
MSG kFramebufferIncomplete = "Framebuffer is incomplete."; MSG kFramebufferIncomplete = "Framebuffer is incomplete.";
MSG kFramebufferIncompleteAttachment = "Attachment type must be compatible with attachment object."; MSG kFramebufferIncompleteAttachment = "Attachment type must be compatible with attachment object.";
MSG kFramebufferIncompleteAttachmentDepthGreaterThanMaxLayers = "Framebuffer is incomplete: Attachment depth is greater than MAX_FRAMEBUFFER_LAYERS.";
MSG kFramebufferIncompleteAttachmentInconsistantBitPlanes = "Framebuffer is incomplete: Attachments have inconsistent bit plane counts.";
MSG kFramebufferIncompleteAttachmentLayerGreaterThanDepth = "Framebuffer is incomplete: Attachment layer is greater than texture layer count.";
MSG kFramebufferIncompleteAttachmentLevelNotBaseLevelForIncompleteMipTexture = "Framebuffer is incomplete: Attachment level not equal to the base level and the texture is not mipmap complete.";
MSG kFramebufferIncompleteAttachmentLevelOutOfBaseMaxLevelRange = "Framebuffer is incomplete: Attachment level is not in the [base level, max level] range.";
MSG kFramebufferIncompleteAttachmentNoDepthBitsInDepthBuffer = "Framebuffer is incomplete: Depth attachment has no depth bits.";
MSG kFramebufferIncompleteAttachmentNoStencilBitsInStencilBuffer = "Framebuffer is incomplete: Stencil attachment has no stencil bits.";
MSG kFramebufferIncompleteAttachmentNotCubeComplete = "Framebuffer is incomplete: Attachment is an incomplete cube map.";
MSG kFramebufferIncompleteAttachmentNotRenderable = "Framebuffer is incomplete: Attachment is not renderable.";
MSG kFramebufferIncompleteAttachmentSamplesGreaterThanMaxSupportedSamples = "Framebuffer is incomplete: Attachment samples are greater than the maximum supported samples for this format.";
MSG kFramebufferIncompleteAttachmentsNotUnique = "Framebuffer is incomplete: All attachments must be unique.";
MSG kFramebufferIncompleteAttachmentWebGLDepthBufferHasStencilBits = "Framebuffer is incomplete: Stencil attachment has depth bits.";
MSG kFramebufferIncompleteAttachmentWebGLDepthStencilNoDepthOrStencilBits = "Framebuffer is incomplete: Depth stencil attachment has no depth bits or no stencil bits.";
MSG kFramebufferIncompleteAttachmentWebGLStencilBufferHasDepthBits = "Framebuffer is incomplete: Stencil attachment has depth bits.";
MSG kFramebufferIncompleteAttachmentZeroSize = "Framebuffer is incomplete: Attachment has zero size.";
MSG kFramebufferIncompleteDefaultZeroSize = "Framebuffer is incomplete: No attachments and default size is zero.";
MSG kFramebufferIncompleteDepthAndStencilBuffersNotTheSame = "Framebuffer is incomplete: Depth and stencil attachments are not the same.";
MSG kFramebufferIncompleteDepthStencilInColorBuffer = "Framebuffer is incomplete: Depth stencil texture in color attachment.";
MSG kFramebufferIncompleteDriverUnsupported = "Framebuffer is incomplete: Driver does not support this framebuffer configuration.";
MSG kFramebufferIncompleteInconsistantAttachmentSizes = "Framebuffer is incomplete: Attachments are not all the same size.";
MSG kFramebufferIncompleteInternalError = "Framebuffer is incomplete: Internal error.";
MSG kFramebufferIncompleteMismatchedLayeredAttachments = "Framebuffer is incomplete: If one attachment is layered, all must be layered.";
MSG kFramebufferIncompleteMismatchedLayeredTexturetypes = "Framebuffer is incomplete: If an attachments are layered, they must all be the same texture type.";
MSG kFramebufferIncompleteMultisampleDepthStencilSampleCountDivisibleByColorSampleCount = "Framebuffer is incomplete: Depth stencil sample count must be divisible by the color sample count.";
MSG kFramebufferIncompleteMultisampleInconsistentFixedSampleLocations = "Framebuffer is incomplete: Attachments have inconsistent fixed sample locations.";
MSG kFramebufferIncompleteMultisampleInconsistentSampleCounts = "Framebuffer is incomplete: Attachments have different sample counts.";
MSG kFramebufferIncompleteMultisampleNonFixedSamplesWithRenderbuffers = "Framebuffer is incomplete: All textures must have fixed samples if paired with multisample renderbuffers.";
MSG kFramebufferIncompleteMultiviewBaseViewMismatch = "Framebuffer is incomplete: Attachments have inconsistent multiview base view.";
MSG kFramebufferIncompleteMultiviewMismatch = "Framebuffer is incomplete: Attachments have inconsistent multiview enabled state.";
MSG kFramebufferIncompleteMultiviewViewsMismatch = "Framebuffer is incomplete: Attachments have inconsistent multiview view counts.";
MSG kFramebufferIncompleteSurfaceless = "Framebuffer is incomplete: Framebuffer is surfaceless.";
MSG kFramebufferIncompleteUnsupportedMissmatchedDimensions = "Framebuffer is incomplete: Mismatched attachment sizes are unsupported.";
MSG kFramebufferIncompleteUnsupportedNonUniqueAttachments = "Framebuffer is incomplete: Non-unique attachments are unsupported.";
MSG kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers = "Framebuffer is incomplete: Separate depth and stencil buffers are unsupported.";
MSG kFramebufferIncompleteWebGLDepthStencilInconsistant = "Framebuffer is incomplete: WebGL depth stencil state is inconsistent.";
MSG kFramebufferTextureInvalidLayer = "Layer invalid for framebuffer texture attachment."; MSG kFramebufferTextureInvalidLayer = "Layer invalid for framebuffer texture attachment.";
MSG kFramebufferTextureInvalidMipLevel = "Mip level invalid for framebuffer texture attachment."; MSG kFramebufferTextureInvalidMipLevel = "Mip level invalid for framebuffer texture attachment.";
MSG kFramebufferTextureLayerIncorrectTextureType = "Texture is not a three-dimensional or two-dimensionsal array texture."; MSG kFramebufferTextureLayerIncorrectTextureType = "Texture is not a three-dimensional or two-dimensionsal array texture.";
......
...@@ -50,6 +50,17 @@ class State; ...@@ -50,6 +50,17 @@ class State;
class Texture; class Texture;
class TextureCapsMap; class TextureCapsMap;
struct FramebufferStatus
{
bool isComplete() const;
static FramebufferStatus Complete();
static FramebufferStatus Incomplete(GLenum status, const char *reason);
GLenum status = GL_FRAMEBUFFER_COMPLETE;
const char *reason = nullptr;
};
class FramebufferState final : angle::NonCopyable class FramebufferState final : angle::NonCopyable
{ {
public: public:
...@@ -293,7 +304,7 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -293,7 +304,7 @@ class Framebuffer final : public angle::ObserverInterface,
void invalidateCompletenessCache(); void invalidateCompletenessCache();
ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); } ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); }
ANGLE_INLINE GLenum checkStatus(const Context *context) const ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const
{ {
// The default framebuffer is always complete except when it is surfaceless in which // The default framebuffer is always complete except when it is surfaceless in which
// case it is always unsupported. // case it is always unsupported.
...@@ -309,7 +320,7 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -309,7 +320,7 @@ class Framebuffer final : public angle::ObserverInterface,
// Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE. // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
ANGLE_INLINE bool isComplete(const Context *context) const ANGLE_INLINE bool isComplete(const Context *context) const
{ {
return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE); return checkStatus(context).isComplete();
} }
bool hasValidDepthStencil() const; bool hasValidDepthStencil() const;
...@@ -429,8 +440,8 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -429,8 +440,8 @@ class Framebuffer final : public angle::ObserverInterface,
FramebufferAttachment *attachment, FramebufferAttachment *attachment,
GLenum matchType, GLenum matchType,
GLuint matchId); GLuint matchId);
GLenum checkStatusWithGLFrontEnd(const Context *context) const; FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const;
GLenum checkStatusImpl(const Context *context) const; const FramebufferStatus &checkStatusImpl(const Context *context) const;
void setAttachment(const Context *context, void setAttachment(const Context *context,
GLenum type, GLenum type,
GLenum binding, GLenum binding,
...@@ -491,7 +502,7 @@ class Framebuffer final : public angle::ObserverInterface, ...@@ -491,7 +502,7 @@ class Framebuffer final : public angle::ObserverInterface,
FramebufferState mState; FramebufferState mState;
rx::FramebufferImpl *mImpl; rx::FramebufferImpl *mImpl;
mutable Optional<GLenum> mCachedStatus; mutable Optional<FramebufferStatus> mCachedStatus;
std::vector<angle::ObserverBinding> mDirtyColorAttachmentBindings; std::vector<angle::ObserverBinding> mDirtyColorAttachmentBindings;
angle::ObserverBinding mDirtyDepthAttachmentBinding; angle::ObserverBinding mDirtyDepthAttachmentBinding;
angle::ObserverBinding mDirtyStencilAttachmentBinding; angle::ObserverBinding mDirtyStencilAttachmentBinding;
......
...@@ -82,7 +82,7 @@ class FramebufferImpl : angle::NonCopyable ...@@ -82,7 +82,7 @@ class FramebufferImpl : angle::NonCopyable
GLbitfield mask, GLbitfield mask,
GLenum filter) = 0; GLenum filter) = 0;
virtual bool checkStatus(const gl::Context *context) const = 0; virtual gl::FramebufferStatus checkStatus(const gl::Context *context) const = 0;
virtual angle::Result syncState(const gl::Context *context, virtual angle::Result syncState(const gl::Context *context,
GLenum binding, GLenum binding,
......
...@@ -52,7 +52,7 @@ class MockFramebufferImpl : public rx::FramebufferImpl ...@@ -52,7 +52,7 @@ class MockFramebufferImpl : public rx::FramebufferImpl
GLbitfield, GLbitfield,
GLenum)); GLenum));
MOCK_CONST_METHOD1(checkStatus, bool(const gl::Context *)); MOCK_CONST_METHOD1(checkStatus, gl::FramebufferStatus(const gl::Context *));
MOCK_METHOD4(syncState, MOCK_METHOD4(syncState,
angle::Result(const gl::Context *, angle::Result(const gl::Context *,
...@@ -68,7 +68,8 @@ inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock() ...@@ -68,7 +68,8 @@ inline ::testing::NiceMock<MockFramebufferImpl> *MakeFramebufferMock()
::testing::NiceMock<MockFramebufferImpl> *framebufferImpl = ::testing::NiceMock<MockFramebufferImpl> *framebufferImpl =
new ::testing::NiceMock<MockFramebufferImpl>(); new ::testing::NiceMock<MockFramebufferImpl>();
// TODO(jmadill): add ON_CALLS for other returning methods // TODO(jmadill): add ON_CALLS for other returning methods
ON_CALL(*framebufferImpl, checkStatus(testing::_)).WillByDefault(::testing::Return(true)); ON_CALL(*framebufferImpl, checkStatus(testing::_))
.WillByDefault(::testing::Return(gl::FramebufferStatus::Complete()));
// We must mock the destructor since NiceMock doesn't work for destructors. // We must mock the destructor since NiceMock doesn't work for destructors.
EXPECT_CALL(*framebufferImpl, destructor()).Times(1).RetiresOnSaturation(); EXPECT_CALL(*framebufferImpl, destructor()).Times(1).RetiresOnSaturation();
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "common/bitset_utils.h" #include "common/bitset_utils.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/Framebuffer.h" #include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Surface.h" #include "libANGLE/Surface.h"
...@@ -249,13 +250,15 @@ angle::Result FramebufferD3D::blit(const gl::Context *context, ...@@ -249,13 +250,15 @@ angle::Result FramebufferD3D::blit(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
bool FramebufferD3D::checkStatus(const gl::Context *context) const gl::FramebufferStatus FramebufferD3D::checkStatus(const gl::Context *context) const
{ {
// if we have both a depth and stencil buffer, they must refer to the same object // if we have both a depth and stencil buffer, they must refer to the same object
// since we only support packed_depth_stencil and not separate depth and stencil // since we only support packed_depth_stencil and not separate depth and stencil
if (mState.hasSeparateDepthAndStencilAttachments()) if (mState.hasSeparateDepthAndStencilAttachments())
{ {
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
} }
// D3D11 does not allow for overlapping RenderTargetViews. // D3D11 does not allow for overlapping RenderTargetViews.
...@@ -266,17 +269,21 @@ bool FramebufferD3D::checkStatus(const gl::Context *context) const ...@@ -266,17 +269,21 @@ bool FramebufferD3D::checkStatus(const gl::Context *context) const
{ {
if (!mState.colorAttachmentsAreUniqueImages()) if (!mState.colorAttachmentsAreUniqueImages())
{ {
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedNonUniqueAttachments);
} }
} }
// D3D requires all render targets to have the same dimensions. // D3D requires all render targets to have the same dimensions.
if (!mState.attachmentsHaveSameDimensions()) if (!mState.attachmentsHaveSameDimensions())
{ {
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedMissmatchedDimensions);
} }
return true; return gl::FramebufferStatus::Complete();
} }
angle::Result FramebufferD3D::syncState(const gl::Context *context, angle::Result FramebufferD3D::syncState(const gl::Context *context,
......
...@@ -92,7 +92,7 @@ class FramebufferD3D : public FramebufferImpl ...@@ -92,7 +92,7 @@ class FramebufferD3D : public FramebufferImpl
GLbitfield mask, GLbitfield mask,
GLenum filter) override; GLenum filter) override;
bool checkStatus(const gl::Context *context) const override; gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
angle::Result syncState(const gl::Context *context, angle::Result syncState(const gl::Context *context,
GLenum binding, GLenum binding,
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "common/bitset_utils.h" #include "common/bitset_utils.h"
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/FramebufferAttachment.h" #include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/State.h" #include "libANGLE/State.h"
#include "libANGLE/angletypes.h" #include "libANGLE/angletypes.h"
...@@ -1188,7 +1189,7 @@ bool FramebufferGL::shouldSyncStateBeforeCheckStatus() const ...@@ -1188,7 +1189,7 @@ bool FramebufferGL::shouldSyncStateBeforeCheckStatus() const
return true; return true;
} }
bool FramebufferGL::checkStatus(const gl::Context *context) const gl::FramebufferStatus FramebufferGL::checkStatus(const gl::Context *context) const
{ {
const FunctionsGL *functions = GetFunctionsGL(context); const FunctionsGL *functions = GetFunctionsGL(context);
StateManagerGL *stateManager = GetStateManagerGL(context); StateManagerGL *stateManager = GetStateManagerGL(context);
...@@ -1197,9 +1198,12 @@ bool FramebufferGL::checkStatus(const gl::Context *context) const ...@@ -1197,9 +1198,12 @@ bool FramebufferGL::checkStatus(const gl::Context *context) const
GLenum status = functions->checkFramebufferStatus(GL_FRAMEBUFFER); GLenum status = functions->checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) if (status != GL_FRAMEBUFFER_COMPLETE)
{ {
WARN() << "GL framebuffer returned incomplete."; WARN() << "GL framebuffer returned incomplete: " << gl::FmtHex(status);
return gl::FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteDriverUnsupported);
} }
return (status == GL_FRAMEBUFFER_COMPLETE);
return gl::FramebufferStatus::Complete();
} }
angle::Result FramebufferGL::syncState(const gl::Context *context, angle::Result FramebufferGL::syncState(const gl::Context *context,
......
...@@ -79,7 +79,7 @@ class FramebufferGL : public FramebufferImpl ...@@ -79,7 +79,7 @@ class FramebufferGL : public FramebufferImpl
// The GL back-end requires a full sync state before we call checkStatus. // The GL back-end requires a full sync state before we call checkStatus.
bool shouldSyncStateBeforeCheckStatus() const override; bool shouldSyncStateBeforeCheckStatus() const override;
bool checkStatus(const gl::Context *context) const override; gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
angle::Result syncState(const gl::Context *context, angle::Result syncState(const gl::Context *context,
GLenum binding, GLenum binding,
......
...@@ -78,7 +78,7 @@ class FramebufferMtl : public FramebufferImpl ...@@ -78,7 +78,7 @@ class FramebufferMtl : public FramebufferImpl
GLbitfield mask, GLbitfield mask,
GLenum filter) override; GLenum filter) override;
bool checkStatus(const gl::Context *context) const override; gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
angle::Result syncState(const gl::Context *context, angle::Result syncState(const gl::Context *context,
GLenum binding, GLenum binding,
...@@ -120,7 +120,7 @@ class FramebufferMtl : public FramebufferImpl ...@@ -120,7 +120,7 @@ class FramebufferMtl : public FramebufferImpl
private: private:
void reset(); void reset();
bool checkPackedDepthStencilAttachment() const; gl::FramebufferStatus checkPackedDepthStencilAttachment() const;
angle::Result invalidateImpl(ContextMtl *contextMtl, size_t count, const GLenum *attachments); angle::Result invalidateImpl(ContextMtl *contextMtl, size_t count, const GLenum *attachments);
angle::Result blitWithDraw(const gl::Context *context, angle::Result blitWithDraw(const gl::Context *context,
FramebufferMtl *srcFrameBuffer, FramebufferMtl *srcFrameBuffer,
......
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "common/MemoryBuffer.h" #include "common/MemoryBuffer.h"
#include "common/angleutils.h" #include "common/angleutils.h"
#include "common/debug.h" #include "common/debug.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/renderer/metal/BufferMtl.h" #include "libANGLE/renderer/metal/BufferMtl.h"
#include "libANGLE/renderer/metal/DisplayMtl.h" #include "libANGLE/renderer/metal/DisplayMtl.h"
#include "libANGLE/renderer/metal/FrameBufferMtl.h" #include "libANGLE/renderer/metal/FrameBufferMtl.h"
...@@ -468,18 +469,22 @@ angle::Result FramebufferMtl::blitWithDraw(const gl::Context *context, ...@@ -468,18 +469,22 @@ angle::Result FramebufferMtl::blitWithDraw(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
bool FramebufferMtl::checkStatus(const gl::Context *context) const gl::FramebufferStatus FramebufferMtl::checkStatus(const gl::Context *context) const
{ {
if (!mState.attachmentsHaveSameDimensions()) if (!mState.attachmentsHaveSameDimensions())
{ {
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedMissmatchedDimensions);
} }
ContextMtl *contextMtl = mtl::GetImpl(context); ContextMtl *contextMtl = mtl::GetImpl(context);
if (!contextMtl->getDisplay()->getFeatures().allowSeparatedDepthStencilBuffers.enabled && if (!contextMtl->getDisplay()->getFeatures().allowSeparatedDepthStencilBuffers.enabled &&
mState.hasSeparateDepthAndStencilAttachments()) mState.hasSeparateDepthAndStencilAttachments())
{ {
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
} }
if (mState.getDepthAttachment() && mState.getDepthAttachment()->getFormat().info->depthBits && if (mState.getDepthAttachment() && mState.getDepthAttachment()->getFormat().info->depthBits &&
...@@ -495,10 +500,10 @@ bool FramebufferMtl::checkStatus(const gl::Context *context) const ...@@ -495,10 +500,10 @@ bool FramebufferMtl::checkStatus(const gl::Context *context) const
return checkPackedDepthStencilAttachment(); return checkPackedDepthStencilAttachment();
} }
return true; return gl::FramebufferStatus::Complete();
} }
bool FramebufferMtl::checkPackedDepthStencilAttachment() const gl::FramebufferStatus FramebufferMtl::checkPackedDepthStencilAttachment() const
{ {
if (ANGLE_APPLE_AVAILABLE_XCI(10.14, 13.0, 12.0)) if (ANGLE_APPLE_AVAILABLE_XCI(10.14, 13.0, 12.0))
{ {
...@@ -509,7 +514,9 @@ bool FramebufferMtl::checkPackedDepthStencilAttachment() const ...@@ -509,7 +514,9 @@ bool FramebufferMtl::checkPackedDepthStencilAttachment() const
{ {
WARN() << "Packed depth stencil texture/buffer must not be mixed with other " WARN() << "Packed depth stencil texture/buffer must not be mixed with other "
"texture/buffer."; "texture/buffer.";
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
} }
} }
else else
...@@ -520,10 +527,12 @@ bool FramebufferMtl::checkPackedDepthStencilAttachment() const ...@@ -520,10 +527,12 @@ bool FramebufferMtl::checkPackedDepthStencilAttachment() const
{ {
WARN() << "Packed depth stencil texture/buffer must be bound to both depth & stencil " WARN() << "Packed depth stencil texture/buffer must be bound to both depth & stencil "
"attachment point."; "attachment point.";
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
} }
} }
return true; return gl::FramebufferStatus::Complete();
} }
angle::Result FramebufferMtl::syncState(const gl::Context *context, angle::Result FramebufferMtl::syncState(const gl::Context *context,
......
...@@ -151,9 +151,9 @@ angle::Result FramebufferNULL::blit(const gl::Context *context, ...@@ -151,9 +151,9 @@ angle::Result FramebufferNULL::blit(const gl::Context *context,
return angle::Result::Continue; return angle::Result::Continue;
} }
bool FramebufferNULL::checkStatus(const gl::Context *context) const gl::FramebufferStatus FramebufferNULL::checkStatus(const gl::Context *context) const
{ {
return true; return gl::FramebufferStatus::Complete();
} }
angle::Result FramebufferNULL::syncState(const gl::Context *context, angle::Result FramebufferNULL::syncState(const gl::Context *context,
......
...@@ -65,7 +65,7 @@ class FramebufferNULL : public FramebufferImpl ...@@ -65,7 +65,7 @@ class FramebufferNULL : public FramebufferImpl
GLbitfield mask, GLbitfield mask,
GLenum filter) override; GLenum filter) override;
bool checkStatus(const gl::Context *context) const override; gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
angle::Result syncState(const gl::Context *context, angle::Result syncState(const gl::Context *context,
GLenum binding, GLenum binding,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include "common/vulkan/vk_headers.h" #include "common/vulkan/vk_headers.h"
#include "libANGLE/Context.h" #include "libANGLE/Context.h"
#include "libANGLE/Display.h" #include "libANGLE/Display.h"
#include "libANGLE/ErrorStrings.h"
#include "libANGLE/formatutils.h" #include "libANGLE/formatutils.h"
#include "libANGLE/renderer/renderer_utils.h" #include "libANGLE/renderer/renderer_utils.h"
#include "libANGLE/renderer/vulkan/ContextVk.h" #include "libANGLE/renderer/vulkan/ContextVk.h"
...@@ -1458,16 +1459,18 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk, ...@@ -1458,16 +1459,18 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
return angle::Result::Continue; return angle::Result::Continue;
} }
bool FramebufferVk::checkStatus(const gl::Context *context) const gl::FramebufferStatus FramebufferVk::checkStatus(const gl::Context *context) const
{ {
// if we have both a depth and stencil buffer, they must refer to the same object // if we have both a depth and stencil buffer, they must refer to the same object
// since we only support packed_depth_stencil and not separate depth and stencil // since we only support packed_depth_stencil and not separate depth and stencil
if (mState.hasSeparateDepthAndStencilAttachments()) if (mState.hasSeparateDepthAndStencilAttachments())
{ {
return false; return gl::FramebufferStatus::Incomplete(
GL_FRAMEBUFFER_UNSUPPORTED,
gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
} }
return true; return gl::FramebufferStatus::Complete();
} }
angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk, angle::Result FramebufferVk::invalidateImpl(ContextVk *contextVk,
......
...@@ -107,7 +107,7 @@ class FramebufferVk : public FramebufferImpl ...@@ -107,7 +107,7 @@ class FramebufferVk : public FramebufferImpl
GLbitfield mask, GLbitfield mask,
GLenum filter) override; GLenum filter) override;
bool checkStatus(const gl::Context *context) const override; gl::FramebufferStatus checkStatus(const gl::Context *context) const override;
angle::Result syncState(const gl::Context *context, angle::Result syncState(const gl::Context *context,
GLenum binding, GLenum binding,
......
...@@ -763,9 +763,11 @@ template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION> ...@@ -763,9 +763,11 @@ template <GLenum ErrorCode = GL_INVALID_FRAMEBUFFER_OPERATION>
ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context, ANGLE_INLINE bool ValidateFramebufferComplete(const Context *context,
const Framebuffer *framebuffer) const Framebuffer *framebuffer)
{ {
if (!framebuffer->isComplete(context)) const FramebufferStatus &framebufferStatus = framebuffer->checkStatus(context);
if (!framebufferStatus.isComplete())
{ {
context->validationError(ErrorCode, err::kFramebufferIncomplete); ASSERT(framebufferStatus.reason != nullptr);
context->validationError(ErrorCode, framebufferStatus.reason);
return false; return false;
} }
......
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