Commit 8acb1b61 by Olli Etuaho Committed by Commit Bot

Allow reads from a multiview framebuffer with one view

It's safe to read from a multiview framebuffer if it is layered and has just one view. The native OVR_multiview spec supports this as well. BUG=angleproject:2062 TEST=angle_end2end_tests Change-Id: I04e1364390574075f7e06e39a64e3bf05a539a05 Reviewed-on: https://chromium-review.googlesource.com/1156509 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 2eb65034
......@@ -24,7 +24,7 @@ Status
Version
Last Modified Date: July 14, 2017
Last Modified Date: July 31, 2018
Author Revision: 1
Number
......@@ -128,7 +128,9 @@ Additions to Chapter 3 of the OpenGL ES 3.0 Specification (Rasterization)
"Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will
result in an INVALID_FRAMEBUFFER_OPERATION error if the multi-view
layout of the current read framebuffer is not NONE."
layout of the current read framebuffer is
FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the
current read framebuffer is more than one."
Additions to Chapter 4 of the OpenGL ES 3.0 Specification
(Per-Fragment Operations and the Framebuffer)
......@@ -169,7 +171,9 @@ Additions to Chapter 4 of the OpenGL ES 3.0 Specification
Add to the end of the section:
" ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if
the multi-view layout of the current read framebuffer is not NONE."
the multi-view layout of the current read framebuffer is
FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the
current read framebuffer is more than one."
Modify section 4.3.3 (Copying pixels), p. 198
......@@ -181,8 +185,10 @@ Additions to Chapter 4 of the OpenGL ES 3.0 Specification
add a new paragraph:
"Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION
error if the multi-view layout of the current draw framebuffer or
read framebuffer is not NONE."
error if the multi-view layout of the current draw framebuffer is not NONE,
or the multi-view layout of the current read framebuffer is
FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, or the number of views in the
current read framebuffer is more than one."
Modify section 4.4.2 (Attaching Images to Framebuffer Objects), p. 202
......
......@@ -2057,6 +2057,12 @@ GLenum Framebuffer::getMultiviewLayout() const
return mState.getMultiviewLayout();
}
bool Framebuffer::readDisallowedByMultiview() const
{
return (mState.getMultiviewLayout() != GL_NONE && mState.getNumViews() > 1) ||
mState.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
}
Error Framebuffer::ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask)
{
const auto &glState = context->getGLState();
......
......@@ -195,6 +195,7 @@ class Framebuffer final : public angle::ObserverInterface, public LabeledObject
const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
GLenum getMultiviewLayout() const;
bool readDisallowedByMultiview() const;
GLsizei getNumViews() const;
GLint getBaseViewIndex() const;
const std::vector<Offset> *getViewportOffsets() const;
......
......@@ -1506,8 +1506,10 @@ bool ValidateBlitFramebufferParameters(Context *context,
// ANGLE_multiview, Revision 1:
// Calling BlitFramebuffer will result in an INVALID_FRAMEBUFFER_OPERATION error if the
// multi-view layout of the current draw framebuffer or read framebuffer is not NONE.
if (readFramebuffer->getMultiviewLayout() != GL_NONE)
// multi-view layout of the current draw framebuffer is not NONE, or if the multi-view layout of
// the current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of
// views in the current read framebuffer is more than one.
if (readFramebuffer->readDisallowedByMultiview())
{
context->handleError(InvalidFramebufferOperation()
<< "Attempt to read from a multi-view framebuffer.");
......@@ -2522,8 +2524,9 @@ bool ValidateCopyTexImageParametersBase(Context *context,
// ANGLE_multiview spec, Revision 1:
// Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
// INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
// is not NONE.
if (source->getMultiviewLayout() != GL_NONE)
// is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views in the current read
// framebuffer is more than one.
if (readFramebuffer->readDisallowedByMultiview())
{
context->handleError(InvalidFramebufferOperation()
<< "The active read framebuffer object has multiview attachments.");
......@@ -5707,8 +5710,9 @@ bool ValidateReadPixelsBase(Context *context,
// ANGLE_multiview, Revision 1:
// ReadPixels generates an INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the
// current read framebuffer is not NONE.
if (readBuffer->getMultiviewLayout() != GL_NONE)
// current read framebuffer is FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE or the number of views
// in the current read framebuffer is more than one.
if (framebuffer->readDisallowedByMultiview())
{
context->handleError(InvalidFramebufferOperation()
<< "Attempting to read from a multi-view framebuffer.");
......
......@@ -231,6 +231,7 @@ ANGLETestBase::ANGLETestBase(const angle::PlatformParameters &params)
mQuadVertexBuffer(0),
mQuadIndexBuffer(0),
m2DTexturedQuadProgram(0),
m3DTexturedQuadProgram(0),
mDeferContextInit(false)
{
mEGLWindow = new EGLWindow(params.majorVersion, params.minorVersion, params.eglParameters);
......@@ -269,6 +270,10 @@ ANGLETestBase::~ANGLETestBase()
{
glDeleteProgram(m2DTexturedQuadProgram);
}
if (m3DTexturedQuadProgram)
{
glDeleteProgram(m3DTexturedQuadProgram);
}
SafeDelete(mEGLWindow);
}
......@@ -639,13 +644,72 @@ GLuint ANGLETestBase::get2DTexturedQuadProgram()
return m2DTexturedQuadProgram;
}
GLuint ANGLETestBase::get3DTexturedQuadProgram()
{
if (m3DTexturedQuadProgram)
{
return m3DTexturedQuadProgram;
}
const std::string &vs =
R"(#version 300 es
in vec2 position;
out vec2 texCoord;
void main()
{
gl_Position = vec4(position, 0, 1);
texCoord = position * 0.5 + vec2(0.5);
})";
const std::string &fs =
R"(#version 300 es
precision highp float;
in vec2 texCoord;
out vec4 my_FragColor;
uniform highp sampler3D tex;
uniform float u_layer;
void main()
{
my_FragColor = texture(tex, vec3(texCoord, u_layer));
})";
m3DTexturedQuadProgram = CompileProgram(vs, fs);
return m3DTexturedQuadProgram;
}
void ANGLETestBase::draw2DTexturedQuad(GLfloat positionAttribZ,
GLfloat positionAttribXYScale,
bool useVertexBuffer)
{
ASSERT_NE(0u, get2DTexturedQuadProgram());
return drawQuad(get2DTexturedQuadProgram(), "position", positionAttribZ, positionAttribXYScale,
useVertexBuffer);
drawQuad(get2DTexturedQuadProgram(), "position", positionAttribZ, positionAttribXYScale,
useVertexBuffer);
}
void ANGLETestBase::draw3DTexturedQuad(GLfloat positionAttribZ,
GLfloat positionAttribXYScale,
bool useVertexBuffer,
float layer)
{
GLuint program = get3DTexturedQuadProgram();
ASSERT_NE(0u, program);
GLint activeProgram = 0;
glGetIntegerv(GL_CURRENT_PROGRAM, &activeProgram);
if (static_cast<GLuint>(activeProgram) != program)
{
glUseProgram(program);
}
glUniform1f(glGetUniformLocation(program, "u_layer"), layer);
drawQuad(program, "position", positionAttribZ, positionAttribXYScale, useVertexBuffer);
if (static_cast<GLuint>(activeProgram) != program)
{
glUseProgram(static_cast<GLuint>(activeProgram));
}
}
GLuint ANGLETestBase::compileShader(GLenum type, const std::string &source)
......
......@@ -314,6 +314,12 @@ class ANGLETestBase
GLfloat positionAttribXYScale,
bool useVertexBuffer);
// The layer parameter chooses the 3D texture layer to sample from.
void draw3DTexturedQuad(GLfloat positionAttribZ,
GLfloat positionAttribXYScale,
bool useVertexBuffer,
float layer);
static GLuint compileShader(GLenum type, const std::string &source);
static bool extensionEnabled(const std::string &extName);
static bool extensionRequestable(const std::string &extName);
......@@ -362,6 +368,9 @@ class ANGLETestBase
GLuint get2DTexturedQuadProgram();
// Has a float uniform "u_layer" to choose the 3D texture layer.
GLuint get3DTexturedQuadProgram();
angle::PlatformMethods mPlatformMethods;
class ScopedIgnorePlatformMessages : angle::NonCopyable
......@@ -399,6 +408,7 @@ class ANGLETestBase
// Used for texture rendering.
GLuint m2DTexturedQuadProgram;
GLuint m3DTexturedQuadProgram;
TestPlatformContext mPlatformContext;
......
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