This patch adds entrypoints glMultiDrawArraysANGLE,
glMultiDrawElementsANGLE, glMultiDrawArraysInstancedANGLE,
annd glMultiDrawElementsInstancedANGLE

Bug: chromium:890539

Change-Id: Ic9c374c53892460f44ca6e73a253b78473ac2dff
Reviewed-on: https://chromium-review.googlesource.com/c/1282268
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Austin Eng <enga@chromium.org>
This commit is contained in:
Austin Eng 2018-10-19 15:34:02 -07:00 коммит произвёл Commit Bot
Родитель bc5834cdad
Коммит 1bf18ce9e2
29 изменённых файлов: 2368 добавлений и 830 удалений

Просмотреть файл

@ -0,0 +1,228 @@
Name
ANGLE_multi_draw
Name Strings
GL_ANGLE_multi_draw
Contributors
Austin Eng, Google Inc.
Kai Ninomiya, Google Inc.
Kenneth Russell, Google Inc.
Contributors to the EXT_multi_draw_arrays specification
Contributors to the ARB_shader_draw_parameters specification
Contact
Austin Eng (enga 'at' google.com)
Status
Incomplete
Version
Last Modified Date: October 24, 2018
Author Revision: 1
Number
OpenGL ES Extension XX
Dependencies
OpenGL ES 2.0 is required.
This extension is written against the OpenGL ES 2.0 specification,
the OpenGL ES 3.0 specification, and the OpenGL ES Shading Language 3.0
specification.
The presence of the GL_ANGLE_instanced_arrays extension affects the
definition of this extension.
Overview
This extension exposes the Multi* draw call variants in
EXT_multi_draw_arrays functionality in addition to the vertex shader builtin
gl_DrawID exposed by ARB_shader_draw_parameters for OpenGL.
These functions behave identically to the standard functions
DrawArrays() and DrawElements() except they handle multiple lists of
vertices in one call. Their main purpose is to allow one function call
to render more than one primitive such as triangle strip, triangle fan,
etc.
Additionally, this extension adds a further built-in variable, gl_DrawID
to the shading language. This variable contains the index of the draw
currently being processed by a Multi* variant of a drawing command.
IP Status
No known IP claims.
New Procedures and Functions
void MultiDrawArraysANGLE(enum mode,
const GLint* firsts,
const GLsizei* counts,
const GLsizei drawcount);
void MultiDrawElementsANGLE(enum mode,
const GLint* counts,
GLenum type,
const GLsizei* offsets,
const GLsizei drawcount);
void MultiDrawArraysInstancedANGLE(enum mode,
const GLint* firsts,
const GLsizei* counts,
const GLsizei* instanceCounts,
const GLsizei drawcount);
void MultiDrawElementsInstancedANGLE(enum mode,
const GLint* counts,
GLenum type,
const GLsizei* offsets,
const GLsizei* instanceCounts,
const GLsizei drawcount);
New Tokens
None.
Additions to Chapter 2 of the OpenGL ES 2.0 Specification
Section 2.8 Vertex Arrays:
The command
void MultiDrawArraysANGLE(GLenum mode,
const GLint* firsts,
const GLsizei *counts,
GLsizei drawcount)
Behaves identically to DrawArrays except that a list of arrays is
specified instead. The number of lists is specified in the drawcount
parameter. It has the same effect as:
for(i=0; i<drawcount; i++) {
if (*(counts+i)>0) DrawArrays(mode, *(firsts+i), *(counts+i));
}
The index of the draw (<i> in the above pseudo-code) may be read by
a vertex shader as <gl_DrawID>.
The command
void MultiDrawElementsANGLE(GLenum mode,
GLsizei* counts,
GLenum type,
GLsizei* offsets,
GLsizei drawcount)
Behaves identically to DrawElements except that a list of arrays is
specified instead. The number of lists is specified in the drawcount
parameter. It has the same effect as:
for(i=0; i<drawcount; i++) {
if (*(counts+i)>0) DrawElements(mode, *(counts+i), type,
(const void*)(long)(*(offsets+i)));
}
The index of the draw (<i> in the above pseudo-code) may be read by
a vertex shader as <gl_DrawID>.
Additions to Chapter 2 of the OpenGL ES 3.0 Specification
Section 2.9.3 Drawing Commands:
The command
void MultiDrawArraysInstancedANGLE(
GLenum mode,
const GLint* firsts,
const GLsizei *counts,
const GLsizei* instanceCounts,
GLsizei drawcount)
Behaves identically to DrawArraysInstanced except that a list of arrays is
specified instead. The number of lists is specified in the drawcount
parameter. It has the same effect as:
for(i=0; i<drawcount; i++) {
if (*(counts+i)>0) DrawArraysInstanced(mode, *(firsts+i), *(counts+i),
*(instanceCounts+1));
}
The index of the draw (<i> in the above pseudo-code) may be read by
a vertex shader as <gl_DrawID>.
The command
void MultiDrawElementsInstancedANGLE(
GLenum mode,
GLsizei* counts,
GLenum type,
GLsizei* offsets,
const GLsizei* instanceCounts,
GLsizei drawcount)
Behaves identically to DrawElementsInstanced except that a list of arrays is
specified instead. The number of lists is specified in the drawcount
parameter. It has the same effect as:
for(i=0; i<drawcount; i++) {
if (*(counts+i)>0) DrawElementsInstanced(mode, *(counts+i), type,
(const void*)(long)(*(offsets+i)), *(instanceCounts+1));
}
The index of the draw (<i> in the above pseudo-code) may be read by
a vertex shader as <gl_DrawID>.
Errors
The error INVALID_VALUE is generated by the new functions if <drawcount>
is less than 0.
MultiDrawArraysANGLE, MultiDrawElementsANGLE,
MultiDrawArraysInstancedANGLE, and MultiDrawElementsInstancedANGLE generate
the same errors as DrawArrays, DrawElements, DrawArraysInstanced,
and DrawElementsInstanced, respectively, for any draw <i> where an error
is generated. If any call would produce an error, no drawing is performed.
Modifications to the OpenGL ES Shading Language Specification, Version 3.00
Including the following line in a shader can be used to control the
language featured described in this extension:
#extension GL_ANGLE_multi_draw : <behavior>
where <behavior> is as specified in section 3.5.
A new preprocessor #define is added to the OpenGL ES Shading Language:
#define GL_ANGLE_multi_draw 1
Dependencies on GL_ANGLE_instanced_arrays
If GL_ANGLE_instanced_arrays is enabled, append the lanuage in "Additions to
Chapter 2 of the OpenGL ES 3.0 Specification, Section 2.9.3 Drawing
Commands" to the language in "Additions to Chapter 2 of the OpenGL ES 2.0
Specification, Section 2.8 Vertex Arrays".
If GL_ANGLE_instanced_arrays is not enabled and the context is less than a
OpenGL ES 3.0 context, the error INVALID_OPERATION is generated by any call
to the functions MultiDrawArraysInstancedANGLE and
MultiDrawElementsInstancedANGLE.
Issues
None
Revision History
Rev. Date Author Changes
---- -------- ---------- --------------------------------------------
1 10/24/18 Austin Eng First revision.
2 10/25/18 Austin Eng Second revision. Add instanced variants

Просмотреть файл

@ -657,6 +657,20 @@ typedef void *GLeglContext;
#include "../GLES3/gl31ext_explicit_context_autogen.inc"
#endif /* GL_ANGLE_explicit_context */
#ifndef GL_ANGLE_multi_draw
#define GL_ANGLE_multi_draw 1
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSANGLEPROC) (GLenum mode, const GLint *firsts, const GLsizei *counts, GLsizei drawcount);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, const GLint *firsts, const GLsizei *counts, const GLsizei *instanceCounts, GLsizei drawcount);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSANGLEPROC) (GLenum mode, const GLsizei *counts, GLenum type, const GLsizei *offsets, GLsizei drawcount);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, const GLsizei *counts, GLenum type, const GLsizei *offsets, const GLsizei *instanceCounts, GLsizei drawcount);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glMultiDrawArraysANGLE (GLenum mode, const GLint *firsts, const GLsizei *counts, GLsizei drawcount);
GL_APICALL void GL_APIENTRY glMultiDrawArraysInstancedANGLE (GLenum mode, const GLint *firsts, const GLsizei *counts, const GLsizei *instanceCounts, GLsizei drawcount);
GL_APICALL void GL_APIENTRY glMultiDrawElementsANGLE (GLenum mode, const GLsizei *counts, GLenum type, const GLsizei *offsets, GLsizei drawcount);
GL_APICALL void GL_APIENTRY glMultiDrawElementsInstancedANGLE (GLenum mode, const GLsizei *counts, GLenum type, const GLsizei *offsets, const GLsizei *instanceCounts, GLsizei drawcount);
#endif
#endif /* GL_ANGLE_multi_draw */
// clang-format on
#endif // INCLUDE_GLES2_GL2EXT_ANGLE_H_

Просмотреть файл

@ -327,6 +327,10 @@ typedef void (GL_APIENTRYP PFNGLCOPYSUBTEXTURE3DANGLECONTEXTANGLE)(GLeglContext
typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DMULTISAMPLEANGLECONTEXTANGLE)(GLeglContext ctx, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERIVANGLECONTEXTANGLE)(GLeglContext ctx, GLenum target, GLint level, GLenum pname, GLint * params);
typedef void (GL_APIENTRYP PFNGLGETTEXLEVELPARAMETERFVANGLECONTEXTANGLE)(GLeglContext ctx, GLenum target, GLint level, GLenum pname, GLfloat * params);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSANGLECONTEXTANGLE)(GLeglContext ctx, GLenum mode, const GLint *firsts, const GLsizei *counts, GLsizei drawcount);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINSTANCEDANGLECONTEXTANGLE)(GLeglContext ctx, GLenum mode, const GLint *firsts, const GLsizei *counts, const GLsizei *instanceCounts, GLsizei drawcount);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSANGLECONTEXTANGLE)(GLeglContext ctx, GLenum mode, const GLsizei *counts, GLenum type, const GLsizei*offsets, GLsizei drawcount);
typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINSTANCEDANGLECONTEXTANGLE)(GLeglContext ctx, GLenum mode, const GLsizei *counts, GLenum type, const GLsizei*offsets, const GLsizei*instanceCounts, GLsizei drawcount);
#ifdef GL_GLEXT_PROTOTYPES
GL_APICALL void GL_APIENTRY glActiveTextureContextANGLE(GLeglContext ctx, GLenum texture);
GL_APICALL void GL_APIENTRY glAttachShaderContextANGLE(GLeglContext ctx, GLuint program, GLuint shader);
@ -647,4 +651,8 @@ GL_APICALL void GL_APIENTRY glCopySubTexture3DANGLEContextANGLE(GLeglContext ctx
GL_APICALL void GL_APIENTRY glTexStorage2DMultisampleANGLEContextANGLE(GLeglContext ctx, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
GL_APICALL void GL_APIENTRY glGetTexLevelParameterivANGLEContextANGLE(GLeglContext ctx, GLenum target, GLint level, GLenum pname, GLint * params);
GL_APICALL void GL_APIENTRY glGetTexLevelParameterfvANGLEContextANGLE(GLeglContext ctx, GLenum target, GLint level, GLenum pname, GLfloat * params);
GL_APICALL void GL_APIENTRY glMultiDrawArraysANGLEContextANGLE(GLeglContext ctx, GLenum mode, const GLint *firsts, const GLsizei *counts, GLsizei drawcount);
GL_APICALL void GL_APIENTRY glMultiDrawArraysInstancedANGLEContextANGLE(GLeglContext ctx, GLenum mode, const GLint *firsts, const GLsizei *counts, const GLsizei *instanceCounts, GLsizei drawcount);
GL_APICALL void GL_APIENTRY glMultiDrawElementsANGLEContextANGLE(GLeglContext ctx, GLenum mode, const GLsizei *counts, GLenum type, const GLsizei*offsets, GLsizei drawcount);
GL_APICALL void GL_APIENTRY glMultiDrawElementsInstancedANGLEContextANGLE(GLeglContext ctx, GLenum mode, const GLsizei *counts, GLenum type, const GLsizei*offsets, const GLsizei*instanceCounts, GLsizei drawcount);
#endif

Просмотреть файл

@ -109,6 +109,7 @@ struct ShaderVariable
std::string* originalFullName) const;
bool isBuiltIn() const;
bool isEmulatedBuiltIn() const;
GLenum type;
GLenum precision;

Просмотреть файл

@ -292,6 +292,18 @@
"glMatrixMode": {
"mode": "MatrixType"
},
"glMultiDrawArraysANGLE": {
"mode": "PrimitiveMode"
},
"glMultiDrawArraysInstancedANGLE": {
"mode": "PrimitiveMode"
},
"glMultiDrawElementsANGLE": {
"mode": "PrimitiveMode"
},
"glMultiDrawElementsInstancedANGLE": {
"mode": "PrimitiveMode"
},
"glPointParameterf": {
"pname" : "PointParameter"
},

Просмотреть файл

@ -74,6 +74,7 @@ supported_extensions = sorted(angle_extensions + gles1_extensions + [
"GL_OES_texture_storage_multisample_2d_array",
"GL_OES_vertex_array_object",
"GL_KHR_parallel_shader_compile",
"GL_ANGLE_multi_draw",
])
# The EGL_ANGLE_explicit_context extension is generated differently from other extensions.

Просмотреть файл

@ -871,6 +871,38 @@
<param><ptype>GLenum</ptype> <name>pname</name></param>
<param><ptype>GLfloat *</ptype> <name>params</name></param>
</command>
<command>
<proto>void <name>glMultiDrawArraysANGLE</name></proto>
<param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
<param len="COMPSIZE(primcount)">const <ptype>GLint</ptype> *<name>firsts</name></param>
<param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>counts</name></param>
<param><ptype>GLsizei</ptype> <name>drawcount</name></param>
</command>
<command>
<proto>void <name>glMultiDrawArraysInstancedANGLE</name></proto>
<param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
<param len="COMPSIZE(primcount)">const <ptype>GLint</ptype> *<name>firsts</name></param>
<param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>counts</name></param>
<param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>instanceCounts</name></param>
<param><ptype>GLsizei</ptype> <name>drawcount</name></param>
</command>
<command>
<proto>void <name>glMultiDrawElementsANGLE</name></proto>
<param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
<param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>counts</name></param>
<param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
<param len="COMPSIZE(primcount)">const GLsizei*<name>offsets</name></param>
<param><ptype>GLsizei</ptype> <name>drawcount</name></param>
</command>
<command>
<proto>void <name>glMultiDrawElementsInstancedANGLE</name></proto>
<param group="PrimitiveType"><ptype>GLenum</ptype> <name>mode</name></param>
<param len="COMPSIZE(primcount)">const <ptype>GLsizei</ptype> *<name>counts</name></param>
<param group="DrawElementsType"><ptype>GLenum</ptype> <name>type</name></param>
<param len="COMPSIZE(primcount)">const GLsizei*<name>offsets</name></param>
<param len="COMPSIZE(primcount)">const GLsizei*<name>instanceCounts</name></param>
<param><ptype>GLsizei</ptype> <name>drawcount</name></param>
</command>
</commands>
<!-- SECTION: ANGLE extension interface definitions -->
<extensions>
@ -1016,5 +1048,13 @@
<command name="glGetTexLevelParameterfvANGLE"/>
</require>
</extension>
<extension name="GL_ANGLE_multi_draw" supported='gl|gles2'>
<require>
<command name="glMultiDrawArraysANGLE"/>
<command name="glMultiDrawArraysInstancedANGLE"/>
<command name="glMultiDrawElementsANGLE"/>
<command name="glMultiDrawElementsInstancedANGLE"/>
</require>
</extension>
</extensions>
</registry>

Просмотреть файл

@ -48,9 +48,9 @@
"GL copy conversion table:src/libANGLE/gen_copy_conversion_table.py":
"ac1afe23d9578bd1d2ef74f4a7aa927a",
"GL entry point:scripts/entry_point_packed_gl_enums.json":
"f16b55c293b38a18e0e9d693bdaa341d",
"91796c2aa1aef35c93b5c4ddd88496d2",
"GL entry point:scripts/generate_entry_points.py":
"24661bb77e40e05ae8de8459e350d373",
"b13f2afab982902852a16caad6b937be",
"GL entry point:scripts/gl.xml":
"b470cb06b06cbbe7adb2c8129ec85708",
"GL format map:src/libANGLE/es3_format_type_combinations.json":

Просмотреть файл

@ -156,7 +156,14 @@ unsigned int ResourcesHLSL::assignUniformRegister(const TType &type,
registerIndex = mUniformRegister;
}
mUniformRegisterMap[uniform->name] = registerIndex;
if (uniform->name == "angle_DrawID" && uniform->mappedName == "angle_DrawID")
{
mUniformRegisterMap["gl_DrawID"] = registerIndex;
}
else
{
mUniformRegisterMap[uniform->name] = registerIndex;
}
unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);

Просмотреть файл

@ -216,6 +216,11 @@ bool ShaderVariable::isBuiltIn() const
return (name.size() >= 4 && name[0] == 'g' && name[1] == 'l' && name[2] == '_');
}
bool ShaderVariable::isEmulatedBuiltIn() const
{
return isBuiltIn() && name != mappedName;
}
bool ShaderVariable::isSameVariableAtLinkTime(const ShaderVariable &other,
bool matchPrecision,
bool matchName) const

Просмотреть файл

@ -5409,6 +5409,162 @@ void Context::memoryBarrierByRegion(GLbitfield barriers)
handleError(mImplementation->memoryBarrierByRegion(this, barriers));
}
void Context::multiDrawArrays(PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount)
{
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
Program *programObject = mGLState.getLinkedProgram(this);
const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
if (hasDrawID)
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDraw(mode, counts[drawID]))
{
continue;
}
programObject->setDrawIDUniform(drawID);
ANGLE_CONTEXT_TRY(
mImplementation->drawArrays(this, mode, firsts[drawID], counts[drawID]));
MarkTransformFeedbackBufferUsage(this, mGLState.getCurrentTransformFeedback(),
counts[drawID], 1);
}
}
else
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDraw(mode, counts[drawID]))
{
continue;
}
ANGLE_CONTEXT_TRY(
mImplementation->drawArrays(this, mode, firsts[drawID], counts[drawID]));
MarkTransformFeedbackBufferUsage(this, mGLState.getCurrentTransformFeedback(),
counts[drawID], 1);
}
}
}
void Context::multiDrawArraysInstanced(PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
Program *programObject = mGLState.getLinkedProgram(this);
const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
if (hasDrawID)
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDrawInstanced(mode, counts[drawID], instanceCounts[drawID]))
{
continue;
}
programObject->setDrawIDUniform(drawID);
ANGLE_CONTEXT_TRY(mImplementation->drawArraysInstanced(
this, mode, firsts[drawID], counts[drawID], instanceCounts[drawID]));
MarkTransformFeedbackBufferUsage(this, mGLState.getCurrentTransformFeedback(),
counts[drawID], instanceCounts[drawID]);
}
}
else
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDrawInstanced(mode, counts[drawID], instanceCounts[drawID]))
{
continue;
}
ANGLE_CONTEXT_TRY(mImplementation->drawArraysInstanced(
this, mode, firsts[drawID], counts[drawID], instanceCounts[drawID]));
MarkTransformFeedbackBufferUsage(this, mGLState.getCurrentTransformFeedback(),
counts[drawID], instanceCounts[drawID]);
}
}
}
void Context::multiDrawElements(PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount)
{
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
Program *programObject = mGLState.getLinkedProgram(this);
const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
if (hasDrawID)
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDraw(mode, counts[drawID]))
{
continue;
}
programObject->setDrawIDUniform(drawID);
const void *indices = reinterpret_cast<void *>(static_cast<long>(offsets[drawID]));
ANGLE_CONTEXT_TRY(
mImplementation->drawElements(this, mode, counts[drawID], type, indices));
}
}
else
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDraw(mode, counts[drawID]))
{
continue;
}
const void *indices = reinterpret_cast<void *>(static_cast<long>(offsets[drawID]));
ANGLE_CONTEXT_TRY(
mImplementation->drawElements(this, mode, counts[drawID], type, indices));
}
}
}
void Context::multiDrawElementsInstanced(PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
ANGLE_CONTEXT_TRY(prepareForDraw(mode));
Program *programObject = mGLState.getLinkedProgram(this);
const bool hasDrawID = programObject && programObject->hasDrawIDUniform();
if (hasDrawID)
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDrawInstanced(mode, counts[drawID], instanceCounts[drawID]))
{
continue;
}
programObject->setDrawIDUniform(drawID);
const void *indices = reinterpret_cast<void *>(static_cast<long>(offsets[drawID]));
ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstanced(
this, mode, counts[drawID], type, indices, instanceCounts[drawID]));
}
}
else
{
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (noopDrawInstanced(mode, counts[drawID], instanceCounts[drawID]))
{
continue;
}
const void *indices = reinterpret_cast<void *>(static_cast<long>(offsets[drawID]));
ANGLE_CONTEXT_TRY(mImplementation->drawElementsInstanced(
this, mode, counts[drawID], type, indices, instanceCounts[drawID]));
}
}
}
GLenum Context::checkFramebufferStatus(GLenum target)
{
Framebuffer *framebuffer = mGLState.getTargetFramebuffer(target);

Просмотреть файл

@ -1565,6 +1565,26 @@ class Context final : public egl::LabeledObject, angle::NonCopyable, public angl
void memoryBarrier(GLbitfield barriers);
void memoryBarrierByRegion(GLbitfield barriers);
void multiDrawArrays(PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount);
void multiDrawArraysInstanced(PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount);
void multiDrawElements(PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount);
void multiDrawElementsInstanced(PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount);
void framebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level);

Просмотреть файл

@ -802,6 +802,7 @@ ProgramState::ProgramState()
mGeometryShaderOutputPrimitiveType(PrimitiveMode::TriangleStrip),
mGeometryShaderInvocations(1),
mGeometryShaderMaxVertices(0),
mDrawIDLocation(-1),
mActiveSamplerRefCounts{}
{
mComputeShaderLocalSize.fill(1);
@ -1314,6 +1315,11 @@ void Program::resolveLinkImpl(const Context *context)
setUniformValuesFromBindingQualifiers();
if (context->getExtensions().multiDraw)
{
mState.mDrawIDLocation = getUniformLocation("gl_DrawID");
}
// Save to the program cache.
auto *cache = linkingState->context->getMemoryProgramCache();
if (cache &&
@ -1419,6 +1425,7 @@ void Program::unlink()
mState.mGeometryShaderOutputPrimitiveType = PrimitiveMode::TriangleStrip;
mState.mGeometryShaderInvocations = 1;
mState.mGeometryShaderMaxVertices = 0;
mState.mDrawIDLocation = -1;
mValidated = false;
@ -2682,6 +2689,19 @@ const TransformFeedbackVarying &Program::getTransformFeedbackVaryingResource(GLu
return mState.mLinkedTransformFeedbackVaryings[index];
}
bool Program::hasDrawIDUniform() const
{
ASSERT(mLinkResolved);
return mState.mDrawIDLocation >= 0;
}
void Program::setDrawIDUniform(GLint drawid)
{
ASSERT(mLinkResolved);
ASSERT(mState.mDrawIDLocation >= 0);
mProgram->setUniform1iv(mState.mDrawIDLocation, 1, &drawid);
}
bool Program::linkVaryings(InfoLog &infoLog) const
{
Shader *previousShader = nullptr;

Просмотреть файл

@ -447,6 +447,9 @@ class ProgramState final : angle::NonCopyable
int mGeometryShaderInvocations;
int mGeometryShaderMaxVertices;
// GL_ANGLE_multi_draw
int mDrawIDLocation;
// The size of the data written to each transform feedback buffer per vertex.
std::vector<GLsizei> mTransformFeedbackStrides;
@ -726,6 +729,9 @@ class Program final : angle::NonCopyable, public LabeledObject
GLuint getTransformFeedbackVaryingResourceIndex(const GLchar *name) const;
const TransformFeedbackVarying &getTransformFeedbackVaryingResource(GLuint index) const;
bool hasDrawIDUniform() const;
void setDrawIDUniform(GLint drawid);
ANGLE_INLINE void addRef()
{
ASSERT(mLinkResolved);

Просмотреть файл

@ -354,7 +354,8 @@ bool UniformLinker::indexUniforms(InfoLog &infoLog, const ProgramBindings &unifo
{
const LinkedUniform &uniform = mUniforms[uniformIndex];
if (uniform.isBuiltIn() || IsAtomicCounterType(uniform.type))
if ((uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn()) ||
IsAtomicCounterType(uniform.type))
{
continue;
}
@ -430,7 +431,7 @@ bool UniformLinker::gatherUniformLocationsAndCheckConflicts(
for (const LinkedUniform &uniform : mUniforms)
{
if (uniform.isBuiltIn())
if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
{
continue;
}

Просмотреть файл

@ -359,7 +359,7 @@ void Shader::compile(const Context *context)
std::string sourcePath;
ShCompileOptions options =
mImplementation->prepareSourceAndReturnOptions(context, &sourceStream, &sourcePath);
options |= (SH_OBJECT_CODE | SH_VARIABLES);
options |= (SH_OBJECT_CODE | SH_VARIABLES | SH_EMULATE_GL_DRAW_ID);
auto source = sourceStream.str();
// Add default options to WebGL shaders to prevent unexpected behavior during compilation.

Просмотреть файл

@ -2170,7 +2170,7 @@ void ProgramD3D::defineUniformBase(const gl::Shader *shader,
mImageBindingMap[uniform.name] = uniform.binding;
return;
}
else if (uniform.isBuiltIn())
else if (uniform.isBuiltIn() && !uniform.isEmulatedBuiltIn())
{
defineUniform(shader->getType(), uniform, uniform.name, HLSLRegisterType::None, nullptr,
uniformMap);

Просмотреть файл

@ -323,6 +323,7 @@ bool ValidateDrawElementsInstancedANGLE(Context *context,
GLenum type,
const void *indices,
GLsizei primcount);
bool ValidateDrawInstancedANGLE(Context *context);
bool ValidateFramebufferTextureBase(Context *context,
GLenum target,

Просмотреть файл

@ -6713,4 +6713,48 @@ bool ValidateMaxShaderCompilerThreadsKHR(Context *context, GLuint count)
return true;
}
bool ValidateMultiDrawArraysANGLE(Context *context,
PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount)
{
if (!context->getExtensions().multiDraw)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (!ValidateDrawArrays(context, mode, firsts[drawID], counts[drawID]))
{
return false;
}
}
return true;
}
bool ValidateMultiDrawElementsANGLE(Context *context,
PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount)
{
if (!context->getExtensions().multiDraw)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
const void *indices = reinterpret_cast<void *>(static_cast<long>(offsets[drawID]));
if (!ValidateDrawElements(context, mode, counts[drawID], type, indices))
{
return false;
}
}
return true;
}
} // namespace gl

Просмотреть файл

@ -738,6 +738,17 @@ bool ValidateTexStorage3DEXT(Context *context,
GLsizei height,
GLsizei depth);
bool ValidateMaxShaderCompilerThreadsKHR(Context *context, GLuint count);
bool ValidateMultiDrawArraysANGLE(Context *context,
PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount);
bool ValidateMultiDrawElementsANGLE(Context *context,
PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount);
} // namespace gl
#include "libANGLE/ErrorStrings.h"

Просмотреть файл

@ -3101,6 +3101,78 @@ bool ValidateDrawElementsInstanced(Context *context,
return ValidateDrawElementsInstancedCommon(context, mode, count, type, indices, instanceCount);
}
bool ValidateMultiDrawArraysInstancedANGLE(Context *context,
PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
if (!context->getExtensions().multiDraw)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (context->getClientMajorVersion() < 3)
{
if (!context->getExtensions().instancedArrays)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (!ValidateDrawInstancedANGLE(context))
{
return false;
}
}
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
if (!ValidateDrawArraysInstancedBase(context, mode, firsts[drawID], counts[drawID],
instanceCounts[drawID]))
{
return false;
}
}
return true;
}
bool ValidateMultiDrawElementsInstancedANGLE(Context *context,
PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
if (!context->getExtensions().multiDraw)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (context->getClientMajorVersion() < 3)
{
if (!context->getExtensions().instancedArrays)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), ExtensionNotEnabled);
return false;
}
if (!ValidateDrawInstancedANGLE(context))
{
return false;
}
}
for (GLsizei drawID = 0; drawID < drawcount; ++drawID)
{
const void *indices = reinterpret_cast<void *>(static_cast<long>(offsets[drawID]));
if (!ValidateDrawElementsInstancedCommon(context, mode, counts[drawID], type, indices,
instanceCounts[drawID]))
{
return false;
}
}
return true;
}
bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
GLenum target,
GLenum attachment,

Просмотреть файл

@ -448,6 +448,21 @@ bool ValidateDrawElementsInstanced(Context *context,
const void *indices,
GLsizei instanceCount);
bool ValidateMultiDrawArraysInstancedANGLE(Context *context,
PrimitiveMode mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount);
bool ValidateMultiDrawElementsInstancedANGLE(Context *context,
PrimitiveMode mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount);
bool ValidateFramebufferTextureMultiviewLayeredANGLE(Context *context,
GLenum target,
GLenum attachment,

Просмотреть файл

@ -405,6 +405,10 @@ enum class EntryPoint
MemoryBarrierByRegion,
MultMatrixf,
MultMatrixx,
MultiDrawArraysANGLE,
MultiDrawArraysInstancedANGLE,
MultiDrawElementsANGLE,
MultiDrawElementsInstancedANGLE,
MultiTexCoord4f,
MultiTexCoord4x,
Normal3f,

Просмотреть файл

@ -223,6 +223,106 @@ void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
}
}
// GL_ANGLE_multi_draw
void GL_APIENTRY MultiDrawArraysANGLE(GLenum mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLint *firsts = 0x%016" PRIxPTR
", const GLsizei *counts = 0x%016" PRIxPTR ", GLsizei drawcount = %d)",
mode, (uintptr_t)firsts, (uintptr_t)counts, drawcount);
Context *context = GetValidGlobalContext();
if (context)
{
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawArraysANGLE(context, modePacked, firsts, counts, drawcount))
{
context->multiDrawArrays(modePacked, firsts, counts, drawcount);
}
}
}
void GL_APIENTRY MultiDrawArraysInstancedANGLE(GLenum mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLint *firsts = 0x%016" PRIxPTR
", const GLsizei *counts = 0x%016" PRIxPTR
", const GLsizei *instanceCounts = 0x%016" PRIxPTR ", GLsizei drawcount = %d)",
mode, (uintptr_t)firsts, (uintptr_t)counts, (uintptr_t)instanceCounts, drawcount);
Context *context = GetValidGlobalContext();
if (context)
{
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawArraysInstancedANGLE(context, modePacked, firsts, counts,
instanceCounts, drawcount))
{
context->multiDrawArraysInstanced(modePacked, firsts, counts, instanceCounts,
drawcount);
}
}
}
void GL_APIENTRY MultiDrawElementsANGLE(GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLsizei *counts = 0x%016" PRIxPTR
", GLenum type = 0x%X, const GLsizei*offsets = 0x%016" PRIxPTR
", GLsizei drawcount = %d)",
mode, (uintptr_t)counts, type, (uintptr_t)offsets, drawcount);
Context *context = GetValidGlobalContext();
if (context)
{
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawElementsANGLE(context, modePacked, counts, type, offsets, drawcount))
{
context->multiDrawElements(modePacked, counts, type, offsets, drawcount);
}
}
}
void GL_APIENTRY MultiDrawElementsInstancedANGLE(GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLsizei *counts = 0x%016" PRIxPTR
", GLenum type = 0x%X, const GLsizei*offsets = 0x%016" PRIxPTR
", const GLsizei*instanceCounts = 0x%016" PRIxPTR ", GLsizei drawcount = %d)",
mode, (uintptr_t)counts, type, (uintptr_t)offsets, (uintptr_t)instanceCounts, drawcount);
Context *context = GetValidGlobalContext();
if (context)
{
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawElementsInstancedANGLE(context, modePacked, counts, type, offsets,
instanceCounts, drawcount))
{
context->multiDrawElementsInstanced(modePacked, counts, type, offsets, instanceCounts,
drawcount);
}
}
}
// GL_ANGLE_multiview
void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
GLenum attachment,
@ -17674,4 +17774,111 @@ void GL_APIENTRY GetTexLevelParameterfvANGLEContextANGLE(GLeglContext ctx,
}
}
}
void GL_APIENTRY MultiDrawArraysANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLint *firsts = 0x%016" PRIxPTR
", const GLsizei *counts = 0x%016" PRIxPTR ", GLsizei drawcount = %d)",
mode, (uintptr_t)firsts, (uintptr_t)counts, drawcount);
Context *context = static_cast<gl::Context *>(ctx);
if (context)
{
ASSERT(context == GetValidGlobalContext());
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawArraysANGLE(context, modePacked, firsts, counts, drawcount))
{
context->multiDrawArrays(modePacked, firsts, counts, drawcount);
}
}
}
void GL_APIENTRY MultiDrawArraysInstancedANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLint *firsts = 0x%016" PRIxPTR
", const GLsizei *counts = 0x%016" PRIxPTR
", const GLsizei *instanceCounts = 0x%016" PRIxPTR ", GLsizei drawcount = %d)",
mode, (uintptr_t)firsts, (uintptr_t)counts, (uintptr_t)instanceCounts, drawcount);
Context *context = static_cast<gl::Context *>(ctx);
if (context)
{
ASSERT(context == GetValidGlobalContext());
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawArraysInstancedANGLE(context, modePacked, firsts, counts,
instanceCounts, drawcount))
{
context->multiDrawArraysInstanced(modePacked, firsts, counts, instanceCounts,
drawcount);
}
}
}
void GL_APIENTRY MultiDrawElementsANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLsizei *counts = 0x%016" PRIxPTR
", GLenum type = 0x%X, const GLsizei*offsets = 0x%016" PRIxPTR
", GLsizei drawcount = %d)",
mode, (uintptr_t)counts, type, (uintptr_t)offsets, drawcount);
Context *context = static_cast<gl::Context *>(ctx);
if (context)
{
ASSERT(context == GetValidGlobalContext());
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawElementsANGLE(context, modePacked, counts, type, offsets, drawcount))
{
context->multiDrawElements(modePacked, counts, type, offsets, drawcount);
}
}
}
void GL_APIENTRY MultiDrawElementsInstancedANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
ANGLE_SCOPED_GLOBAL_LOCK();
EVENT("(GLenum mode = 0x%X, const GLsizei *counts = 0x%016" PRIxPTR
", GLenum type = 0x%X, const GLsizei*offsets = 0x%016" PRIxPTR
", const GLsizei*instanceCounts = 0x%016" PRIxPTR ", GLsizei drawcount = %d)",
mode, (uintptr_t)counts, type, (uintptr_t)offsets, (uintptr_t)instanceCounts, drawcount);
Context *context = static_cast<gl::Context *>(ctx);
if (context)
{
ASSERT(context == GetValidGlobalContext());
PrimitiveMode modePacked = FromGLenum<PrimitiveMode>(mode);
if (context->skipValidation() ||
ValidateMultiDrawElementsInstancedANGLE(context, modePacked, counts, type, offsets,
instanceCounts, drawcount))
{
context->multiDrawElementsInstanced(modePacked, counts, type, offsets, instanceCounts,
drawcount);
}
}
}
} // namespace gl

Просмотреть файл

@ -80,6 +80,28 @@ ANGLE_EXPORT void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode,
GLsizei primcount);
ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor);
// GL_ANGLE_multi_draw
ANGLE_EXPORT void GL_APIENTRY MultiDrawArraysANGLE(GLenum mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount);
ANGLE_EXPORT void GL_APIENTRY MultiDrawArraysInstancedANGLE(GLenum mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount);
ANGLE_EXPORT void GL_APIENTRY MultiDrawElementsANGLE(GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount);
ANGLE_EXPORT void GL_APIENTRY MultiDrawElementsInstancedANGLE(GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount);
// GL_ANGLE_multiview
ANGLE_EXPORT void GL_APIENTRY FramebufferTextureMultiviewLayeredANGLE(GLenum target,
GLenum attachment,
@ -3464,6 +3486,32 @@ ANGLE_EXPORT void GL_APIENTRY GetTexLevelParameterfvANGLEContextANGLE(GLeglConte
GLint level,
GLenum pname,
GLfloat *params);
ANGLE_EXPORT void GL_APIENTRY MultiDrawArraysANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount);
ANGLE_EXPORT void GL_APIENTRY
MultiDrawArraysInstancedANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount);
ANGLE_EXPORT void GL_APIENTRY MultiDrawElementsANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount);
ANGLE_EXPORT void GL_APIENTRY
MultiDrawElementsInstancedANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount);
} // namespace gl
#endif // LIBGLESV2_ENTRY_POINTS_GLES_EXT_AUTOGEN_H_

Просмотреть файл

@ -2507,6 +2507,44 @@ void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
return gl::VertexAttribDivisorANGLE(index, divisor);
}
// GL_ANGLE_multi_draw
void GL_APIENTRY glMultiDrawArraysANGLE(GLenum mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount)
{
return gl::MultiDrawArraysANGLE(mode, firsts, counts, drawcount);
}
void GL_APIENTRY glMultiDrawArraysInstancedANGLE(GLenum mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
return gl::MultiDrawArraysInstancedANGLE(mode, firsts, counts, instanceCounts, drawcount);
}
void GL_APIENTRY glMultiDrawElementsANGLE(GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount)
{
return gl::MultiDrawElementsANGLE(mode, counts, type, offsets, drawcount);
}
void GL_APIENTRY glMultiDrawElementsInstancedANGLE(GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
return gl::MultiDrawElementsInstancedANGLE(mode, counts, type, offsets, instanceCounts,
drawcount);
}
// GL_ANGLE_multiview
void GL_APIENTRY glFramebufferTextureMultiviewLayeredANGLE(GLenum target,
GLenum attachment,
@ -9055,4 +9093,46 @@ void GL_APIENTRY glGetTexLevelParameterfvANGLEContextANGLE(GLeglContext ctx,
return gl::GetTexLevelParameterfvANGLEContextANGLE(ctx, target, level, pname, params);
}
void GL_APIENTRY glMultiDrawArraysANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLint *firsts,
const GLsizei *counts,
GLsizei drawcount)
{
return gl::MultiDrawArraysANGLEContextANGLE(ctx, mode, firsts, counts, drawcount);
}
void GL_APIENTRY glMultiDrawArraysInstancedANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLint *firsts,
const GLsizei *counts,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
return gl::MultiDrawArraysInstancedANGLEContextANGLE(ctx, mode, firsts, counts, instanceCounts,
drawcount);
}
void GL_APIENTRY glMultiDrawElementsANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
GLsizei drawcount)
{
return gl::MultiDrawElementsANGLEContextANGLE(ctx, mode, counts, type, offsets, drawcount);
}
void GL_APIENTRY glMultiDrawElementsInstancedANGLEContextANGLE(GLeglContext ctx,
GLenum mode,
const GLsizei *counts,
GLenum type,
const GLsizei *offsets,
const GLsizei *instanceCounts,
GLsizei drawcount)
{
return gl::MultiDrawElementsInstancedANGLEContextANGLE(ctx, mode, counts, type, offsets,
instanceCounts, drawcount);
}
} // extern "C"

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -74,6 +74,7 @@ angle_end2end_tests_sources = [
"gl_tests/MaxTextureSizeTest.cpp",
"gl_tests/MemorySizeTest.cpp",
"gl_tests/MipmapTest.cpp",
"gl_tests/MultiDrawTest.cpp",
"gl_tests/MultisampleCompatibilityTest.cpp",
"gl_tests/MultithreadingTest.cpp",
"gl_tests/MultiviewDrawTest.cpp",

Просмотреть файл

@ -0,0 +1,526 @@
//
// Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// MultiDrawTest: Tests of GL_ANGLE_multi_draw
#include "test_utils/ANGLETest.h"
#include "test_utils/gl_raii.h"
using namespace angle;
namespace
{
// Create a kWidth * kHeight canvas equally split into kCountX * kCountY tiles
// each containing a quad partially coverting each tile
constexpr uint32_t kWidth = 256;
constexpr uint32_t kHeight = 256;
constexpr uint32_t kCountX = 8;
constexpr uint32_t kCountY = 8;
constexpr uint32_t kQuadCount = kCountX * kCountY;
constexpr uint32_t kTriCount = kQuadCount * 2;
constexpr std::array<GLfloat, 2> kTileSize = {
1.f / static_cast<GLfloat>(kCountX), 1.f / static_cast<GLfloat>(kCountY),
};
constexpr std::array<uint32_t, 2> kTilePixelSize = {kWidth / kCountX, kHeight / kCountY};
constexpr std::array<GLfloat, 2> kQuadRadius = {0.25f * kTileSize[0], 0.25f * kTileSize[1]};
constexpr std::array<uint32_t, 2> kPixelCheckSize = {kQuadRadius[0] * kWidth,
kQuadRadius[1] * kHeight};
constexpr std::array<GLfloat, 2> getTileCenter(uint32_t x, uint32_t y)
{
return {
kTileSize[0] * (0.5f + static_cast<GLfloat>(x)),
kTileSize[1] * (0.5f + static_cast<GLfloat>(y)),
};
}
constexpr std::array<std::array<GLfloat, 3>, 4> getQuadVertices(uint32_t x, uint32_t y)
{
const auto center = getTileCenter(x, y);
return {
std::array<GLfloat, 3>{center[0] - kQuadRadius[0], center[1] - kQuadRadius[1], 0.0f},
std::array<GLfloat, 3>{center[0] + kQuadRadius[0], center[1] - kQuadRadius[1], 0.0f},
std::array<GLfloat, 3>{center[0] + kQuadRadius[0], center[1] + kQuadRadius[1], 0.0f},
std::array<GLfloat, 3>{center[0] - kQuadRadius[0], center[1] + kQuadRadius[1], 0.0f},
};
}
enum class DrawIDOption
{
NoDrawID,
UseDrawID,
};
enum class InstancingOption
{
NoInstancing,
UseInstancing,
};
using MultiDrawTestParams = std::tuple<angle::PlatformParameters, DrawIDOption, InstancingOption>;
struct PrintToStringParamName
{
std::string operator()(const ::testing::TestParamInfo<MultiDrawTestParams> &info) const
{
::std::stringstream ss;
ss << (std::get<2>(info.param) == InstancingOption::UseInstancing ? "Instanced_" : "")
<< (std::get<1>(info.param) == DrawIDOption::UseDrawID ? "DrawID_" : "")
<< std::get<0>(info.param);
return ss.str();
}
};
// These tests check correctness of the ANGLE_multi_draw extension.
// An array of quads is drawn across the screen.
// gl_DrawID is checked by using it to select the color of the draw.
// MultiDraw*Instanced entrypoints use the existing instancing APIs which are
// more fully tested in InstancingTest.cpp.
// Correct interaction with the instancing APIs is tested here by using scaling
// and then instancing the array of quads over four quadrants on the screen.
class MultiDrawTest : public ANGLETestBase, public ::testing::TestWithParam<MultiDrawTestParams>
{
protected:
MultiDrawTest()
: ANGLETestBase(std::get<0>(GetParam())),
mNonIndexedVertexBuffer(0u),
mVertexBuffer(0u),
mIndexBuffer(0u),
mInstanceBuffer(0u),
mProgram(0u)
{
setWindowWidth(kWidth);
setWindowHeight(kHeight);
setConfigRedBits(8);
setConfigGreenBits(8);
setConfigBlueBits(8);
setConfigAlphaBits(8);
}
void SetUp() override { ANGLETestBase::ANGLETestSetUp(); }
bool IsDrawIDTest() const { return std::get<1>(GetParam()) == DrawIDOption::UseDrawID; }
bool IsInstancedTest() const
{
return std::get<2>(GetParam()) == InstancingOption::UseInstancing;
}
std::string VertexShaderSource()
{
std::stringstream shader;
shader << (IsDrawIDTest() ? "#extension GL_ANGLE_multi_draw : require\n" : "")
<< (IsInstancedTest() ? "attribute float vInstance;" : "") << R"(
attribute vec2 vPosition;
varying vec4 color;
void main()
{
int id = )"
<< (IsDrawIDTest() ? "gl_DrawID" : "0") << ";"
<< R"(
float quad_id = float(id / 2);
float color_id = quad_id - (3.0 * floor(quad_id / 3.0));
if (color_id == 0.0) {
color = vec4(1, 0, 0, 1);
} else if (color_id == 1.0) {
color = vec4(0, 1, 0, 1);
} else {
color = vec4(0, 0, 1, 1);
}
mat3 transform = mat3(1.0);
)" << (IsInstancedTest() ? R"(
transform[0][0] = 0.5;
transform[1][1] = 0.5;
if (vInstance == 0.0) {
} else if (vInstance == 1.0) {
transform[2][0] = 0.5;
} else if (vInstance == 2.0) {
transform[2][1] = 0.5;
} else if (vInstance == 3.0) {
transform[2][0] = 0.5;
transform[2][1] = 0.5;
}
)" : "")
<< R"(
gl_Position = vec4(transform * vec3(vPosition, 1.0) * 2.0 - 1.0, 1);
})";
return shader.str();
}
std::string FragmentShaderSource()
{
return
R"(precision mediump float;
varying vec4 color;
void main()
{
gl_FragColor = color;
})";
}
void SetupProgram()
{
mProgram = CompileProgram(VertexShaderSource().c_str(), FragmentShaderSource().c_str());
EXPECT_GL_NO_ERROR();
ASSERT_GE(mProgram, 1u);
glUseProgram(mProgram);
mPositionLoc = glGetAttribLocation(mProgram, "vPosition");
mInstanceLoc = glGetAttribLocation(mProgram, "vInstance");
}
void SetupBuffers()
{
for (uint32_t y = 0; y < kCountY; ++y)
{
for (uint32_t x = 0; x < kCountX; ++x)
{
// v3 ---- v2
// | |
// | |
// v0 ---- v1
uint32_t quadIndex = y * kCountX + x;
GLushort starting_index = static_cast<GLushort>(4 * quadIndex);
std::array<GLushort, 6> is = {0, 1, 2, 0, 2, 3};
const auto vs = getQuadVertices(x, y);
for (GLushort i : is)
{
mIndices.push_back(starting_index + i);
}
for (const auto &v : vs)
{
mVertices.insert(mVertices.end(), v.begin(), v.end());
}
for (GLushort i : is)
{
mNonIndexedVertices.insert(mNonIndexedVertices.end(), vs[i].begin(),
vs[i].end());
}
}
}
std::array<GLfloat, 4> instances{0, 1, 2, 3};
glGenBuffers(1, &mNonIndexedVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mNonIndexedVertices.size(),
mNonIndexedVertices.data(), GL_STATIC_DRAW);
glGenBuffers(1, &mVertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * mVertices.size(), mVertices.data(),
GL_STATIC_DRAW);
glGenBuffers(1, &mIndexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * mIndices.size(), mIndices.data(),
GL_STATIC_DRAW);
glGenBuffers(1, &mInstanceBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * instances.size(), instances.data(),
GL_STATIC_DRAW);
ASSERT_GL_NO_ERROR();
}
void DoVertexAttribDivisor(GLint location, GLuint divisor)
{
if (getClientMajorVersion() <= 2)
{
ASSERT(extensionEnabled("GL_ANGLE_instanced_arrays"));
glVertexAttribDivisorANGLE(location, divisor);
}
else
{
glVertexAttribDivisor(location, divisor);
}
}
void DoDrawArrays()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
glEnableVertexAttribArray(mPositionLoc);
glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
std::vector<GLint> firsts(kTriCount);
std::vector<GLsizei> counts(kTriCount, 3);
for (uint32_t i = 0; i < kTriCount; ++i)
firsts[i] = i * 3;
if (IsInstancedTest())
{
glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
glEnableVertexAttribArray(mInstanceLoc);
glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
DoVertexAttribDivisor(mInstanceLoc, 1);
std::vector<GLsizei> instanceCounts(kTriCount, 4);
glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, firsts.data(), counts.data(),
instanceCounts.data(), kTriCount);
}
else
{
glMultiDrawArraysANGLE(GL_TRIANGLES, firsts.data(), counts.data(), kTriCount);
}
}
void DoDrawElements()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glEnableVertexAttribArray(mPositionLoc);
glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
std::vector<GLsizei> counts(kTriCount, 3);
std::vector<GLsizei> offsets(kTriCount);
for (uint32_t i = 0; i < kTriCount; ++i)
offsets[i] = i * 3 * 2;
if (IsInstancedTest())
{
glBindBuffer(GL_ARRAY_BUFFER, mInstanceBuffer);
glEnableVertexAttribArray(mInstanceLoc);
glVertexAttribPointer(mInstanceLoc, 1, GL_FLOAT, GL_FALSE, 0, 0);
DoVertexAttribDivisor(mInstanceLoc, 1);
std::vector<GLsizei> instanceCounts(kTriCount, 4);
glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT,
offsets.data(), instanceCounts.data(), kTriCount);
}
else
{
glMultiDrawElementsANGLE(GL_TRIANGLES, counts.data(), GL_UNSIGNED_SHORT, offsets.data(),
kTriCount);
}
}
void CheckDrawResult()
{
for (uint32_t y = 0; y < kCountY; ++y)
{
for (uint32_t x = 0; x < kCountX; ++x)
{
uint32_t center_x = x * kTilePixelSize[0] + kTilePixelSize[0] / 2;
uint32_t center_y = y * kTilePixelSize[1] + kTilePixelSize[1] / 2;
uint32_t quadID = IsDrawIDTest() ? y * kCountX + x : 0;
uint32_t colorID = quadID % 3u;
std::array<GLColor, 3> colors = {GLColor(255, 0, 0, 255), GLColor(0, 255, 0, 255),
GLColor(0, 0, 255, 255)};
GLColor expected = colors[colorID];
if (IsInstancedTest())
{
EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
center_y / 2 - kPixelCheckSize[1] / 4,
kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
center_y / 2 - kPixelCheckSize[1] / 4,
kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4,
center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
EXPECT_PIXEL_RECT_EQ(center_x / 2 - kPixelCheckSize[0] / 4 + kWidth / 2,
center_y / 2 - kPixelCheckSize[1] / 4 + kHeight / 2,
kPixelCheckSize[0] / 2, kPixelCheckSize[1] / 2, expected);
}
else
{
EXPECT_PIXEL_RECT_EQ(center_x - kPixelCheckSize[0] / 2,
center_y - kPixelCheckSize[1] / 2, kPixelCheckSize[0],
kPixelCheckSize[1], expected);
}
}
}
}
void TearDown() override
{
if (mNonIndexedVertexBuffer != 0u)
{
glDeleteBuffers(1, &mNonIndexedVertexBuffer);
}
if (mVertexBuffer != 0u)
{
glDeleteBuffers(1, &mVertexBuffer);
}
if (mIndexBuffer != 0u)
{
glDeleteBuffers(1, &mIndexBuffer);
}
if (mInstanceBuffer != 0u)
{
glDeleteBuffers(1, &mInstanceBuffer);
}
if (mProgram != 0)
{
glDeleteProgram(mProgram);
}
ANGLETestBase::ANGLETestTearDown();
}
bool requestMultiDrawExtension()
{
if (extensionRequestable("GL_ANGLE_multi_draw"))
{
glRequestExtensionANGLE("GL_ANGLE_multi_draw");
}
if (!extensionEnabled("GL_ANGLE_multi_draw"))
{
return false;
}
return true;
}
bool requestInstancedExtension()
{
if (extensionRequestable("GL_ANGLE_instanced_arrays"))
{
glRequestExtensionANGLE("GL_ANGLE_instanced_arrays");
}
if (!extensionEnabled("GL_ANGLE_instanced_arrays"))
{
return false;
}
return true;
}
bool requestExtensions()
{
if (IsInstancedTest() && getClientMajorVersion() <= 2)
{
if (!requestInstancedExtension())
{
return false;
}
}
return requestMultiDrawExtension();
}
std::vector<GLushort> mIndices;
std::vector<GLfloat> mVertices;
std::vector<GLfloat> mNonIndexedVertices;
GLuint mNonIndexedVertexBuffer;
GLuint mVertexBuffer;
GLuint mIndexBuffer;
GLuint mInstanceBuffer;
GLuint mProgram;
GLint mPositionLoc;
GLint mInstanceLoc;
};
class MultiDrawNoInstancingSupportTest : public MultiDrawTest
{
void SetUp() override
{
ASSERT_LE(getClientMajorVersion(), 2);
ASSERT_TRUE(IsInstancedTest());
MultiDrawTest::SetUp();
}
};
// glMultiDraw*ANGLE are emulated and should always be available
TEST_P(MultiDrawTest, RequestExtension)
{
EXPECT_TRUE(requestMultiDrawExtension());
}
// Test that compile a program with the extension succeeds
TEST_P(MultiDrawTest, CanCompile)
{
ANGLE_SKIP_TEST_IF(!requestExtensions());
SetupProgram();
}
// Tests basic functionality of glMultiDrawArraysANGLE
TEST_P(MultiDrawTest, MultiDrawArrays)
{
ANGLE_SKIP_TEST_IF(!requestExtensions());
SetupBuffers();
SetupProgram();
DoDrawArrays();
EXPECT_GL_NO_ERROR();
CheckDrawResult();
}
// Tests basic functionality of glMultiDrawElementsANGLE
TEST_P(MultiDrawTest, MultiDrawElements)
{
ANGLE_SKIP_TEST_IF(!requestExtensions());
SetupBuffers();
SetupProgram();
DoDrawElements();
EXPECT_GL_NO_ERROR();
CheckDrawResult();
}
// Check that glMultiDraw*Instanced without instancing support results in GL_INVALID_OPERATION
TEST_P(MultiDrawNoInstancingSupportTest, InvalidOperation)
{
ANGLE_SKIP_TEST_IF(extensionEnabled("GL_ANGLE_instanced_arrays"));
requestMultiDrawExtension();
SetupBuffers();
SetupProgram();
GLint first = 0;
GLsizei count = 3;
GLsizei offset = 0;
GLsizei instances = 1;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindBuffer(GL_ARRAY_BUFFER, mNonIndexedVertexBuffer);
glEnableVertexAttribArray(mPositionLoc);
glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glMultiDrawArraysInstancedANGLE(GL_TRIANGLES, &first, &count, &instances, 1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mIndexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, mVertexBuffer);
glEnableVertexAttribArray(mPositionLoc);
glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, 0);
glMultiDrawElementsInstancedANGLE(GL_TRIANGLES, &count, GL_UNSIGNED_SHORT, &offset, &instances,
1);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
const angle::PlatformParameters platforms[] = {
ES2_D3D9(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(),
ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES(),
};
const angle::PlatformParameters es2_platforms[] = {
ES2_D3D9(), ES2_OPENGL(), ES2_OPENGLES(), ES2_VULKAN(),
};
INSTANTIATE_TEST_CASE_P(
,
MultiDrawTest,
testing::Combine(testing::ValuesIn(::angle::FilterTestParams(platforms, ArraySize(platforms))),
testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
testing::Values(InstancingOption::NoInstancing,
InstancingOption::UseInstancing)),
PrintToStringParamName());
INSTANTIATE_TEST_CASE_P(
,
MultiDrawNoInstancingSupportTest,
testing::Combine(testing::ValuesIn(::angle::FilterTestParams(es2_platforms,
ArraySize(es2_platforms))),
testing::Values(DrawIDOption::NoDrawID, DrawIDOption::UseDrawID),
testing::Values(InstancingOption::UseInstancing)),
PrintToStringParamName());
} // namespace