summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--java/Samples/res/raw/shaderarrayf.glsl16
-rw-r--r--java/Samples/res/raw/shaderarrayv.glsl32
-rw-r--r--java/Samples/res/raw/shaderf.glsl6
-rw-r--r--java/Samples/res/raw/shaderv.glsl6
-rw-r--r--java/Samples/src/com/android/samples/RsRenderStatesRS.java30
-rw-r--r--java/Samples/src/com/android/samples/rsrenderstates.rs83
-rw-r--r--java/Samples/src/com/android/samples/shader_def.rsh27
-rw-r--r--rs.spec4
-rw-r--r--rsContextHostStub.h1
-rw-r--r--rsElement.cpp40
-rw-r--r--rsElement.h2
-rw-r--r--rsFont.cpp7
-rw-r--r--rsMesh.cpp112
-rw-r--r--rsMesh.h10
-rw-r--r--rsProgram.cpp255
-rw-r--r--rsProgram.h21
-rw-r--r--rsProgramFragment.cpp10
-rw-r--r--rsProgramVertex.cpp8
-rw-r--r--rsScriptC_LibGL.cpp8
-rw-r--r--rsShaderCache.cpp118
-rw-r--r--rsShaderCache.h92
-rw-r--r--rsType.cpp89
-rw-r--r--rsType.h12
-rw-r--r--rsVertexArray.cpp64
-rw-r--r--rsVertexArray.h24
25 files changed, 700 insertions, 377 deletions
diff --git a/java/Samples/res/raw/shaderarrayf.glsl b/java/Samples/res/raw/shaderarrayf.glsl
new file mode 100644
index 00000000..238ecad5
--- /dev/null
+++ b/java/Samples/res/raw/shaderarrayf.glsl
@@ -0,0 +1,16 @@
+
+varying lowp float light0_Diffuse;
+varying lowp float light0_Specular;
+varying lowp float light1_Diffuse;
+varying lowp float light1_Specular;
+varying vec2 varTex0;
+
+void main() {
+ vec2 t0 = varTex0.xy;
+ lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
+ col.xyz = col.xyz * (light0_Diffuse * UNI_light_DiffuseColor[0].xyz + light1_Diffuse * UNI_light_DiffuseColor[1].xyz);
+ col.xyz += light0_Specular * UNI_light_SpecularColor[0].xyz;
+ col.xyz += light1_Specular * UNI_light_SpecularColor[1].xyz;
+ gl_FragColor = col;
+}
+
diff --git a/java/Samples/res/raw/shaderarrayv.glsl b/java/Samples/res/raw/shaderarrayv.glsl
new file mode 100644
index 00000000..7a1310ac
--- /dev/null
+++ b/java/Samples/res/raw/shaderarrayv.glsl
@@ -0,0 +1,32 @@
+varying float light0_Diffuse;
+varying float light0_Specular;
+varying float light1_Diffuse;
+varying float light1_Specular;
+varying vec2 varTex0;
+
+// This is where actual shader code begins
+void main() {
+ vec4 worldPos = UNI_model[0] * ATTRIB_position;
+ worldPos = UNI_model[1] * worldPos;
+ gl_Position = UNI_proj * worldPos;
+
+ mat4 model0 = UNI_model[0];
+ mat3 model3 = mat3(model0[0].xyz, model0[1].xyz, model0[2].xyz);
+ vec3 worldNorm = model3 * ATTRIB_normal;
+ vec3 V = normalize(-worldPos.xyz);
+
+ vec3 light0Vec = normalize(UNI_light_Posision[0].xyz - worldPos.xyz);
+ vec3 light0R = -reflect(light0Vec, worldNorm);
+ light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light_Diffuse[0];
+ float light0Spec = clamp(dot(light0R, V), 0.001, 1.0);
+ light0_Specular = pow(light0Spec, UNI_light_CosinePower[0]) * UNI_light_Specular[0];
+
+ vec3 light1Vec = normalize(UNI_light_Posision[1].xyz - worldPos.xyz);
+ vec3 light1R = reflect(light1Vec, worldNorm);
+ light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light_Diffuse[1];
+ float light1Spec = clamp(dot(light1R, V), 0.001, 1.0);
+ light1_Specular = pow(light1Spec, UNI_light_CosinePower[1]) * UNI_light_Specular[1];
+
+ gl_PointSize = 1.0;
+ varTex0 = ATTRIB_texture0;
+}
diff --git a/java/Samples/res/raw/shaderf.glsl b/java/Samples/res/raw/shaderf.glsl
index fcbe7ee5..d56e2034 100644
--- a/java/Samples/res/raw/shaderf.glsl
+++ b/java/Samples/res/raw/shaderf.glsl
@@ -8,9 +8,9 @@ varying vec2 varTex0;
void main() {
vec2 t0 = varTex0.xy;
lowp vec4 col = texture2D(UNI_Tex0, t0).rgba;
- col.xyz = col.xyz * (light0_Diffuse * UNI_light0_DiffuseColor + light1_Diffuse * UNI_light1_DiffuseColor);
- col.xyz += light0_Specular * UNI_light0_SpecularColor;
- col.xyz += light1_Specular * UNI_light1_SpecularColor;
+ col.xyz = col.xyz * (light0_Diffuse * UNI_light0_DiffuseColor.xyz + light1_Diffuse * UNI_light1_DiffuseColor.xyz);
+ col.xyz += light0_Specular * UNI_light0_SpecularColor.xyz;
+ col.xyz += light1_Specular * UNI_light1_SpecularColor.xyz;
gl_FragColor = col;
}
diff --git a/java/Samples/res/raw/shaderv.glsl b/java/Samples/res/raw/shaderv.glsl
index 867589cf..f7d01de3 100644
--- a/java/Samples/res/raw/shaderv.glsl
+++ b/java/Samples/res/raw/shaderv.glsl
@@ -13,13 +13,13 @@ void main() {
vec3 worldNorm = model3 * ATTRIB_normal;
vec3 V = normalize(-worldPos.xyz);
- vec3 light0Vec = normalize(UNI_light0_Posision - worldPos.xyz);
- vec3 light0R = reflect(light0Vec, worldNorm);
+ vec3 light0Vec = normalize(UNI_light0_Posision.xyz - worldPos.xyz);
+ vec3 light0R = -reflect(light0Vec, worldNorm);
light0_Diffuse = clamp(dot(worldNorm, light0Vec), 0.0, 1.0) * UNI_light0_Diffuse;
float light0Spec = clamp(dot(light0R, V), 0.001, 1.0);
light0_Specular = pow(light0Spec, UNI_light0_CosinePower) * UNI_light0_Specular;
- vec3 light1Vec = normalize(UNI_light1_Posision - worldPos.xyz);
+ vec3 light1Vec = normalize(UNI_light1_Posision.xyz - worldPos.xyz);
vec3 light1R = reflect(light1Vec, worldNorm);
light1_Diffuse = clamp(dot(worldNorm, light1Vec), 0.0, 1.0) * UNI_light1_Diffuse;
float light1Spec = clamp(dot(light1R, V), 0.001, 1.0);
diff --git a/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/java/Samples/src/com/android/samples/RsRenderStatesRS.java
index 85c2557c..dd2daa78 100644
--- a/java/Samples/src/com/android/samples/RsRenderStatesRS.java
+++ b/java/Samples/src/com/android/samples/RsRenderStatesRS.java
@@ -43,7 +43,7 @@ public class RsRenderStatesRS {
mOptionsARGB.inScaled = false;
mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
mMode = 0;
- mMaxModes = 9;
+ mMaxModes = 0;
initRS();
}
@@ -73,7 +73,12 @@ public class RsRenderStatesRS {
private ProgramFragment mProgFragmentCustom;
private ProgramFragment mProgFragmentMultitex;
private ScriptField_VertexShaderConstants_s mVSConst;
+ private ScriptField_VertexShaderConstants2_s mVSConst2;
private ScriptField_FragentShaderConstants_s mFSConst;
+ private ScriptField_FragentShaderConstants2_s mFSConst2;
+
+ private ProgramVertex mProgVertexCustom2;
+ private ProgramFragment mProgFragmentCustom2;
private ProgramRaster mCullBack;
private ProgramRaster mCullFront;
@@ -189,10 +194,14 @@ public class RsRenderStatesRS {
private void initCustomShaders() {
mVSConst = new ScriptField_VertexShaderConstants_s(mRS, 1);
+ mVSConst2 = new ScriptField_VertexShaderConstants2_s(mRS, 1);
mFSConst = new ScriptField_FragentShaderConstants_s(mRS, 1);
+ mFSConst2 = new ScriptField_FragentShaderConstants2_s(mRS, 1);
mScript.bind_gVSConstants(mVSConst);
+ mScript.bind_gVSConstants2(mVSConst2);
mScript.bind_gFSConstants(mFSConst);
+ mScript.bind_gFSConstants2(mFSConst2);
// Initialize the shader builder
ProgramVertex.ShaderBuilder pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
@@ -217,6 +226,20 @@ public class RsRenderStatesRS {
// Bind the source of constant data
mProgFragmentCustom.bindConstants(mFSConst.getAllocation(), 0);
+ pvbCustom = new ProgramVertex.ShaderBuilder(mRS);
+ pvbCustom.setShader(mRes, R.raw.shaderarrayv);
+ pvbCustom.addInput(ScriptField_VertexShaderInputs_s.createElement(mRS));
+ pvbCustom.addConstant(mVSConst2.getAllocation().getType());
+ mProgVertexCustom2 = pvbCustom.create();
+ mProgVertexCustom2.bindConstants(mVSConst2.getAllocation(), 0);
+
+ pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
+ pfbCustom.setShader(mRes, R.raw.shaderarrayf);
+ pfbCustom.setTextureCount(1);
+ pfbCustom.addConstant(mFSConst2.getAllocation().getType());
+ mProgFragmentCustom2 = pfbCustom.create();
+ mProgFragmentCustom2.bindConstants(mFSConst2.getAllocation(), 0);
+
pfbCustom = new ProgramFragment.ShaderBuilder(mRS);
pfbCustom.setShader(mRes, R.raw.multitexf);
pfbCustom.setTextureCount(3);
@@ -225,6 +248,9 @@ public class RsRenderStatesRS {
mScript.set_gProgVertexCustom(mProgVertexCustom);
mScript.set_gProgFragmentCustom(mProgFragmentCustom);
mScript.set_gProgFragmentMultitex(mProgFragmentMultitex);
+
+ mScript.set_gProgVertexCustom2(mProgVertexCustom2);
+ mScript.set_gProgFragmentCustom2(mProgFragmentCustom2);
}
private Allocation loadTextureRGB(int id) {
@@ -334,6 +360,8 @@ public class RsRenderStatesRS {
mScript = new ScriptC_rsrenderstates(mRS, mRes, R.raw.rsrenderstates);
+ mMaxModes = mScript.get_gMaxModes();
+
initSamplers();
initProgramStore();
initProgramFragment();
diff --git a/java/Samples/src/com/android/samples/rsrenderstates.rs b/java/Samples/src/com/android/samples/rsrenderstates.rs
index 8be35f8e..4f8eada1 100644
--- a/java/Samples/src/com/android/samples/rsrenderstates.rs
+++ b/java/Samples/src/com/android/samples/rsrenderstates.rs
@@ -19,6 +19,8 @@
#include "rs_graphics.rsh"
#include "shader_def.rsh"
+const int gMaxModes = 10;
+
rs_program_vertex gProgVertex;
rs_program_fragment gProgFragmentColor;
rs_program_fragment gProgFragmentTexture;
@@ -59,12 +61,16 @@ rs_program_raster gCullNone;
// Custom vertex shader compunents
VertexShaderConstants *gVSConstants;
+VertexShaderConstants2 *gVSConstants2;
FragentShaderConstants *gFSConstants;
+FragentShaderConstants2 *gFSConstants2;
// Export these out to easily set the inputs to shader
VertexShaderInputs *gVSInputs;
// Custom shaders we use for lighting
rs_program_vertex gProgVertexCustom;
rs_program_fragment gProgFragmentCustom;
+rs_program_vertex gProgVertexCustom2;
+rs_program_fragment gProgFragmentCustom2;
rs_program_fragment gProgFragmentMultitex;
float gDt = 0;
@@ -367,10 +373,10 @@ float gLight1Rotation = 0;
void setupCustomShaderLights() {
float4 light0Pos = {-5.0f, 5.0f, -10.0f, 1.0f};
float4 light1Pos = {2.0f, 5.0f, 15.0f, 1.0f};
- float3 light0DiffCol = {0.9f, 0.7f, 0.7f};
- float3 light0SpecCol = {0.9f, 0.6f, 0.6f};
- float3 light1DiffCol = {0.5f, 0.5f, 0.9f};
- float3 light1SpecCol = {0.5f, 0.5f, 0.9f};
+ float4 light0DiffCol = {0.9f, 0.7f, 0.7f, 1.0f};
+ float4 light0SpecCol = {0.9f, 0.6f, 0.6f, 1.0f};
+ float4 light1DiffCol = {0.5f, 0.5f, 0.9f, 1.0f};
+ float4 light1SpecCol = {0.5f, 0.5f, 0.9f, 1.0f};
gLight0Rotation += 50.0f * gDt;
if(gLight0Rotation > 360.0f) {
@@ -389,21 +395,27 @@ void setupCustomShaderLights() {
light1Pos = rsMatrixMultiply(&l1Mat, light1Pos);
// Set light 0 properties
- gVSConstants->light0_Posision.x = light0Pos.x;
- gVSConstants->light0_Posision.y = light0Pos.y;
- gVSConstants->light0_Posision.z = light0Pos.z;
+ gVSConstants->light0_Posision = light0Pos;
gVSConstants->light0_Diffuse = 1.0f;
gVSConstants->light0_Specular = 0.5f;
- gVSConstants->light0_CosinePower = 40.0f;
+ gVSConstants->light0_CosinePower = 10.0f;
// Set light 1 properties
- gVSConstants->light1_Posision.x = light1Pos.x;
- gVSConstants->light1_Posision.y = light1Pos.y;
- gVSConstants->light1_Posision.z = light1Pos.z;
+ gVSConstants->light1_Posision = light1Pos;
gVSConstants->light1_Diffuse = 1.0f;
gVSConstants->light1_Specular = 0.7f;
- gVSConstants->light1_CosinePower = 50.0f;
+ gVSConstants->light1_CosinePower = 25.0f;
rsAllocationMarkDirty(rsGetAllocation(gVSConstants));
+ gVSConstants2->light_Posision[0] = light0Pos;
+ gVSConstants2->light_Diffuse[0] = 1.0f;
+ gVSConstants2->light_Specular[0] = 0.5f;
+ gVSConstants2->light_CosinePower[0] = 10.0f;
+ gVSConstants2->light_Posision[1] = light1Pos;
+ gVSConstants2->light_Diffuse[1] = 1.0f;
+ gVSConstants2->light_Specular[1] = 0.7f;
+ gVSConstants2->light_CosinePower[1] = 25.0f;
+ rsAllocationMarkDirty(rsGetAllocation(gVSConstants2));
+
// Update fragmetn shader constants
// Set light 0 colors
gFSConstants->light0_DiffuseColor = light0DiffCol;
@@ -412,6 +424,13 @@ void setupCustomShaderLights() {
gFSConstants->light1_DiffuseColor = light1DiffCol;
gFSConstants->light1_SpecularColor = light1SpecCol;
rsAllocationMarkDirty(rsGetAllocation(gFSConstants));
+
+ gFSConstants2->light_DiffuseColor[0] = light0DiffCol;
+ gFSConstants2->light_SpecularColor[0] = light0SpecCol;
+ // Set light 1 colors
+ gFSConstants2->light_DiffuseColor[1] = light1DiffCol;
+ gFSConstants2->light_SpecularColor[1] = light1SpecCol;
+ rsAllocationMarkDirty(rsGetAllocation(gFSConstants2));
}
void displayCustomShaderSamples() {
@@ -450,6 +469,43 @@ void displayCustomShaderSamples() {
rsgDrawText("Custom shader sample", 10, rsgGetHeight() - 10);
}
+void displayCustomShaderSamples2() {
+
+ // Update vertex shader constants
+ // Load model matrix
+ // Aplly a rotation to our mesh
+ gTorusRotation += 50.0f * gDt;
+ if(gTorusRotation > 360.0f) {
+ gTorusRotation -= 360.0f;
+ }
+
+ // Position our model on the screen
+ rsMatrixLoadTranslate(&gVSConstants2->model[1], 0.0f, 0.0f, -10.0f);
+ rsMatrixLoadIdentity(&gVSConstants2->model[0]);
+ rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 1.0f, 0.0f, 0.0f);
+ rsMatrixRotate(&gVSConstants2->model[0], gTorusRotation, 0.0f, 0.0f, 1.0f);
+ // Setup the projectioni matrix
+ float aspect = (float)rsgGetWidth() / (float)rsgGetHeight();
+ rsMatrixLoadPerspective(&gVSConstants2->proj, 30.0f, aspect, 0.1f, 100.0f);
+ setupCustomShaderLights();
+
+ rsgBindProgramVertex(gProgVertexCustom2);
+
+ // Fragment shader with texture
+ rsgBindProgramStore(gProgStoreBlendNoneDepth);
+ rsgBindProgramFragment(gProgFragmentCustom2);
+ rsgBindSampler(gProgFragmentCustom2, 0, gLinearClamp);
+ rsgBindTexture(gProgFragmentCustom2, 0, gTexTorus);
+
+ // Use back face culling
+ rsgBindProgramRaster(gCullBack);
+ rsgDrawMesh(gTorusMesh);
+
+ rsgFontColor(1.0f, 1.0f, 1.0f, 1.0f);
+ rsgBindFont(gFontMono);
+ rsgDrawText("Custom shader sample with array uniforms", 10, rsgGetHeight() - 10);
+}
+
void displayMultitextureSample() {
bindProgramVertexOrtho();
rs_matrix4x4 matrix;
@@ -577,6 +633,9 @@ int root(int launchID) {
case 8:
displayAnisoSample();
break;
+ case 9:
+ displayCustomShaderSamples2();
+ break;
}
return 10;
diff --git a/java/Samples/src/com/android/samples/shader_def.rsh b/java/Samples/src/com/android/samples/shader_def.rsh
index e3f62063..3f51785b 100644
--- a/java/Samples/src/com/android/samples/shader_def.rsh
+++ b/java/Samples/src/com/android/samples/shader_def.rsh
@@ -19,26 +19,39 @@
typedef struct VertexShaderConstants_s {
rs_matrix4x4 model;
rs_matrix4x4 proj;
- float3 light0_Posision;
+ float4 light0_Posision;
float light0_Diffuse;
float light0_Specular;
float light0_CosinePower;
- float3 light1_Posision;
+ float4 light1_Posision;
float light1_Diffuse;
float light1_Specular;
float light1_CosinePower;
} VertexShaderConstants;
-typedef struct FragentShaderConstants_s {
- float3 light0_DiffuseColor;
- float3 light0_SpecularColor;
+typedef struct VertexShaderConstants2_s {
+ rs_matrix4x4 model[2];
+ rs_matrix4x4 proj;
+ float4 light_Posision[2];
+ float light_Diffuse[2];
+ float light_Specular[2];
+ float light_CosinePower[2];
+} VertexShaderConstants2;
- float3 light1_DiffuseColor;
- float3 light1_SpecularColor;
+typedef struct FragentShaderConstants_s {
+ float4 light0_DiffuseColor;
+ float4 light0_SpecularColor;
+ float4 light1_DiffuseColor;
+ float4 light1_SpecularColor;
} FragentShaderConstants;
+typedef struct FragentShaderConstants2_s {
+ float4 light_DiffuseColor[2];
+ float4 light_SpecularColor[2];
+} FragentShaderConstants2;
+
typedef struct VertexShaderInputs_s {
float4 position;
float3 normal;
diff --git a/rs.spec b/rs.spec
index 14809e98..ac9abe07 100644
--- a/rs.spec
+++ b/rs.spec
@@ -435,6 +435,10 @@ MeshBindVertex {
param uint32_t slot
}
+MeshInitVertexAttribs {
+ param RsMesh mesh
+ }
+
AnimationCreate {
param const float *inValues
param const float *outValues
diff --git a/rsContextHostStub.h b/rsContextHostStub.h
index f3e9dab3..ee32b570 100644
--- a/rsContextHostStub.h
+++ b/rsContextHostStub.h
@@ -122,6 +122,7 @@ public:
mutable const ObjectBase * mObjHead;
bool ext_OES_texture_npot() const {return mGL.OES_texture_npot;}
+ bool ext_GL_NV_texture_npot_2D_mipmap() const {return false;}
float ext_texture_max_aniso() const {return 1.0f;}
uint32_t getMaxFragmentTextures() const {return mGL.mMaxFragmentTextureImageUnits;}
uint32_t getMaxFragmentUniformVectors() const {return mGL.mMaxFragmentUniformVectors;}
diff --git a/rsElement.cpp b/rsElement.cpp
index d207dcf0..2ab37298 100644
--- a/rsElement.cpp
+++ b/rsElement.cpp
@@ -113,24 +113,15 @@ Element *Element::createFromStream(Context *rsc, IStream *stream)
Element *elem = new Element(rsc);
elem->mComponent.loadFromStream(stream);
- elem->mBits = elem->mComponent.getBits();
- elem->mHasReference = elem->mComponent.isReference();
elem->mFieldCount = stream->loadU32();
if(elem->mFieldCount) {
- uint32_t offset = 0;
elem->mFields = new ElementField_t [elem->mFieldCount];
for(uint32_t ct = 0; ct < elem->mFieldCount; ct ++) {
stream->loadString(&elem->mFields[ct].name);
elem->mFields[ct].arraySize = stream->loadU32();
Element *fieldElem = Element::createFromStream(rsc, stream);
elem->mFields[ct].e.set(fieldElem);
- elem->mFields[ct].offsetBits = offset;
- offset += fieldElem->getSizeBits();
- // Check if our sub-elements have references
- if(fieldElem->mHasReference) {
- elem->mHasReference = true;
- }
}
}
@@ -144,6 +135,7 @@ Element *Element::createFromStream(Context *rsc, IStream *stream)
}
}
+ elem->compute();
rsc->mStateElement.mElements.push(elem);
return elem;
}
@@ -175,6 +167,25 @@ bool Element::isEqual(const Element *other) const {
return false;
}
+void Element::compute() {
+ if(mFieldCount == 0) {
+ mBits = mComponent.getBits();
+ mHasReference = mComponent.isReference();
+ return;
+ }
+
+ size_t bits = 0;
+ for (size_t ct=0; ct < mFieldCount; ct++) {
+ mFields[ct].offsetBits = bits;
+ bits += mFields[ct].e->getSizeBits() * mFields[ct].arraySize;
+
+ if (mFields[ct].e->mHasReference) {
+ mHasReference = true;
+ }
+ }
+
+}
+
const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
bool isNorm, uint32_t vecSize)
{
@@ -194,8 +205,7 @@ const Element * Element::create(Context *rsc, RsDataType dt, RsDataKind dk,
Element *e = new Element(rsc);
e->mComponent.set(dt, dk, isNorm, vecSize);
- e->mBits = e->mComponent.getBits();
- e->mHasReference = e->mComponent.isReference();
+ e->compute();
rsc->mStateElement.mElements.push(e);
return e;
}
@@ -227,18 +237,12 @@ const Element * Element::create(Context *rsc, size_t count, const Element **ein,
Element *e = new Element(rsc);
e->mFields = new ElementField_t [count];
e->mFieldCount = count;
- size_t bits = 0;
for (size_t ct=0; ct < count; ct++) {
e->mFields[ct].e.set(ein[ct]);
e->mFields[ct].name.setTo(nin[ct], lengths[ct]);
- e->mFields[ct].offsetBits = bits;
e->mFields[ct].arraySize = asin[ct];
- bits += ein[ct]->getSizeBits();
-
- if (ein[ct]->mHasReference) {
- e->mHasReference = true;
- }
}
+ e->compute();
rsc->mStateElement.mElements.push(e);
return e;
diff --git a/rsElement.h b/rsElement.h
index 70e2619d..506a5302 100644
--- a/rsElement.h
+++ b/rsElement.h
@@ -94,6 +94,8 @@ protected:
Component mComponent;
uint32_t mBits;
+
+ void compute();
};
diff --git a/rsFont.cpp b/rsFont.cpp
index 9e762152..66f455c0 100644
--- a/rsFont.cpp
+++ b/rsFont.cpp
@@ -663,9 +663,10 @@ void FontState::issueDrawCommand() {
float *vtx = (float*)mVertexArray->getPtr();
float *tex = vtx + 3;
- VertexArray va;
- va.add(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
- va.add(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
+ VertexArray::Attrib attribs[2];
+ attribs[0].set(GL_FLOAT, 3, 20, false, (uint32_t)vtx, "ATTRIB_position");
+ attribs[1].set(GL_FLOAT, 2, 20, false, (uint32_t)tex, "ATTRIB_texture0");
+ VertexArray va(attribs, 2);
va.setupGL2(mRSC, &mRSC->mStateVertexArray, &mRSC->mShaderCache);
mIndexBuffer->uploadCheck(mRSC);
diff --git a/rsMesh.cpp b/rsMesh.cpp
index fd604e5e..f2dd6879 100644
--- a/rsMesh.cpp
+++ b/rsMesh.cpp
@@ -37,6 +37,10 @@ Mesh::Mesh(Context *rsc) : ObjectBase(rsc)
mPrimitivesCount = 0;
mVertexBuffers = NULL;
mVertexBufferCount = 0;
+ mAttribs = NULL;
+ mAttribAllocationIndex = NULL;
+
+ mAttribCount = 0;
}
Mesh::~Mesh()
@@ -51,6 +55,87 @@ Mesh::~Mesh()
}
delete[] mPrimitives;
}
+
+ if(mAttribs) {
+ delete[] mAttribs;
+ delete[] mAttribAllocationIndex;
+ }
+}
+
+bool Mesh::isValidGLComponent(const Element *elem, uint32_t fieldIdx) {
+ // Do not create attribs for padding
+ if(elem->getFieldName(fieldIdx)[0] == '#') {
+ return false;
+ }
+
+ // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
+ // Filter rs types accordingly
+ RsDataType dt = elem->getField(fieldIdx)->getComponent().getType();
+ if(dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
+ dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
+ dt != RS_TYPE_SIGNED_16) {
+ return false;
+ }
+
+ // Now make sure they are not arrays
+ uint32_t arraySize = elem->getFieldArraySize(fieldIdx);
+ if(arraySize != 1) {
+ return false;
+ }
+
+ return true;
+}
+
+void Mesh::initVertexAttribs() {
+ // Count the number of gl attrs to initialize
+ mAttribCount = 0;
+ for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
+ const Element *elem = mVertexBuffers[ct]->getType()->getElement();
+ for (uint32_t ct=0; ct < elem->getFieldCount(); ct++) {
+ if(isValidGLComponent(elem, ct)) {
+ mAttribCount ++;
+ }
+ }
+ }
+
+ if(mAttribs) {
+ delete [] mAttribs;
+ delete [] mAttribAllocationIndex;
+ mAttribs = NULL;
+ mAttribAllocationIndex = NULL;
+ }
+ if(!mAttribCount) {
+ return;
+ }
+
+ mAttribs = new VertexArray::Attrib[mAttribCount];
+ mAttribAllocationIndex = new uint32_t[mAttribCount];
+
+ uint32_t userNum = 0;
+ for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
+ const Element *elem = mVertexBuffers[ct]->getType()->getElement();
+ uint32_t stride = elem->getSizeBytes();
+ for (uint32_t fieldI=0; fieldI < elem->getFieldCount(); fieldI++) {
+ const Component &c = elem->getField(fieldI)->getComponent();
+
+ if(!isValidGLComponent(elem, fieldI)) {
+ continue;
+ }
+
+ mAttribs[userNum].size = c.getVectorSize();
+ mAttribs[userNum].offset = elem->getFieldOffsetBytes(fieldI);
+ mAttribs[userNum].type = c.getGLType();
+ mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
+ mAttribs[userNum].stride = stride;
+ String8 tmp(RS_SHADER_ATTR);
+ tmp.append(elem->getFieldName(fieldI));
+ mAttribs[userNum].name.setTo(tmp.string());
+
+ // Remember which allocation this attribute came from
+ mAttribAllocationIndex[userNum] = ct;
+ userNum ++;
+ }
+ }
}
void Mesh::render(Context *rsc) const
@@ -78,21 +163,29 @@ void Mesh::renderPrimitive(Context *rsc, uint32_t primIndex) const {
void Mesh::renderPrimitiveRange(Context *rsc, uint32_t primIndex, uint32_t start, uint32_t len) const
{
- if (len < 1 || primIndex >= mPrimitivesCount) {
+ if (len < 1 || primIndex >= mPrimitivesCount || mAttribCount == 0) {
+ LOGE("Invalid mesh or parameters");
return;
}
rsc->checkError("Mesh::renderPrimitiveRange 1");
- VertexArray va;
for (uint32_t ct=0; ct < mVertexBufferCount; ct++) {
mVertexBuffers[ct]->uploadCheck(rsc);
- if (mVertexBuffers[ct]->getIsBufferObject()) {
- va.setActiveBuffer(mVertexBuffers[ct]->getBufferObjectID());
+ }
+ // update attributes with either buffer information or data ptr based on their current state
+ for (uint32_t ct=0; ct < mAttribCount; ct++) {
+ uint32_t allocIndex = mAttribAllocationIndex[ct];
+ Allocation *alloc = mVertexBuffers[allocIndex].get();
+ if (alloc->getIsBufferObject()) {
+ mAttribs[ct].buffer = alloc->getBufferObjectID();
+ mAttribs[ct].ptr = NULL;
} else {
- va.setActiveBuffer(mVertexBuffers[ct]->getPtr());
+ mAttribs[ct].buffer = 0;
+ mAttribs[ct].ptr = (const uint8_t*)alloc->getPtr();
}
- mVertexBuffers[ct]->getType()->enableGLVertexBuffer(&va);
}
+
+ VertexArray va(mAttribs, mAttribCount);
va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
rsc->checkError("Mesh::renderPrimitiveRange 2");
@@ -215,6 +308,7 @@ Mesh *Mesh::createFromStream(Context *rsc, IStream *stream)
}
mesh->updateGLPrimitives();
+ mesh->initVertexAttribs();
mesh->uploadAll(rsc);
return mesh;
@@ -310,6 +404,12 @@ void rsi_MeshBindIndex(Context *rsc, RsMesh mv, RsAllocation va, uint32_t primTy
sm->updateGLPrimitives();
}
+void rsi_MeshInitVertexAttribs(Context *rsc, RsMesh mv)
+{
+ Mesh *sm = static_cast<Mesh *>(mv);
+ sm->initVertexAttribs();
+}
+
}}
void rsaMeshGetVertexBufferCount(RsContext con, RsMesh mv, int32_t *numVtx)
diff --git a/rsMesh.h b/rsMesh.h
index ed01c384..261b5a6b 100644
--- a/rsMesh.h
+++ b/rsMesh.h
@@ -66,7 +66,17 @@ public:
float mBBoxMax[3];
void computeBBox();
+ void initVertexAttribs();
+
protected:
+ bool isValidGLComponent(const Element *elem, uint32_t fieldIdx);
+ // Attribues that allow us to map to GL
+ VertexArray::Attrib *mAttribs;
+ // This allows us to figure out which allocation the attribute
+ // belongs to. In the event the allocation is uploaded to GL
+ // buffer, it lets us properly map it
+ uint32_t *mAttribAllocationIndex;
+ uint32_t mAttribCount;
};
class MeshContext
diff --git a/rsProgram.cpp b/rsProgram.cpp
index 72d1b026..ce3af2dd 100644
--- a/rsProgram.cpp
+++ b/rsProgram.cpp
@@ -31,37 +31,14 @@ using namespace android::renderscript;
Program::Program(Context *rsc) : ObjectBase(rsc)
{
- mDirty = true;
- mShaderID = 0;
- mAttribCount = 0;
- mUniformCount = 0;
- mTextureCount = 0;
-
- mTextures = NULL;
- mSamplers = NULL;
- mInputElements = NULL;
- mOutputElements = NULL;
- mConstantTypes = NULL;
- mInputCount = 0;
- mOutputCount = 0;
- mConstantCount = 0;
- mIsValid = false;
- mIsInternal = false;
+ initMemberVars();
}
Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
const uint32_t * params, uint32_t paramLength) :
ObjectBase(rsc)
{
- mDirty = true;
- mShaderID = 0;
- mAttribCount = 0;
- mUniformCount = 0;
- mTextureCount = 0;
-
- mInputCount = 0;
- mOutputCount = 0;
- mConstantCount = 0;
+ initMemberVars();
for (uint32_t ct=0; ct < paramLength; ct+=2) {
if (params[ct] == RS_PROGRAM_PARAM_INPUT) {
@@ -83,6 +60,7 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
mInputElements = new ObjectBaseRef<Element>[mInputCount];
mOutputElements = new ObjectBaseRef<Element>[mOutputCount];
mConstantTypes = new ObjectBaseRef<Type>[mConstantCount];
+ mConstants = new ObjectBaseRef<Allocation>[mConstantCount];
uint32_t input = 0;
uint32_t output = 0;
@@ -107,6 +85,8 @@ Program::Program(Context *rsc, const char * shaderText, uint32_t shaderLength,
shaderLength -= internalTokenLen;
}
mUserShader.setTo(shaderText, shaderLength);
+
+ initAttribAndUniformArray();
}
Program::~Program()
@@ -119,7 +99,7 @@ Program::~Program()
glDeleteShader(mShaderID);
}
- for (uint32_t ct=0; ct < MAX_UNIFORMS; ct++) {
+ for (uint32_t ct=0; ct < mConstantCount; ct++) {
bindAllocation(NULL, NULL, ct);
}
@@ -132,11 +112,37 @@ Program::~Program()
delete[] mInputElements;
delete[] mOutputElements;
delete[] mConstantTypes;
+ delete[] mConstants;
+ delete[] mAttribNames;
+ delete[] mUniformNames;
+ delete[] mUniformArraySizes;
mInputCount = 0;
mOutputCount = 0;
mConstantCount = 0;
}
+void Program::initMemberVars() {
+ mDirty = true;
+ mShaderID = 0;
+ mAttribCount = 0;
+ mUniformCount = 0;
+ mTextureCount = 0;
+
+ mTextures = NULL;
+ mSamplers = NULL;
+ mInputElements = NULL;
+ mOutputElements = NULL;
+ mConstantTypes = NULL;
+ mConstants = NULL;
+ mAttribNames = NULL;
+ mUniformNames = NULL;
+ mUniformArraySizes = NULL;
+ mInputCount = 0;
+ mOutputCount = 0;
+ mConstantCount = 0;
+ mIsValid = false;
+ mIsInternal = false;
+}
void Program::bindAllocation(Context *rsc, Allocation *alloc, uint32_t slot)
{
@@ -314,11 +320,95 @@ void Program::appendUserConstants() {
}
mShader.append(fn);
+ if(e->getFieldArraySize(field) > 1) {
+ mShader.appendFormat("[%d]", e->getFieldArraySize(field));
+ }
mShader.append(";\n");
}
}
}
+void Program::logUniform(const Element *field, const float *fd, uint32_t arraySize ) {
+ RsDataType dataType = field->getType();
+ uint32_t elementSize = field->getSizeBytes() / sizeof(float);
+ for(uint32_t i = 0; i < arraySize; i ++) {
+ if(arraySize > 1) {
+ LOGV("Array Element [%u]", i);
+ }
+ if(dataType == RS_TYPE_MATRIX_4X4) {
+ LOGV("Matrix4x4");
+ LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]);
+ LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]);
+ LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]);
+ LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
+ }
+ else if(dataType == RS_TYPE_MATRIX_3X3) {
+ LOGV("Matrix3x3");
+ LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]);
+ LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]);
+ LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
+ }
+ else if(dataType == RS_TYPE_MATRIX_2X2) {
+ LOGV("Matrix2x2");
+ LOGV("{%f, %f", fd[0], fd[2]);
+ LOGV(" %f, %f}", fd[1], fd[3]);
+ }
+ else {
+ switch(field->getComponent().getVectorSize()) {
+ case 1:
+ LOGV("Uniform 1 = %f", fd[0]);
+ break;
+ case 2:
+ LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
+ break;
+ case 3:
+ LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
+ break;
+ case 4:
+ LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
+ break;
+ default:
+ rsAssert(0);
+ }
+ }
+ LOGE("Element size %u data=%p", elementSize, fd);
+ fd += elementSize;
+ LOGE("New data=%p", fd);
+ }
+}
+
+void Program::setUniform(Context *rsc, const Element *field, const float *fd,
+ int32_t slot, uint32_t arraySize ) {
+ RsDataType dataType = field->getType();
+ if(dataType == RS_TYPE_MATRIX_4X4) {
+ glUniformMatrix4fv(slot, arraySize, GL_FALSE, fd);
+ }
+ else if(dataType == RS_TYPE_MATRIX_3X3) {
+ glUniformMatrix3fv(slot, arraySize, GL_FALSE, fd);
+ }
+ else if(dataType == RS_TYPE_MATRIX_2X2) {
+ glUniformMatrix2fv(slot, arraySize, GL_FALSE, fd);
+ }
+ else {
+ switch(field->getComponent().getVectorSize()) {
+ case 1:
+ glUniform1fv(slot, arraySize, fd);
+ break;
+ case 2:
+ glUniform2fv(slot, arraySize, fd);
+ break;
+ case 3:
+ glUniform3fv(slot, arraySize, fd);
+ break;
+ case 4:
+ glUniform4fv(slot, arraySize, fd);
+ break;
+ default:
+ rsAssert(0);
+ }
+ }
+}
+
void Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment) {
uint32_t uidx = 0;
for (uint32_t ct=0; ct < mConstantCount; ct++) {
@@ -343,92 +433,77 @@ void Program::setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment)
const float *fd = reinterpret_cast<const float *>(&data[offset]);
int32_t slot = -1;
+ uint32_t arraySize = 1;
if(!isFragment) {
slot = sc->vtxUniformSlot(uidx);
- }
- else {
+ arraySize = sc->vtxUniformSize(uidx);
+ } else {
slot = sc->fragUniformSlot(uidx);
+ arraySize = sc->fragUniformSize(uidx);
}
-
if(rsc->props.mLogShadersUniforms) {
LOGV("Uniform slot=%i, offset=%i, constant=%i, field=%i, uidx=%i, name=%s", slot, offset, ct, field, uidx, fieldName);
}
- if (slot >= 0) {
- if(f->getType() == RS_TYPE_MATRIX_4X4) {
- if(rsc->props.mLogShadersUniforms) {
- LOGV("Matrix4x4");
- LOGV("{%f, %f, %f, %f", fd[0], fd[4], fd[8], fd[12]);
- LOGV(" %f, %f, %f, %f", fd[1], fd[5], fd[9], fd[13]);
- LOGV(" %f, %f, %f, %f", fd[2], fd[6], fd[10], fd[14]);
- LOGV(" %f, %f, %f, %f}", fd[3], fd[7], fd[11], fd[15]);
- }
- glUniformMatrix4fv(slot, 1, GL_FALSE, fd);
- }
- else if(f->getType() == RS_TYPE_MATRIX_3X3) {
- if(rsc->props.mLogShadersUniforms) {
- LOGV("Matrix3x3");
- LOGV("{%f, %f, %f", fd[0], fd[3], fd[6]);
- LOGV(" %f, %f, %f", fd[1], fd[4], fd[7]);
- LOGV(" %f, %f, %f}", fd[2], fd[5], fd[8]);
- }
- glUniformMatrix3fv(slot, 1, GL_FALSE, fd);
- }
- else if(f->getType() == RS_TYPE_MATRIX_2X2) {
- if(rsc->props.mLogShadersUniforms){
- LOGV("Matrix2x2");
- LOGV("{%f, %f", fd[0], fd[2]);
- LOGV(" %f, %f}", fd[1], fd[3]);
- }
- glUniformMatrix2fv(slot, 1, GL_FALSE, fd);
- }
- else {
- switch(f->getComponent().getVectorSize()) {
- case 1:
- if(rsc->props.mLogShadersUniforms) {
- LOGV("Uniform 1 = %f", fd[0]);
- }
- glUniform1fv(slot, 1, fd);
- break;
- case 2:
- if(rsc->props.mLogShadersUniforms) {
- LOGV("Uniform 2 = %f %f", fd[0], fd[1]);
- }
- glUniform2fv(slot, 1, fd);
- break;
- case 3:
- if(rsc->props.mLogShadersUniforms) {
- LOGV("Uniform 3 = %f %f %f", fd[0], fd[1], fd[2]);
- }
- glUniform3fv(slot, 1, fd);
- break;
- case 4:
- if(rsc->props.mLogShadersUniforms) {
- LOGV("Uniform 4 = %f %f %f %f", fd[0], fd[1], fd[2], fd[3]);
- }
- glUniform4fv(slot, 1, fd);
- break;
- default:
- rsAssert(0);
- }
- }
- }
uidx ++;
+ if (slot < 0) {
+ continue;
+ }
+
+ if(rsc->props.mLogShadersUniforms) {
+ logUniform(f, fd, arraySize);
+ }
+ setUniform(rsc, f, fd, slot, arraySize);
}
}
}
-void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix)
+void Program::initAttribAndUniformArray() {
+ mAttribCount = 0;
+ for (uint32_t ct=0; ct < mInputCount; ct++) {
+ const Element *elem = mInputElements[ct].get();
+ for (uint32_t field=0; field < elem->getFieldCount(); field++) {
+ if(elem->getFieldName(field)[0] != '#') {
+ mAttribCount ++;
+ }
+ }
+ }
+
+ mUniformCount = 0;
+ for (uint32_t ct=0; ct < mConstantCount; ct++) {
+ const Element *elem = mConstantTypes[ct]->getElement();
+
+ for (uint32_t field=0; field < elem->getFieldCount(); field++) {
+ if(elem->getFieldName(field)[0] != '#') {
+ mUniformCount ++;
+ }
+ }
+ }
+ mUniformCount += mTextureCount;
+
+ if(mAttribCount) {
+ mAttribNames = new String8[mAttribCount];
+ }
+ if(mUniformCount) {
+ mUniformNames = new String8[mUniformCount];
+ mUniformArraySizes = new uint32_t[mUniformCount];
+ }
+}
+
+void Program::initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix)
{
rsAssert(e->getFieldCount());
for (uint32_t ct=0; ct < e->getFieldCount(); ct++) {
const Element *ce = e->getField(ct);
if (ce->getFieldCount()) {
- initAddUserElement(ce, names, count, prefix);
+ initAddUserElement(ce, names, arrayLengths, count, prefix);
}
else if(e->getFieldName(ct)[0] != '#') {
String8 tmp(prefix);
tmp.append(e->getFieldName(ct));
names[*count].setTo(tmp.string());
+ if(arrayLengths) {
+ arrayLengths[*count] = e->getFieldArraySize(ct);
+ }
(*count)++;
}
}
diff --git a/rsProgram.h b/rsProgram.h
index c93033b6..46692fdc 100644
--- a/rsProgram.h
+++ b/rsProgram.h
@@ -32,8 +32,6 @@ class ShaderCache;
class Program : public ObjectBase
{
public:
- const static uint32_t MAX_ATTRIBS = 8;
- const static uint32_t MAX_UNIFORMS = 16;
Program(Context *);
Program(Context *, const char * shaderText, uint32_t shaderLength,
@@ -55,12 +53,14 @@ public:
uint32_t getUniformCount() const {return mUniformCount;}
const String8 & getAttribName(uint32_t i) const {return mAttribNames[i];}
const String8 & getUniformName(uint32_t i) const {return mUniformNames[i];}
+ uint32_t getUniformArraySize(uint32_t i) const {return mUniformArraySizes[i];}
String8 getGLSLInputString() const;
String8 getGLSLOutputString() const;
String8 getGLSLConstantString() const;
bool isValid() const {return mIsValid;}
+ void forceDirty() const {mDirty = true;}
protected:
// Components not listed in "in" will be passed though
@@ -68,6 +68,7 @@ protected:
ObjectBaseRef<Element> *mInputElements;
ObjectBaseRef<Element> *mOutputElements;
ObjectBaseRef<Type> *mConstantTypes;
+ ObjectBaseRef<Allocation> *mConstants;
uint32_t mInputCount;
uint32_t mOutputCount;
uint32_t mConstantCount;
@@ -77,9 +78,9 @@ protected:
// Applies to vertex and fragment shaders only
void appendUserConstants();
void setupUserConstants(Context *rsc, ShaderCache *sc, bool isFragment);
- void initAddUserElement(const Element *e, String8 *names, uint32_t *count, const char *prefix);
+ void initAddUserElement(const Element *e, String8 *names, uint32_t *arrayLengths, uint32_t *count, const char *prefix);
- ObjectBaseRef<Allocation> mConstants[MAX_UNIFORMS];
+ void initAttribAndUniformArray();
mutable bool mDirty;
String8 mShader;
@@ -89,8 +90,13 @@ protected:
uint32_t mTextureCount;
uint32_t mAttribCount;
uint32_t mUniformCount;
- String8 mAttribNames[MAX_ATTRIBS];
- String8 mUniformNames[MAX_UNIFORMS];
+ String8 *mAttribNames;
+ String8 *mUniformNames;
+ uint32_t *mUniformArraySizes;
+
+ void logUniform(const Element *field, const float *fd, uint32_t arraySize );
+ void setUniform(Context *rsc, const Element *field, const float *fd, int32_t slot, uint32_t arraySize );
+ void initMemberVars();
// The difference between Textures and Constants is how they are accessed
// Texture lookups go though a sampler which in effect converts normalized
@@ -102,9 +108,6 @@ protected:
ObjectBaseRef<Sampler> *mSamplers;
bool loadShader(Context *, uint32_t type);
-
-public:
- void forceDirty() const {mDirty = true;}
};
diff --git a/rsProgramFragment.cpp b/rsProgramFragment.cpp
index 800854b4..d089a5a3 100644
--- a/rsProgramFragment.cpp
+++ b/rsProgramFragment.cpp
@@ -146,17 +146,19 @@ void ProgramFragment::createShader()
void ProgramFragment::init(Context *rsc)
{
- mUniformCount = 0;
+ uint32_t uniformIndex = 0;
if (mUserShader.size() > 0) {
for (uint32_t ct=0; ct < mConstantCount; ct++) {
- initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, RS_SHADER_UNI);
+ initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformIndex, RS_SHADER_UNI);
}
}
- mTextureUniformIndexStart = mUniformCount;
+ mTextureUniformIndexStart = uniformIndex;
char buf[256];
for (uint32_t ct=0; ct < mTextureCount; ct++) {
sprintf(buf, "UNI_Tex%i", ct);
- mUniformNames[mUniformCount++].setTo(buf);
+ mUniformNames[uniformIndex].setTo(buf);
+ mUniformArraySizes[uniformIndex] = 1;
+ uniformIndex++;
}
createShader();
diff --git a/rsProgramVertex.cpp b/rsProgramVertex.cpp
index 4e64008c..9ee2eeb3 100644
--- a/rsProgramVertex.cpp
+++ b/rsProgramVertex.cpp
@@ -202,14 +202,14 @@ void ProgramVertex::transformToScreen(Context *rsc, float *v4out, const float *v
void ProgramVertex::init(Context *rsc)
{
- mAttribCount = 0;
+ uint32_t attribCount = 0;
+ uint32_t uniformCount = 0;
if (mUserShader.size() > 0) {
for (uint32_t ct=0; ct < mInputCount; ct++) {
- initAddUserElement(mInputElements[ct].get(), mAttribNames, &mAttribCount, RS_SHADER_ATTR);
+ initAddUserElement(mInputElements[ct].get(), mAttribNames, NULL, &attribCount, RS_SHADER_ATTR);
}
- mUniformCount = 0;
for (uint32_t ct=0; ct < mConstantCount; ct++) {
- initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, &mUniformCount, RS_SHADER_UNI);
+ initAddUserElement(mConstantTypes[ct]->getElement(), mUniformNames, mUniformArraySizes, &uniformCount, RS_SHADER_UNI);
}
}
createShader();
diff --git a/rsScriptC_LibGL.cpp b/rsScriptC_LibGL.cpp
index 5b07e7bd..d877ebdc 100644
--- a/rsScriptC_LibGL.cpp
+++ b/rsScriptC_LibGL.cpp
@@ -159,9 +159,11 @@ static void SC_drawQuadTexCoords(float x1, float y1, float z1,
float vtx[] = {x1,y1,z1, x2,y2,z2, x3,y3,z3, x4,y4,z4};
const float tex[] = {u1,v1, u2,v2, u3,v3, u4,v4};
- VertexArray va;
- va.add(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position");
- va.add(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0");
+ VertexArray::Attrib attribs[2];
+ attribs[0].set(GL_FLOAT, 3, 12, false, (uint32_t)vtx, "ATTRIB_position");
+ attribs[1].set(GL_FLOAT, 2, 8, false, (uint32_t)tex, "ATTRIB_texture0");
+
+ VertexArray va(attribs, 2);
va.setupGL2(rsc, &rsc->mStateVertexArray, &rsc->mShaderCache);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
diff --git a/rsShaderCache.cpp b/rsShaderCache.cpp
index 45f6207f..193ced3f 100644
--- a/rsShaderCache.cpp
+++ b/rsShaderCache.cpp
@@ -27,19 +27,62 @@ using namespace android;
using namespace android::renderscript;
-ShaderCache::ShaderCache()
-{
+ShaderCache::ShaderCache() {
mEntries.setCapacity(16);
}
-ShaderCache::~ShaderCache()
-{
+ShaderCache::~ShaderCache() {
for (uint32_t ct=0; ct < mEntries.size(); ct++) {
glDeleteProgram(mEntries[ct]->program);
free(mEntries[ct]);
}
}
+void ShaderCache::updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID,
+ UniformData *data, const char* logTag,
+ UniformQueryData **uniformList, uint32_t uniListSize) {
+
+ for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) {
+ if(data[ct].slot >= 0 && data[ct].arraySize > 1) {
+ //Iterate over the list of active GL uniforms and find highest array index
+ for(uint32_t ui = 0; ui < uniListSize; ui ++) {
+ if(prog->getUniformName(ct) == uniformList[ui]->name) {
+ data[ct].arraySize = (uint32_t)uniformList[ui]->arraySize;
+ break;
+ }
+ }
+ }
+
+ if (rsc->props.mLogShaders) {
+ LOGV("%s U, %s = %d, arraySize = %d\n", logTag,
+ prog->getUniformName(ct).string(), data[ct].slot, data[ct].arraySize);
+ }
+ }
+}
+
+void ShaderCache::populateUniformData(Program *prog, uint32_t linkedID, UniformData *data) {
+ for (uint32_t ct=0; ct < prog->getUniformCount(); ct++) {
+ data[ct].slot = glGetUniformLocation(linkedID, prog->getUniformName(ct));
+ data[ct].arraySize = prog->getUniformArraySize(ct);
+ }
+}
+
+bool ShaderCache::hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag) {
+ UniformData *data = mCurrent->vtxUniforms;
+ for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) {
+ if(data[ct].slot >= 0 && data[ct].arraySize > 1) {
+ return true;
+ }
+ }
+ data = mCurrent->fragUniforms;
+ for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) {
+ if(data[ct].slot >= 0 && data[ct].arraySize > 1) {
+ return true;
+ }
+ }
+ return false;
+}
+
bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag)
{
if (!vtx->getShaderID()) {
@@ -70,13 +113,14 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
//LOGV("ShaderCache miss");
//LOGE("e0 %x", glGetError());
- entry_t *e = (entry_t *)malloc(sizeof(entry_t));
+ ProgramEntry *e = new ProgramEntry(vtx->getAttribCount(),
+ vtx->getUniformCount(),
+ frag->getUniformCount());
mEntries.push(e);
mCurrent = e;
e->vtx = vtx->getShaderID();
e->frag = frag->getShaderID();
e->program = glCreateProgram();
- e->vtxAttrCount = vtx->getAttribCount();
if (e->program) {
GLuint pgm = e->program;
glAttachShader(pgm, vtx->getShaderID());
@@ -112,28 +156,58 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
}
for (uint32_t ct=0; ct < e->vtxAttrCount; ct++) {
- e->mVtxAttribSlots[ct] = glGetAttribLocation(pgm, vtx->getAttribName(ct));
- e->mVtxAttribNames[ct] = vtx->getAttribName(ct).string();
+ e->vtxAttrs[ct].slot = glGetAttribLocation(pgm, vtx->getAttribName(ct));
+ e->vtxAttrs[ct].name = vtx->getAttribName(ct).string();
if (rsc->props.mLogShaders) {
- LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->mVtxAttribSlots[ct]);
+ LOGV("vtx A %i, %s = %d\n", ct, vtx->getAttribName(ct).string(), e->vtxAttrs[ct].slot);
}
}
- for (uint32_t ct=0; ct < vtx->getUniformCount(); ct++) {
- e->mVtxUniformSlots[ct] = glGetUniformLocation(pgm, vtx->getUniformName(ct));
- if (rsc->props.mLogShaders) {
- LOGV("vtx U, %s = %d\n", vtx->getUniformName(ct).string(), e->mVtxUniformSlots[ct]);
+ populateUniformData(vtx, pgm, e->vtxUniforms);
+ populateUniformData(frag, pgm, e->fragUniforms);
+
+ // Only populate this list if we have arrays in our uniforms
+ UniformQueryData **uniformList = NULL;
+ GLint numUniforms = 0;
+ bool hasArrays = hasArrayUniforms(vtx, frag);
+ if(hasArrays) {
+ // Get the number of active uniforms and the length of the longest name
+ glGetProgramiv(pgm, GL_ACTIVE_UNIFORMS, &numUniforms);
+ GLint maxNameLength = 0;
+ glGetProgramiv(pgm, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxNameLength);
+ if(numUniforms > 0 && maxNameLength > 0) {
+ uniformList = new UniformQueryData*[numUniforms];
+ // Iterate over all the uniforms and build the list we
+ // can later use to match our uniforms to
+ for(uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) {
+ uniformList[ct] = new UniformQueryData(maxNameLength);
+ glGetActiveUniform(pgm, ct, maxNameLength, &uniformList[ct]->writtenLength,
+ &uniformList[ct]->arraySize, &uniformList[ct]->type,
+ uniformList[ct]->name);
+ //LOGE("GL UNI idx=%u, arraySize=%u, name=%s", ct,
+ // uniformList[ct]->arraySize, uniformList[ct]->name);
+ }
}
}
- for (uint32_t ct=0; ct < frag->getUniformCount(); ct++) {
- e->mFragUniformSlots[ct] = glGetUniformLocation(pgm, frag->getUniformName(ct));
- if (rsc->props.mLogShaders) {
- LOGV("frag U, %s = %d\n", frag->getUniformName(ct).string(), e->mFragUniformSlots[ct]);
+
+ // We now know the highest index of all of the array uniforms
+ // and we need to update our cache to reflect that
+ // we may have declared [n], but only m < n elements are used
+ updateUniformArrayData(rsc, vtx, pgm, e->vtxUniforms, "vtx",
+ uniformList, (uint32_t)numUniforms);
+ updateUniformArrayData(rsc, frag, pgm, e->fragUniforms, "frag",
+ uniformList, (uint32_t)numUniforms);
+
+ // Clean up the uniform data from GL
+ if(uniformList != NULL) {
+ for(uint32_t ct = 0; ct < (uint32_t)numUniforms; ct++) {
+ delete uniformList[ct];
}
+ delete[] uniformList;
+ uniformList = NULL;
}
}
- e->mIsValid = true;
//LOGV("SC made program %i", e->program);
glUseProgram(e->program);
rsc->checkError("ShaderCache::lookup (miss)");
@@ -142,8 +216,8 @@ bool ShaderCache::lookup(Context *rsc, ProgramVertex *vtx, ProgramFragment *frag
int32_t ShaderCache::vtxAttribSlot(const String8 &attrName) const {
for (uint32_t ct=0; ct < mCurrent->vtxAttrCount; ct++) {
- if(attrName == mCurrent->mVtxAttribNames[ct]) {
- return mCurrent->mVtxAttribSlots[ct];
+ if(attrName == mCurrent->vtxAttrs[ct].name) {
+ return mCurrent->vtxAttrs[ct].slot;
}
}
return -1;
@@ -156,7 +230,7 @@ void ShaderCache::cleanupVertex(uint32_t id)
if (mEntries[ct]->vtx == id) {
glDeleteProgram(mEntries[ct]->program);
- free(mEntries[ct]);
+ delete mEntries[ct];
mEntries.removeAt(ct);
numEntries = (int32_t)mEntries.size();
ct --;
@@ -171,7 +245,7 @@ void ShaderCache::cleanupFragment(uint32_t id)
if (mEntries[ct]->frag == id) {
glDeleteProgram(mEntries[ct]->program);
- free(mEntries[ct]);
+ delete mEntries[ct];
mEntries.removeAt(ct);
numEntries = (int32_t)mEntries.size();
ct --;
diff --git a/rsShaderCache.h b/rsShaderCache.h
index 35ff95be..6b49e5f8 100644
--- a/rsShaderCache.h
+++ b/rsShaderCache.h
@@ -41,30 +41,86 @@ public:
void cleanupAll();
int32_t vtxAttribSlot(const String8 &attrName) const;
- int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->mVtxUniformSlots[a];}
- int32_t fragAttribSlot(uint32_t a) const {return mCurrent->mFragAttribSlots[a];}
- int32_t fragUniformSlot(uint32_t a) const {return mCurrent->mFragUniformSlots[a];}
+ int32_t vtxUniformSlot(uint32_t a) const {return mCurrent->vtxUniforms[a].slot;}
+ uint32_t vtxUniformSize(uint32_t a) const {return mCurrent->vtxUniforms[a].arraySize;}
+ int32_t fragUniformSlot(uint32_t a) const {return mCurrent->fragUniforms[a].slot;}
+ uint32_t fragUniformSize(uint32_t a) const {return mCurrent->fragUniforms[a].arraySize;}
protected:
- typedef struct {
+ struct UniformQueryData {
+ char *name;
+ uint32_t nameLength;
+ int32_t writtenLength;
+ int32_t arraySize;
+ uint32_t type;
+ UniformQueryData(uint32_t maxName) {
+ name = NULL;
+ nameLength = maxName;
+ if(nameLength > 0 ) {
+ name = new char[nameLength];
+ }
+ }
+ ~UniformQueryData() {
+ if(name != NULL) {
+ delete[] name;
+ name = NULL;
+ }
+ }
+ };
+ struct UniformData {
+ int32_t slot;
+ uint32_t arraySize;
+ };
+ struct AttrData {
+ int32_t slot;
+ const char* name;
+ };
+ struct ProgramEntry {
+ ProgramEntry(uint32_t numVtxAttr, uint32_t numVtxUnis,
+ uint32_t numFragUnis) : vtx(0), frag(0), program(0), vtxAttrCount(0),
+ vtxAttrs(0), vtxUniforms(0), fragUniforms(0) {
+ vtxAttrCount = numVtxAttr;
+ if(numVtxAttr) {
+ vtxAttrs = new AttrData[numVtxAttr];
+ }
+ if(numVtxUnis) {
+ vtxUniforms = new UniformData[numVtxUnis];
+ }
+ if(numFragUnis) {
+ fragUniforms = new UniformData[numFragUnis];
+ }
+ }
+ ~ProgramEntry() {
+ if(vtxAttrs) {
+ delete[] vtxAttrs;
+ vtxAttrs = NULL;
+ }
+ if(vtxUniforms) {
+ delete[] vtxUniforms;
+ vtxUniforms = NULL;
+ }
+ if(fragUniforms) {
+ delete[] fragUniforms;
+ fragUniforms = NULL;
+ }
+ }
uint32_t vtx;
uint32_t frag;
uint32_t program;
uint32_t vtxAttrCount;
- const char* mVtxAttribNames[Program::MAX_ATTRIBS];
- int32_t mVtxAttribSlots[Program::MAX_ATTRIBS];
- int32_t mVtxUniformSlots[Program::MAX_UNIFORMS];
- int32_t mFragAttribSlots[Program::MAX_ATTRIBS];
- int32_t mFragUniformSlots[Program::MAX_UNIFORMS];
- bool mIsValid;
- } entry_t;
- //entry_t *mEntries;
- Vector<entry_t*> mEntries;
- entry_t *mCurrent;
-
- /*uint32_t mEntryCount;
- uint32_t mEntryAllocationCount;*/
-
+ AttrData *vtxAttrs;
+ UniformData *vtxUniforms;
+ UniformData *fragUniforms;
+
+ };
+ Vector<ProgramEntry*> mEntries;
+ ProgramEntry *mCurrent;
+
+ bool hasArrayUniforms(ProgramVertex *vtx, ProgramFragment *frag);
+ void populateUniformData(Program *prog, uint32_t linkedID, UniformData *data);
+ void updateUniformArrayData(Context *rsc, Program *prog, uint32_t linkedID,
+ UniformData *data, const char* logTag,
+ UniformQueryData **uniformList, uint32_t uniListSize);
};
diff --git a/rsType.cpp b/rsType.cpp
index caaa9f55..cc07412c 100644
--- a/rsType.cpp
+++ b/rsType.cpp
@@ -29,8 +29,6 @@ Type::Type(Context *rsc) : ObjectBase(rsc)
{
mLODs = 0;
mLODCount = 0;
- mAttribs = NULL;
- mAttribsSize = 0;
clear();
}
@@ -50,10 +48,6 @@ Type::~Type()
delete [] mLODs;
mLODs = NULL;
}
- if(mAttribs) {
- delete [] mAttribs;
- mAttribs = NULL;
- }
}
void Type::clear()
@@ -126,8 +120,6 @@ void Type::compute()
offset *= 6;
}
mTotalSizeBytes = offset;
-
- makeGLComponents();
}
uint32_t Type::getLODOffset(uint32_t lod, uint32_t x) const
@@ -151,87 +143,6 @@ uint32_t Type::getLODOffset(uint32_t lod, uint32_t x, uint32_t y, uint32_t z) co
return offset;
}
-bool Type::isValidGLComponent(uint32_t fieldIdx) {
- // Do not create attribs for padding
- if(mElement->getFieldName(fieldIdx)[0] == '#') {
- return false;
- }
-
- // Only GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FIXED, GL_FLOAT are accepted.
- // Filter rs types accordingly
- RsDataType dt = mElement->getField(fieldIdx)->getComponent().getType();
- if(dt != RS_TYPE_FLOAT_32 && dt != RS_TYPE_UNSIGNED_8 &&
- dt != RS_TYPE_UNSIGNED_16 && dt != RS_TYPE_SIGNED_8 &&
- dt != RS_TYPE_SIGNED_16) {
- return false;
- }
-
- // Now make sure they are not arrays
- uint32_t arraySize = mElement->getFieldArraySize(fieldIdx);
- if(arraySize != 1) {
- return false;
- }
-
- return true;
-}
-
-void Type::makeGLComponents()
-{
- // Count the number of gl attrs to initialize
- mAttribsSize = 0;
-
- for (uint32_t ct=0; ct < mElement->getFieldCount(); ct++) {
- if(isValidGLComponent(ct)) {
- mAttribsSize ++;
- }
- }
- if(mAttribs) {
- delete [] mAttribs;
- mAttribs = NULL;
- }
- if(mAttribsSize) {
- mAttribs = new VertexArray::Attrib[mAttribsSize];
- }
-
- uint32_t userNum = 0;
- for (uint32_t ct=0; ct < mElement->getFieldCount(); ct++) {
- const Component &c = mElement->getField(ct)->getComponent();
-
- if(!isValidGLComponent(ct)) {
- continue;
- }
-
- mAttribs[userNum].size = c.getVectorSize();
- mAttribs[userNum].offset = mElement->getFieldOffsetBytes(ct);
- mAttribs[userNum].type = c.getGLType();
- mAttribs[userNum].normalized = c.getType() != RS_TYPE_FLOAT_32;//c.getIsNormalized();
- String8 tmp(RS_SHADER_ATTR);
- tmp.append(mElement->getFieldName(ct));
- mAttribs[userNum].name.setTo(tmp.string());
-
- userNum ++;
- }
-}
-
-
-void Type::enableGLVertexBuffer(VertexArray *va) const
-{
- uint32_t stride = mElement->getSizeBytes();
- for (uint32_t ct=0; ct < mAttribsSize; ct++) {
- // Load up to RS_MAX_ATTRIBS inputs
- // TODO: grow vertexarray dynamically
- if(ct >= RS_MAX_ATTRIBS) {
- LOGE("More GL attributes than we can handle");
- break;
- }
- if (mAttribs[ct].size) {
- va->add(mAttribs[ct], stride);
- }
- }
-}
-
-
-
void Type::dumpLOGV(const char *prefix) const
{
char buf[1024];
diff --git a/rsType.h b/rsType.h
index 0ca5bb6e..fd626ed1 100644
--- a/rsType.h
+++ b/rsType.h
@@ -58,8 +58,6 @@ public:
void clear();
void compute();
- void enableGLVertexBuffer(class VertexArray *) const;
-
void dumpLOGV(const char *prefix) const;
virtual void serialize(OStream *stream) const;
virtual RsA3DClassID getClassId() const { return RS_A3D_CLASS_ID_TYPE; }
@@ -100,10 +98,6 @@ protected:
bool mDimLOD;
bool mFaces;
- // A list of array dimensions. The count is the number of array dimensions and the
- // sizes is a per array size.
- //Vector<size_t> mDimArraysSizes;
-
// count of mipmap levels, 0 indicates no mipmapping
size_t mMipChainSizeBytes;
@@ -111,12 +105,6 @@ protected:
LOD *mLODs;
uint32_t mLODCount;
- VertexArray::Attrib *mAttribs;
- uint32_t mAttribsSize;
- bool isValidGLComponent(uint32_t fieldIdx);
- void makeGLComponents();
-
-
protected:
virtual void preDestroy();
virtual ~Type();
diff --git a/rsVertexArray.cpp b/rsVertexArray.cpp
index 4d501246..8eb94d06 100644
--- a/rsVertexArray.cpp
+++ b/rsVertexArray.cpp
@@ -28,43 +28,21 @@ using namespace android;
using namespace android::renderscript;
-VertexArray::VertexArray()
+VertexArray::VertexArray(const Attrib *attribs, uint32_t numAttribs)
{
- clearAll();
+ mAttribs = attribs;
+ mCount = numAttribs;
}
VertexArray::~VertexArray()
{
}
-
-void VertexArray::clearAll()
-{
- for (uint32_t ct=0; ct < RS_MAX_ATTRIBS; ct++) {
- mAttribs[ct].clear();
- }
- mActiveBuffer = 0;
- mActivePointer = NULL;
- mCount = 0;
-}
-
VertexArray::Attrib::Attrib()
{
clear();
}
-void VertexArray::Attrib::set(const Attrib &a)
-{
- buffer = a.buffer;
- ptr = a.ptr;
- offset = a.offset;
- type = a.type;
- size = a.size;
- stride = a.stride;
- normalized = a.normalized;
- name.setTo(a.name);
-}
-
void VertexArray::Attrib::clear()
{
buffer = 0;
@@ -77,35 +55,15 @@ void VertexArray::Attrib::clear()
name.setTo("");
}
-void VertexArray::clear(uint32_t n)
+void VertexArray::Attrib::set(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset, const char *name)
{
- mAttribs[n].clear();
-}
-
-void VertexArray::add(const Attrib &a, uint32_t stride)
-{
- rsAssert(mCount < RS_MAX_ATTRIBS);
- mAttribs[mCount].set(a);
- mAttribs[mCount].buffer = mActiveBuffer;
- mAttribs[mCount].ptr = mActivePointer;
- mAttribs[mCount].stride = stride;
- mCount ++;
-}
-
-void VertexArray::add(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset, const char *name)
-{
- rsAssert(mCount < RS_MAX_ATTRIBS);
- mAttribs[mCount].clear();
- mAttribs[mCount].type = type;
- mAttribs[mCount].size = size;
- mAttribs[mCount].offset = offset;
- mAttribs[mCount].normalized = normalized;
- mAttribs[mCount].stride = stride;
- mAttribs[mCount].name.setTo(name);
-
- mAttribs[mCount].buffer = mActiveBuffer;
- mAttribs[mCount].ptr = mActivePointer;
- mCount ++;
+ clear();
+ this->type = type;
+ this->size = size;
+ this->offset = offset;
+ this->normalized = normalized;
+ this->stride = stride;
+ this->name.setTo(name);
}
void VertexArray::logAttrib(uint32_t idx, uint32_t slot) const {
diff --git a/rsVertexArray.h b/rsVertexArray.h
index dea7d41a..c2d10e62 100644
--- a/rsVertexArray.h
+++ b/rsVertexArray.h
@@ -30,10 +30,6 @@ class ShaderCache;
class VertexArray
{
public:
- VertexArray();
- virtual ~VertexArray();
-
-
class Attrib {
public:
uint32_t buffer;
@@ -46,23 +42,12 @@ public:
String8 name;
Attrib();
- void set(const Attrib &);
void clear();
+ void set(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset, const char *name);
};
-
- void clearAll();
- void setActiveBuffer(uint32_t id) {
- mActiveBuffer = id;
- mActivePointer = NULL;
- }
- void setActiveBuffer(const void *ptr) {
- mActiveBuffer = 0;
- mActivePointer = (const uint8_t *)ptr;
- }
-
- void add(const Attrib &, uint32_t stride);
- void add(uint32_t type, uint32_t size, uint32_t stride, bool normalized, uint32_t offset, const char *name);
+ VertexArray(const Attrib *attribs, uint32_t numAttribs);
+ virtual ~VertexArray();
void setupGL2(const Context *rsc, class VertexArrayState *, ShaderCache *) const;
void logAttrib(uint32_t idx, uint32_t slot) const;
@@ -73,7 +58,7 @@ protected:
const uint8_t * mActivePointer;
uint32_t mCount;
- Attrib mAttribs[RS_MAX_ATTRIBS];
+ const Attrib *mAttribs;
};
@@ -82,7 +67,6 @@ public:
void init(Context *);
uint32_t mLastEnableCount;
- //VertexArray::Attrib mAttribs[VertexArray::_LAST];
};