Create queue of sync objects in FinalShaderProgramWrapper

PiperOrigin-RevId: 544683524
This commit is contained in:
tofunmi 2023-06-30 16:58:15 +00:00 committed by microkatz
parent e8fdd83558
commit d14122b029
3 changed files with 9 additions and 10 deletions

View file

@ -85,6 +85,8 @@ public final class GlUtil {
EGL14.EGL_NONE EGL14.EGL_NONE
}; };
// https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glFenceSync.xhtml
private static final long GL_FENCE_SYNC_FAILED = 0;
// https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_protected_content.txt // https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_protected_content.txt
private static final String EXTENSION_PROTECTED_CONTENT = "EGL_EXT_protected_content"; private static final String EXTENSION_PROTECTED_CONTENT = "EGL_EXT_protected_content";
// https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_surfaceless_context.txt // https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_surfaceless_context.txt
@ -410,7 +412,7 @@ public final class GlUtil {
* CPU, and only affects the current OpenGL context. Otherwise, this will block the CPU. * CPU, and only affects the current OpenGL context. Otherwise, this will block the CPU.
*/ */
public static void awaitSyncObject(long syncObject) throws GlException { public static void awaitSyncObject(long syncObject) throws GlException {
if (syncObject == 0) { if (syncObject == GL_FENCE_SYNC_FAILED) {
// Fallback to using glFinish for synchronization when fence creation failed. // Fallback to using glFinish for synchronization when fence creation failed.
GLES20.glFinish(); GLES20.glFinish();
} else { } else {

View file

@ -25,7 +25,6 @@ import android.opengl.EGLDisplay;
import android.opengl.EGLExt; import android.opengl.EGLExt;
import android.opengl.EGLSurface; import android.opengl.EGLSurface;
import android.opengl.GLES20; import android.opengl.GLES20;
import android.opengl.GLES30;
import android.util.Pair; import android.util.Pair;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceHolder; import android.view.SurfaceHolder;
@ -94,6 +93,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
private final Queue<Pair<GlTextureInfo, Long>> availableFrames; private final Queue<Pair<GlTextureInfo, Long>> availableFrames;
private final TexturePool outputTexturePool; private final TexturePool outputTexturePool;
private final Queue<Long> outputTextureTimestamps; // Synchronized with outputTexturePool. private final Queue<Long> outputTextureTimestamps; // Synchronized with outputTexturePool.
private final Queue<Long> syncObjects;
@Nullable private final DefaultVideoFrameProcessor.TextureOutputListener textureOutputListener; @Nullable private final DefaultVideoFrameProcessor.TextureOutputListener textureOutputListener;
private int inputWidth; private int inputWidth;
@ -107,7 +107,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
@Nullable private SurfaceView debugSurfaceView; @Nullable private SurfaceView debugSurfaceView;
@Nullable private OnInputStreamProcessedListener onInputStreamProcessedListener; @Nullable private OnInputStreamProcessedListener onInputStreamProcessedListener;
private boolean matrixTransformationsChanged; private boolean matrixTransformationsChanged;
private long syncObject;
@GuardedBy("this") @GuardedBy("this")
private boolean outputSurfaceInfoChanged; private boolean outputSurfaceInfoChanged;
@ -154,6 +153,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
boolean useHighPrecisionColorComponents = ColorInfo.isTransferHdr(outputColorInfo); boolean useHighPrecisionColorComponents = ColorInfo.isTransferHdr(outputColorInfo);
outputTexturePool = new TexturePool(useHighPrecisionColorComponents, textureOutputCapacity); outputTexturePool = new TexturePool(useHighPrecisionColorComponents, textureOutputCapacity);
outputTextureTimestamps = new ArrayDeque<>(textureOutputCapacity); outputTextureTimestamps = new ArrayDeque<>(textureOutputCapacity);
syncObjects = new ArrayDeque<>(textureOutputCapacity);
} }
@Override @Override
@ -238,11 +238,12 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
videoFrameProcessingTaskExecutor.submit(() -> releaseOutputFrameInternal(presentationTimeUs)); videoFrameProcessingTaskExecutor.submit(() -> releaseOutputFrameInternal(presentationTimeUs));
} }
private void releaseOutputFrameInternal(long presentationTimeUs) { private void releaseOutputFrameInternal(long presentationTimeUs) throws GlUtil.GlException {
while (outputTexturePool.freeTextureCount() < outputTexturePool.capacity() while (outputTexturePool.freeTextureCount() < outputTexturePool.capacity()
&& checkNotNull(outputTextureTimestamps.peek()) <= presentationTimeUs) { && checkNotNull(outputTextureTimestamps.peek()) <= presentationTimeUs) {
outputTexturePool.freeTexture(); outputTexturePool.freeTexture();
outputTextureTimestamps.remove(); outputTextureTimestamps.remove();
GlUtil.deleteSyncObject(syncObjects.remove());
maybeOnReadyToAcceptInputFrame(); maybeOnReadyToAcceptInputFrame();
} }
} }
@ -266,7 +267,6 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
try { try {
outputTexturePool.deleteAllTextures(); outputTexturePool.deleteAllTextures();
GlUtil.destroyEglSurface(eglDisplay, outputEglSurface); GlUtil.destroyEglSurface(eglDisplay, outputEglSurface);
GLES30.glDeleteSync(syncObject);
GlUtil.checkGlError(); GlUtil.checkGlError();
} catch (GlUtil.GlException e) { } catch (GlUtil.GlException e) {
throw new VideoFrameProcessingException(e); throw new VideoFrameProcessingException(e);
@ -385,7 +385,8 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
outputTexture.getFboId(), outputTexture.getWidth(), outputTexture.getHeight()); outputTexture.getFboId(), outputTexture.getWidth(), outputTexture.getHeight());
GlUtil.clearFocusedBuffers(); GlUtil.clearFocusedBuffers();
checkNotNull(defaultShaderProgram).drawFrame(inputTexture.getTexId(), presentationTimeUs); checkNotNull(defaultShaderProgram).drawFrame(inputTexture.getTexId(), presentationTimeUs);
syncObject = GlUtil.createGlSyncFence(); long syncObject = GlUtil.createGlSyncFence();
syncObjects.add(syncObject);
checkNotNull(textureOutputListener) checkNotNull(textureOutputListener)
.onTextureRendered(outputTexture, presentationTimeUs, this::releaseOutputFrame, syncObject); .onTextureRendered(outputTexture, presentationTimeUs, this::releaseOutputFrame, syncObject);
} }

View file

@ -66,10 +66,6 @@ import org.junit.runner.RunWith;
// TODO(b/263395272): Move this test to effects/mh tests, and remove @TestOnly dependencies. // TODO(b/263395272): Move this test to effects/mh tests, and remove @TestOnly dependencies.
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public final class DefaultVideoFrameProcessorTextureOutputPixelTest { public final class DefaultVideoFrameProcessorTextureOutputPixelTest {
// Documentation reference:
// https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glFenceSync.xhtml
private static final long GL_FENCE_SYNC_FAILED = 0;
private static final String ORIGINAL_PNG_ASSET_PATH = private static final String ORIGINAL_PNG_ASSET_PATH =
"media/bitmap/sample_mp4_first_frame/electrical_colors/original.png"; "media/bitmap/sample_mp4_first_frame/electrical_colors/original.png";
private static final String BITMAP_OVERLAY_PNG_ASSET_PATH = private static final String BITMAP_OVERLAY_PNG_ASSET_PATH =