diff options
28 files changed, 715 insertions, 377 deletions
diff --git a/graphics/java/android/renderscript/Mesh.java b/graphics/java/android/renderscript/Mesh.java index d36b2f1..bb382f2 100644 --- a/graphics/java/android/renderscript/Mesh.java +++ b/graphics/java/android/renderscript/Mesh.java @@ -212,6 +212,7 @@ public class Mesh extends BaseObj { rs.nMeshBindVertex(id, alloc.getID(), ct); newMesh.mVertexBuffers[ct] = alloc; } + rs.nMeshInitVertexAttribs(id); return newMesh; } @@ -294,6 +295,7 @@ public class Mesh extends BaseObj { rs.nMeshBindVertex(id, entry.a.mID, ct); newMesh.mVertexBuffers[ct] = entry.a; } + rs.nMeshInitVertexAttribs(id); return newMesh; } diff --git a/graphics/java/android/renderscript/RenderScript.java b/graphics/java/android/renderscript/RenderScript.java index 21efa39..0c9a4ed 100644 --- a/graphics/java/android/renderscript/RenderScript.java +++ b/graphics/java/android/renderscript/RenderScript.java @@ -486,6 +486,10 @@ public class RenderScript { synchronized void nMeshBindIndex(int id, int alloc, int prim, int slot) { rsnMeshBindIndex(mContext, id, alloc, prim, slot); } + native void rsnMeshInitVertexAttribs(int con, int id); + synchronized void nMeshInitVertexAttribs(int id) { + rsnMeshInitVertexAttribs(mContext, id); + } native int rsnMeshGetVertexBufferCount(int con, int id); synchronized int nMeshGetVertexBufferCount(int id) { return rsnMeshGetVertexBufferCount(mContext, id); diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp index 1cc6dc1..77cbc10 100644 --- a/graphics/jni/android_renderscript_RenderScript.cpp +++ b/graphics/jni/android_renderscript_RenderScript.cpp @@ -1152,6 +1152,14 @@ nMeshBindIndex(JNIEnv *_env, jobject _this, RsContext con, jint mesh, jint alloc rsMeshBindIndex(con, (RsMesh)mesh, (RsAllocation)alloc, primID, slot); } +static void +nMeshInitVertexAttribs(JNIEnv *_env, jobject _this, RsContext con, jint mesh) +{ + LOG_API("nMeshInitVertexAttribs, con(%p), Mesh(%p)", con, (RsMesh)mesh); + rsMeshInitVertexAttribs(con, (RsMesh)mesh); +} + + static jint nMeshGetVertexBufferCount(JNIEnv *_env, jobject _this, RsContext con, jint mesh) { @@ -1334,6 +1342,7 @@ static JNINativeMethod methods[] = { {"rsnMeshCreate", "(III)I", (void*)nMeshCreate }, {"rsnMeshBindVertex", "(IIII)V", (void*)nMeshBindVertex }, {"rsnMeshBindIndex", "(IIIII)V", (void*)nMeshBindIndex }, +{"rsnMeshInitVertexAttribs", "(II)V", (void*)nMeshInitVertexAttribs }, {"rsnMeshGetVertexBufferCount", "(II)I", (void*)nMeshGetVertexBufferCount }, {"rsnMeshGetIndexCount", "(II)I", (void*)nMeshGetIndexCount }, diff --git a/libs/rs/java/Samples/res/raw/shaderarrayf.glsl b/libs/rs/java/Samples/res/raw/shaderarrayf.glsl new file mode 100644 index 0000000..238ecad --- /dev/null +++ b/libs/rs/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/libs/rs/java/Samples/res/raw/shaderarrayv.glsl b/libs/rs/java/Samples/res/raw/shaderarrayv.glsl new file mode 100644 index 0000000..7a1310a --- /dev/null +++ b/libs/rs/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/libs/rs/java/Samples/res/raw/shaderf.glsl b/libs/rs/java/Samples/res/raw/shaderf.glsl index fcbe7ee..d56e203 100644 --- a/libs/rs/java/Samples/res/raw/shaderf.glsl +++ b/libs/rs/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/libs/rs/java/Samples/res/raw/shaderv.glsl b/libs/rs/java/Samples/res/raw/shaderv.glsl index 867589c..f7d01de 100644 --- a/libs/rs/java/Samples/res/raw/shaderv.glsl +++ b/libs/rs/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/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java b/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java index 85c2557..dd2daa7 100644 --- a/libs/rs/java/Samples/src/com/android/samples/RsRenderStatesRS.java +++ b/libs/rs/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/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs b/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs index 8be35f8..4f8eada 100644 --- a/libs/rs/java/Samples/src/com/android/samples/rsrenderstates.rs +++ b/libs/rs/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/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh b/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh index e3f6206..3f51785 100644 --- a/libs/rs/java/Samples/src/com/android/samples/shader_def.rsh +++ b/libs/rs/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/libs/rs/rs.spec b/libs/rs/rs.spec index 14809e9..ac9abe0 100644 --- a/libs/rs/rs.spec +++ b/libs/rs/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/libs/rs/rsContextHostStub.h b/libs/rs/rsContextHostStub.h index f3e9dab..ee32b57 100644 --- a/libs/rs/rsContextHostStub.h +++ b/libs/rs/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/libs/rs/rsElement.cpp b/libs/rs/rsElement.cpp index d207dcf..2ab3729 100644 --- a/libs/rs/rsElement.cpp +++ b/libs/rs/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/libs/rs/rsElement.h b/libs/rs/rsElement.h index 70e2619..506a530 100644 --- a/libs/rs/rsElement.h +++ b/libs/rs/rsElement.h @@ -94,6 +94,8 @@ protected: Component mComponent; uint32_t mBits; + + void compute(); }; diff --git a/libs/rs/rsFont.cpp b/libs/rs/rsFont.cpp index 9e76215..66f455c 100644 --- a/libs/rs/rsFont.cpp +++ b/libs/rs/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/libs/rs/rsMesh.cpp b/libs/rs/rsMesh.cpp index fd604e5..f2dd687 100644 --- a/libs/rs/rsMesh.cpp +++ b/libs/rs/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/libs/rs/rsMesh.h b/libs/rs/rsMesh.h index ed01c38..261b5a6 100644 --- a/libs/rs/rsMesh.h +++ b/libs/rs/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/libs/rs/rsProgram.cpp b/libs/rs/rsProgram.cpp index 72d1b02..ce3af2d 100644 --- a/libs/rs/rsProgram.cpp +++ b/libs/rs/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/libs/rs/rsProgram.h b/libs/rs/rsProgram.h index c93033b..46692fd 100644 --- a/libs/rs/rsProgram.h +++ b/libs/rs/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/libs/rs/rsProgramFragment.cpp b/libs/rs/rsProgramFragment.cpp index 800854b..d089a5a 100644 --- a/libs/rs/rsProgramFragment.cpp +++ b/libs/rs/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/libs/rs/rsProgramVertex.cpp b/libs/rs/rsProgramVertex.cpp index 4e64008..9ee2eeb 100644 --- a/libs/rs/rsProgramVertex.cpp +++ b/libs/rs/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/libs/rs/rsScriptC_LibGL.cpp b/libs/rs/rsScriptC_LibGL.cpp index 5b07e7b..d877ebd 100644 --- a/libs/rs/rsScriptC_LibGL.cpp +++ b/libs/rs/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/libs/rs/rsShaderCache.cpp b/libs/rs/rsShaderCache.cpp index 45f6207..193ced3 100644 --- a/libs/rs/rsShaderCache.cpp +++ b/libs/rs/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/libs/rs/rsShaderCache.h b/libs/rs/rsShaderCache.h index 35ff95b..6b49e5f 100644 --- a/libs/rs/rsShaderCache.h +++ b/libs/rs/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/libs/rs/rsType.cpp b/libs/rs/rsType.cpp index caaa9f5..cc07412 100644 --- a/libs/rs/rsType.cpp +++ b/libs/rs/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/libs/rs/rsType.h b/libs/rs/rsType.h index 0ca5bb6..fd626ed 100644 --- a/libs/rs/rsType.h +++ b/libs/rs/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/libs/rs/rsVertexArray.cpp b/libs/rs/rsVertexArray.cpp index 4d50124..8eb94d0 100644 --- a/libs/rs/rsVertexArray.cpp +++ b/libs/rs/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/libs/rs/rsVertexArray.h b/libs/rs/rsVertexArray.h index dea7d41..c2d10e6 100644 --- a/libs/rs/rsVertexArray.h +++ b/libs/rs/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]; }; |