Project

General

Profile

« Previous | Next » 

Revision 2dbed690

Added by Leszek Koltunski over 6 years ago

In an attempt to contain the flashes on Mali GPU, re-structure the post-processing FBOs from 1 FBO with 2 color attachments + combined depth-stencil to 2 separate FBOs sharing a depth-stencil texture.

Result: this appears to make the flashes slightly worse.

View differences:

src/main/java/org/distorted/library/effect/PostprocessEffect.java
139 139
 *
140 140
 * @y.exclude
141 141
 */
142
  public abstract int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers);
142
  public abstract int apply(float[] uniforms, int index, DistortedOutputSurface[][] buffers);
143 143

  
144 144
///////////////////////////////////////////////////////////////////////////////////////////////////
145 145
/**
src/main/java/org/distorted/library/effect/PostprocessEffectBlur.java
140 140
 *
141 141
 * @y.exclude
142 142
 */
143
  public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers)
143
  public int apply(float[] uniforms, int index, DistortedOutputSurface[][] buffers)
144 144
    {
145 145
    if( mProgram1 ==null)
146 146
      {
......
157 157

  
158 158
    DistortedRenderState.useStencilMark();
159 159

  
160
    DistortedFramebuffer buffer = (DistortedFramebuffer)buffers[mQualityLevel];
160
    DistortedFramebuffer buffer0 = (DistortedFramebuffer)buffers[mQualityLevel][0];
161
    DistortedFramebuffer buffer1 = (DistortedFramebuffer)buffers[mQualityLevel][1];
161 162

  
162
    buffer.setAsOutput();
163
    float w= buffer0.getWidth();
164
    float h= buffer0.getHeight();
165
    float n= 1.0f - buffer0.getNear();
163 166

  
164
    float w= buffer.getWidth();
165
    float h= buffer.getHeight();
166
    float n= 1.0f - buffer.getNear();
167

  
168
    float corrW = buffer.getWidthCorrection();
169
    float corrH = buffer.getHeightCorrection();
167
    float corrW = buffer0.getWidthCorrection();
168
    float corrH = buffer0.getHeightCorrection();
170 169
    float offsetCorrW = corrW/w;
171 170
    float offsetCorrH = corrH/h;
172 171

  
......
182 181
    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW;
183 182

  
184 183
    mProgram1.useProgram();
185
    buffer.bindForOutput(1);
186
    buffer.setAsInput(0);
184
    buffer1.setAsOutput();
185
    buffer0.setAsInput();
187 186

  
188 187
    GLES31.glColorMask(true,true,true,true);
189 188
    GLES31.glClearColor(1.0f,1.0f,1.0f,0.0f);
......
203 202
    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH;
204 203

  
205 204
    mProgram2.useProgram();
206
    buffer.bindForOutput(0);
207
    buffer.setAsInput(1);
205
    buffer0.setAsOutput();
206
    buffer1.setAsInput();
208 207

  
209 208
    GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
210 209

  
src/main/java/org/distorted/library/effect/PostprocessEffectGlow.java
144 144
 *
145 145
 * @y.exclude
146 146
 */
147
  public int apply(float[] uniforms, int index, DistortedOutputSurface[] buffers)
147
  public int apply(float[] uniforms, int index, DistortedOutputSurface[][] buffers)
148 148
    {
149 149
    if( mProgram1 ==null)
150 150
      {
......
161 161

  
162 162
    DistortedRenderState.useStencilMark();
163 163

  
164
    DistortedFramebuffer  inBuffer = (DistortedFramebuffer)buffers[0];
165
    DistortedFramebuffer outBuffer = (DistortedFramebuffer)buffers[mQualityLevel];
164
    DistortedFramebuffer  inBuffer  = (DistortedFramebuffer)buffers[0][0];
165
    DistortedFramebuffer outBuffer0 = (DistortedFramebuffer)buffers[mQualityLevel][0];
166
    DistortedFramebuffer outBuffer1 = (DistortedFramebuffer)buffers[mQualityLevel][1];
166 167

  
167
    float w= outBuffer.getWidth();
168
    float h= outBuffer.getHeight();
169
    float n= 1.0f - outBuffer.getNear();
168
    float w= outBuffer0.getWidth();
169
    float h= outBuffer0.getHeight();
170
    float n= 1.0f - outBuffer0.getNear();
170 171

  
171 172
    float corrW = inBuffer.getWidthCorrection();
172 173
    float corrH = inBuffer.getHeightCorrection();
......
180 181
    int offset = radius + radius*radius/4;
181 182
    radius = (radius+1)/2;
182 183

  
183
    outBuffer.setAsOutput();
184 184
    GLES31.glViewport(0, 0, (int)w, (int)h);
185 185

  
186 186
    // horizontal glow
187 187
    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrW;
188 188

  
189 189
    mProgram1.useProgram();
190
    outBuffer.bindForOutput(1);
191
    inBuffer.setAsInput(0);
190
    outBuffer1.setAsOutput();
191
    inBuffer.setAsInput();
192 192

  
193 193
    GLES31.glColorMask(true,true,true,true);
194 194
    GLES31.glClearColor(1.0f,1.0f,1.0f,0.0f);
......
209 209
    for(int i=0; i<=radius; i++) mOffsets[i] = offsetsCache[offset+i]*offsetCorrH;
210 210

  
211 211
    mProgram2.useProgram();
212
    outBuffer.bindForOutput(0);
213
    outBuffer.setAsInput(1);
212
    outBuffer0.setAsOutput();
213
    outBuffer1.setAsInput();
214 214

  
215 215
    GLES31.glUniform1f ( mProgram2.mUniform[0] , n );
216 216
    GLES31.glUniform2f ( mProgram2.mUniform[1] , corrW, corrH );
......
229 229
    if( mQualityLevel>0 )
230 230
      {
231 231
      inBuffer.setAsOutput();
232
      outBuffer.setAsInput(0);
232
      outBuffer0.setAsInput();
233 233
      GLES31.glEnable(GLES31.GL_BLEND);
234 234
      DistortedEffects.blitPriv(inBuffer);
235 235
      GLES31.glDisable(GLES31.GL_BLEND);
src/main/java/org/distorted/library/main/DistortedFramebuffer.java
39 39
    if( mColorCreated==NOT_CREATED_YET )
40 40
      {
41 41
      GLES31.glGenTextures( mNumColors, mColorH, 0);
42
      GLES31.glGenFramebuffers(1, mFBOH, 0);
43
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
44 42

  
45 43
      for(int i=0; i<mNumColors; i++)
46 44
        {
......
51 49
        GLES31.glTexParameterf(GLES31.GL_TEXTURE_2D, GLES31.GL_TEXTURE_MAG_FILTER, GLES31.GL_LINEAR);
52 50
        GLES31.glTexImage2D(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA, mRealWidth, mRealHeight, 0, GLES31.GL_RGBA, GLES31.GL_UNSIGNED_BYTE, null);
53 51
        }
54
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mColorH[0], 0);
55 52
      GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
53

  
54
      GLES31.glGenFramebuffers(1, mFBOH, 0);
55
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
56
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mColorH[0], 0);
56 57
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, 0);
57 58

  
58 59
      mColorCreated = checkStatus("color");
......
77 78
        }
78 79

  
79 80
      GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, 0);
81

  
80 82
      GLES31.glBindFramebuffer(GLES31.GL_FRAMEBUFFER, mFBOH[0]);
81 83

  
82 84
      if( mDepthStencil==DEPTH_NO_STENCIL )
......
105 107
      GLES31.glDeleteTextures(1, mDepthStencilH, 0);
106 108
      mDepthStencilH[0]=0;
107 109
      }
110
    if( mDepthStencilCreated==COPIED && mDepthStencilH[0]>0 )
111
      {
112
      mDepthStencilCreated = DONT_CREATE;
113
      mDepthStencilH[0]=0;
114
      }
108 115
    }
109 116

  
110 117
///////////////////////////////////////////////////////////////////////////////////////////////////
......
128 135
    return CREATED;
129 136
    }
130 137

  
138
///////////////////////////////////////////////////////////////////////////////////////////////////
139
// the Framebuffer was created without DEPTH or STENCIL but now we want to copy it from some other.
140
// Framebuffer 'from' MUST be already created!!
141
// Must be called from a thread holding OpenGL Context
142
//
143
// 'Private' , library-only function used only for the postprocessing buffers!
144

  
145
  void copyDepthAndStencil(DistortedFramebuffer from)
146
    {
147
    mDepthStencilCreated = COPIED;
148
    mDepthStencilH[0] = from.mDepthStencilH[0];
149
    }
150

  
131 151
///////////////////////////////////////////////////////////////////////////////////////////////////
132 152
// Must be called from a thread holding OpenGL Context
133 153

  
src/main/java/org/distorted/library/main/DistortedObject.java
39 39
  static final int NOT_CREATED_YET  = 2;
40 40
  static final int DONT_CREATE      = 3;
41 41
  static final int CREATED          = 4;
42
  static final int COPIED           = 5;
42 43

  
43 44
  static final int TYPE_USER = 0;
44 45
  static final int TYPE_TREE = 1;
src/main/java/org/distorted/library/main/DistortedOutputSurface.java
69 69

  
70 70
  private ArrayList<Job> mJobs = new ArrayList<>();
71 71

  
72
  // Global buffers used for postprocessing.
73
  private static DistortedOutputSurface[] mBuffer = new DistortedOutputSurface[EffectQuality.LENGTH];
72
  // Global buffers used for postprocessing. MipmapLevels x PING_PONG of each for postprocessing ping-pong.
73
  private static final int PING_PONG = 2;
74
  private static DistortedOutputSurface[][] mBuffer = null;
74 75

  
75 76
  private long mTime;
76 77
  private float mFOV;
......
171 172

  
172 173
  private static void createPostprocessingBuffers(int width, int height, float near)
173 174
    {
175
    mBuffer = new DistortedOutputSurface[EffectQuality.LENGTH][PING_PONG];
174 176
    float mipmap=1.0f;
175 177

  
176
    for (int j=0; j<EffectQuality.LENGTH; j++)
178
    for (int i=0; i<EffectQuality.LENGTH; i++)
177 179
      {
178
      mBuffer[j] = new DistortedFramebuffer(2, BOTH_DEPTH_STENCIL, TYPE_SYST, (int) (width * mipmap), (int) (height * mipmap));
179
      mBuffer[j].mMipmap = mipmap;
180
      mBuffer[j].mNear = near;  // copy mNear as well (for blitting- see PostprocessEffect.apply() )
181
      mBuffer[j].glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
180
      mBuffer[i][0] = new DistortedFramebuffer(1, BOTH_DEPTH_STENCIL, TYPE_SYST, (int) (width * mipmap), (int) (height * mipmap));
181
      mBuffer[i][0].mMipmap = mipmap;
182
      mBuffer[i][0].mNear = near;  // copy mNear as well (for blitting- see PostprocessEffect.apply() )
183
      mBuffer[i][0].glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
184

  
185
      for(int j=1; j<PING_PONG; j++)
186
        {
187
        mBuffer[i][j] = new DistortedFramebuffer(1, NO_DEPTH_NO_STENCIL, TYPE_SYST, (int) (width * mipmap), (int) (height * mipmap));
188
        mBuffer[i][j].mMipmap = mipmap;
189
        mBuffer[i][j].mNear = near;
190
        mBuffer[i][j].glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
191
        }
182 192

  
183 193
      mipmap *= EffectQuality.MULTIPLIER;
184 194
      }
185 195

  
186 196
    DistortedObject.toDo(); // create the FBOs immediately. This is safe as we must be holding the OpenGL context now.
187 197

  
198
    for (int i=0; i<EffectQuality.LENGTH; i++)
199
      {
200
      for(int j=1; j<PING_PONG; j++)
201
        {
202
        ( (DistortedFramebuffer)mBuffer[i][j]).copyDepthAndStencil( (DistortedFramebuffer)mBuffer[i][0] );
203
        }
204
      }
205

  
188 206
    GLES31.glStencilMask(0xff);
189 207
    GLES31.glDepthMask(true);
190 208
    GLES31.glColorMask(true, true, true, true);
......
192 210
    GLES31.glClearDepthf(1.0f);
193 211
    GLES31.glClearStencil(0);
194 212

  
195
    for (int j=0; j<EffectQuality.LENGTH; j++)
213
    for (int i=0; i<EffectQuality.LENGTH; i++)
196 214
      {
197
      mBuffer[j].setAsOutput();
198
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[1], 0);
215
      mBuffer[i][0].setAsOutput();
199 216
      GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT | GLES31.GL_DEPTH_BUFFER_BIT | GLES31.GL_STENCIL_BUFFER_BIT);
200
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, mBuffer[j].mColorH[0], 0);
201
      GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
217

  
218
      for(int j=1; j<PING_PONG; j++)
219
        {
220
        mBuffer[i][j].setAsOutput();
221
        GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
222
        }
202 223
      }
203 224
    }
204 225

  
......
206 227

  
207 228
  static synchronized void onDestroy()
208 229
    {
209
    for(int j=0; j<EffectQuality.LENGTH; j++)
230
    if( mBuffer!=null )
210 231
      {
211
      mBuffer[j] = null;
232
      for (int i=0; i<EffectQuality.LENGTH; i++)
233
        {
234
        for (int j=1; j<PING_PONG; j++)
235
          {
236
          mBuffer[i][j] = null;
237
          }
238
        }
239

  
240
      mBuffer = null;
212 241
      }
213 242
    }
214 243

  
......
220 249

  
221 250
  private static void clonePostprocessingViewport(DistortedOutputSurface from)
222 251
    {
223
    if( mBuffer[0].mWidth != from.mWidth || mBuffer[0].mHeight != from.mHeight )
252
    if( mBuffer[0][0].mWidth != from.mWidth || mBuffer[0][0].mHeight != from.mHeight )
224 253
      {
225 254
      DistortedOutputSurface surface;
226 255

  
227 256
      for(int i=0; i<EffectQuality.LENGTH; i++)
228 257
        {
229
        surface = mBuffer[i];
258
        for(int j=0; j<PING_PONG; j++)
259
          {
260
          surface = mBuffer[i][j];
230 261

  
231
        surface.mWidth  = (int)(from.mWidth *surface.mMipmap);
232
        surface.mHeight = (int)(from.mHeight*surface.mMipmap);
262
          surface.mWidth  = (int) (from.mWidth  * surface.mMipmap);
263
          surface.mHeight = (int) (from.mHeight * surface.mMipmap);
233 264

  
234
        surface.mNear   = from.mNear;  // Near plane is independent of the mipmap level
265
          surface.mNear = from.mNear;  // Near plane is independent of the mipmap level
235 266

  
236
        //android.util.Log.e("surface", "viewport "+i+" to ("+from.mWidth+"x"+from.mHeight+")");
267
          //android.util.Log.e("surface", "viewport "+i+" to ("+from.mWidth+"x"+from.mHeight+")");
237 268

  
238
        surface.createProjection();
269
          surface.createProjection();
239 270

  
240
        int maxw = surface.mWidth  > surface.mRealWidth  ? surface.mWidth  : surface.mRealWidth;
241
        int maxh = surface.mHeight > surface.mRealHeight ? surface.mHeight : surface.mRealHeight;
271
          int maxw = surface.mWidth  > surface.mRealWidth  ? surface.mWidth  : surface.mRealWidth;
272
          int maxh = surface.mHeight > surface.mRealHeight ? surface.mHeight : surface.mRealHeight;
242 273

  
243
        if (maxw > surface.mRealWidth || maxh > surface.mRealHeight)
244
          {
245
          surface.mRealWidth = maxw;
246
          surface.mRealHeight = maxh;
274
          if (maxw > surface.mRealWidth || maxh > surface.mRealHeight)
275
            {
276
            surface.mRealWidth = maxw;
277
            surface.mRealHeight = maxh;
247 278

  
248
          surface.recreate();
249
          surface.create();
279
            surface.recreate();
280
            surface.create();
281
            }
250 282
          }
251 283
        }
252 284
      }
......
288 320
    }
289 321

  
290 322
///////////////////////////////////////////////////////////////////////////////////////////////////
291
// two phases: 1. collapse the SSBO 2. blend the ssbo's color
323
// two phases: 1. collapse the SSBO 2. blend the SSBO's color
292 324

  
293 325
  private int oitRender(long currTime)
294 326
    {
......
318 350

  
319 351
///////////////////////////////////////////////////////////////////////////////////////////////////
320 352

  
321
  private static void clearBuffer(DistortedOutputSurface buffer)
353
  private static void clearPostprocessingBuffer(int quality)
322 354
    {
323 355
    GLES31.glStencilMask(0xff);
324 356
    GLES31.glDepthMask(true);
......
327 359
    GLES31.glClearDepthf(1.0f);
328 360
    GLES31.glClearStencil(0);
329 361

  
330
    buffer.setAsOutput();
331
    GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[buffer.mNumColors-1], 0);
362
    mBuffer[quality][0].setAsOutput();
332 363
    GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT|GLES31.GL_DEPTH_BUFFER_BIT|GLES31.GL_STENCIL_BUFFER_BIT);
333 364

  
334
    for(int i=buffer.mNumColors-2; i>=0; i--)
365
    for(int j=1; j<PING_PONG; j++)
335 366
      {
336
      GLES31.glFramebufferTexture2D(GLES31.GL_FRAMEBUFFER, GLES31.GL_COLOR_ATTACHMENT0, GLES31.GL_TEXTURE_2D, buffer.mColorH[i], 0);
367
      mBuffer[quality][j].setAsOutput();
337 368
      GLES31.glClear(GLES31.GL_COLOR_BUFFER_BIT);
338 369
      }
339 370
    }
......
375 406
        }
376 407
      else
377 408
        {
378
        if( mBuffer[0]==null ) createPostprocessingBuffers(mWidth,mHeight,mNear);
409
        if( mBuffer==null ) createPostprocessingBuffers(mWidth,mHeight,mNear);
379 410

  
380 411
        if( lastBucket!=currBucket )
381 412
          {
......
389 420
            for(int j=bucketChange; j<i; j++)
390 421
              {
391 422
              child2 = children.get(j);
392
              numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality],lastQueue);
423
              numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality][0],lastQueue);
393 424
              }
394 425

  
395 426
            numRenders += lastQueue.postprocess(mBuffer);
396
            numRenders += oitBuild(mBuffer[quality]);
427
            numRenders += oitBuild(mBuffer[quality][0]);
397 428
            GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT|GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
398
            clearBuffer(mBuffer[quality]);
429
            clearPostprocessingBuffer(quality);
399 430
            }
400 431

  
401 432
          internalQuality = currQueue.getInternalQuality();
......
403 434
          bucketChange    = i;
404 435
          }
405 436

  
406
        mBuffer[quality].setAsOutput(time);
407
        child1.drawNoBlend(time,mBuffer[quality]);
437
        mBuffer[quality][0].setAsOutput(time);
438
        child1.drawNoBlend(time,mBuffer[quality][0]);
408 439

  
409 440
        if( i==numChildren-1 )
410 441
          {
411 442
          for(int j=bucketChange; j<numChildren; j++)
412 443
            {
413 444
            child2 = children.get(j);
414
            numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality],currQueue);
445
            numRenders += child2.markStencilAndDepth(time,mBuffer[internalQuality][0],currQueue);
415 446
            }
416 447

  
417 448
          numRenders += currQueue.postprocess(mBuffer);
418
          numRenders += oitBuild(mBuffer[quality]);
449
          numRenders += oitBuild(mBuffer[quality][0]);
419 450
          GLES31.glMemoryBarrier(GLES31.GL_SHADER_STORAGE_BARRIER_BIT|GLES31.GL_ATOMIC_COUNTER_BARRIER_BIT);
420 451
          numRenders += oitRender(time);  // merge the OIT linked list
421
          clearBuffer(mBuffer[quality]);
452
          clearPostprocessingBuffer(quality);
422 453
          }
423 454
        } // end else (postprocessed child)
424 455

  
src/main/java/org/distorted/library/main/EffectQueuePostprocess.java
100 100

  
101 101
///////////////////////////////////////////////////////////////////////////////////////////////////
102 102

  
103
  int postprocess(DistortedOutputSurface[] buffers)
103
  int postprocess(DistortedOutputSurface[][] buffers)
104 104
    {
105 105
    int numRenders = 0;
106 106

  

Also available in: Unified diff