Commit bf6dc379 by Luc Ferron Committed by Commit Bot

Vulkan: Flip viewport on y for the backbuffer only

- Hide the implementation behind a feature flag, currently disabled permanently as I'm working on fixing the different failures. - SimpleOperationTest.* passing Bug: angleproject:2673 Change-Id: Ic86520c3cc478d62bebbaeaf4c6b33c439a67b0f Reviewed-on: https://chromium-review.googlesource.com/1119089 Commit-Queue: Luc Ferron <lucferron@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 258e8718
......@@ -1522,6 +1522,11 @@ Error Framebuffer::blit(const Context *context,
return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
}
bool Framebuffer::isDefault() const
{
return id() == 0;
}
int Framebuffer::getSamples(const Context *context)
{
return (isComplete(context) ? getCachedSamples(context) : 0);
......
......@@ -287,6 +287,7 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject
const Rectangle &destArea,
GLbitfield mask,
GLenum filter);
bool isDefault() const;
enum DirtyBitType : size_t
{
......
......@@ -378,6 +378,12 @@ void ContextVk::popDebugGroup()
UNIMPLEMENTED();
}
bool ContextVk::isViewportFlipEnabled()
{
gl::Framebuffer *framebuffer = mState.getState().getDrawFramebuffer();
return framebuffer->isDefault() && mRenderer->getFeatures().flipViewportY;
}
void ContextVk::updateColorMask(const gl::BlendState &blendState)
{
mClearColorMask =
......@@ -391,16 +397,20 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState)
void ContextVk::updateScissor(const gl::State &glState)
{
FramebufferVk *framebufferVk = vk::GetImpl(getGLState().getDrawFramebuffer());
gl::Box dimensions = framebufferVk->getState().getDimensions();
gl::Rectangle renderArea(0, 0, dimensions.width, dimensions.height);
if (glState.isScissorTestEnabled())
{
mPipelineDesc->updateScissor(glState.getScissor());
mPipelineDesc->updateScissor(glState.getScissor(), isViewportFlipEnabled(), renderArea);
}
else
{
// If the scissor test isn't enabled, we can simply use a really big scissor that's
// certainly larger than the current surface using the maximum size of a 2D texture
// for the width and height.
mPipelineDesc->updateScissor(kMaxSizedScissor);
mPipelineDesc->updateScissor(kMaxSizedScissor, isViewportFlipEnabled(), renderArea);
}
}
......@@ -426,7 +436,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
break;
case gl::State::DIRTY_BIT_VIEWPORT:
mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
glState.getFarPlane());
glState.getFarPlane(), isViewportFlipEnabled());
break;
case gl::State::DIRTY_BIT_DEPTH_RANGE:
mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
......@@ -495,7 +505,8 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
break;
case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
case gl::State::DIRTY_BIT_CULL_FACE:
mPipelineDesc->updateCullMode(glState.getRasterizerState());
mPipelineDesc->updateCullMode(glState.getRasterizerState(),
isViewportFlipEnabled());
break;
case gl::State::DIRTY_BIT_FRONT_FACE:
mPipelineDesc->updateFrontFace(glState.getRasterizerState());
......@@ -555,7 +566,12 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
WARN() << "DIRTY_BIT_READ_FRAMEBUFFER_BINDING unimplemented";
break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
glState.getFarPlane(), isViewportFlipEnabled());
updateColorMask(glState.getBlendState());
mPipelineDesc->updateCullMode(glState.getRasterizerState(),
isViewportFlipEnabled());
updateScissor(glState);
break;
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented";
......
......@@ -87,6 +87,8 @@ class ContextVk : public ContextImpl
void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
void popDebugGroup() override;
bool isViewportFlipEnabled();
// State sync with dirty bits.
void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override;
......
......@@ -18,6 +18,21 @@ struct FeaturesVk
// shader patching to implement OpenGL basic line rasterization rules. This feature will
// normally always be enabled. Exposing it as an option enables performance testing.
bool basicGLLineRasterization = false;
// Flips the viewport to render upside-down. This has the effect to render the same way as
// OpenGL. If this feature gets enabled, we enable the KHR_MAINTENANCE_1 extension to allow
// negative viewports. We inverse rendering to the backbuffer by reversing the height of the
// viewport and increasing Y by the height. So if the viewport was (0,0,width,height), it
// becomes (0, height, width, -height). Unfortunately, when we start doing this, we also need
// to adjust a lot of places since the rendering now happens upside-down. Affected places so
// far:
// -readPixels
// -copyTexImage
// -framebuffer blit
// -generating mipmaps
// -Point sprites tests
// -texStorage
bool flipViewportY = false;
};
} // namespace rx
......
......@@ -296,20 +296,32 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
// Clip read area to framebuffer.
const gl::Extents &fbSize = getState().getReadAttachment()->getSize();
const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
gl::Rectangle clippedArea;
if (!ClipRectangle(area, fbRect, &clippedArea))
{
// nothing to read
return gl::NoError();
}
gl::Rectangle flippedArea = clippedArea;
if (contextVk->isViewportFlipEnabled())
{
flippedArea.y = fbRect.height - flippedArea.y - flippedArea.height;
}
const gl::State &glState = context->getGLState();
RendererVk *renderer = vk::GetImpl(context)->getRenderer();
vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
const gl::PixelPackState &packState = context->getGLState().getPackState();
gl::PixelPackState packState(context->getGLState().getPackState());
if (contextVk->isViewportFlipEnabled())
{
packState.reverseRowOrder = !packState.reverseRowOrder;
}
const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
GLuint outputPitch = 0;
......@@ -324,14 +336,14 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
(clippedArea.y - area.y) * outputPitch;
PackPixelsParams params;
params.area = clippedArea;
params.area = flippedArea;
params.format = format;
params.type = type;
params.outputPitch = outputPitch;
params.packBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelPack);
params.pack = glState.getPackState();
ANGLE_TRY(readPixelsImpl(context, clippedArea, params,
ANGLE_TRY(readPixelsImpl(context, flippedArea, params,
static_cast<uint8_t *>(pixels) + outputSkipBytes));
mReadPixelsBuffer.releaseRetainedBuffers(renderer);
return gl::NoError();
......@@ -877,7 +889,7 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context,
pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial());
pipelineDesc.updateViewport(renderArea, 0.0f, 1.0f);
pipelineDesc.updateViewport(renderArea, 0.0f, 1.0f, contextVk->isViewportFlipEnabled());
const gl::State &glState = contextVk->getGLState();
if (glState.isScissorTestEnabled())
......@@ -888,11 +900,11 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context,
return gl::NoError();
}
pipelineDesc.updateScissor(intersection);
pipelineDesc.updateScissor(intersection, contextVk->isViewportFlipEnabled(), renderArea);
}
else
{
pipelineDesc.updateScissor(renderArea);
pipelineDesc.updateScissor(renderArea, contextVk->isViewportFlipEnabled(), renderArea);
}
vk::PipelineAndSerial *pipeline = nullptr;
......
......@@ -478,6 +478,12 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
std::vector<const char *> enabledDeviceExtensions;
enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
// Selectively enable KHR_MAINTENANCE1 to support viewport flipping.
if (getFeatures().flipViewportY)
{
enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
}
ANGLE_VK_TRY(VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
VkDeviceQueueCreateInfo queueCreateInfo;
......
......@@ -637,12 +637,21 @@ void PipelineDesc::updateShaders(Serial vertexSerial, Serial fragmentSerial)
static_cast<uint32_t>(fragmentSerial.getValue());
}
void PipelineDesc::updateViewport(const gl::Rectangle &viewport, float nearPlane, float farPlane)
void PipelineDesc::updateViewport(const gl::Rectangle &viewport,
float nearPlane,
float farPlane,
bool invertViewport)
{
mViewport.x = static_cast<float>(viewport.x);
mViewport.y = static_cast<float>(viewport.y);
mViewport.width = static_cast<float>(viewport.width);
mViewport.height = static_cast<float>(viewport.height);
if (invertViewport)
{
mViewport.y += viewport.height;
mViewport.height = -mViewport.height;
}
updateDepthRange(nearPlane, farPlane);
}
......@@ -666,9 +675,10 @@ void PipelineDesc::updateTopology(gl::PrimitiveMode drawMode)
mInputAssemblyInfo.topology = static_cast<uint32_t>(gl_vk::GetPrimitiveTopology(drawMode));
}
void PipelineDesc::updateCullMode(const gl::RasterizerState &rasterState)
void PipelineDesc::updateCullMode(const gl::RasterizerState &rasterState, bool invertCullMode)
{
mRasterizationStateInfo.cullMode = static_cast<uint16_t>(gl_vk::GetCullMode(rasterState));
mRasterizationStateInfo.cullMode =
static_cast<uint16_t>(gl_vk::GetCullMode(rasterState, invertCullMode));
}
void PipelineDesc::updateFrontFace(const gl::RasterizerState &rasterState)
......@@ -805,9 +815,15 @@ void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc)
mRenderPassDesc = renderPassDesc;
}
void PipelineDesc::updateScissor(const gl::Rectangle &rect)
void PipelineDesc::updateScissor(const gl::Rectangle &rect,
bool invertScissor,
const gl::Rectangle &renderArea)
{
mScissor = gl_vk::GetRect(rect);
if (invertScissor)
{
mScissor.offset.y = renderArea.height - mScissor.offset.y - mScissor.extent.height;
}
}
// AttachmentOpsArray implementation.
......
......@@ -350,7 +350,10 @@ class PipelineDesc final
const ShaderModule &fragmentModule,
Pipeline *pipelineOut) const;
void updateViewport(const gl::Rectangle &viewport, float nearPlane, float farPlane);
void updateViewport(const gl::Rectangle &viewport,
float nearPlane,
float farPlane,
bool invertViewport);
void updateDepthRange(float nearPlane, float farPlane);
// Shader stage info
......@@ -365,7 +368,7 @@ class PipelineDesc final
void updateTopology(gl::PrimitiveMode drawMode);
// Raster states
void updateCullMode(const gl::RasterizerState &rasterState);
void updateCullMode(const gl::RasterizerState &rasterState, bool invertCullMode);
void updateFrontFace(const gl::RasterizerState &rasterState);
void updateLineWidth(float lineWidth);
......@@ -375,7 +378,9 @@ class PipelineDesc final
// Scissor support
const VkRect2D &getScissor() const { return mScissor; }
void updateScissor(const gl::Rectangle &rect);
void updateScissor(const gl::Rectangle &rect,
bool invertScissor,
const gl::Rectangle &renderArea);
// Blend states
void updateBlendEnabled(bool isBlendEnabled);
......
......@@ -145,6 +145,11 @@ void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
// Use OpenGL line rasterization rules by default.
features->basicGLLineRasterization = true;
// For now, set this manually to true to enable viewport flipping. A couple of features are not
// working well like copyTexImage, copySubTexImage, blit, and probably some more. Until
// everything is fixed, we will keep the viewport flipping feature disabled.
features->flipViewportY = false;
}
} // namespace vk
......
......@@ -1304,7 +1304,7 @@ VkPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode)
}
}
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState)
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState, bool invertCullMode)
{
if (!rasterState.cullFace)
{
......@@ -1314,9 +1314,9 @@ VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState)
switch (rasterState.cullMode)
{
case gl::CullFaceMode::Front:
return VK_CULL_MODE_FRONT_BIT;
return invertCullMode ? VK_CULL_MODE_BACK_BIT : VK_CULL_MODE_FRONT_BIT;
case gl::CullFaceMode::Back:
return VK_CULL_MODE_BACK_BIT;
return invertCullMode ? VK_CULL_MODE_FRONT_BIT : VK_CULL_MODE_BACK_BIT;
case gl::CullFaceMode::FrontAndBack:
return VK_CULL_MODE_FRONT_AND_BACK;
default:
......
......@@ -706,7 +706,7 @@ VkFilter GetFilter(const GLenum filter);
VkSamplerMipmapMode GetSamplerMipmapMode(const GLenum filter);
VkSamplerAddressMode GetSamplerAddressMode(const GLenum wrap);
VkPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode);
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState);
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState, bool invertCullMode);
VkFrontFace GetFrontFace(GLenum frontFace);
VkSampleCountFlagBits GetSamples(GLint sampleCount);
VkComponentSwizzle GetSwizzle(const GLenum swizzle);
......
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