Project

General

Profile

« Previous | Next » 

Revision d99fcc9c

Added by Leszek Koltunski almost 4 years ago

Only compile the Full, Normal & OIT programs when they are actually needed.

View differences:

src/main/java/org/distorted/library/main/DistortedLibrary.java
58 58
  {
59 59
  private static int mGLSL;
60 60
  private static String mGLSL_VERSION;
61
  private static boolean mOITCompilationSuccessful;
61
  private static boolean mOITCompilationAttempted;
62 62
  /**
63 63
   * When creating an instance of a DistortedTexture from another instance, clone the Bitmap that's
64 64
   * backing up our DistortedTexture.
......
202 202

  
203 203
  /// END PROGRAMS //////
204 204

  
205
  /**
206
   * Every application using the library must implement this interface so that the library can send
207
   * it exceptions that arise. The exceptions may come at any time, for example the library will
208
   * compile its OIT problem only on the first attempt to use the OIT
209
   * Those will mainly be hardware-related: shaders do not compile on particular hardware, the required
210
   * OpenGL ES 3.0 is not supported, etc.
211
   */
212
  public interface ExceptionListener
213
    {
214
    void distortedException(Exception ex);
215
    }
216

  
217
  private static ExceptionListener mListener;
218
  private static Resources mResources;
219

  
205 220
///////////////////////////////////////////////////////////////////////////////////////////////////
206 221
// private: hide this from Javadoc
207 222

  
......
212 227

  
213 228
///////////////////////////////////////////////////////////////////////////////////////////////////
214 229

  
215
  private static void createPrograms(Resources resources)
230
  private static void createMainProgram()
216 231
    {
217 232
    // MAIN PROGRAM ////////////////////////////////////
218
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
219
    final InputStream mainFragStream = resources.openRawResource(R.raw.main_fragment_shader);
233
    final InputStream mainVertStream = mResources.openRawResource(R.raw.main_vertex_shader);
234
    final InputStream mainFragStream = mResources.openRawResource(R.raw.main_fragment_shader);
220 235

  
221 236
    int numF = FragmentEffect.getNumEnabled();
222 237
    int numV = VertexEffect.getNumEnabled();
......
248 263
    mMainTextureH= GLES30.glGetUniformLocation( mainProgramH, "u_Texture");
249 264

  
250 265
    // BLIT PROGRAM ////////////////////////////////////
251
    final InputStream blitVertStream = resources.openRawResource(R.raw.blit_vertex_shader);
252
    final InputStream blitFragStream = resources.openRawResource(R.raw.blit_fragment_shader);
266
    final InputStream blitVertStream = mResources.openRawResource(R.raw.blit_vertex_shader);
267
    final InputStream blitFragStream = mResources.openRawResource(R.raw.blit_fragment_shader);
253 268

  
254 269
    try
255 270
      {
......
266 281
    mBlitDepthH    = GLES30.glGetUniformLocation( blitProgramH, "u_Depth");
267 282

  
268 283
    // BLIT DEPTH PROGRAM ////////////////////////////////////
269
    final InputStream blitDepthVertStream = resources.openRawResource(R.raw.blit_depth_vertex_shader);
270
    final InputStream blitDepthFragStream = resources.openRawResource(R.raw.blit_depth_fragment_shader);
284
    final InputStream blitDepthVertStream = mResources.openRawResource(R.raw.blit_depth_vertex_shader);
285
    final InputStream blitDepthFragStream = mResources.openRawResource(R.raw.blit_depth_fragment_shader);
271 286

  
272 287
    try
273 288
      {
......
284 299
    mBlitDepthDepthTextureH = GLES30.glGetUniformLocation( blitDepthProgramH, "u_DepthTexture");
285 300
    mBlitDepthDepthH        = GLES30.glGetUniformLocation( blitDepthProgramH, "u_Depth");
286 301
    mBlitDepthTexCorrH      = GLES30.glGetUniformLocation( blitDepthProgramH, "u_TexCorr");
302
    }
303

  
304
///////////////////////////////////////////////////////////////////////////////////////////////////
287 305

  
306
  private static void createNormalProgram(Resources resources)
307
    {
288 308
    // NORMAL PROGRAM //////////////////////////////////////
289 309
    final InputStream normalVertexStream   = resources.openRawResource(R.raw.normal_vertex_shader);
290 310
    final InputStream normalFragmentStream = resources.openRawResource(R.raw.normal_fragment_shader);
......
342 362

  
343 363
///////////////////////////////////////////////////////////////////////////////////////////////////
344 364

  
345
  private static void createProgramsOIT(Resources resources)
365
  private static void createOITProgram(Resources resources)
346 366
    {
347 367
    // MAIN OIT PROGRAM ////////////////////////////////
348 368
    final InputStream mainVertStream = resources.openRawResource(R.raw.main_vertex_shader);
......
462 482

  
463 483
  private static void displayNormals(EffectQueue[] queues, MeshBase mesh)
464 484
    {
485
    if( mNormalProgram==null )
486
      {
487
      try
488
        {
489
        createNormalProgram(mResources);
490
        }
491
      catch(Exception ex)
492
        {
493
        mListener.distortedException(ex);
494
        return;
495
        }
496
      }
497

  
465 498
    int num = mesh.getNumVertices();
466 499
    int tfo = mesh.getTFO();
467 500

  
......
485 518

  
486 519
  public static void adjustVertices(MeshBase mesh, EffectQueueVertex queue)
487 520
    {
488
    if( mFullProgram!=null )
521
    if( mFullProgram==null )
489 522
      {
490
      int num = mesh.getNumVertices();
491
      int tfo = mesh.getTFO();
492

  
493
      mFullProgram.useProgram();
494
      mesh.bindVertexAttribs(mFullProgram);
495
      queue.compute(1);
496
      queue.send(0.0f,3);
497
      mesh.send(3);
498

  
499
      GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfo );
500
      GLES30.glBeginTransformFeedback( GLES30.GL_POINTS);
501
      InternalRenderState.switchOffDrawing();
502
      GLES30.glDrawArrays( GLES30.GL_POINTS, 0, num );
503
      InternalRenderState.restoreDrawing();
504
      GLES30.glEndTransformFeedback();
505
      mesh.copyTransformToVertex();
506
      GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
523
      try
524
        {
525
        createFullProgram(mResources);
526
        }
527
      catch(Exception ex)
528
        {
529
        mListener.distortedException(ex);
530
        return;
531
        }
507 532
      }
533

  
534
    int num = mesh.getNumVertices();
535
    int tfo = mesh.getTFO();
536

  
537
    mFullProgram.useProgram();
538
    mesh.bindVertexAttribs(mFullProgram);
539
    queue.compute(1);
540
    queue.send(0.0f,3);
541
    mesh.send(3);
542

  
543
    GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfo );
544
    GLES30.glBeginTransformFeedback( GLES30.GL_POINTS);
545
    InternalRenderState.switchOffDrawing();
546
    GLES30.glDrawArrays( GLES30.GL_POINTS, 0, num );
547
    InternalRenderState.restoreDrawing();
548
    GLES30.glEndTransformFeedback();
549
    mesh.copyTransformToVertex();
550
    GLES30.glBindBufferBase(GLES30.GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
508 551
    }
509 552

  
510 553
///////////////////////////////////////////////////////////////////////////////////////////////////
......
516 559
    EffectQueue.compute(queues, currTime);
517 560
    GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight );
518 561

  
519
    DistortedLibrary.mMainOITProgram.useProgram();
520
    GLES30.glUniform1i(DistortedLibrary.mMainOITTextureH, 0);
521
    GLES30.glUniform2ui(DistortedLibrary.mMainOITSizeH, surface.mWidth, surface.mHeight);
522
    GLES30.glUniform1ui(DistortedLibrary.mMainOITNumRecordsH, (int)(DistortedLibrary.mBufferSize*surface.mWidth*surface.mHeight) );
523
    mesh.bindVertexAttribs(DistortedLibrary.mMainOITProgram);
562
    mMainOITProgram.useProgram();
563
    GLES30.glUniform1i(mMainOITTextureH, 0);
564
    GLES30.glUniform2ui(mMainOITSizeH, surface.mWidth, surface.mHeight);
565
    GLES30.glUniform1ui(mMainOITNumRecordsH, (int)(mBufferSize*surface.mWidth*surface.mHeight) );
566
    mesh.bindVertexAttribs(mMainOITProgram);
524 567
    mesh.send(1);
525 568

  
526 569
    float inflate     = mesh.getInflate();
......
533 576

  
534 577
    if( mesh.getShowNormals() )
535 578
      {
536
      DistortedLibrary.mMainProgram.useProgram();
579
      mMainProgram.useProgram();
537 580
      mesh.send(0);
538 581
      EffectQueue.send(queues, distance, mipmap, projection, inflate, mesh, 0 );
539 582
      displayNormals(queues,mesh);
......
667 710
      }
668 711

  
669 712
    // reading the value of the buffer on every frame would slow down rendering by
670
    // dialog_about 3%; doing it only once every 5 frames affects speed by less than 1%.
713
    // about 3%; doing it only once every 5 frames affects speed by less than 1%.
671 714
    if( mCurrBuffer==0 )
672 715
      {
673 716
      GLES30.glBindBufferBase(GLES31.GL_ATOMIC_COUNTER_BUFFER, 0, mAtomicCounter[mCurrBuffer]);
......
687 730

  
688 731
  static void oitClear(InternalOutputSurface surface, int counter)
689 732
    {
690
    if( mOITClearProgram!=null )
733
    if( mOITClearProgram==null )
691 734
      {
692
      if( mLinkedListSSBO[0]<0 )
735
      android.util.Log.e("aa", "attempting OIT compilation");
736

  
737
      if( mGLSL>=310 && !mOITCompilationAttempted )
693 738
        {
694
        GLES30.glGenBuffers(1,mLinkedListSSBO,0);
739
        mOITCompilationAttempted = true;
695 740

  
696
        int size = (int)(surface.mWidth*surface.mHeight*(3*mBufferSize+1)*4);
697
        GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
698
        GLES30.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, size, null, GLES30.GL_DYNAMIC_READ|GLES30.GL_DYNAMIC_DRAW);
699
        GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
741
        try
742
          {
743
          createOITProgram(mResources);
744
          }
745
        catch(Exception ex)
746
          {
747
          mListener.distortedException(ex);
748
          return;
749
          }
700 750

  
701
        GLES30.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 1, mLinkedListSSBO[0]);
751
        android.util.Log.e("aa", "OIT compilation successfull");
702 752
        }
703

  
704
      // See if we have overflown the SSBO in one of the previous frames.
705
      // If yes, assume we need to make the SSBO larger.
706
      float overflow = counter/(mBufferSize*surface.mWidth*surface.mHeight);
707

  
708
      if( overflow>1.0f )
753
      else
709 754
        {
710
        //android.util.Log.e("effects", "previous frame rendered "+counter+
711
        //                   " fragments, but there was only "+(mBufferSize*surface.mWidth*surface.mHeight)+" space");
712

  
713
        mBufferSize *= (int)(overflow+1.0f);
714
        int size = (int)(surface.mWidth*surface.mHeight*(3*mBufferSize+1)*4);
715
        GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
716
        GLES30.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, size, null, GLES30.GL_DYNAMIC_READ|GLES30.GL_DYNAMIC_DRAW);
717
        GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
755
        return;
718 756
        }
757
      }
719 758

  
720
      mOITClearProgram.useProgram();
759
    if( mLinkedListSSBO[0]<0 )
760
      {
761
      GLES30.glGenBuffers(1,mLinkedListSSBO,0);
721 762

  
722
      GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight );
723
      GLES30.glUniform2f(mOITClearTexCorrH, 1.0f, 1.0f );   // corrections do not really matter here - only present because of common vertex shader.
724
      GLES30.glUniform1f( mOITClearDepthH , 1.0f);          // likewise depth
725
      GLES30.glUniform2ui(mOITClearSizeH, surface.mWidth, surface.mHeight);
726
      GLES30.glVertexAttribPointer(mOITClearProgram.mAttribute[0], 2, GLES30.GL_FLOAT, false, 0, mQuadPositions);
727
      GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
763
      int size = (int)(surface.mWidth*surface.mHeight*(3*mBufferSize+1)*4);
764
      GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
765
      GLES30.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, size, null, GLES30.GL_DYNAMIC_READ|GLES30.GL_DYNAMIC_DRAW);
766
      GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
767

  
768
      GLES30.glBindBufferBase(GLES31.GL_SHADER_STORAGE_BUFFER, 1, mLinkedListSSBO[0]);
769
      }
770

  
771
    // See if we have overflown the SSBO in one of the previous frames.
772
    // If yes, assume we need to make the SSBO larger.
773
    float overflow = counter/(mBufferSize*surface.mWidth*surface.mHeight);
774

  
775
    if( overflow>1.0f )
776
      {
777
      mBufferSize *= (int)(overflow+1.0f);
778
      int size = (int)(surface.mWidth*surface.mHeight*(3*mBufferSize+1)*4);
779
      GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, mLinkedListSSBO[0]);
780
      GLES30.glBufferData(GLES31.GL_SHADER_STORAGE_BUFFER, size, null, GLES30.GL_DYNAMIC_READ|GLES30.GL_DYNAMIC_DRAW);
781
      GLES30.glBindBuffer(GLES31.GL_SHADER_STORAGE_BUFFER, 0);
728 782
      }
783

  
784
    mOITClearProgram.useProgram();
785

  
786
    GLES30.glViewport(0, 0, surface.mWidth, surface.mHeight );
787
    GLES30.glUniform2f(mOITClearTexCorrH, 1.0f, 1.0f );   // corrections do not really matter here - only present because of common vertex shader.
788
    GLES30.glUniform1f( mOITClearDepthH , 1.0f);          // likewise depth
789
    GLES30.glUniform2ui(mOITClearSizeH, surface.mWidth, surface.mHeight);
790
    GLES30.glVertexAttribPointer(mOITClearProgram.mAttribute[0], 2, GLES30.GL_FLOAT, false, 0, mQuadPositions);
791
    GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, 0, 4);
729 792
    }
730 793

  
731 794
///////////////////////////////////////////////////////////////////////////////////////////////////
......
864 927
    return mGLSL;
865 928
    }
866 929

  
867
///////////////////////////////////////////////////////////////////////////////////////////////////
868
/**
869
 * Have we successfully managed to compile the OIT programs?
870
 * Some hardware ( Imagination GE8100 / 8300, driver build 1.8@4490469 present in my HTC phone and,
871
 * sadly, Amazon Fire Stick 4K ) fails to compile the shaders. See relevant thread in Imagination's
872
 * support forum:
873
 *
874
 * https://forums.imgtec.com/t/ge8100-in-htc-desire-12-android-7-1-1-fragment-shader-fails-to-compile/2708
875
 */
876
  public static boolean OITCompilationSuccessful()
877
    {
878
    return mOITCompilationSuccessful;
879
    }
880

  
881 930
///////////////////////////////////////////////////////////////////////////////////////////////////
882 931
/**
883 932
 * Have we called onCreate yet, ie have we initialized the library?
......
896 945
 * Needs to be called from a thread holding the OpenGL context.
897 946
 *
898 947
 * @param context Context of the App using the library - used to open up Resources and read Shader code.
948
 * @param listener The library will send all (asynchronous!) exceptions there.
899 949
 */
900
  public static void onCreate(final Context context) throws Exception
950
  public static void onCreate(final Context context, final ExceptionListener listener)
901 951
    {
902
    onCreate(context,4);
952
    onCreate(context,listener,4);
903 953
    }
904 954

  
905 955
///////////////////////////////////////////////////////////////////////////////////////////////////
......
910 960
 * Needs to be called from a thread holding the OpenGL context.
911 961
 *   
912 962
 * @param context Context of the App using the library - used to open up Resources and read Shader code.
963
 * @param listener The library will send all (asynchronous!) exceptions there.
913 964
 * @param queueSize the size of the FBO queue, a workaround for the bug on Mali drivers.
914 965
 */
915
  public static void onCreate(final Context context, int queueSize) throws Exception
966
  public static void onCreate(final Context context, final ExceptionListener listener, int queueSize)
916 967
    {
917 968
    final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
918 969
    final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
......
921 972
    int major = glESversion >> 16;
922 973
    int minor = glESversion & 0xff;
923 974

  
975
    mListener = listener;
976

  
924 977
    if( major< 3 )
925 978
      {
926 979
      mGLSL = 100*major + 10*minor;
927
      throw new VertexCompilationException("at least OpenGL ES 3.0 required, this device supports only "+major+"."+minor);
980
      VertexCompilationException ex = new VertexCompilationException("at least OpenGL ES 3.0 required, this device supports only "+major+"."+minor);
981
      mListener.distortedException(ex);
928 982
      }
929 983
    else
930 984
      {
......
935 989
    mGLSL_VERSION = "#version "+mGLSL+" es\n";
936 990

  
937 991
    mInitialized = true;
938
    mOITCompilationSuccessful = false;
992
    mOITCompilationAttempted = false;
939 993

  
940 994
    detectBuggyDriversAndSetQueueSize(queueSize);
941 995

  
942 996
    EffectMessageSender.startSending();
943 997

  
944
    final Resources resources = context.getResources();
945

  
946
    Exception exception=null;
998
    mResources = context.getResources();
947 999

  
948 1000
    try
949 1001
      {
950
      createPrograms(resources);
1002
      createMainProgram();
951 1003
      }
952 1004
    catch(Exception ex)
953 1005
      {
954
      exception = ex;
1006
      mListener.distortedException(ex);
955 1007
      }
956 1008

  
957 1009
    try
958 1010
      {
959
      createFullProgram(resources);
1011
      EffectQueuePostprocess.createPrograms(mResources, mGLSL);
960 1012
      }
961 1013
    catch(Exception ex)
962 1014
      {
963
      exception = ex;
964
      }
965

  
966
    if( mGLSL>=310)
967
      {
968
      try
969
        {
970
        createProgramsOIT(resources);
971
        mOITCompilationSuccessful = true;
972
        }
973
      catch(Exception ex)
974
        {
975
        exception = ex;
976
        }
977
      }
978

  
979
    try
980
      {
981
      EffectQueuePostprocess.createPrograms(resources, mGLSL);
982
      }
983
    catch(Exception ex)
984
      {
985
      exception = ex;
1015
      mListener.distortedException(ex);
986 1016
      }
987 1017

  
988 1018
    try
......
991 1021
      }
992 1022
    catch(Exception ex)
993 1023
      {
994
      exception = ex;
995
      }
996

  
997
    if( exception!=null)
998
      {
999
      throw exception;
1024
      mListener.distortedException(ex);
1000 1025
      }
1001 1026
    }
1002 1027

  
......
1031 1056
    EffectMessageSender.stopSending();
1032 1057

  
1033 1058
    mInitialized = false;
1059
    mOITCompilationAttempted = false;
1060

  
1061
    mNormalProgram     = null;
1062
    mMainOITProgram    = null;
1063
    mMainProgram       = null;
1064
    mFullProgram       = null;
1065
    mOITClearProgram   = null;
1066
    mOITBuildProgram   = null;
1067
    mOITCollapseProgram= null;
1068
    mOITRenderProgram  = null;
1069
    mBlitDepthProgram  = null;
1070
    mBlitProgram       = null;
1034 1071
    }
1035 1072

  
1036 1073
///////////////////////////////////////////////////////////////////////////////////////////////////

Also available in: Unified diff