Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit bf6dc37

Browse files
lucferronCommit Bot
authored andcommitted
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 <[email protected]> Reviewed-by: Geoff Lang <[email protected]>
1 parent 258e871 commit bf6dc37

File tree

12 files changed

+105
-22
lines changed

12 files changed

+105
-22
lines changed

src/libANGLE/Framebuffer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,11 @@ Error Framebuffer::blit(const Context *context,
15221522
return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
15231523
}
15241524

1525+
bool Framebuffer::isDefault() const
1526+
{
1527+
return id() == 0;
1528+
}
1529+
15251530
int Framebuffer::getSamples(const Context *context)
15261531
{
15271532
return (isComplete(context) ? getCachedSamples(context) : 0);

src/libANGLE/Framebuffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject
287287
const Rectangle &destArea,
288288
GLbitfield mask,
289289
GLenum filter);
290+
bool isDefault() const;
290291

291292
enum DirtyBitType : size_t
292293
{

src/libANGLE/renderer/vulkan/ContextVk.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,12 @@ void ContextVk::popDebugGroup()
378378
UNIMPLEMENTED();
379379
}
380380

381+
bool ContextVk::isViewportFlipEnabled()
382+
{
383+
gl::Framebuffer *framebuffer = mState.getState().getDrawFramebuffer();
384+
return framebuffer->isDefault() && mRenderer->getFeatures().flipViewportY;
385+
}
386+
381387
void ContextVk::updateColorMask(const gl::BlendState &blendState)
382388
{
383389
mClearColorMask =
@@ -391,16 +397,20 @@ void ContextVk::updateColorMask(const gl::BlendState &blendState)
391397

392398
void ContextVk::updateScissor(const gl::State &glState)
393399
{
400+
FramebufferVk *framebufferVk = vk::GetImpl(getGLState().getDrawFramebuffer());
401+
gl::Box dimensions = framebufferVk->getState().getDimensions();
402+
gl::Rectangle renderArea(0, 0, dimensions.width, dimensions.height);
403+
394404
if (glState.isScissorTestEnabled())
395405
{
396-
mPipelineDesc->updateScissor(glState.getScissor());
406+
mPipelineDesc->updateScissor(glState.getScissor(), isViewportFlipEnabled(), renderArea);
397407
}
398408
else
399409
{
400410
// If the scissor test isn't enabled, we can simply use a really big scissor that's
401411
// certainly larger than the current surface using the maximum size of a 2D texture
402412
// for the width and height.
403-
mPipelineDesc->updateScissor(kMaxSizedScissor);
413+
mPipelineDesc->updateScissor(kMaxSizedScissor, isViewportFlipEnabled(), renderArea);
404414
}
405415
}
406416

@@ -426,7 +436,7 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
426436
break;
427437
case gl::State::DIRTY_BIT_VIEWPORT:
428438
mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
429-
glState.getFarPlane());
439+
glState.getFarPlane(), isViewportFlipEnabled());
430440
break;
431441
case gl::State::DIRTY_BIT_DEPTH_RANGE:
432442
mPipelineDesc->updateDepthRange(glState.getNearPlane(), glState.getFarPlane());
@@ -495,7 +505,8 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
495505
break;
496506
case gl::State::DIRTY_BIT_CULL_FACE_ENABLED:
497507
case gl::State::DIRTY_BIT_CULL_FACE:
498-
mPipelineDesc->updateCullMode(glState.getRasterizerState());
508+
mPipelineDesc->updateCullMode(glState.getRasterizerState(),
509+
isViewportFlipEnabled());
499510
break;
500511
case gl::State::DIRTY_BIT_FRONT_FACE:
501512
mPipelineDesc->updateFrontFace(glState.getRasterizerState());
@@ -555,7 +566,12 @@ void ContextVk::syncState(const gl::Context *context, const gl::State::DirtyBits
555566
WARN() << "DIRTY_BIT_READ_FRAMEBUFFER_BINDING unimplemented";
556567
break;
557568
case gl::State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING:
569+
mPipelineDesc->updateViewport(glState.getViewport(), glState.getNearPlane(),
570+
glState.getFarPlane(), isViewportFlipEnabled());
558571
updateColorMask(glState.getBlendState());
572+
mPipelineDesc->updateCullMode(glState.getRasterizerState(),
573+
isViewportFlipEnabled());
574+
updateScissor(glState);
559575
break;
560576
case gl::State::DIRTY_BIT_RENDERBUFFER_BINDING:
561577
WARN() << "DIRTY_BIT_RENDERBUFFER_BINDING unimplemented";

src/libANGLE/renderer/vulkan/ContextVk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ class ContextVk : public ContextImpl
8787
void pushDebugGroup(GLenum source, GLuint id, GLsizei length, const char *message) override;
8888
void popDebugGroup() override;
8989

90+
bool isViewportFlipEnabled();
91+
9092
// State sync with dirty bits.
9193
void syncState(const gl::Context *context, const gl::State::DirtyBits &dirtyBits) override;
9294

src/libANGLE/renderer/vulkan/FeaturesVk.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,21 @@ struct FeaturesVk
1818
// shader patching to implement OpenGL basic line rasterization rules. This feature will
1919
// normally always be enabled. Exposing it as an option enables performance testing.
2020
bool basicGLLineRasterization = false;
21+
22+
// Flips the viewport to render upside-down. This has the effect to render the same way as
23+
// OpenGL. If this feature gets enabled, we enable the KHR_MAINTENANCE_1 extension to allow
24+
// negative viewports. We inverse rendering to the backbuffer by reversing the height of the
25+
// viewport and increasing Y by the height. So if the viewport was (0,0,width,height), it
26+
// becomes (0, height, width, -height). Unfortunately, when we start doing this, we also need
27+
// to adjust a lot of places since the rendering now happens upside-down. Affected places so
28+
// far:
29+
// -readPixels
30+
// -copyTexImage
31+
// -framebuffer blit
32+
// -generating mipmaps
33+
// -Point sprites tests
34+
// -texStorage
35+
bool flipViewportY = false;
2136
};
2237
} // namespace rx
2338

src/libANGLE/renderer/vulkan/FramebufferVk.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -296,20 +296,32 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
296296
// Clip read area to framebuffer.
297297
const gl::Extents &fbSize = getState().getReadAttachment()->getSize();
298298
const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
299+
ContextVk *contextVk = vk::GetImpl(context);
300+
RendererVk *renderer = contextVk->getRenderer();
301+
299302
gl::Rectangle clippedArea;
300303
if (!ClipRectangle(area, fbRect, &clippedArea))
301304
{
302305
// nothing to read
303306
return gl::NoError();
304307
}
308+
gl::Rectangle flippedArea = clippedArea;
309+
if (contextVk->isViewportFlipEnabled())
310+
{
311+
flippedArea.y = fbRect.height - flippedArea.y - flippedArea.height;
312+
}
305313

306314
const gl::State &glState = context->getGLState();
307-
RendererVk *renderer = vk::GetImpl(context)->getRenderer();
308315

309316
vk::CommandBuffer *commandBuffer = nullptr;
310317
ANGLE_TRY(beginWriteResource(renderer, &commandBuffer));
311318

312-
const gl::PixelPackState &packState = context->getGLState().getPackState();
319+
gl::PixelPackState packState(context->getGLState().getPackState());
320+
if (contextVk->isViewportFlipEnabled())
321+
{
322+
packState.reverseRowOrder = !packState.reverseRowOrder;
323+
}
324+
313325
const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
314326

315327
GLuint outputPitch = 0;
@@ -324,14 +336,14 @@ gl::Error FramebufferVk::readPixels(const gl::Context *context,
324336
(clippedArea.y - area.y) * outputPitch;
325337

326338
PackPixelsParams params;
327-
params.area = clippedArea;
339+
params.area = flippedArea;
328340
params.format = format;
329341
params.type = type;
330342
params.outputPitch = outputPitch;
331343
params.packBuffer = glState.getTargetBuffer(gl::BufferBinding::PixelPack);
332344
params.pack = glState.getPackState();
333345

334-
ANGLE_TRY(readPixelsImpl(context, clippedArea, params,
346+
ANGLE_TRY(readPixelsImpl(context, flippedArea, params,
335347
static_cast<uint8_t *>(pixels) + outputSkipBytes));
336348
mReadPixelsBuffer.releaseRetainedBuffers(renderer);
337349
return gl::NoError();
@@ -877,7 +889,7 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context,
877889
pipelineDesc.updateColorWriteMask(colorMaskFlags, getEmulatedAlphaAttachmentMask());
878890
pipelineDesc.updateRenderPassDesc(getRenderPassDesc());
879891
pipelineDesc.updateShaders(fullScreenQuad->queueSerial(), pushConstantColor->queueSerial());
880-
pipelineDesc.updateViewport(renderArea, 0.0f, 1.0f);
892+
pipelineDesc.updateViewport(renderArea, 0.0f, 1.0f, contextVk->isViewportFlipEnabled());
881893

882894
const gl::State &glState = contextVk->getGLState();
883895
if (glState.isScissorTestEnabled())
@@ -888,11 +900,11 @@ gl::Error FramebufferVk::clearWithDraw(const gl::Context *context,
888900
return gl::NoError();
889901
}
890902

891-
pipelineDesc.updateScissor(intersection);
903+
pipelineDesc.updateScissor(intersection, contextVk->isViewportFlipEnabled(), renderArea);
892904
}
893905
else
894906
{
895-
pipelineDesc.updateScissor(renderArea);
907+
pipelineDesc.updateScissor(renderArea, contextVk->isViewportFlipEnabled(), renderArea);
896908
}
897909

898910
vk::PipelineAndSerial *pipeline = nullptr;

src/libANGLE/renderer/vulkan/RendererVk.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,12 @@ vk::Error RendererVk::initializeDevice(uint32_t queueFamilyIndex)
478478
std::vector<const char *> enabledDeviceExtensions;
479479
enabledDeviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
480480

481+
// Selectively enable KHR_MAINTENANCE1 to support viewport flipping.
482+
if (getFeatures().flipViewportY)
483+
{
484+
enabledDeviceExtensions.push_back(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
485+
}
486+
481487
ANGLE_VK_TRY(VerifyExtensionsPresent(deviceExtensionProps, enabledDeviceExtensions));
482488

483489
VkDeviceQueueCreateInfo queueCreateInfo;

src/libANGLE/renderer/vulkan/vk_cache_utils.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -637,12 +637,21 @@ void PipelineDesc::updateShaders(Serial vertexSerial, Serial fragmentSerial)
637637
static_cast<uint32_t>(fragmentSerial.getValue());
638638
}
639639

640-
void PipelineDesc::updateViewport(const gl::Rectangle &viewport, float nearPlane, float farPlane)
640+
void PipelineDesc::updateViewport(const gl::Rectangle &viewport,
641+
float nearPlane,
642+
float farPlane,
643+
bool invertViewport)
641644
{
642645
mViewport.x = static_cast<float>(viewport.x);
643646
mViewport.y = static_cast<float>(viewport.y);
644647
mViewport.width = static_cast<float>(viewport.width);
645648
mViewport.height = static_cast<float>(viewport.height);
649+
650+
if (invertViewport)
651+
{
652+
mViewport.y += viewport.height;
653+
mViewport.height = -mViewport.height;
654+
}
646655
updateDepthRange(nearPlane, farPlane);
647656
}
648657

@@ -666,9 +675,10 @@ void PipelineDesc::updateTopology(gl::PrimitiveMode drawMode)
666675
mInputAssemblyInfo.topology = static_cast<uint32_t>(gl_vk::GetPrimitiveTopology(drawMode));
667676
}
668677

669-
void PipelineDesc::updateCullMode(const gl::RasterizerState &rasterState)
678+
void PipelineDesc::updateCullMode(const gl::RasterizerState &rasterState, bool invertCullMode)
670679
{
671-
mRasterizationStateInfo.cullMode = static_cast<uint16_t>(gl_vk::GetCullMode(rasterState));
680+
mRasterizationStateInfo.cullMode =
681+
static_cast<uint16_t>(gl_vk::GetCullMode(rasterState, invertCullMode));
672682
}
673683

674684
void PipelineDesc::updateFrontFace(const gl::RasterizerState &rasterState)
@@ -805,9 +815,15 @@ void PipelineDesc::updateRenderPassDesc(const RenderPassDesc &renderPassDesc)
805815
mRenderPassDesc = renderPassDesc;
806816
}
807817

808-
void PipelineDesc::updateScissor(const gl::Rectangle &rect)
818+
void PipelineDesc::updateScissor(const gl::Rectangle &rect,
819+
bool invertScissor,
820+
const gl::Rectangle &renderArea)
809821
{
810822
mScissor = gl_vk::GetRect(rect);
823+
if (invertScissor)
824+
{
825+
mScissor.offset.y = renderArea.height - mScissor.offset.y - mScissor.extent.height;
826+
}
811827
}
812828

813829
// AttachmentOpsArray implementation.

src/libANGLE/renderer/vulkan/vk_cache_utils.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,10 @@ class PipelineDesc final
350350
const ShaderModule &fragmentModule,
351351
Pipeline *pipelineOut) const;
352352

353-
void updateViewport(const gl::Rectangle &viewport, float nearPlane, float farPlane);
353+
void updateViewport(const gl::Rectangle &viewport,
354+
float nearPlane,
355+
float farPlane,
356+
bool invertViewport);
354357
void updateDepthRange(float nearPlane, float farPlane);
355358

356359
// Shader stage info
@@ -365,7 +368,7 @@ class PipelineDesc final
365368
void updateTopology(gl::PrimitiveMode drawMode);
366369

367370
// Raster states
368-
void updateCullMode(const gl::RasterizerState &rasterState);
371+
void updateCullMode(const gl::RasterizerState &rasterState, bool invertCullMode);
369372
void updateFrontFace(const gl::RasterizerState &rasterState);
370373
void updateLineWidth(float lineWidth);
371374

@@ -375,7 +378,9 @@ class PipelineDesc final
375378

376379
// Scissor support
377380
const VkRect2D &getScissor() const { return mScissor; }
378-
void updateScissor(const gl::Rectangle &rect);
381+
void updateScissor(const gl::Rectangle &rect,
382+
bool invertScissor,
383+
const gl::Rectangle &renderArea);
379384

380385
// Blend states
381386
void updateBlendEnabled(bool isBlendEnabled);

src/libANGLE/renderer/vulkan/vk_caps_utils.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,11 @@ void GenerateCaps(const VkPhysicalDeviceProperties &physicalDeviceProperties,
145145

146146
// Use OpenGL line rasterization rules by default.
147147
features->basicGLLineRasterization = true;
148+
149+
// For now, set this manually to true to enable viewport flipping. A couple of features are not
150+
// working well like copyTexImage, copySubTexImage, blit, and probably some more. Until
151+
// everything is fixed, we will keep the viewport flipping feature disabled.
152+
features->flipViewportY = false;
148153
}
149154
} // namespace vk
150155

0 commit comments

Comments
 (0)