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, ...@@ -1522,6 +1522,11 @@ Error Framebuffer::blit(const Context *context,
return mImpl->blit(context, sourceArea, destArea, blitMask, filter); return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
} }
bool Framebuffer::isDefault() const
{
return id() == 0;
}
int Framebuffer::getSamples(const Context *context) int Framebuffer::getSamples(const Context *context)
{ {
return (isComplete(context) ? getCachedSamples(context) : 0); return (isComplete(context) ? getCachedSamples(context) : 0);
......
...@@ -287,6 +287,7 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject ...@@ -287,6 +287,7 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject
const Rectangle &destArea, const Rectangle &destArea,
GLbitfield mask, GLbitfield mask,
GLenum filter); GLenum filter);
bool isDefault() const;
enum DirtyBitType : size_t enum DirtyBitType : size_t
{ {
......
...@@ -378,6 +378,12 @@ void ContextVk::popDebugGroup() ...@@ -378,6 +378,12 @@ void ContextVk::popDebugGroup()
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
bool ContextVk::isViewportFlipEnabled()
{
gl::Framebuffer *framebuffer = mState.getState().getDrawFramebuffer();
return framebuffer->isDefault() && mRenderer->getFeatures().flipViewportY;
}
void ContextVk::updateColorMask(const gl::BlendState &blendState) void ContextVk::updateColorMask(const gl::BlendState &blendState)
{ {
mClearColorMask = mClearColorMask =
...@@ -391,16 +397,20 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState) ...@@ -391,16 +397,20 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState)
void ContextVk::updateScissor(const gl::State &glState) 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()) if (glState.isScissorTestEnabled())
{ {
mPipelineDesc->updateScissor(glState.getScissor()); mPipelineDesc->updateScissor(glState.getScissor(), isViewportFlipEnabled(), renderArea);
} }
else else
{ {
// If the scissor test isn't enabled, we can simply use a really big scissor that's // 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 // certainly larger than the current surface using the maximum size of a 2D texture
// for the width and height. // 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 ...@@ -426,7 +436,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
break; break;
case gl::State::DIRTY_BIT_VIEWPORT: case gl::State::DIRTY_BIT_VIEWPORT:
mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(), mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
glState.getFarPlane()); glState.getFarPlane(), isViewportFlipEnabled());
break; break;
case gl::State::DIRTY_BIT_DEPTH_RANGE: case gl::State::DIRTY_BIT_DEPTH_RANGE:
mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane()); mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
...@@ -495,7 +505,8 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -495,7 +505,8 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
break; break;
case gl::State::DIRTY_BIT_CULL_FACE_ENABLED: case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
case gl::State::DIRTY_BIT_CULL_FACE: case gl::State::DIRTY_BIT_CULL_FACE:
mPipelineDesc->updateCullMode(glState.getRasterizerState()); mPipelineDesc->updateCullMode(glState.getRasterizerState(),
isViewportFlipEnabled());
break; break;
case gl::State::DIRTY_BIT_FRONT_FACE: case gl::State::DIRTY_BIT_FRONT_FACE:
mPipelineDesc->updateFrontFace(glState.getRasterizerState()); mPipelineDesc->updateFrontFace(glState.getRasterizerState());
...@@ -555,7 +566,12 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits ...@@ -555,7 +566,12 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
WARN() << "DIRTY_BIT_READ_FRAMEBUFFER_BINDING unimplemented"; WARN() << "DIRTY_BIT_READ_FRAMEBUFFER_BINDING unimplemented";
break; break;
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING: case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
glState.getFarPlane(), isViewportFlipEnabled());
updateColorMask(glState.getBlendState()); updateColorMask(glState.getBlendState());
mPipelineDesc->updateCullMode(glState.getRasterizerState(),
isViewportFlipEnabled());
updateScissor(glState);
break; break;
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING: case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented"; WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented";
......
...@@ -87,6 +87,8 @@ class ContextVk : public ContextImpl ...@@ -87,6 +87,8 @@ class ContextVk : public ContextImpl
void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override; void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
void popDebugGroup() override; void popDebugGroup() override;
bool isViewportFlipEnabled();
// State sync with dirty bits. // State sync with dirty bits.
void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override; void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override;
......
...@@ -18,6 +18,21 @@ struct FeaturesVk ...@@ -18,6 +18,21 @@ struct FeaturesVk
// shader patching to implement OpenGL basic line rasterization rules. This feature will // shader patching to implement OpenGL basic line rasterization rules. This feature will
// normally always be enabled. Exposing it as an option enables performance testing. // normally always be enabled. Exposing it as an option enables performance testing.
bool basicGLLineRasterization = false; 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 } // namespace rx
......
...@@ -296,20 +296,32 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context, ...@@ -296,20 +296,32 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
// Clip read area to framebuffer. // Clip read area to framebuffer.
const gl::Extents &fbSize = getState().getReadAttachment()->getSize(); const gl::Extents &fbSize = getState().getReadAttachment()->getSize();
const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height); const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
ContextVk *contextVk = vk::GetImpl(context);
RendererVk *renderer = contextVk->getRenderer();
gl::Rectangle clippedArea; gl::Rectangle clippedArea;
if (!ClipRectangle(area, fbRect, &clippedArea)) if (!ClipRectangle(area, fbRect, &clippedArea))
{ {
// nothing to read // nothing to read
return gl::NoError(); return gl::NoError();
} }
gl::Rectangle flippedArea = clippedArea;
if (contextVk->isViewportFlipEnabled())
{
flippedArea.y = fbRect.height - flippedArea.y - flippedArea.height;
}
const gl::State &glState = context->getGLState(); const gl::State &glState = context->getGLState();
RendererVk *renderer = vk::GetImpl(context)->getRenderer();
vk::CommandBuffer *commandBuffer = nullptr; vk::CommandBuffer *commandBuffer = nullptr;
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer)); 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); const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
GLuint outputPitch = 0; GLuint outputPitch = 0;
...@@ -324,14 +336,14 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context, ...@@ -324,14 +336,14 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
(clippedArea.y - area.y) * outputPitch; (clippedArea.y - area.y) * outputPitch;
PackPixelsParams params; PackPixelsParams params;
params.area = clippedArea; params.area = flippedArea;
params.format = format; params.format = format;
params.type = type; params.type = type;
params.outputPitch = outputPitch; params.outputPitch = outputPitch;
params.packBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelPack); params.packBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelPack);
params.pack = glState.getPackState(); params.pack = glState.getPackState();
ANGLE_TRY(readPixelsImpl(context, clippedArea, params, ANGLE_TRY(readPixelsImpl(context, flippedArea, params,
static_cast<uint8_t *>(pixels) + outputSkipBytes)); static_cast<uint8_t *>(pixels) + outputSkipBytes));
mReadPixelsBuffer.releaseRetainedBuffers(renderer); mReadPixelsBuffer.releaseRetainedBuffers(renderer);
return gl::NoError(); return gl::NoError();
...@@ -877,7 +889,7 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context, ...@@ -877,7 +889,7 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context,
pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask()); pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
pipelineDesc.updateRenderPassDesc(getRenderPassDesc()); pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial()); 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(); const gl::State &glState = contextVk->getGLState();
if (glState.isScissorTestEnabled()) if (glState.isScissorTestEnabled())
...@@ -888,11 +900,11 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context, ...@@ -888,11 +900,11 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context,
return gl::NoError(); return gl::NoError();
} }
pipelineDesc.updateScissor(intersection); pipelineDesc.updateScissor(intersection, contextVk->isViewportFlipEnabled(), renderArea);
} }
else else
{ {
pipelineDesc.updateScissor(renderArea); pipelineDesc.updateScissor(renderArea, contextVk->isViewportFlipEnabled(), renderArea);
} }
vk::PipelineAndSerial *pipeline = nullptr; vk::PipelineAndSerial *pipeline = nullptr;
......
...@@ -478,6 +478,12 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex) ...@@ -478,6 +478,12 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
std::vector<const char *> enabledDeviceExtensions; std::vector<const char *> enabledDeviceExtensions;
enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); 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)); ANGLE_VK_TRY(VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
VkDeviceQueueCreateInfo queueCreateInfo; VkDeviceQueueCreateInfo queueCreateInfo;
......
...@@ -637,12 +637,21 @@ void PipelineDesc::updateShaders(Serial vertexSerial, Serial fragmentSerial) ...@@ -637,12 +637,21 @@ void PipelineDesc::updateShaders(Serial vertexSerial, Serial fragmentSerial)
static_cast<uint32_t>(fragmentSerial.getValue()); 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.x = static_cast<float>(viewport.x);
mViewport.y = static_cast<float>(viewport.y); mViewport.y = static_cast<float>(viewport.y);
mViewport.width = static_cast<float>(viewport.width); mViewport.width = static_cast<float>(viewport.width);
mViewport.height = static_cast<float>(viewport.height); mViewport.height = static_cast<float>(viewport.height);
if (invertViewport)
{
mViewport.y += viewport.height;
mViewport.height = -mViewport.height;
}
updateDepthRange(nearPlane, farPlane); updateDepthRange(nearPlane, farPlane);
} }
...@@ -666,9 +675,10 @@ void PipelineDesc::updateTopology(gl::PrimitiveMode drawMode) ...@@ -666,9 +675,10 @@ void PipelineDesc::updateTopology(gl::PrimitiveMode drawMode)
mInputAssemblyInfo.topology = static_cast<uint32_t>(gl_vk::GetPrimitiveTopology(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) void PipelineDesc::updateFrontFace(const gl::RasterizerState &rasterState)
...@@ -805,9 +815,15 @@ void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc) ...@@ -805,9 +815,15 @@ void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc)
mRenderPassDesc = 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); mScissor = gl_vk::GetRect(rect);
if (invertScissor)
{
mScissor.offset.y = renderArea.height - mScissor.offset.y - mScissor.extent.height;
}
} }
// AttachmentOpsArray implementation. // AttachmentOpsArray implementation.
......
...@@ -350,7 +350,10 @@ class PipelineDesc final ...@@ -350,7 +350,10 @@ class PipelineDesc final
const ShaderModule &fragmentModule, const ShaderModule &fragmentModule,
Pipeline *pipelineOut) const; 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); void updateDepthRange(float nearPlane, float farPlane);
// Shader stage info // Shader stage info
...@@ -365,7 +368,7 @@ class PipelineDesc final ...@@ -365,7 +368,7 @@ class PipelineDesc final
void updateTopology(gl::PrimitiveMode drawMode); void updateTopology(gl::PrimitiveMode drawMode);
// Raster states // Raster states
void updateCullMode(const gl::RasterizerState &rasterState); void updateCullMode(const gl::RasterizerState &rasterState, bool invertCullMode);
void updateFrontFace(const gl::RasterizerState &rasterState); void updateFrontFace(const gl::RasterizerState &rasterState);
void updateLineWidth(float lineWidth); void updateLineWidth(float lineWidth);
...@@ -375,7 +378,9 @@ class PipelineDesc final ...@@ -375,7 +378,9 @@ class PipelineDesc final
// Scissor support // Scissor support
const VkRect2D &getScissor() const { return mScissor; } 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 // Blend states
void updateBlendEnabled(bool isBlendEnabled); void updateBlendEnabled(bool isBlendEnabled);
......
...@@ -145,6 +145,11 @@ void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties, ...@@ -145,6 +145,11 @@ void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
// Use OpenGL line rasterization rules by default. // Use OpenGL line rasterization rules by default.
features->basicGLLineRasterization = true; 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 } // namespace vk
......
...@@ -1304,7 +1304,7 @@ VkPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode) ...@@ -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) if (!rasterState.cullFace)
{ {
...@@ -1314,9 +1314,9 @@ VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState) ...@@ -1314,9 +1314,9 @@ VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState)
switch (rasterState.cullMode) switch (rasterState.cullMode)
{ {
case gl::CullFaceMode::Front: 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: 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: case gl::CullFaceMode::FrontAndBack:
return VK_CULL_MODE_FRONT_AND_BACK; return VK_CULL_MODE_FRONT_AND_BACK;
default: default:
......
...@@ -706,7 +706,7 @@ VkFilter GetFilter(const GLenum filter); ...@@ -706,7 +706,7 @@ VkFilter GetFilter(const GLenum filter);
VkSamplerMipmapMode GetSamplerMipmapMode(const GLenum filter); VkSamplerMipmapMode GetSamplerMipmapMode(const GLenum filter);
VkSamplerAddressMode GetSamplerAddressMode(const GLenum wrap); VkSamplerAddressMode GetSamplerAddressMode(const GLenum wrap);
VkPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode); VkPrimitiveTopology GetPrimitiveTopology(gl::PrimitiveMode mode);
VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState); VkCullModeFlags GetCullMode(const gl::RasterizerState &rasterState, bool invertCullMode);
VkFrontFace GetFrontFace(GLenum frontFace); VkFrontFace GetFrontFace(GLenum frontFace);
VkSampleCountFlagBits GetSamples(GLint sampleCount); VkSampleCountFlagBits GetSamples(GLint sampleCount);
VkComponentSwizzle GetSwizzle(const GLenum swizzle); 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