Developer Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
OITLinkedList.cc
1 /*===========================================================================*\
2 * *
3 * OpenFlipper *
4 * Copyright (C) 2001-2014 by Computer Graphics Group, RWTH Aachen *
5 * www.openflipper.org *
6 * *
7 *--------------------------------------------------------------------------- *
8 * This file is part of OpenFlipper. *
9 * *
10 * OpenFlipper is free software: you can redistribute it and/or modify *
11 * it under the terms of the GNU Lesser General Public License as *
12 * published by the Free Software Foundation, either version 3 of *
13 * the License, or (at your option) any later version with the *
14 * following exceptions: *
15 * *
16 * If other files instantiate templates or use macros *
17 * or inline functions from this file, or you compile this file and *
18 * link it with other files to produce an executable, this file does *
19 * not by itself cause the resulting executable to be covered by the *
20 * GNU Lesser General Public License. This exception does not however *
21 * invalidate any other reasons why the executable file might be *
22 * covered by the GNU Lesser General Public License. *
23 * *
24 * OpenFlipper is distributed in the hope that it will be useful, *
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
27 * GNU Lesser General Public License for more details. *
28 * *
29 * You should have received a copy of the GNU LesserGeneral Public *
30 * License along with OpenFlipper. If not, *
31 * see <http://www.gnu.org/licenses/>. *
32 * *
33 \*===========================================================================*/
34 
35 /*===========================================================================*\
36 * *
37 * $Revision$ *
38 * $LastChangedBy$ *
39 * $Date$ *
40 * *
41 \*===========================================================================*/
42 
43 #include <ACG/GL/acg_glew.hh>
44 
45 #include "OITLinkedList.hh"
46 
47 
50 
51 #include <ACG/GL/ShaderCache.hh>
52 #include <ACG/GL/ScreenQuad.hh>
53 
54 #include <ACG/GL/GLError.hh>
55 
56 
57 
58 /*
59 OIT with per pixel linked list (A-Buffer).
60 
61 Implementation based on AMD presentation at GDC 2010:
62  "OIT and GI using DX11 linked lists" by Nick Thibieroz & Holger Gr�n
63 
64 
65 porting from DX11 to GL:
66 
67 UAV : image load/store with glBindImageTexture()
68 
69 [earlydepthstencil] : layout(early_fragment_tests) in;
70 
71 UAV counter: atomic counter
72 
73 
74 glsl gpu_shader5:
75 
76 convert between float4 color and uint r8g8b8a8: packUnorm4x8(color) unpackUnorm4x8(r8g8b8a8)
77 reinterpret cast between float and int: i_val = floatBitsToInt(f_val) intBitsToFloat(i_val)
78 
79 
80 
81 msaa support:
82 SV_Coverage : gl_SampleMaskIn[0], gl_SampleMask[0]
83 SV_SampleIndex : gl_SampleID
84 
85 msaa implementation: two different methods tested
86  - shading per sample via gl_SampleID
87  - shading per pixel and manually resolve sample colors
88 
89  Generation of the ABuffer is problematic in msaa mode, as it seems to run per-sample as indicated by the atomic counter value.
90  Although per-sample and per-fragment give the same result, per-fragment shading is preferred to save gpu ram.
91 
92  Forcing per fragment via glDisable(GL_MULTISAMPLING) will give a coverage mask of 0x01,
93  and only a single sample gets shaded and the others stay black..
94 
95  glDisable(GL_SAMPLE_SHADING) and glMinSampleShading(0.0f) still results in per sample shading
96 */
97 
98 // =================================================
99 
100 // generation of per pixel linked lists (ABuffer)
102 {
103 public:
104 
106  {
107  _shader->setGLSLVersion(420);
108 
109 
110  _shader->addUniform("layout(binding = 0, offset = 0) uniform atomic_uint g_FragmentCounter");
111  _shader->addUniform("layout(binding = 0, r32ui) uniform uimageBuffer g_StartOffsetBuffer");
112  _shader->addUniform("layout(binding = 1, rgba32ui) uniform uimageBuffer g_ABuffer");
113 
114 
115  _shader->addUniform("uniform uvec2 g_ScreenSize");
116  }
117 
118  void modifyFragmentBeginCode(QStringList* _code)
119  {
120  }
121 
122  void modifyFragmentEndCode(QStringList* _code)
123  {
124  // convert color from float4 to uint
125  _code->push_back("uint uiColor = packUnorm4x8(outFragment);");
126 
127  // convert float depth to uint
128  _code->push_back("uint uiDepth = floatBitsToUint(gl_FragCoord.z);");
129  // alternative depth [0,1] to uint cast:
130  // uiDepth = depth * (2^32-1)
131 
132  // get last fragment id
133  _code->push_back("uint uiFragCount = atomicCounterIncrement(g_FragmentCounter);");
134 
135  // get pixel index of current fragment
136  _code->push_back("uvec2 absFragCoord = uvec2(gl_FragCoord.xy);");
137  _code->push_back("uint uiPixelID = absFragCoord.x + uint(g_ScreenSize.x) * absFragCoord.y;");
138 
139  // take current offset from StartOffsetBuffer for fragment and replace it with the current fragment id
140  // this builds a reverse linked list (last inserted fragment is the head of the list of the current pixel)
141  // note: this operation doesnt even have to be atomic (the counter is atomic already), so optimization could be possible
142  _code->push_back("uint uiNextFragment = imageAtomicExchange(g_StartOffsetBuffer, int(uiPixelID), uiFragCount);");
143 
144  // append fragment entry at end of ABuffer, each fragment stores: (color, depth, nextEntry, msaaCoverageMask)
145  _code->push_back("imageStore(g_ABuffer, int(uiFragCount), uvec4(uiColor, uiDepth, uiNextFragment, uint(gl_SampleMaskIn[0])) );");
146 
147 
148  // in this pass we write into the UAV buffers only
149  // transparent objects should not change the depth buffer
150  // color is resolved in a post-processing step
151 // _code->push_back("discard;");
152  }
153 
154  static ABufferGenModifier instance;
155 };
156 
157 ABufferGenModifier ABufferGenModifier::instance;
158 
159 OITLinkedList::OITLinkedList()
160 {
161 }
162 
163 
164 OITLinkedList::~OITLinkedList()
165 {
166 }
167 
168 
169 void OITLinkedList::initializePlugin()
170 {
171  ACG::ShaderProgGenerator::setShaderDir(OpenFlipper::Options::shaderDirStr());
172  ACG::ShaderProgGenerator::registerModifier(&ABufferGenModifier::instance);
173 }
174 
175 
176 
177 void OITLinkedList::render(ACG::GLState* _glState, Viewer::ViewerProperties& _properties)
178 {
179  // collect renderobjects + prepare OpenGL state
181 
182 
183  renderOIT(_glState->viewport_width(), _glState->viewport_height(), _properties.multisampling());
184 
185  // restore common opengl state
186  // log window remains hidden otherwise
188 }
189 
190 void OITLinkedList::prepareBuffers(int w, int h)
191 {
192  ACG::Vec2ui screenSize = ACG::Vec2ui(GLuint(w), GLuint(h));
193 
194  // prepare buffers
195  const int estAvgLayers = 3;
196 
197  const int numPixels = w * h;
198  const int offsetBufSize = numPixels * 4; // uint buffer for each pixel
199  const int ABufSize = numPixels * 16 * estAvgLayers;
200 
201  if (startOffsetBuffer_.getBufferSize() < offsetBufSize)
202  startOffsetBuffer_.setBufferData(offsetBufSize, 0, GL_R32UI, GL_DYNAMIC_DRAW);
203 
204  if (ABuffer_.getBufferSize() < ABufSize)
205  ABuffer_.setBufferData(ABufSize, 0, GL_RGBA32UI, GL_DYNAMIC_DRAW);
206 
207 
208  // dbg: force unbind
209  glBindTexture(GL_TEXTURE_BUFFER, 0);
210 
211  // reset fragment counter
212  fragCounter_.set(0);
213 
214  // wait for buffer allocation
215  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
216 }
217 
218 void OITLinkedList::renderOIT(int w, int h, bool multisampled)
219 {
220  ACG::Vec2ui screenSize = ACG::Vec2ui(GLuint(w), GLuint(h));
221 
222  prepareBuffers(w, h);
223 
224 
225  // ----------------------------------
226  // invalidate per-pixel linked lists ( reset startOffsetBuffer to 0xffffffff )
227  glColorMask(0, 0, 0, 0);
228  glDepthMask(0);
229  glDisable(GL_DEPTH_TEST);
230 
231  // load reset shader for startOffsetBuffer
232  GLSL::Program* shaderReset = ACG::ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "OITLinkedList/reset.glsl");
233 
234  startOffsetBuffer_.bindAsImage(0, GL_WRITE_ONLY);
235 
236  shaderReset->use();
237 
238  shaderReset->setUniform("g_ScreenSize", screenSize);
239 
240  // screenquad scale and offset
241  shaderReset->setUniform("size", ACG::Vec2f(1.0f, 1.0f));
242  shaderReset->setUniform("offset", ACG::Vec2f(0.0f, 0.0f));
243 
244  ACG::ScreenQuad::draw(shaderReset);
245 
246  // wait for atomic counter and reset pass to finish!
247  glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
248 
249  // ----------------------------------
250  // 1. pass
251  // render scene into A-Buffer
252 
253  // msaa: per pixel lists instead of per sample lists
254  // note: shader seems to be run per sample anyway
255  // (ati driver: AtomicCounter with msaa enabled is a lot higher than without for the same scene)
256  if (multisampled)
257  {
258  glDisable(GL_SAMPLE_SHADING);
259  glEnable(GL_MULTISAMPLE);
260  glMinSampleShading(0.0f);
261  }
262 
263  int msaaSampleCount = 1;
264  glGetIntegerv(GL_SAMPLES, &msaaSampleCount);
265 
266  // bind UAV buffers
267  startOffsetBuffer_.bindAsImage(0, GL_READ_WRITE);
268  ABuffer_.bindAsImage(1, GL_WRITE_ONLY);
269 
270  // bind atomic counter
271  fragCounter_.bind(0);
272 
273  for (int i = 0; i < getNumRenderObjects(); ++i)
274  {
275  // apply ABufferGenModifier to all objects
277 
278  GLSL::Program* shaderRender = ACG::ShaderCache::getInstance()->getProgram(&obj->shaderDesc, ABufferGenModifier::instance);
279 
280  shaderRender->use();
281  shaderRender->setUniform("g_ScreenSize", screenSize);
282 
283  // disable writing to back-buffer
284  // only write linked lists in A-Buffer
285  obj->glColorMask(0,0,0,0);
286  obj->depthTest = false;
287  obj->depthWrite = false;
288  obj->culling = false;
289 
290  renderObject(obj, shaderRender);
291  }
292 
293  fragCounter_.unbind();
294 
295 
296  // wait for render pass to finish!
297  glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
298 
299  // ----------------------------------
300  // 2. pass
301  // resolve A-Buffer
302  glColorMask(1, 1, 1, 1);
303  glDepthMask(1);
304 
305  // msaa: resolve lists per sample
306  if (multisampled)
307  {
308  // force per sample shading
309  glEnable(GL_SAMPLE_SHADING);
310  glEnable(GL_MULTISAMPLE);
311  glMinSampleShading(1.0f);
312  }
313 
314  glGetIntegerv(GL_SAMPLES, &msaaSampleCount);
315 
316 
317  glDepthFunc(GL_ALWAYS);
318 
319 
320  // load resolve shader from cache
321  GLSL::Program* shaderResolve = 0;
322 
323  // msaa is enabled via preprocessor macro in the shader
324  QStringList shaderMacros;
325  if (multisampled)
326  shaderMacros.push_back("#define OITLL_MSAA");
327 
328  shaderResolve = ACG::ShaderCache::getInstance()->getProgram("ScreenQuad/screenquad.glsl", "OITLinkedList/resolve.glsl", &shaderMacros);
329 
330 
331  // init shader constants
332  shaderResolve->use();
333 
334  startOffsetBuffer_.bindAsImage(0, GL_READ_ONLY);
335  ABuffer_.bindAsImage(1, GL_READ_ONLY);
336 
337  shaderResolve->setUniform("g_ScreenSize", screenSize);
338 
339  if (multisampled)
340  shaderResolve->setUniform("g_SampleCount", GLuint(msaaSampleCount));
341 
342  // screenquad scale and offset
343  shaderResolve->setUniform("size", ACG::Vec2f(1.0f, 1.0f));
344  shaderResolve->setUniform("offset", ACG::Vec2f(0.0f, 0.0f));
345 
346 
347  ACG::ScreenQuad::draw(shaderResolve);
348 
349 
350  // wait for resolve pass
351  glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
352 
353 
354 
355  if (multisampled)
356  {
357  glDisable(GL_SAMPLE_SHADING);
358  glMinSampleShading(0.0f);
359  }
360 
361  // unbind
362 
363  const int numBoundImages = 3;
364 
365  for (int i = 0; i < numBoundImages; ++i)
366  glBindImageTexture(i, 0, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI);
367 
368  // -----------------------
369  // get result of fragment counter, ie. the total fragment count of the scene
370 
371  unsigned int actualFragmentCount = 0;
372 
373  fragCounter_.get(&actualFragmentCount);
374 
375 
376  // resize ABuffer if too small
377  // RGBA32UI : 16 bytes per fragment
378  if (int(actualFragmentCount) * 16 > ABuffer_.getBufferSize())
379  {
380  ABuffer_.setBufferData(actualFragmentCount * 18, 0, ABuffer_.getFormat(), ABuffer_.getUsage());
381 
382 // std::cout << "buffer size too small: " << actualFragmentCount << std::endl;
383  }
384 }
385 
386 
387 
388 QString OITLinkedList::checkOpenGL()
389 {
390  // Get version and check
391  if ( !ACG::openGLVersion(4,2) )
392  return QString("Insufficient OpenGL Version! OpenGL 4.2 or higher required");
393 
394  // Check extensions
395  QString glExtensions = QString((const char*)glGetString(GL_EXTENSIONS));
396  QString missing("");
397  if ( !glExtensions.contains("ARB_shader_image_load_store") )
398  missing += "ARB_shader_image_load_store extension missing\n";
399 
400  if ( !glExtensions.contains("GL_ARB_shader_atomic_counters") )
401  missing += "GL_ARB_shader_atomic_counters extension missing\n";
402 
403  if ( !glExtensions.contains("GL_ARB_gpu_shader5") )
404  missing += "GL_ARB_gpu_shader5 extension missing\n";
405 
406  return missing;
407 }
408 
409 
410 QString OITLinkedList::renderObjectsInfo( bool _outputShaderInfo )
411 {
412  std::vector<ACG::ShaderModifier*> mods;
413  mods.push_back(&ABufferGenModifier::instance);
414  return dumpCurrentRenderObjectsToString(&sortedObjects_[0],_outputShaderInfo, &mods);
415 }
416 
417 #if QT_VERSION < 0x050000
418  Q_EXPORT_PLUGIN2( oitlinkedlist , OITLinkedList );
419 #endif
420 
421 
422 
int viewport_width() const
get viewport width
Definition: GLState.hh:825
QString renderObjectsInfo(bool _outputShaderInfo)
Return a qstring of the current render objects.
void modifyFragmentEndCode(QStringList *_code)
Append code the the fragment shader.
static void draw(GLSL::Program *_prog=0)
Draw the screen quad.
Definition: ScreenQuad.cc:147
virtual void finishRenderingPipeline(bool _drawOverlay=true)
Draw overlay objects and reset OpenGL state.
Definition: IRenderer.cc:654
void setGLSLVersion(int _version)
Set glsl version.
static ShaderCache * getInstance()
Return instance of the ShaderCache singleton.
Definition: ShaderCache.cc:90
std::vector< ACG::RenderObject * > sortedObjects_
sorted list of renderobjects without overlay objects (sorted in rendering order)
Definition: IRenderer.hh:515
virtual QString dumpCurrentRenderObjectsToString(ACG::RenderObject **_list=0, bool _outputShaders=false, std::vector< ACG::ShaderModifier * > *_modifiers=0)
Outputs the current render objects to the string.
Definition: IRenderer.cc:1250
void modifyFragmentBeginCode(QStringList *_code)
Append code the the fragment shader.
static void setShaderDir(QString _dir)
void multisampling(bool _state)
set multisampling on/off
bool openGLVersion(const int _major, const int _minor)
Definition: gl.cc:95
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: GLSLShader.cc:391
ACG::RenderObject * getRenderObject(int i)
Get render objects in the sorted list by index (not including overlay objects)
Definition: IRenderer.cc:1189
virtual void renderObject(ACG::RenderObject *_obj, GLSL::Program *_prog=0, bool _constRenderStates=false, const std::vector< unsigned int > *_shaderModifiers=0)
Render one renderobject.
Definition: IRenderer.cc:1107
GLSL::Program * getProgram(const ShaderGenDesc *_desc, const std::vector< unsigned int > &_mods)
Query a dynamically generated program from cache.
Definition: ShaderCache.cc:108
VectorT< unsigned int, 2 > Vec2ui
Definition: VectorT.hh:106
GLSL program class.
Definition: GLSLShader.hh:217
int viewport_height() const
get viewport height
Definition: GLState.hh:827
int getNumRenderObjects() const
Get the number of collected render objects (not including overlay objects or gl4.2 line objects) ...
Definition: IRenderer.cc:1179
virtual void prepareRenderingPipeline(ACG::GLState *_glState, ACG::SceneGraph::DrawModes::DrawMode _drawMode, ACG::SceneGraph::BaseNode *_scenegraphRoot)
Prepares renderer and OpenGL for any draw-related calls including.
Definition: IRenderer.cc:529
void addUniform(QString _uniform, QString _comment="")
Add one GLSL uniform specifier.
Interface class between scenegraph and renderer.
void drawMode(ACG::SceneGraph::DrawModes::DrawMode _mode)
set draw mode (No test if this mode is available!)
void use()
Enables the program object for using.
Definition: GLSLShader.cc:351
static unsigned int registerModifier(ShaderModifier *_modifier)
Shader modifiers have to be registered before they can be used. They also must remain allocated for t...
ACG::SceneGraph::BaseNode * getSceneGraphRootNode()
get scenegraph root node
ShaderGenDesc shaderDesc
Drawmode and other shader params.
void modifyFragmentIO(ACG::ShaderGenerator *_shader)
Add your own inputs/outputs to the fragment shader.