зеркало из https://github.com/AvaloniaUI/angle.git
Implement GL_ANGLE_multi_draw
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:
Родитель
bc5834cdad
Коммит
1bf18ce9e2
|
@ -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;
|
||||
}
|
||||
|
||||
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
|
Загрузка…
Ссылка в новой задаче