Bug 1313541 - Uniform impl. - r=ethlin

MozReview-Commit-ID: DN8sUfRR0z7
This commit is contained in:
Jeff Gilbert (:jgilbert) 2016-10-13 16:15:16 -07:00
Родитель 85e4f2e105
Коммит ec29704197
5 изменённых файлов: 235 добавлений и 225 удалений

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

@ -175,81 +175,29 @@ public:
// Uniforms and attributes - WebGL2ContextUniforms.cpp
void VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, GLintptr offset);
// GL 3.0 & ES 3.0
void Uniform1ui(WebGLUniformLocation* loc, GLuint v0);
void Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1);
void Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2);
void Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
GLuint v3);
////////////////
protected:
typedef Arr<GLuint, dom::Uint32Array> UintArr;
void UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const UintArr& arr);
//////
public:
template<typename T>
void Uniform1uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform1uiv", 1, loc, UintArr(arr));
}
template<typename T>
void Uniform2uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform2uiv", 2, loc, UintArr(arr));
}
template<typename T>
void Uniform3uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform3uiv", 3, loc, UintArr(arr));
}
template<typename T>
void Uniform4uiv(WebGLUniformLocation* loc, const T& arr) {
UniformNuiv("uniform4uiv", 4, loc, UintArr(arr));
}
//////
template<typename T>
void UniformMatrix2x3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix2x3fv", 2, 3, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix2x4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix2x4fv", 2, 4, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix3x2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix3x2fv", 3, 2, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix3x4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix3x4fv", 3, 4, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix4x2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix4x2fv", 4, 2, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix4x3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix4x3fv", 4, 3, loc, transpose, FloatArr(arr));
}
////////////////
private:
void VertexAttribI4iv(GLuint index, size_t length, const GLint* v);
void VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v);
public:
// GL 3.0 & ES 3.0
void VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
void VertexAttribI4iv(GLuint index, const dom::Sequence<GLint>& v);
void VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
void VertexAttribI4uiv(GLuint index, const dom::Sequence<GLuint>& v);
void VertexAttribI4iv(GLuint index, const Int32ListU& list) {
const auto& arr = Int32Arr::From(list);
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, arr.elemCount))
return;
const auto& itr = arr.elemBytes;
VertexAttribI4i(index, itr[0], itr[1], itr[2], itr[3]);
}
void VertexAttribI4uiv(GLuint index, const Uint32ListU& list) {
const auto& arr = Uint32Arr::From(list);
if (!ValidateAttribArraySetter("vertexAttribI4uiv", 4, arr.elemCount))
return;
const auto& itr = arr.elemBytes;
VertexAttribI4ui(index, itr[0], itr[1], itr[2], itr[3]);
}
// -------------------------------------------------------------------------
// Writing to the drawing buffer

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

@ -27,7 +27,7 @@ WebGL2Context::ValidateUniformMatrixTranspose(bool /*transpose*/, const char* /*
// Uniforms
void
WebGL2Context::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
WebGLContext::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
{
if (!ValidateUniformSetter(loc, 1, LOCAL_GL_UNSIGNED_INT, "uniform1ui"))
return;
@ -37,7 +37,7 @@ WebGL2Context::Uniform1ui(WebGLUniformLocation* loc, GLuint v0)
}
void
WebGL2Context::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1)
WebGLContext::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1)
{
if (!ValidateUniformSetter(loc, 2, LOCAL_GL_UNSIGNED_INT, "uniform2ui"))
return;
@ -47,7 +47,7 @@ WebGL2Context::Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1)
}
void
WebGL2Context::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2)
WebGLContext::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2)
{
if (!ValidateUniformSetter(loc, 3, LOCAL_GL_UNSIGNED_INT, "uniform3ui"))
return;
@ -57,8 +57,8 @@ WebGL2Context::Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuin
}
void
WebGL2Context::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
GLuint v3)
WebGLContext::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
GLuint v3)
{
if (!ValidateUniformSetter(loc, 4, LOCAL_GL_UNSIGNED_INT, "uniform4ui"))
return;
@ -67,7 +67,6 @@ WebGL2Context::Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuin
gl->fUniform4ui(loc->mLoc, v0, v1, v2, v3);
}
// -------------------------------------------------------------------------
// Uniform Buffer Objects and Transform Feedback Buffers

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

@ -116,38 +116,6 @@ WebGL2Context::VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
}
}
void
WebGL2Context::VertexAttribI4iv(GLuint index, size_t length, const GLint* v)
{
if (!ValidateAttribArraySetter("vertexAttribI4iv", 4, length))
return;
if (!ValidateAttribIndex(index, "vertexAttribI4iv"))
return;
mVertexAttribType[index] = LOCAL_GL_INT;
MakeContextCurrent();
if (index) {
gl->fVertexAttribI4iv(index, v);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(v[0]);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(v[1]);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(v[2]);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(v[3]);
if (gl->IsGLES()) {
gl->fVertexAttribI4iv(index, v);
}
}
}
void
WebGL2Context::VertexAttribI4iv(GLuint index, const dom::Sequence<GLint>& v)
{
VertexAttribI4iv(index, v.Length(), v.Elements());
}
void
WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
{
@ -174,39 +142,4 @@ WebGL2Context::VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLui
}
}
void
WebGL2Context::VertexAttribI4uiv(GLuint index, size_t length, const GLuint* v)
{
if (IsContextLost())
return;
if (!ValidateAttribArraySetter("vertexAttribI4uiv", 4, length))
return;
if (!ValidateAttribIndex(index, "vertexAttribI4uiv"))
return;
mVertexAttribType[index] = LOCAL_GL_UNSIGNED_INT;
MakeContextCurrent();
if (index) {
gl->fVertexAttribI4uiv(index, v);
} else {
mVertexAttrib0Vector[0] = BitwiseCast<GLfloat>(v[0]);
mVertexAttrib0Vector[1] = BitwiseCast<GLfloat>(v[1]);
mVertexAttrib0Vector[2] = BitwiseCast<GLfloat>(v[2]);
mVertexAttrib0Vector[3] = BitwiseCast<GLfloat>(v[3]);
if (gl->IsGLES()) {
gl->fVertexAttribI4uiv(index, v);
}
}
}
void
WebGL2Context::VertexAttribI4uiv(GLuint index, const dom::Sequence<GLuint>& v)
{
VertexAttribI4uiv(index, v.Length(), v.Elements());
}
} // namespace mozilla

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

@ -48,6 +48,8 @@
#include "mozilla/dom/HTMLCanvasElement.h"
#include "nsWrapperCache.h"
#include "nsLayoutUtils.h"
#include "mozilla/dom/WebGLRenderingContextBinding.h"
#include "mozilla/dom/WebGL2RenderingContextBinding.h"
class nsIDocShell;
@ -615,104 +617,174 @@ public:
//////
void Uniform1i(WebGLUniformLocation* loc, GLint x);
void Uniform2i(WebGLUniformLocation* loc, GLint x, GLint y);
void Uniform3i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z);
void Uniform4i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z, GLint w);
void Uniform1f(WebGLUniformLocation* loc, GLfloat x);
void Uniform2f(WebGLUniformLocation* loc, GLfloat x, GLfloat y);
void Uniform3f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z);
void Uniform4f(WebGLUniformLocation* loc, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
void Uniform1i(WebGLUniformLocation* loc, GLint x);
void Uniform2i(WebGLUniformLocation* loc, GLint x, GLint y);
void Uniform3i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z);
void Uniform4i(WebGLUniformLocation* loc, GLint x, GLint y, GLint z, GLint w);
void Uniform1ui(WebGLUniformLocation* loc, GLuint v0);
void Uniform2ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1);
void Uniform3ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2);
void Uniform4ui(WebGLUniformLocation* loc, GLuint v0, GLuint v1, GLuint v2,
GLuint v3);
//////////////////////////
protected:
template<typename elemT, typename arrT>
struct Arr {
size_t dataCount;
const elemT* data;
typedef dom::Float32ArrayOrUnrestrictedFloatSequence Float32ListU;
typedef dom::Int32ArrayOrLongSequence Int32ListU;
typedef dom::Uint32ArrayOrUnsignedLongSequence Uint32ListU;
explicit Arr(const arrT& arr) {
arr.ComputeLengthAndData();
dataCount = arr.LengthAllowShared();
data = arr.DataAllowShared();
protected:
template<typename elemT, typename viewT>
struct Arr {
const size_t elemCount;
const elemT* const elemBytes;
private:
static size_t ComputeAndReturnLength(const viewT& view) {
view.ComputeLengthAndData();
return view.LengthAllowShared();
}
explicit Arr(const dom::Sequence<elemT>& arr) {
dataCount = arr.Length();
data = arr.Elements();
public:
explicit Arr(const viewT& view)
: elemCount(ComputeAndReturnLength(view))
, elemBytes(view.DataAllowShared())
{ }
explicit Arr(const dom::Sequence<elemT>& seq)
: elemCount(seq.Length())
, elemBytes(seq.Elements())
{ }
Arr(size_t _elemCount, const elemT* _elemBytes)
: elemCount(_elemCount)
, elemBytes(_elemBytes)
{ }
////
static Arr From(const Float32ListU& list) {
if (list.IsFloat32Array())
return Arr(list.GetAsFloat32Array());
return Arr(list.GetAsUnrestrictedFloatSequence());
}
static Arr From(const Int32ListU& list) {
if (list.IsInt32Array())
return Arr(list.GetAsInt32Array());
return Arr(list.GetAsLongSequence());
}
static Arr From(const Uint32ListU& list) {
if (list.IsUint32Array())
return Arr(list.GetAsUint32Array());
return Arr(list.GetAsUnsignedLongSequence());
}
};
typedef Arr<GLint, dom::Int32Array> IntArr;
typedef Arr<GLfloat, dom::Float32Array> FloatArr;
typedef Arr<GLfloat, dom::Float32Array> Float32Arr;
typedef Arr<GLint, dom::Int32Array> Int32Arr;
typedef Arr<GLuint, dom::Uint32Array> Uint32Arr;
////////////////
void UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const IntArr& arr);
void UniformNfv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const FloatArr& arr);
const Float32Arr& arr, GLuint elemOffset, GLuint elemCountOverride);
void UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const Int32Arr& arr, GLuint elemOffset, GLuint elemCountOverride);
void UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const Uint32Arr& arr, GLuint elemOffset, GLuint elemCountOverride);
void UniformMatrixAxBfv(const char* funcName, uint8_t A, uint8_t B,
WebGLUniformLocation* loc, bool transpose,
const FloatArr& arr);
const Float32Arr& arr, GLuint elemOffset,
GLuint elemCountOverride);
////////////////
public:
template<typename T>
void Uniform1iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform1iv", 1, loc, IntArr(arr));
}
template<typename T>
void Uniform2iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform2iv", 2, loc, IntArr(arr));
}
template<typename T>
void Uniform3iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform3iv", 3, loc, IntArr(arr));
}
template<typename T>
void Uniform4iv(WebGLUniformLocation* loc, const T& arr) {
UniformNiv("uniform4iv", 4, loc, IntArr(arr));
}
#define FOO(N) \
void Uniform ## N ## fv(WebGLUniformLocation* loc, const Float32ListU& list, \
GLuint elemOffset = 0, GLuint elemCountOverride = 0) \
{ \
UniformNfv("uniform" #N "fv", N, loc, Float32Arr::From(list), elemOffset, \
elemCountOverride); \
}
FOO(1)
FOO(2)
FOO(3)
FOO(4)
#undef FOO
//////
template<typename T>
void Uniform1fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform1fv", 1, loc, FloatArr(arr));
}
template<typename T>
void Uniform2fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform2fv", 2, loc, FloatArr(arr));
}
template<typename T>
void Uniform3fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform3fv", 3, loc, FloatArr(arr));
}
template<typename T>
void Uniform4fv(WebGLUniformLocation* loc, const T& arr) {
UniformNfv("uniform4fv", 4, loc, FloatArr(arr));
}
#define FOO(N) \
void Uniform ## N ## iv(WebGLUniformLocation* loc, const Int32ListU& list, \
GLuint elemOffset = 0, GLuint elemCountOverride = 0) \
{ \
UniformNiv("uniform" #N "iv", N, loc, Int32Arr::From(list), elemOffset, \
elemCountOverride); \
}
FOO(1)
FOO(2)
FOO(3)
FOO(4)
#undef FOO
//////
template<typename T>
void UniformMatrix2fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix2fv", 2, 2, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix3fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix3fv", 3, 3, loc, transpose, FloatArr(arr));
}
template<typename T>
void UniformMatrix4fv(WebGLUniformLocation* loc, bool transpose, const T& arr) {
UniformMatrixAxBfv("uniformMatrix4fv", 4, 4, loc, transpose, FloatArr(arr));
}
#define FOO(N) \
void Uniform ## N ## uiv(WebGLUniformLocation* loc, const Uint32ListU& list, \
GLuint elemOffset = 0, GLuint elemCountOverride = 0) \
{ \
UniformNuiv("uniform" #N "uiv", N, loc, Uint32Arr::From(list), elemOffset, \
elemCountOverride); \
}
FOO(1)
FOO(2)
FOO(3)
FOO(4)
#undef FOO
//////
#define FOO(X,A,B) \
void UniformMatrix ## X ## fv(WebGLUniformLocation* loc, bool transpose, \
const Float32ListU& list, GLuint elemOffset = 0, \
GLuint elemCountOverride = 0) \
{ \
UniformMatrixAxBfv("uniformMatrix" #X "fv", A, B, loc, transpose, \
Float32Arr::From(list), elemOffset, elemCountOverride); \
}
FOO(2,2,2)
FOO(2x3,2,3)
FOO(2x4,2,4)
FOO(3x2,3,2)
FOO(3,3,3)
FOO(3x4,3,4)
FOO(4x2,4,2)
FOO(4x3,4,3)
FOO(4,4,4)
#undef FOO
////////////////////////////////////

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

@ -2023,12 +2023,43 @@ WebGLContext::Uniform4f(WebGLUniformLocation* loc, GLfloat a1, GLfloat a2,
////////////////////////////////////////
// Array
static bool
ValidateArrOffsetAndCount(WebGLContext* webgl, const char* funcName, size_t elemsAvail,
GLuint elemOffset, GLuint elemCountOverride,
size_t* const out_elemCount)
{
if (elemOffset > elemsAvail) {
webgl->ErrorInvalidValue("%s: Bad offset into list.", funcName);
return false;
}
elemsAvail -= elemOffset;
if (elemCountOverride) {
if (elemCountOverride > elemsAvail) {
webgl->ErrorInvalidValue("%s: Bad count override for sub-list.", funcName);
return false;
}
elemsAvail = elemCountOverride;
}
*out_elemCount = elemsAvail;
return true;
}
void
WebGLContext::UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const IntArr& arr)
const Int32Arr& arr, GLuint elemOffset, GLuint elemCountOverride)
{
size_t elemCount;
if (!ValidateArrOffsetAndCount(this, funcName, arr.elemCount, elemOffset,
elemCountOverride, &elemCount))
{
return;
}
const auto elemBytes = arr.elemBytes + elemOffset;
uint32_t numElementsToUpload;
if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_INT, arr.dataCount, funcName,
if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_INT, elemCount, funcName,
&numElementsToUpload))
{
return;
@ -2036,7 +2067,7 @@ WebGLContext::UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation*
bool error;
const ValidateIfSampler samplerValidator(this, funcName, loc, numElementsToUpload,
arr.data, &error);
elemBytes, &error);
if (error)
return;
@ -2049,16 +2080,25 @@ WebGLContext::UniformNiv(const char* funcName, uint8_t N, WebGLUniformLocation*
const auto func = kFuncList[N-1];
MakeContextCurrent();
(gl->*func)(loc->mLoc, numElementsToUpload, arr.data);
(gl->*func)(loc->mLoc, numElementsToUpload, elemBytes);
}
void
WebGL2Context::UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const UintArr& arr)
WebGLContext::UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const Uint32Arr& arr, GLuint elemOffset,
GLuint elemCountOverride)
{
size_t elemCount;
if (!ValidateArrOffsetAndCount(this, funcName, arr.elemCount, elemOffset,
elemCountOverride, &elemCount))
{
return;
}
const auto elemBytes = arr.elemBytes + elemOffset;
uint32_t numElementsToUpload;
if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_UNSIGNED_INT, arr.dataCount,
funcName, &numElementsToUpload))
if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_UNSIGNED_INT, elemCount, funcName,
&numElementsToUpload))
{
return;
}
@ -2073,15 +2113,24 @@ WebGL2Context::UniformNuiv(const char* funcName, uint8_t N, WebGLUniformLocation
const auto func = kFuncList[N-1];
MakeContextCurrent();
(gl->*func)(loc->mLoc, numElementsToUpload, arr.data);
(gl->*func)(loc->mLoc, numElementsToUpload, elemBytes);
}
void
WebGLContext::UniformNfv(const char* funcName, uint8_t N, WebGLUniformLocation* loc,
const FloatArr& arr)
const Float32Arr& arr, GLuint elemOffset,
GLuint elemCountOverride)
{
size_t elemCount;
if (!ValidateArrOffsetAndCount(this, funcName, arr.elemCount, elemOffset,
elemCountOverride, &elemCount))
{
return;
}
const auto elemBytes = arr.elemBytes + elemOffset;
uint32_t numElementsToUpload;
if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_FLOAT, arr.dataCount, funcName,
if (!ValidateUniformArraySetter(loc, N, LOCAL_GL_FLOAT, elemCount, funcName,
&numElementsToUpload))
{
return;
@ -2097,16 +2146,25 @@ WebGLContext::UniformNfv(const char* funcName, uint8_t N, WebGLUniformLocation*
const auto func = kFuncList[N-1];
MakeContextCurrent();
(gl->*func)(loc->mLoc, numElementsToUpload, arr.data);
(gl->*func)(loc->mLoc, numElementsToUpload, elemBytes);
}
void
WebGLContext::UniformMatrixAxBfv(const char* funcName, uint8_t A, uint8_t B,
WebGLUniformLocation* loc, bool transpose,
const FloatArr& arr)
const Float32Arr& arr, GLuint elemOffset,
GLuint elemCountOverride)
{
size_t elemCount;
if (!ValidateArrOffsetAndCount(this, funcName, arr.elemCount, elemOffset,
elemCountOverride, &elemCount))
{
return;
}
const auto elemBytes = arr.elemBytes + elemOffset;
uint32_t numElementsToUpload;
if (!ValidateUniformMatrixArraySetter(loc, A, B, LOCAL_GL_FLOAT, arr.dataCount,
if (!ValidateUniformMatrixArraySetter(loc, A, B, LOCAL_GL_FLOAT, elemCount,
transpose, funcName, &numElementsToUpload))
{
return;
@ -2129,7 +2187,7 @@ WebGLContext::UniformMatrixAxBfv(const char* funcName, uint8_t A, uint8_t B,
const auto func = kFuncList[3*(A-2) + (B-2)];
MakeContextCurrent();
(gl->*func)(loc->mLoc, numElementsToUpload, false, arr.data);
(gl->*func)(loc->mLoc, numElementsToUpload, false, elemBytes);
}
////////////////////////////////////////////////////////////////////////////////