Commit 80a4223e by Mohan Maiya Committed by Commit Bot

Vulkan: Handle changes to viewport when clip origin is modified

The expected view port is different from current viewport translation when the clip origin is the upper left. So now, it has four different view port translations based on clip origin and y-flip of framebuffer. - add query and state management for EXT_clip_control - add dirty bit for clip control - change viewport, scissor and cull face when clip origin changes Bug: angleproject:5471 Tests: dEQP-GLES2.functional.clip_control.* Change-Id: I78dc752c3287b09f25496034e0d0d2724138010c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2615863 Commit-Queue: Mohan Maiya <m.maiya@samsung.com> Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 6cfbe252
...@@ -1035,6 +1035,7 @@ const ExtensionInfoMap &GetExtensionInfoMap() ...@@ -1035,6 +1035,7 @@ const ExtensionInfoMap &GetExtensionInfoMap()
map["GL_EXT_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexEXT); map["GL_EXT_draw_elements_base_vertex"] = enableableExtension(&Extensions::drawElementsBaseVertexEXT);
map["GL_EXT_gpu_shader5"] = enableableExtension(&Extensions::gpuShader5EXT); map["GL_EXT_gpu_shader5"] = enableableExtension(&Extensions::gpuShader5EXT);
map["GL_APPLE_clip_distance"] = enableableExtension(&Extensions::clipDistanceAPPLE); map["GL_APPLE_clip_distance"] = enableableExtension(&Extensions::clipDistanceAPPLE);
map["GL_EXT_clip_control"] = enableableExtension(&Extensions::clipControlEXT);
map["GL_EXT_EGL_image_array"] = enableableExtension(&Extensions::eglImageArray); map["GL_EXT_EGL_image_array"] = enableableExtension(&Extensions::eglImageArray);
map["GL_EXT_buffer_storage"] = enableableExtension(&Extensions::bufferStorageEXT); map["GL_EXT_buffer_storage"] = enableableExtension(&Extensions::bufferStorageEXT);
map["GL_EXT_external_buffer"] = enableableExtension(&Extensions::externalBufferEXT); map["GL_EXT_external_buffer"] = enableableExtension(&Extensions::externalBufferEXT);
......
...@@ -655,6 +655,9 @@ struct Extensions ...@@ -655,6 +655,9 @@ struct Extensions
// GL_APPLE_clip_distance // GL_APPLE_clip_distance
bool clipDistanceAPPLE = false; bool clipDistanceAPPLE = false;
// GL_EXT_clip_control
bool clipControlEXT = false;
// GL_OES_texture_cube_map_array // GL_OES_texture_cube_map_array
bool textureCubeMapArrayOES = false; bool textureCubeMapArrayOES = false;
// GL_EXT_texture_cube_map_array // GL_EXT_texture_cube_map_array
......
...@@ -2020,6 +2020,14 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const ...@@ -2020,6 +2020,14 @@ void Context::getIntegervImpl(GLenum pname, GLint *params) const
*params = mState.mCaps.textureBufferOffsetAlignment; *params = mState.mCaps.textureBufferOffsetAlignment;
break; break;
// GL_EXT_clip_control
case GL_CLIP_ORIGIN_EXT:
*params = mState.mClipControlOrigin;
break;
case GL_CLIP_DEPTH_MODE_EXT:
*params = mState.mClipControlDepth;
break;
default: default:
ANGLE_CONTEXT_TRY(mState.getIntegerv(this, pname, params)); ANGLE_CONTEXT_TRY(mState.getIntegerv(this, pname, params));
break; break;
...@@ -5287,6 +5295,11 @@ void Context::depthRangef(GLfloat zNear, GLfloat zFar) ...@@ -5287,6 +5295,11 @@ void Context::depthRangef(GLfloat zNear, GLfloat zFar)
mState.setDepthRange(clamp01(zNear), clamp01(zFar)); mState.setDepthRange(clamp01(zNear), clamp01(zFar));
} }
void Context::clipControl(GLenum origin, GLenum depth)
{
mState.setClipControl(origin, depth);
}
void Context::disable(GLenum cap) void Context::disable(GLenum cap)
{ {
mState.setEnableFeature(cap, false); mState.setEnableFeature(cap, false);
......
...@@ -2935,11 +2935,6 @@ void Context::clearNamedFramebufferuiv(FramebufferID framebuffer, ...@@ -2935,11 +2935,6 @@ void Context::clearNamedFramebufferuiv(FramebufferID framebuffer,
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
void Context::clipControl(GLenum origin, GLenum depth)
{
UNIMPLEMENTED();
}
void Context::compressedTextureSubImage1D(TextureID texture, void Context::compressedTextureSubImage1D(TextureID texture,
GLint level, GLint level,
GLint xoffset, GLint xoffset,
......
...@@ -416,6 +416,9 @@ void State::initialize(Context *context) ...@@ -416,6 +416,9 @@ void State::initialize(Context *context)
mNearZ = 0.0f; mNearZ = 0.0f;
mFarZ = 1.0f; mFarZ = 1.0f;
mClipControlOrigin = GL_LOWER_LEFT_EXT;
mClipControlDepth = GL_NEGATIVE_ONE_TO_ONE_EXT;
mActiveSampler = 0; mActiveSampler = 0;
mVertexAttribCurrentValues.resize(caps.maxVertexAttributes); mVertexAttribCurrentValues.resize(caps.maxVertexAttributes);
...@@ -817,6 +820,21 @@ void State::setDepthRange(float zNear, float zFar) ...@@ -817,6 +820,21 @@ void State::setDepthRange(float zNear, float zFar)
} }
} }
void State::setClipControl(GLenum origin, GLenum depth)
{
if (mClipControlOrigin != origin)
{
mClipControlOrigin = origin;
mDirtyBits.set(DIRTY_BIT_EXTENDED);
}
if (mClipControlDepth != depth)
{
mClipControlDepth = depth;
mDirtyBits.set(DIRTY_BIT_EXTENDED);
}
}
void State::setBlend(bool enabled) void State::setBlend(bool enabled)
{ {
mBlendState.blend = enabled; mBlendState.blend = enabled;
...@@ -2366,6 +2384,16 @@ void State::getBooleanv(GLenum pname, GLboolean *params) const ...@@ -2366,6 +2384,16 @@ void State::getBooleanv(GLenum pname, GLboolean *params) const
case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED: case GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED:
*params = isPrimitiveRestartEnabled() && getExtensions().tessellationShaderEXT; *params = isPrimitiveRestartEnabled() && getExtensions().tessellationShaderEXT;
break; break;
// 2.2.2 Data Conversions For State Query Commands, in GLES 3.2 spec.
// If a command returning boolean data is called, such as GetBooleanv, a floating-point or
// integer value converts to FALSE if and only if it is zero. Otherwise it converts to TRUE.
// GL_EXT_clip_control
case GL_CLIP_ORIGIN_EXT:
*params = GL_TRUE;
break;
case GL_CLIP_DEPTH_MODE_EXT:
*params = GL_TRUE;
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
...@@ -2482,6 +2510,15 @@ void State::getFloatv(GLenum pname, GLfloat *params) const ...@@ -2482,6 +2510,15 @@ void State::getFloatv(GLenum pname, GLfloat *params) const
case GL_MIN_SAMPLE_SHADING_VALUE: case GL_MIN_SAMPLE_SHADING_VALUE:
*params = mMinSampleShading; *params = mMinSampleShading;
break; break;
// 2.2.2 Data Conversions For State Query Commands, in GLES 3.2 spec.
// If a command returning floating-point data is called, such as GetFloatv, ... An integer
// value is coerced to floating-point.
case GL_CLIP_ORIGIN_EXT:
*params = static_cast<float>(mClipControlOrigin);
break;
case GL_CLIP_DEPTH_MODE_EXT:
*params = static_cast<float>(mClipControlDepth);
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
...@@ -2948,6 +2985,13 @@ angle::Result State::getIntegerv(const Context *context, GLenum pname, GLint *pa ...@@ -2948,6 +2985,13 @@ angle::Result State::getIntegerv(const Context *context, GLenum pname, GLint *pa
*params = mPatchVertices; *params = mPatchVertices;
break; break;
// GL_EXT_clip_control
case GL_CLIP_ORIGIN_EXT:
*params = mClipControlOrigin;
break;
case GL_CLIP_DEPTH_MODE_EXT:
*params = mClipControlDepth;
break;
default: default:
UNREACHABLE(); UNREACHABLE();
break; break;
......
...@@ -173,6 +173,15 @@ class State : angle::NonCopyable ...@@ -173,6 +173,15 @@ class State : angle::NonCopyable
float getNearPlane() const { return mNearZ; } float getNearPlane() const { return mNearZ; }
float getFarPlane() const { return mFarZ; } float getFarPlane() const { return mFarZ; }
// Clip control extension
void setClipControl(GLenum origin, GLenum depth);
bool isClipControlDepthZeroToOne() const { return mClipControlDepth == GL_ZERO_TO_ONE_EXT; }
gl::ClipSpaceOrigin getClipSpaceOrigin() const
{
return mClipControlOrigin == GL_UPPER_LEFT_EXT ? ClipSpaceOrigin::UpperLeft
: ClipSpaceOrigin::LowerLeft;
}
// Blend state manipulation // Blend state manipulation
bool isBlendEnabled() const { return mBlendStateExt.mEnabledMask.test(0); } bool isBlendEnabled() const { return mBlendStateExt.mEnabledMask.test(0); }
bool isBlendEnabledIndexed(GLuint index) const bool isBlendEnabledIndexed(GLuint index) const
...@@ -651,7 +660,8 @@ class State : angle::NonCopyable ...@@ -651,7 +660,8 @@ class State : angle::NonCopyable
DIRTY_BIT_PROVOKING_VERTEX, DIRTY_BIT_PROVOKING_VERTEX,
DIRTY_BIT_SAMPLE_SHADING, DIRTY_BIT_SAMPLE_SHADING,
DIRTY_BIT_PATCH_VERTICES, DIRTY_BIT_PATCH_VERTICES,
DIRTY_BIT_EXTENDED, // clip distances, mipmap generation hint, derivative hint. DIRTY_BIT_EXTENDED, // clip distances, mipmap generation hint, derivative hint,
// EXT_clip_control
DIRTY_BIT_INVALID, DIRTY_BIT_INVALID,
DIRTY_BIT_MAX = DIRTY_BIT_INVALID, DIRTY_BIT_MAX = DIRTY_BIT_INVALID,
}; };
...@@ -989,6 +999,9 @@ class State : angle::NonCopyable ...@@ -989,6 +999,9 @@ class State : angle::NonCopyable
float mNearZ; float mNearZ;
float mFarZ; float mFarZ;
GLenum mClipControlOrigin;
GLenum mClipControlDepth;
Framebuffer *mReadFramebuffer; Framebuffer *mReadFramebuffer;
Framebuffer *mDrawFramebuffer; Framebuffer *mDrawFramebuffer;
BindingPointer<Renderbuffer> mRenderbuffer; BindingPointer<Renderbuffer> mRenderbuffer;
......
...@@ -83,6 +83,12 @@ struct Rectangle ...@@ -83,6 +83,12 @@ struct Rectangle
bool operator==(const Rectangle &a, const Rectangle &b); bool operator==(const Rectangle &a, const Rectangle &b);
bool operator!=(const Rectangle &a, const Rectangle &b); bool operator!=(const Rectangle &a, const Rectangle &b);
enum class ClipSpaceOrigin
{
LowerLeft = 0,
UpperLeft = 1
};
// Calculate the intersection of two rectangles. Returns false if the intersection is empty. // Calculate the intersection of two rectangles. Returns false if the intersection is empty.
bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection); bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
// Calculate the smallest rectangle that covers both rectangles. This rectangle may cover areas // Calculate the smallest rectangle that covers both rectangles. This rectangle may cover areas
......
...@@ -3270,6 +3270,7 @@ bool GetQueryParameterInfo(const State &glState, ...@@ -3270,6 +3270,7 @@ bool GetQueryParameterInfo(const State &glState,
*numParams = 1; *numParams = 1;
return true; return true;
case GL_MAX_CULL_DISTANCES_EXT: case GL_MAX_CULL_DISTANCES_EXT:
case GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT:
if (!extensions.clipCullDistanceEXT) if (!extensions.clipCullDistanceEXT)
{ {
return false; return false;
...@@ -3277,8 +3278,9 @@ bool GetQueryParameterInfo(const State &glState, ...@@ -3277,8 +3278,9 @@ bool GetQueryParameterInfo(const State &glState,
*type = GL_INT; *type = GL_INT;
*numParams = 1; *numParams = 1;
return true; return true;
case GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT: case GL_CLIP_ORIGIN_EXT:
if (!extensions.clipCullDistanceEXT) case GL_CLIP_DEPTH_MODE_EXT:
if (!extensions.clipControlEXT)
{ {
return false; return false;
} }
......
...@@ -2071,6 +2071,7 @@ angle::Result StateManagerGL::syncState(const gl::Context *context, ...@@ -2071,6 +2071,7 @@ angle::Result StateManagerGL::syncState(const gl::Context *context,
setClipDistancesEnable(state.getEnabledClipDistances()); setClipDistancesEnable(state.getEnabledClipDistances());
// TODO(jmadill): handle mipmap generation hint // TODO(jmadill): handle mipmap generation hint
// TODO(jmadill): handle shader derivative hint // TODO(jmadill): handle shader derivative hint
// Nothing to do until EXT_clip_contorl is implemented.
break; break;
case gl::State::DIRTY_BIT_SAMPLE_SHADING: case gl::State::DIRTY_BIT_SAMPLE_SHADING:
// Nothing to do until OES_sample_shading is implemented. // Nothing to do until OES_sample_shading is implemented.
......
...@@ -1044,6 +1044,7 @@ angle::Result ContextMtl::syncState(const gl::Context *context, ...@@ -1044,6 +1044,7 @@ angle::Result ContextMtl::syncState(const gl::Context *context,
break; break;
case gl::State::DIRTY_BIT_EXTENDED: case gl::State::DIRTY_BIT_EXTENDED:
updateExtendedState(glState); updateExtendedState(glState);
// Nothing to do until EXT_clip_control is implemented.
break; break;
case gl::State::DIRTY_BIT_SAMPLE_SHADING: case gl::State::DIRTY_BIT_SAMPLE_SHADING:
// Nothing to do until OES_sample_shading is implemented. // Nothing to do until OES_sample_shading is implemented.
......
...@@ -368,6 +368,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk ...@@ -368,6 +368,7 @@ ContextVk::ContextVk(const gl::State &state, gl::ErrorSet *errorSet, RendererVk
mXfbVertexCountPerInstance(0), mXfbVertexCountPerInstance(0),
mClearColorMasks(0), mClearColorMasks(0),
mFlipYForCurrentSurface(false), mFlipYForCurrentSurface(false),
mClipSpaceOrigin(gl::ClipSpaceOrigin::LowerLeft),
mIsAnyHostVisibleBufferWritten(false), mIsAnyHostVisibleBufferWritten(false),
mEmulateSeamfulCubeMapSampling(false), mEmulateSeamfulCubeMapSampling(false),
mOutsideRenderPassCommands(nullptr), mOutsideRenderPassCommands(nullptr),
...@@ -2642,11 +2643,15 @@ void ContextVk::updateViewport(FramebufferVk *framebufferVk, ...@@ -2642,11 +2643,15 @@ void ContextVk::updateViewport(FramebufferVk *framebufferVk,
correctedRect, &rotatedRect); correctedRect, &rotatedRect);
VkViewport vkViewport; VkViewport vkViewport;
gl_vk::GetViewport(rotatedRect, nearPlane, farPlane, invertViewport, gl_vk::GetViewport(
// If the surface is rotated 90/270 degrees, use the framebuffer's width rotatedRect, nearPlane, farPlane, invertViewport,
// instead of the height for calculating the final viewport. // If clip space origin is upper left, viewport origin's y value will be offset by the
isRotatedAspectRatioForDrawFBO() ? fbDimensions.width : fbDimensions.height, // height of the viewport when clip space is mapped into screen space.
&vkViewport); mClipSpaceOrigin == gl::ClipSpaceOrigin::UpperLeft,
// If the surface is rotated 90/270 degrees, use the framebuffer's width instead of the
// height for calculating the final viewport.
isRotatedAspectRatioForDrawFBO() ? fbDimensions.width : fbDimensions.height, &vkViewport);
mGraphicsPipelineDesc->updateViewport(&mGraphicsPipelineTransition, vkViewport); mGraphicsPipelineDesc->updateViewport(&mGraphicsPipelineTransition, vkViewport);
invalidateGraphicsDriverUniforms(); invalidateGraphicsDriverUniforms();
} }
...@@ -2904,7 +2909,7 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2904,7 +2909,7 @@ angle::Result ContextVk::syncState(const gl::Context *context,
case gl::State::DIRTY_BIT_FRONT_FACE: case gl::State::DIRTY_BIT_FRONT_FACE:
mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
glState.getRasterizerState(), glState.getRasterizerState(),
isViewportFlipEnabledForDrawFBO()); isYFlipEnabledForDrawFBO());
break; break;
case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED: case gl::State::DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED:
mGraphicsPipelineDesc->updatePolygonOffsetFillEnabled( mGraphicsPipelineDesc->updatePolygonOffsetFillEnabled(
...@@ -2980,9 +2985,10 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -2980,9 +2985,10 @@ angle::Result ContextVk::syncState(const gl::Context *context,
glState.getFarPlane(), isViewportFlipEnabledForDrawFBO()); glState.getFarPlane(), isViewportFlipEnabledForDrawFBO());
updateColorMasks(glState.getBlendStateExt()); updateColorMasks(glState.getBlendStateExt());
updateRasterizationSamples(mDrawFramebuffer->getSamples()); updateRasterizationSamples(mDrawFramebuffer->getSamples());
mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
glState.getRasterizerState(), glState.getRasterizerState(),
isViewportFlipEnabledForDrawFBO()); isYFlipEnabledForDrawFBO());
updateScissor(glState); updateScissor(glState);
const gl::DepthStencilState depthStencilState = glState.getDepthStencilState(); const gl::DepthStencilState depthStencilState = glState.getDepthStencilState();
mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updateDepthTestEnabled(&mGraphicsPipelineTransition,
...@@ -3079,10 +3085,30 @@ angle::Result ContextVk::syncState(const gl::Context *context, ...@@ -3079,10 +3085,30 @@ angle::Result ContextVk::syncState(const gl::Context *context,
case gl::State::DIRTY_BIT_PROVOKING_VERTEX: case gl::State::DIRTY_BIT_PROVOKING_VERTEX:
break; break;
case gl::State::DIRTY_BIT_EXTENDED: case gl::State::DIRTY_BIT_EXTENDED:
{
// Handling clip distance enabled flags, mipmap generation hint & shader derivative // Handling clip distance enabled flags, mipmap generation hint & shader derivative
// hint. // hint.
invalidateGraphicsDriverUniforms(); invalidateGraphicsDriverUniforms();
// Handling clip space origin for EXT_clip_control.
if (glState.getClipSpaceOrigin() != getClipSpaceOrigin())
{
updateClipSpaceOrigin(glState);
updateViewport(vk::GetImpl(glState.getDrawFramebuffer()), glState.getViewport(),
glState.getNearPlane(), glState.getFarPlane(),
isViewportFlipEnabledForDrawFBO());
// Since we are flipping the y coordinate, update front face state
mGraphicsPipelineDesc->updateFrontFace(&mGraphicsPipelineTransition,
glState.getRasterizerState(),
isYFlipEnabledForDrawFBO());
updateScissor(glState);
// Nothing is needed for depth correction for EXT_clip_control.
// glState will be used to toggle control path of depth correction code in
// SPIR-V tranform options.
}
break; break;
}
case gl::State::DIRTY_BIT_PATCH_VERTICES: case gl::State::DIRTY_BIT_PATCH_VERTICES:
mGraphicsPipelineDesc->updatePatchVertices(&mGraphicsPipelineTransition, mGraphicsPipelineDesc->updatePatchVertices(&mGraphicsPipelineTransition,
glState.getPatchVertices()); glState.getPatchVertices());
...@@ -3281,6 +3307,16 @@ void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState) ...@@ -3281,6 +3307,16 @@ void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState)
DetermineSurfaceRotation(readFramebuffer, mCurrentWindowSurface); DetermineSurfaceRotation(readFramebuffer, mCurrentWindowSurface);
} }
gl::ClipSpaceOrigin ContextVk::getClipSpaceOrigin() const
{
return mClipSpaceOrigin;
}
void ContextVk::updateClipSpaceOrigin(const gl::State &glState)
{
mClipSpaceOrigin = glState.getClipSpaceOrigin();
}
gl::Caps ContextVk::getNativeCaps() const gl::Caps ContextVk::getNativeCaps() const
{ {
return mRenderer->getNativeCaps(); return mRenderer->getNativeCaps();
......
...@@ -208,6 +208,20 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -208,6 +208,20 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
SurfaceRotation getRotationDrawFramebuffer() const; SurfaceRotation getRotationDrawFramebuffer() const;
SurfaceRotation getRotationReadFramebuffer() const; SurfaceRotation getRotationReadFramebuffer() const;
// View port (x, y, w, h) will be determined by a combination of -
// 1. clip space origin
// 2. isViewportFlipEnabledForDrawFBO
// For userdefined FBOs it will be based on the value of isViewportFlipEnabledForDrawFBO.
// For default FBOs it will be XOR of ClipOrigin and isViewportFlipEnabledForDrawFBO.
// isYFlipEnabledForDrawFBO indicates the rendered image is upside-down.
ANGLE_INLINE bool isYFlipEnabledForDrawFBO() const
{
return mClipSpaceOrigin == gl::ClipSpaceOrigin::UpperLeft
? !isViewportFlipEnabledForDrawFBO()
: isViewportFlipEnabledForDrawFBO();
}
gl::ClipSpaceOrigin getClipSpaceOrigin() const;
void invalidateProgramBindingHelper(const gl::State &glState); void invalidateProgramBindingHelper(const gl::State &glState);
angle::Result invalidateProgramExecutableHelper(const gl::Context *context); angle::Result invalidateProgramExecutableHelper(const gl::Context *context);
...@@ -735,6 +749,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -735,6 +749,8 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
void updateSurfaceRotationDrawFramebuffer(const gl::State &glState); void updateSurfaceRotationDrawFramebuffer(const gl::State &glState);
void updateSurfaceRotationReadFramebuffer(const gl::State &glState); void updateSurfaceRotationReadFramebuffer(const gl::State &glState);
void updateClipSpaceOrigin(const gl::State &glState);
angle::Result updateActiveTextures(const gl::Context *context); angle::Result updateActiveTextures(const gl::Context *context);
angle::Result updateActiveImages(const gl::Context *context, angle::Result updateActiveImages(const gl::Context *context,
vk::CommandBufferHelper *commandBufferHelper); vk::CommandBufferHelper *commandBufferHelper);
...@@ -941,6 +957,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText ...@@ -941,6 +957,9 @@ class ContextVk : public ContextImpl, public vk::Context, public MultisampleText
bool mFlipViewportForDrawFramebuffer; bool mFlipViewportForDrawFramebuffer;
bool mFlipViewportForReadFramebuffer; bool mFlipViewportForReadFramebuffer;
// Cache clip origin state, needed for viewport calculation.
gl::ClipSpaceOrigin mClipSpaceOrigin;
// If any host-visible buffer is written by the GPU since last submission, a barrier is inserted // If any host-visible buffer is written by the GPU since last submission, a barrier is inserted
// at the end of the command buffer to make that write available to the host. // at the end of the command buffer to make that write available to the host.
bool mIsAnyHostVisibleBufferWritten; bool mIsAnyHostVisibleBufferWritten;
......
...@@ -1571,11 +1571,13 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk, ...@@ -1571,11 +1571,13 @@ angle::Result UtilsVk::clearFramebuffer(ContextVk *contextVk,
VkViewport viewport; VkViewport viewport;
gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk); gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO(); bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
bool clipSpaceOriginUpperLeft =
contextVk->getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft;
// Set depth range to clear value. If clearing depth, the vertex shader depth output is clamped // Set depth range to clear value. If clearing depth, the vertex shader depth output is clamped
// to this value, thus clearing the depth buffer to the desired clear value. // to this value, thus clearing the depth buffer to the desired clear value.
const float clearDepthValue = params.depthStencilClearValue.depth; const float clearDepthValue = params.depthStencilClearValue.depth;
gl_vk::GetViewport(completeRenderArea, clearDepthValue, clearDepthValue, invertViewport, gl_vk::GetViewport(completeRenderArea, clearDepthValue, clearDepthValue, invertViewport,
completeRenderArea.height, &viewport); clipSpaceOriginUpperLeft, completeRenderArea.height, &viewport);
pipelineDesc.setViewport(viewport); pipelineDesc.setViewport(viewport);
// Scissored clears can create a large number of pipelines in some tests. Use dynamic state for // Scissored clears can create a large number of pipelines in some tests. Use dynamic state for
...@@ -1801,7 +1803,8 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk, ...@@ -1801,7 +1803,8 @@ angle::Result UtilsVk::blitResolveImpl(ContextVk *contextVk,
VkViewport viewport; VkViewport viewport;
gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk); gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, completeRenderArea.height, &viewport); gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, false, false, completeRenderArea.height,
&viewport);
pipelineDesc.setViewport(viewport); pipelineDesc.setViewport(viewport);
pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea)); pipelineDesc.setScissor(gl_vk::GetRect(params.blitArea));
...@@ -2235,7 +2238,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk, ...@@ -2235,7 +2238,7 @@ angle::Result UtilsVk::copyImage(ContextVk *contextVk,
} }
VkViewport viewport; VkViewport viewport;
gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, dest->getExtents().height, &viewport); gl_vk::GetViewport(renderArea, 0.0f, 1.0f, false, false, dest->getExtents().height, &viewport);
pipelineDesc.setViewport(viewport); pipelineDesc.setViewport(viewport);
VkRect2D scissor = gl_vk::GetRect(renderArea); VkRect2D scissor = gl_vk::GetRect(renderArea);
...@@ -2690,8 +2693,10 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk, ...@@ -2690,8 +2693,10 @@ angle::Result UtilsVk::unresolve(ContextVk *contextVk,
VkViewport viewport; VkViewport viewport;
gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk); gl::Rectangle completeRenderArea = framebuffer->getRotatedCompleteRenderArea(contextVk);
bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO(); bool invertViewport = contextVk->isViewportFlipEnabledForDrawFBO();
gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, completeRenderArea.height, bool clipSpaceOriginUpperLeft =
&viewport); contextVk->getClipSpaceOrigin() == gl::ClipSpaceOrigin::UpperLeft;
gl_vk::GetViewport(completeRenderArea, 0.0f, 1.0f, invertViewport, clipSpaceOriginUpperLeft,
completeRenderArea.height, &viewport);
pipelineDesc.setViewport(viewport); pipelineDesc.setViewport(viewport);
pipelineDesc.setScissor(gl_vk::GetRect(completeRenderArea)); pipelineDesc.setScissor(gl_vk::GetRect(completeRenderArea));
......
...@@ -1310,6 +1310,7 @@ void GetViewport(const gl::Rectangle &viewport, ...@@ -1310,6 +1310,7 @@ void GetViewport(const gl::Rectangle &viewport,
float nearPlane, float nearPlane,
float farPlane, float farPlane,
bool invertViewport, bool invertViewport,
bool clipSpaceOriginUpperLeft,
GLint renderAreaHeight, GLint renderAreaHeight,
VkViewport *viewportOut) VkViewport *viewportOut)
{ {
...@@ -1320,10 +1321,60 @@ void GetViewport(const gl::Rectangle &viewport, ...@@ -1320,10 +1321,60 @@ void GetViewport(const gl::Rectangle &viewport,
viewportOut->minDepth = gl::clamp01(nearPlane); viewportOut->minDepth = gl::clamp01(nearPlane);
viewportOut->maxDepth = gl::clamp01(farPlane); viewportOut->maxDepth = gl::clamp01(farPlane);
if (invertViewport) // Say an application intends to draw a primitive (shown as 'o' below), it can choose to use
// different clip space origin. When clip space origin (shown as 'C' below) is switched from
// lower-left to upper-left, primitives will be rendered with its y-coordinate flipped.
// Rendered content will differ based on whether it is a default framebuffer or a user defined
// framebuffer. We modify the viewport's 'y' and 'h' accordingly.
// clip space origin is lower-left
// Expected draw in GLES default framebuffer user defined framebuffer
// (0,H) (0,0) (0,0)
// + +-----------+ (W,0) +-----------+ (W,0)
// | | | C----+
// | | | | | (h)
// | +----+ | +----+ | | O |
// | | O | | | O | (-h) | +----+
// | | | | | | |
// | C----+ | C----+ |
// +-----------+ (W,0) + +
// (0,0) (0,H) (0,H)
// y' = H - h y' = y
// clip space origin is upper-left
// Expected draw in GLES default framebuffer user defined framebuffer
// (0,H) (0,0) (0,0)
// + +-----------+ (W,0) +-----------+ (W,0)
// | | | +----+
// | | | | O | (-h)
// | C----+ | C----+ | | |
// | | | | | | (h) | C----+
// | | O | | | O | |
// | +----+ | +----+ |
// +-----------+ (W,0) + +
// (0,0) (0,H) (0,H)
// y' = H - (y + h) y' = y + H
if (clipSpaceOriginUpperLeft)
{ {
viewportOut->y = static_cast<float>(renderAreaHeight - viewport.y); if (invertViewport)
viewportOut->height = -viewportOut->height; {
viewportOut->y = static_cast<float>(renderAreaHeight - (viewport.height + viewport.y));
}
else
{
viewportOut->y = static_cast<float>(viewport.height + viewport.y);
viewportOut->height = -viewportOut->height;
}
}
else
{
if (invertViewport)
{
viewportOut->y = static_cast<float>(renderAreaHeight - viewport.y);
viewportOut->height = -viewportOut->height;
}
} }
} }
......
...@@ -960,6 +960,7 @@ void GetViewport(const gl::Rectangle &viewport, ...@@ -960,6 +960,7 @@ void GetViewport(const gl::Rectangle &viewport,
float nearPlane, float nearPlane,
float farPlane, float farPlane,
bool invertViewport, bool invertViewport,
bool upperLeftOrigin,
GLint renderAreaHeight, GLint renderAreaHeight,
VkViewport *viewportOut); VkViewport *viewportOut);
......
...@@ -1338,7 +1338,19 @@ bool ValidateBufferStorageEXT(const Context *context, ...@@ -1338,7 +1338,19 @@ bool ValidateBufferStorageEXT(const Context *context,
// GL_EXT_clip_control // GL_EXT_clip_control
bool ValidateClipControlEXT(const Context *context, GLenum origin, GLenum depth) bool ValidateClipControlEXT(const Context *context, GLenum origin, GLenum depth)
{ {
return false; if ((origin != GL_LOWER_LEFT_EXT) && (origin != GL_UPPER_LEFT_EXT))
{
context->validationError(GL_INVALID_ENUM, kInvalidOriginEnum);
return false;
}
if ((depth != GL_NEGATIVE_ONE_TO_ONE_EXT) && (depth != GL_ZERO_TO_ONE_EXT))
{
context->validationError(GL_INVALID_ENUM, kInvalidDepthEnum);
return false;
}
return true;
} }
// GL_EXT_external_buffer // GL_EXT_external_buffer
......
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