Add caching for compositeRgbMatrixArray.

* Refactor caching for matrix transformations to reuse it for rgb matrices.

PiperOrigin-RevId: 473042194
This commit is contained in:
leonwind 2022-09-08 18:31:11 +00:00 committed by Marc Baechinger
parent 260aabb6e9
commit 55afa598e7

View File

@ -100,11 +100,18 @@ import java.util.List;
* for the most recent frame. * for the most recent frame.
*/ */
private final float[][] transformationMatrixCache; private final float[][] transformationMatrixCache;
/** The RGB matrices provided by the {@link RgbMatrix RgbMatrices} for the most recent frame. */
private final float[][] rgbMatrixCache;
/** /**
* The product of the {@link #transformationMatrixCache} for the most recent frame, to be applied * The product of the {@link #transformationMatrixCache} for the most recent frame, to be applied
* in the vertex shader. * in the vertex shader.
*/ */
private final float[] compositeTransformationMatrix; private final float[] compositeTransformationMatrixArray;
/**
* The product of the {@link #rgbMatrixCache} for the most recent frame, to be applied in the
* fragment shader.
*/
private final float[] compositeRgbMatrixArray;
/** Matrix for storing an intermediate calculation result. */ /** Matrix for storing an intermediate calculation result. */
private final float[] tempResultMatrix; private final float[] tempResultMatrix;
@ -112,9 +119,9 @@ import java.util.List;
* A polygon in the input space chosen such that no additional clipping is needed to keep vertices * A polygon in the input space chosen such that no additional clipping is needed to keep vertices
* inside the NDC range when applying each of the {@link #matrixTransformations}. * inside the NDC range when applying each of the {@link #matrixTransformations}.
* *
* <p>This means that this polygon and {@link #compositeTransformationMatrix} can be used instead * <p>This means that this polygon and {@link #compositeTransformationMatrixArray} can be used
* of applying each of the {@link #matrixTransformations} to {@link #NDC_SQUARE} in separate * instead of applying each of the {@link #matrixTransformations} to {@link #NDC_SQUARE} in
* shaders. * separate shaders.
*/ */
private ImmutableList<float[]> visiblePolygon; private ImmutableList<float[]> visiblePolygon;
@ -345,8 +352,11 @@ import java.util.List;
this.useHdr = useHdr; this.useHdr = useHdr;
transformationMatrixCache = new float[matrixTransformations.size()][16]; transformationMatrixCache = new float[matrixTransformations.size()][16];
compositeTransformationMatrix = new float[16]; rgbMatrixCache = new float[rgbMatrices.size()][16];
Matrix.setIdentityM(compositeTransformationMatrix, /* smOffset= */ 0); compositeTransformationMatrixArray = new float[16];
Matrix.setIdentityM(compositeTransformationMatrixArray, /* smOffset= */ 0);
compositeRgbMatrixArray = new float[16];
Matrix.setIdentityM(compositeRgbMatrixArray, /* smOffset= */ 0);
tempResultMatrix = new float[16]; tempResultMatrix = new float[16];
visiblePolygon = NDC_SQUARE; visiblePolygon = NDC_SQUARE;
} }
@ -380,17 +390,17 @@ import java.util.List;
@Override @Override
public void drawFrame(int inputTexId, long presentationTimeUs) throws FrameProcessingException { public void drawFrame(int inputTexId, long presentationTimeUs) throws FrameProcessingException {
updateCompositeRgbaMatrixArray(presentationTimeUs);
updateCompositeTransformationMatrixAndVisiblePolygon(presentationTimeUs); updateCompositeTransformationMatrixAndVisiblePolygon(presentationTimeUs);
if (visiblePolygon.size() < 3) { if (visiblePolygon.size() < 3) {
return; // Need at least three visible vertices for a triangle. return; // Need at least three visible vertices for a triangle.
} }
float[] compositeRgbMatrix =
createCompositeRgbaMatrixArray(rgbMatrices, useHdr, presentationTimeUs);
try { try {
glProgram.use(); glProgram.use();
glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* texUnitIndex= */ 0); glProgram.setSamplerTexIdUniform("uTexSampler", inputTexId, /* texUnitIndex= */ 0);
glProgram.setFloatsUniform("uTransformationMatrix", compositeTransformationMatrix); glProgram.setFloatsUniform("uTransformationMatrix", compositeTransformationMatrixArray);
glProgram.setFloatsUniform("uRgbMatrix", compositeRgbMatrix); glProgram.setFloatsUniform("uRgbMatrix", compositeRgbMatrixArray);
glProgram.setBufferAttribute( glProgram.setBufferAttribute(
"aFramePosition", "aFramePosition",
GlUtil.createVertexBuffer(visiblePolygon), GlUtil.createVertexBuffer(visiblePolygon),
@ -415,17 +425,23 @@ import java.util.List;
} }
/** /**
* Updates {@link #compositeTransformationMatrix} and {@link #visiblePolygon} based on the given * Updates {@link #compositeTransformationMatrixArray} and {@link #visiblePolygon} based on the
* frame timestamp. * given frame timestamp.
*/ */
private void updateCompositeTransformationMatrixAndVisiblePolygon(long presentationTimeUs) { private void updateCompositeTransformationMatrixAndVisiblePolygon(long presentationTimeUs) {
if (!updateTransformationMatrixCache(presentationTimeUs)) { float[][] matricesAtPresentationTime = new float[matrixTransformations.size()][16];
for (int i = 0; i < matrixTransformations.size(); i++) {
matricesAtPresentationTime[i] =
matrixTransformations.get(i).getGlMatrixArray(presentationTimeUs);
}
if (!updateMatrixCache(transformationMatrixCache, matricesAtPresentationTime)) {
return; return;
} }
// Compute the compositeTransformationMatrix and transform and clip the visiblePolygon for each // Compute the compositeTransformationMatrix and transform and clip the visiblePolygon for each
// MatrixTransformation's matrix. // MatrixTransformation's matrix.
Matrix.setIdentityM(compositeTransformationMatrix, /* smOffset= */ 0); Matrix.setIdentityM(compositeTransformationMatrixArray, /* smOffset= */ 0);
visiblePolygon = NDC_SQUARE; visiblePolygon = NDC_SQUARE;
for (float[] transformationMatrix : transformationMatrixCache) { for (float[] transformationMatrix : transformationMatrixCache) {
Matrix.multiplyMM( Matrix.multiplyMM(
@ -433,12 +449,12 @@ import java.util.List;
/* resultOffset= */ 0, /* resultOffset= */ 0,
/* lhs= */ transformationMatrix, /* lhs= */ transformationMatrix,
/* lhsOffset= */ 0, /* lhsOffset= */ 0,
/* rhs= */ compositeTransformationMatrix, /* rhs= */ compositeTransformationMatrixArray,
/* rhsOffset= */ 0); /* rhsOffset= */ 0);
System.arraycopy( System.arraycopy(
/* src= */ tempResultMatrix, /* src= */ tempResultMatrix,
/* srcPos= */ 0, /* srcPos= */ 0,
/* dest= */ compositeTransformationMatrix, /* dest= */ compositeTransformationMatrixArray,
/* destPost= */ 0, /* destPost= */ 0,
/* length= */ tempResultMatrix.length); /* length= */ tempResultMatrix.length);
visiblePolygon = visiblePolygon =
@ -451,41 +467,23 @@ import java.util.List;
} }
// Calculate the input frame vertices corresponding to the output frame's visible polygon. // Calculate the input frame vertices corresponding to the output frame's visible polygon.
Matrix.invertM( Matrix.invertM(
tempResultMatrix, /* mInvOffset= */ 0, compositeTransformationMatrix, /* mOffset= */ 0); tempResultMatrix,
/* mInvOffset= */ 0,
compositeTransformationMatrixArray,
/* mOffset= */ 0);
visiblePolygon = MatrixUtils.transformPoints(tempResultMatrix, visiblePolygon); visiblePolygon = MatrixUtils.transformPoints(tempResultMatrix, visiblePolygon);
} }
/** /** Updates {@link #compositeRgbMatrixArray} based on the given frame timestamp. */
* Updates {@link #transformationMatrixCache} with the transformation matrices provided by the private void updateCompositeRgbaMatrixArray(long presentationTimeUs) {
* {@link #matrixTransformations} for the given frame timestamp and returns whether any matrix in float[][] matricesCurrTimestamp = new float[rgbMatrices.size()][16];
* {@link #transformationMatrixCache} changed. for (int i = 0; i < rgbMatrices.size(); i++) {
*/ matricesCurrTimestamp[i] = rgbMatrices.get(i).getMatrix(presentationTimeUs, useHdr);
private boolean updateTransformationMatrixCache(long presentationTimeUs) {
boolean matrixChanged = false;
for (int i = 0; i < matrixTransformations.size(); i++) {
float[] cachedMatrix = transformationMatrixCache[i];
float[] matrix = matrixTransformations.get(i).getGlMatrixArray(presentationTimeUs);
if (!Arrays.equals(cachedMatrix, matrix)) {
checkState(matrix.length == 16, "A 4x4 transformation matrix must have 16 elements");
System.arraycopy(
/* src= */ matrix,
/* srcPos= */ 0,
/* dest= */ cachedMatrix,
/* destPost= */ 0,
/* length= */ matrix.length);
matrixChanged = true;
}
}
return matrixChanged;
} }
// TODO(b/239757183): Add caching for RgbMatrix and refactor RgbMatrix and MatrixTransformation if (!updateMatrixCache(rgbMatrixCache, matricesCurrTimestamp)) {
// composing. return;
private static float[] createCompositeRgbaMatrixArray( }
ImmutableList<RgbMatrix> rgbMatrices, boolean useHdr, long presentationTimeUs) {
float[] tempResultMatrix = new float[16];
float[] compositeRgbaMatrix = new float[16];
Matrix.setIdentityM(compositeRgbaMatrix, /* smOffset= */ 0);
for (int i = 0; i < rgbMatrices.size(); i++) { for (int i = 0; i < rgbMatrices.size(); i++) {
Matrix.multiplyMM( Matrix.multiplyMM(
@ -493,16 +491,40 @@ import java.util.List;
/* resultOffset= */ 0, /* resultOffset= */ 0,
/* lhs= */ rgbMatrices.get(i).getMatrix(presentationTimeUs, useHdr), /* lhs= */ rgbMatrices.get(i).getMatrix(presentationTimeUs, useHdr),
/* lhsOffset= */ 0, /* lhsOffset= */ 0,
/* rhs= */ compositeRgbaMatrix, /* rhs= */ compositeRgbMatrixArray,
/* rhsOffset= */ 0); /* rhsOffset= */ 0);
System.arraycopy( System.arraycopy(
/* src= */ tempResultMatrix, /* src= */ tempResultMatrix,
/* srcPos= */ 0, /* srcPos= */ 0,
/* dest= */ compositeRgbaMatrix, /* dest= */ compositeRgbMatrixArray,
/* destPost= */ 0, /* destPost= */ 0,
/* length= */ tempResultMatrix.length); /* length= */ tempResultMatrix.length);
} }
}
return compositeRgbaMatrix; /**
* Updates the {@code cachedMatrices} with the {@code newMatrices}. Returns whether a matrix has
* changed inside the cache.
*
* @param cachedMatrices The existing cached matrices. Gets updated if it is out of date.
* @param newMatrices The new matrices to compare the cached matrices against.
*/
private static boolean updateMatrixCache(float[][] cachedMatrices, float[][] newMatrices) {
boolean matrixChanged = false;
for (int i = 0; i < cachedMatrices.length; i++) {
float[] cachedMatrix = cachedMatrices[i];
float[] newMatrix = newMatrices[i];
if (!Arrays.equals(cachedMatrix, newMatrix)) {
checkState(newMatrix.length == 16, "A 4x4 transformation matrix must have 16 elements");
System.arraycopy(
/* src= */ newMatrix,
/* srcPos= */ 0,
/* dest= */ cachedMatrix,
/* destPost= */ 0,
/* length= */ newMatrix.length);
matrixChanged = true;
}
}
return matrixChanged;
} }
} }