diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp | 305 |
1 files changed, 162 insertions, 143 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp index 82967aced0..3d73b2c840 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp @@ -8,14 +8,16 @@ #include "libANGLE/renderer/d3d/FramebufferD3D.h" -#include "common/BitSetIterator.h" -#include "libANGLE/formatutils.h" +#include "common/bitset_utils.h" +#include "libANGLE/Context.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Surface.h" -#include "libANGLE/renderer/d3d/RendererD3D.h" -#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/formatutils.h" +#include "libANGLE/renderer/ContextImpl.h" #include "libANGLE/renderer/d3d/RenderTargetD3D.h" +#include "libANGLE/renderer/d3d/RenderbufferD3D.h" +#include "libANGLE/renderer/d3d/RendererD3D.h" #include "libANGLE/renderer/d3d/SurfaceD3D.h" #include "libANGLE/renderer/d3d/SwapChainD3D.h" #include "libANGLE/renderer/d3d/TextureD3D.h" @@ -37,19 +39,19 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) { clearParams.clearColor[i] = false; } - clearParams.colorFClearValue = state.getColorClearValue(); - clearParams.colorClearType = GL_FLOAT; - clearParams.colorMaskRed = blendState.colorMaskRed; - clearParams.colorMaskGreen = blendState.colorMaskGreen; - clearParams.colorMaskBlue = blendState.colorMaskBlue; - clearParams.colorMaskAlpha = blendState.colorMaskAlpha; - clearParams.clearDepth = false; - clearParams.depthClearValue = state.getDepthClearValue(); - clearParams.clearStencil = false; - clearParams.stencilClearValue = state.getStencilClearValue(); + clearParams.colorF = state.getColorClearValue(); + clearParams.colorType = GL_FLOAT; + clearParams.colorMaskRed = blendState.colorMaskRed; + clearParams.colorMaskGreen = blendState.colorMaskGreen; + clearParams.colorMaskBlue = blendState.colorMaskBlue; + clearParams.colorMaskAlpha = blendState.colorMaskAlpha; + clearParams.clearDepth = false; + clearParams.depthValue = state.getDepthClearValue(); + clearParams.clearStencil = false; + clearParams.stencilValue = state.getStencilClearValue(); clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask; - clearParams.scissorEnabled = state.isScissorTestEnabled(); - clearParams.scissor = state.getScissor(); + clearParams.scissorEnabled = state.isScissorTestEnabled(); + clearParams.scissor = state.getScissor(); const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer(); if (mask & GL_COLOR_BUFFER_BIT) @@ -65,7 +67,8 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) if (mask & GL_DEPTH_BUFFER_BIT) { - if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL) + if (state.getDepthStencilState().depthMask && + framebufferObject->getDepthbuffer() != nullptr) { clearParams.clearDepth = true; } @@ -73,7 +76,7 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) if (mask & GL_STENCIL_BUFFER_BIT) { - if (framebufferObject->getStencilbuffer() != NULL && + if (framebufferObject->getStencilbuffer() != nullptr && framebufferObject->getStencilbuffer()->getStencilSize() > 0) { clearParams.clearStencil = true; @@ -82,10 +85,13 @@ ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask) return clearParams; } - } -FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer) +ClearParameters::ClearParameters() = default; + +ClearParameters::ClearParameters(const ClearParameters &other) = default; + +FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer) : FramebufferImpl(data), mRenderer(renderer) { } @@ -94,20 +100,19 @@ FramebufferD3D::~FramebufferD3D() { } -gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask) +gl::Error FramebufferD3D::clear(const gl::Context *context, GLbitfield mask) { - const gl::State &state = *data.state; - ClearParameters clearParams = GetClearParameters(state, mask); - return clear(data, clearParams); + ClearParameters clearParams = GetClearParameters(context->getGLState(), mask); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferfv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLfloat *values) { // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); if (buffer == GL_COLOR) { @@ -115,43 +120,43 @@ gl::Error FramebufferD3D::clearBufferfv(const gl::Data &data, { clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); } - clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_FLOAT; + clearParams.colorF = gl::ColorF(values[0], values[1], values[2], values[3]); + clearParams.colorType = GL_FLOAT; } if (buffer == GL_DEPTH) { clearParams.clearDepth = true; - clearParams.depthClearValue = values[0]; + clearParams.depthValue = values[0]; } - return clear(data, clearParams); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferuiv(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferuiv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLuint *values) { // glClearBufferuiv can only be called to clear a color buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); } - clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_UNSIGNED_INT; + clearParams.colorUI = gl::ColorUI(values[0], values[1], values[2], values[3]); + clearParams.colorType = GL_UNSIGNED_INT; - return clear(data, clearParams); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferiv(const gl::Context *context, GLenum buffer, GLint drawbuffer, const GLint *values) { // glClearBufferiv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); if (buffer == GL_COLOR) { @@ -159,167 +164,154 @@ gl::Error FramebufferD3D::clearBufferiv(const gl::Data &data, { clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i)); } - clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]); - clearParams.colorClearType = GL_INT; + clearParams.colorI = gl::ColorI(values[0], values[1], values[2], values[3]); + clearParams.colorType = GL_INT; } if (buffer == GL_STENCIL) { clearParams.clearStencil = true; - clearParams.stencilClearValue = values[1]; + clearParams.stencilValue = values[0]; } - return clear(data, clearParams); + return clearImpl(context, clearParams); } -gl::Error FramebufferD3D::clearBufferfi(const gl::Data &data, +gl::Error FramebufferD3D::clearBufferfi(const gl::Context *context, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) { // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = GetClearParameters(*data.state, 0); - clearParams.clearDepth = true; - clearParams.depthClearValue = depth; - clearParams.clearStencil = true; - clearParams.stencilClearValue = stencil; + ClearParameters clearParams = GetClearParameters(context->getGLState(), 0); + clearParams.clearDepth = true; + clearParams.depthValue = depth; + clearParams.clearStencil = true; + clearParams.stencilValue = stencil; - return clear(data, clearParams); + return clearImpl(context, clearParams); } -GLenum FramebufferD3D::getImplementationColorReadFormat() const +GLenum FramebufferD3D::getImplementationColorReadFormat(const gl::Context *context) const { - const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); if (readAttachment == nullptr) { return GL_NONE; } - RenderTargetD3D *attachmentRenderTarget = NULL; - gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); + RenderTargetD3D *attachmentRenderTarget = nullptr; + gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget); if (error.isError()) { return GL_NONE; } GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); - const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + const gl::InternalFormat &implementationFormatInfo = + gl::GetSizedInternalFormatInfo(implementationFormat); - return implementationFormatInfo.format; + return implementationFormatInfo.getReadPixelsFormat(); } -GLenum FramebufferD3D::getImplementationColorReadType() const +GLenum FramebufferD3D::getImplementationColorReadType(const gl::Context *context) const { - const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment(); + const gl::FramebufferAttachment *readAttachment = mState.getReadAttachment(); if (readAttachment == nullptr) { return GL_NONE; } - RenderTargetD3D *attachmentRenderTarget = NULL; - gl::Error error = readAttachment->getRenderTarget(&attachmentRenderTarget); + RenderTargetD3D *attachmentRenderTarget = nullptr; + gl::Error error = readAttachment->getRenderTarget(context, &attachmentRenderTarget); if (error.isError()) { return GL_NONE; } GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget); - const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat); + const gl::InternalFormat &implementationFormatInfo = + gl::GetSizedInternalFormatInfo(implementationFormat); - return implementationFormatInfo.type; + return implementationFormatInfo.getReadPixelsType(context->getClientVersion()); } -gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const +gl::Error FramebufferD3D::readPixels(const gl::Context *context, + const gl::Rectangle &origArea, + GLenum format, + GLenum type, + void *pixels) { - const gl::PixelPackState &packState = state.getPackState(); - - GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type); - const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); - GLuint outputPitch = - sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, packState.rowLength); - GLsizei outputSkipBytes = sizedFormatInfo.computeSkipPixels( - outputPitch, 0, 0, packState.skipRows, packState.skipPixels); - - return readPixelsImpl(area, format, type, outputPitch, packState, - reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes); -} - -gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, - GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) -{ - bool blitRenderTarget = false; - if ((mask & GL_COLOR_BUFFER_BIT) && - sourceFramebuffer->getReadColorbuffer() != nullptr && - mData.getFirstColorAttachment() != nullptr) + // Clip read area to framebuffer. + const gl::Extents fbSize = getState().getReadAttachment()->getSize(); + const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height); + gl::Rectangle area; + if (!ClipRectangle(origArea, fbRect, &area)) { - blitRenderTarget = true; + // nothing to read + return gl::NoError(); } - bool blitStencil = false; - if ((mask & GL_STENCIL_BUFFER_BIT) && - sourceFramebuffer->getStencilbuffer() != nullptr && - mData.getStencilAttachment() != nullptr) - { - blitStencil = true; - } + const gl::PixelPackState &packState = context->getGLState().getPackState(); - bool blitDepth = false; - if ((mask & GL_DEPTH_BUFFER_BIT) && - sourceFramebuffer->getDepthbuffer() != nullptr && - mData.getDepthAttachment() != nullptr) - { - blitDepth = true; - } + const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type); - if (blitRenderTarget || blitDepth || blitStencil) - { - const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL; - gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil, - filter, sourceFramebuffer); - if (error.isError()) - { - return error; - } - } + GLuint outputPitch = 0; + ANGLE_TRY_RESULT(sizedFormatInfo.computeRowPitch(type, origArea.width, packState.alignment, + packState.rowLength), + outputPitch); + GLuint outputSkipBytes = 0; + ANGLE_TRY_RESULT(sizedFormatInfo.computeSkipBytes(outputPitch, 0, packState, false), + outputSkipBytes); + outputSkipBytes += + (area.x - origArea.x) * sizedFormatInfo.pixelBytes + (area.y - origArea.y) * outputPitch; + + return readPixelsImpl(context, area, format, type, outputPitch, packState, + reinterpret_cast<uint8_t *>(pixels) + outputSkipBytes); +} - return gl::Error(GL_NO_ERROR); +gl::Error FramebufferD3D::blit(const gl::Context *context, + const gl::Rectangle &sourceArea, + const gl::Rectangle &destArea, + GLbitfield mask, + GLenum filter) +{ + const auto &glState = context->getGLState(); + const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer(); + const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr; + ANGLE_TRY(blitImpl(context, sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0, + (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0, + filter, sourceFramebuffer)); + + return gl::NoError(); } -bool FramebufferD3D::checkStatus() const +bool FramebufferD3D::checkStatus(const gl::Context *context) const { // 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 - if (mData.getDepthAttachment() != nullptr && mData.getStencilAttachment() != nullptr && - mData.getDepthStencilAttachment() == nullptr) + if (mState.getDepthAttachment() != nullptr && mState.getStencilAttachment() != nullptr && + mState.getDepthStencilAttachment() == nullptr) { return false; } - // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness - const auto &colorAttachments = mData.getColorAttachments(); - for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++) + // D3D11 does not allow for overlapping RenderTargetViews. + // If WebGL compatibility is enabled, this has already been checked at a higher level. + ASSERT(!context->getExtensions().webglCompatibility || mState.colorAttachmentsAreUniqueImages()); + if (!context->getExtensions().webglCompatibility) { - const gl::FramebufferAttachment &attachment = colorAttachments[colorAttachment]; - if (attachment.isAttached()) + if (!mState.colorAttachmentsAreUniqueImages()) { - for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++) - { - const gl::FramebufferAttachment &prevAttachment = colorAttachments[prevColorAttachment]; - if (prevAttachment.isAttached() && - (attachment.id() == prevAttachment.id() && - attachment.type() == prevAttachment.type())) - { - return false; - } - } + return false; } } // D3D requires all render targets to have the same dimensions. - if (!mData.attachmentsHaveSameDimensions()) + if (!mState.attachmentsHaveSameDimensions()) { return false; } @@ -327,45 +319,52 @@ bool FramebufferD3D::checkStatus() const return true; } -void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) +void FramebufferD3D::syncState(const gl::Context *context, + const gl::Framebuffer::DirtyBits &dirtyBits) { - bool invalidateColorAttachmentCache = false; - if (!mColorAttachmentsForRender.valid()) { - invalidateColorAttachmentCache = true; + return; } - for (auto dirtyBit : angle::IterateBitSet(dirtyBits)) + for (auto dirtyBit : dirtyBits) { if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 && dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) || dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS) { - invalidateColorAttachmentCache = true; + mColorAttachmentsForRender.reset(); } } +} - if (!invalidateColorAttachmentCache) +const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const gl::Context *context) +{ + gl::DrawBufferMask activeProgramOutputs = + context->getContextState().getState().getProgram()->getActiveOutputVariables(); + + if (mColorAttachmentsForRender.valid() && mCurrentActiveProgramOutputs == activeProgramOutputs) { - return; + return mColorAttachmentsForRender.value(); } // Does not actually free memory gl::AttachmentList colorAttachmentsForRender; - const auto &colorAttachments = mData.getColorAttachments(); - const auto &drawBufferStates = mData.getDrawBufferStates(); + const auto &colorAttachments = mState.getColorAttachments(); + const auto &drawBufferStates = mState.getDrawBufferStates(); const auto &workarounds = mRenderer->getWorkarounds(); for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex) { - GLenum drawBufferState = drawBufferStates[attachmentIndex]; + GLenum drawBufferState = drawBufferStates[attachmentIndex]; const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex]; - if (colorAttachment.isAttached() && drawBufferState != GL_NONE) + if (colorAttachment.isAttached() && drawBufferState != GL_NONE && + activeProgramOutputs[attachmentIndex]) { - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); + ASSERT(drawBufferState == GL_BACK || + drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex)); colorAttachmentsForRender.push_back(&colorAttachment); } else if (!workarounds.mrtPerfWorkaround) @@ -374,12 +373,32 @@ void FramebufferD3D::syncState(const gl::Framebuffer::DirtyBits &dirtyBits) } } + // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel + // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel + // shader. We add a dummy texture as render target in such case. + if (mRenderer->getWorkarounds().addDummyTextureNoRenderTarget && + colorAttachmentsForRender.empty()) + { + static_assert(static_cast<size_t>(activeProgramOutputs.size()) <= 32, + "Size of active program outputs should less or equal than 32."); + GLenum i = static_cast<GLenum>( + gl::ScanForward(static_cast<uint32_t>(activeProgramOutputs.bits()))); + + gl::Texture *dummyTex = nullptr; + // TODO(Jamie): Handle error if dummy texture can't be created. + ANGLE_SWALLOW_ERR(mRenderer->getIncompleteTexture(context, GL_TEXTURE_2D, &dummyTex)); + if (dummyTex) + { + gl::ImageIndex index = gl::ImageIndex::Make2D(0); + gl::FramebufferAttachment *dummyAttach = new gl::FramebufferAttachment( + context, GL_TEXTURE, GL_COLOR_ATTACHMENT0_EXT + i, index, dummyTex); + colorAttachmentsForRender.push_back(dummyAttach); + } + } + mColorAttachmentsForRender = std::move(colorAttachmentsForRender); -} + mCurrentActiveProgramOutputs = activeProgramOutputs; -const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender() const -{ - ASSERT(mColorAttachmentsForRender.valid()); return mColorAttachmentsForRender.value(); } |