diff options
Diffstat (limited to 'graphics/asymptote/glrender.cc')
-rw-r--r-- | graphics/asymptote/glrender.cc | 462 |
1 files changed, 313 insertions, 149 deletions
diff --git a/graphics/asymptote/glrender.cc b/graphics/asymptote/glrender.cc index 9b75e9c847..68f298d10a 100644 --- a/graphics/asymptote/glrender.cc +++ b/graphics/asymptote/glrender.cc @@ -84,12 +84,15 @@ GLint countShader; GLint transparentShader; GLint blendShader; GLint zeroShader; -GLint preSumShader; -GLint partialSumShader; +GLint sum1Shader; +GLint sum2Shader; +GLint sum3Shader; -GLuint countBuffer; GLuint offsetBuffer; -GLuint sumBuffer; +GLuint countBuffer; +GLuint maxBuffer; +GLuint localSumBuffer; +GLuint globalSumBuffer; GLuint fragmentBuffer; GLuint depthBuffer; GLuint opaqueBuffer; @@ -157,7 +160,13 @@ extern void exitHandler(int); namespace gl { -GLint processors; +GLint gs2; +GLint gs; +GLint g; +GLuint processors; +GLuint localsize; +GLint maxgroups; +GLuint maxSize; bool outlinemode=false; bool ibl=false; @@ -198,6 +207,8 @@ const picture* Picture; string Format; int fullWidth,fullHeight; int Width,Height; +GLuint pixels; +GLuint lastpixels; double oWidth,oHeight; int screenWidth,screenHeight; int maxTileWidth; @@ -428,7 +439,6 @@ int window; using utils::statistics; statistics S; -GLint shaderProg,shaderProgColor; GLTexture2<float,GL_FLOAT> IBLbrdfTex; GLTexture2<float,GL_FLOAT> irradiance; @@ -529,26 +539,83 @@ uint32_t ceillog2(uint32_t n) return 32-CLZ(n-1); } +void initComputeShaders() +{ + string sum1=locateFile("shaders/sum1.glsl"); + string sum2=locateFile("shaders/sum2.glsl"); + string sum3=locateFile("shaders/sum3.glsl"); + + if(sum1.empty() || sum2.empty() || sum3.empty()) + noShaders(); + + std::vector<ShaderfileModePair> shaders(1); + std::vector<std::string> shaderParams; + + shaders[0]=ShaderfileModePair(sum1.c_str(),GL_COMPUTE_SHADER); + ostringstream s; + s << "LOCAL_SIZE_X " << localsize << "u" << endl; + shaderParams.push_back(s.str().c_str()); + GLuint rc=compileAndLinkShader(shaders,shaderParams,true,false,true); + if(rc == 0) { + GPUindexing=false; // Compute shaders are unavailable. + if(settings::verbose > 2) + cout << "No compute shader support" << endl; + } else { + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT,0,&maxgroups); + maxgroups=min(1024,maxgroups/(GLint) (localsize*localsize)); + camp::sum1Shader=rc; + + shaders[0]=ShaderfileModePair(sum2.c_str(),GL_COMPUTE_SHADER); + camp::sum2Shader=compileAndLinkShader(shaders,shaderParams,true,false,true); + + shaders[0]=ShaderfileModePair(sum3.c_str(),GL_COMPUTE_SHADER); + camp::sum3Shader=compileAndLinkShader(shaders,shaderParams,true,false, + true); + } +} + +void initBlendShader() +{ + string screen=locateFile("shaders/screen.glsl"); + string blend=locateFile("shaders/blend.glsl"); + + if(screen.empty() || blend.empty()) + noShaders(); + + std::vector<ShaderfileModePair> shaders(2); + std::vector<std::string> shaderParams; + + ostringstream s,m2; + s << "ARRAYSIZE " << maxSize << "u" << endl; + shaderParams.push_back(s.str().c_str()); + m2 << "m2 " << localsize; + shaderParams.push_back(m2.str().c_str()); + if(GPUindexing) + shaderParams.push_back("GPUINDEXING"); + shaders[0]=ShaderfileModePair(screen.c_str(),GL_VERTEX_SHADER); + shaders[1]=ShaderfileModePair(blend.c_str(),GL_FRAGMENT_SHADER); + camp::blendShader=compileAndLinkShader(shaders,shaderParams,ssbo); +} + void initShaders() { Nlights=nlights == 0 ? 0 : max(Nlights,nlights); Nmaterials=max(Nmaterials,nmaterials); - shaderProg=glCreateProgram(); - - string zero=locateFile("shaders/count0.glsl"); + string zero=locateFile("shaders/zero.glsl"); string vertex=locateFile("shaders/vertex.glsl"); + string count=locateFile("shaders/count.glsl"); string fragment=locateFile("shaders/fragment.glsl"); - string blend=locateFile("shaders/blend.glsl"); string screen=locateFile("shaders/screen.glsl"); - string pre=locateFile("shaders/presum.glsl"); - string partial=locateFile("shaders/partialsum.glsl"); - if(vertex.empty() || fragment.empty() || blend.empty() || screen.empty() || - zero.empty() || pre.empty() || partial.empty()) + if(zero.empty() || vertex.empty() || fragment.empty() || screen.empty() || + count.empty()) noShaders(); - std::vector<ShaderfileModePair> shaders(1); + if(GPUindexing) + initComputeShaders(); + + std::vector<ShaderfileModePair> shaders(2); std::vector<std::string> shaderParams; if(ibl) { @@ -556,46 +623,15 @@ void initShaders() initIBL(); } -#ifdef HAVE_SSBO - if(GPUindexing) { - shaders[0]=ShaderfileModePair(pre.c_str(),GL_COMPUTE_SHADER); - GLuint rc=compileAndLinkShader(shaders,shaderParams,true,interlock,true); - if(rc == 0) { - GPUindexing=false; // Compute shaders are unavailable. - if(settings::verbose > 2) - cout << "No compute shader support" << endl; - } else { - camp::preSumShader=rc; - - ostringstream s,S; - s << "PROCESSORS " << processors << "u" << endl; - shaderParams.push_back(s.str().c_str()); - - S << "STEPSM1 " << ceillog2(processors)-1 << "u" << endl; - shaderParams.push_back(S.str().c_str()); - shaders[0]=ShaderfileModePair(partial.c_str(),GL_COMPUTE_SHADER); - camp::partialSumShader=compileAndLinkShader(shaders,shaderParams, - true,interlock,true); - } - } -#endif - string count=locateFile(GPUindexing ? "shaders/offset.glsl" : - "shaders/count.glsl"); - if(count.empty()) - noShaders(); - - shaders.push_back(ShaderfileModePair()); - shaders[0]=ShaderfileModePair(vertex.c_str(),GL_VERTEX_SHADER); #ifdef HAVE_SSBO + if(GPUindexing) + shaderParams.push_back("GPUINDEXING"); shaders[1]=ShaderfileModePair(count.c_str(),GL_FRAGMENT_SHADER); camp::countShader=compileAndLinkShader(shaders,shaderParams,true); - if(camp::countShader) { + if(camp::countShader) shaderParams.push_back("HAVE_SSBO"); - if(GPUindexing) - shaderParams.push_back("GPUINDEXING"); - } #else camp::countShader=0; #endif @@ -611,6 +647,10 @@ void initShaders() cout << "No SSBO support; order-independent transparency unavailable" << endl; + ostringstream m2; + m2 << "m2 " << localsize; + shaderParams.push_back(m2.str().c_str()); + shaders[1]=ShaderfileModePair(fragment.c_str(),GL_FRAGMENT_SHADER); shaderParams.push_back("MATERIAL"); if(orthographic) @@ -662,30 +702,38 @@ void initShaders() camp::transparentShader=compileAndLinkShader(shaders,shaderParams,ssbo, interlock); shaderParams.clear(); - if(ssbo) { - shaders[0]=ShaderfileModePair(screen.c_str(),GL_VERTEX_SHADER); - if(GPUindexing) - shaderParams.push_back("GPUINDEXING"); - else { + if(ssbo) { + if(!GPUindexing) { + shaders[0]=ShaderfileModePair(screen.c_str(),GL_VERTEX_SHADER); shaders[1]=ShaderfileModePair(zero.c_str(),GL_FRAGMENT_SHADER); camp::zeroShader=compileAndLinkShader(shaders,shaderParams,ssbo); } - - shaders[1]=ShaderfileModePair(blend.c_str(),GL_FRAGMENT_SHADER); - camp::blendShader=compileAndLinkShader(shaders,shaderParams,ssbo); + maxSize=1; + initBlendShader(); } lastshader=-1; } +void deleteComputeShaders() +{ + glDeleteProgram(camp::sum1Shader); + glDeleteProgram(camp::sum2Shader); + glDeleteProgram(camp::sum3Shader); +} + +void deleteBlendShader() +{ + glDeleteProgram(camp::blendShader); +} + void deleteShaders() { if(camp::ssbo) { - glDeleteProgram(camp::blendShader); - if(GPUindexing) { - glDeleteProgram(camp::preSumShader); - glDeleteProgram(camp::partialSumShader); - } else + deleteBlendShader(); + if(GPUindexing) + deleteComputeShaders(); + else glDeleteProgram(camp::zeroShader); glDeleteProgram(camp::countShader); } @@ -712,10 +760,13 @@ void setBuffers() camp::transparentData.Reserve(); #ifdef HAVE_SSBO - glGenBuffers(1, &camp::countBuffer); glGenBuffers(1, &camp::offsetBuffer); - if(GPUindexing) - glGenBuffers(1, &camp::sumBuffer); + glGenBuffers(1, &camp::maxBuffer); + if(GPUindexing) { + glGenBuffers(1, &camp::localSumBuffer); + glGenBuffers(1, &camp::globalSumBuffer); + } else + glGenBuffers(1, &camp::countBuffer); glGenBuffers(1, &camp::fragmentBuffer); glGenBuffers(1, &camp::depthBuffer); glGenBuffers(1, &camp::opaqueBuffer); @@ -803,6 +854,7 @@ void Export() trBeginTile(tr); remesh=true; drawscene(fullWidth,fullHeight); + gl::lastshader=-1; ++count; } while (trEndTile(tr)); if(settings::verbose > 1) @@ -955,6 +1007,16 @@ void reshape0(int width, int height) Width=width; Height=height; + static int lastWidth=1; + static int lastHeight=1; + if(View && Width*Height > 1 && (Width != lastWidth || Height != lastHeight) + && settings::verbose > 1) { + cout << "Rendering " << stripDir(Prefix) << " as " + << Width << "x" << Height << " image" << endl; + lastWidth=Width; + lastHeight=Height; + } + setProjection(); glViewport(0,0,Width,Height); if(camp::ssbo) @@ -1066,7 +1128,7 @@ void togglefitscreen() void initTimer() { gettimeofday(&lasttime,NULL); - gettimeofday(&lastframetime,NULL); + lastframetime=lasttime; } void idleFunc(void (*f)()) @@ -1102,7 +1164,7 @@ void display() bool fps=settings::verbose > 2; drawscene(Width,Height); if(fps) { - if(framecount < 10) // Measure steady-state framerate + if(framecount < 20) // Measure steady-state framerate seconds(); else { double s=seconds(); @@ -1960,10 +2022,6 @@ void glrender(const string& prefix, const picture *pic, const string& format, #ifdef HAVE_LIBGLUT setosize(); #endif - - if(View && settings::verbose > 1) - cout << "Rendering " << stripDir(prefix) << " as " - << Width << "x" << Height << " image" << endl; #endif } @@ -2069,11 +2127,8 @@ void glrender(const string& prefix, const picture *pic, const string& format, GLint val; glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE,&val); - if(GPUindexing) { - glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS,&processors); - if(processors <= 1) - GPUindexing=false; - } + if(GPUindexing) + localsize=getSetting<Int>("GPUlocalSize"); Maxmaterials=val/sizeof(Material); if(nmaterials > Maxmaterials) nmaterials=Maxmaterials; @@ -2216,67 +2271,137 @@ void registerBuffer(const std::vector<T>& buffervector, GLuint& bufferIndex, void clearCount() { glUseProgram(zeroShader); - glUniform1ui(glGetUniformLocation(zeroShader,"width"),gl::Width); gl::lastshader=zeroShader; + glUniform1ui(glGetUniformLocation(zeroShader,"width"),gl::Width); fpu_trap(false); // Work around FE_INVALID glDrawArrays(GL_TRIANGLES, 0, 3); fpu_trap(settings::trap()); glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); } +void initPartialSums() +{ + gl::gs=gl::localsize*gl::g; + gl::gs2=gl::localsize*gl::gs; + gl::processors=gl::localsize*gl::gs2; + GLuint zero=0; + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::localSumBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,(gl::processors+gl::gs2+2)*sizeof(GLuint),NULL, + GL_DYNAMIC_DRAW); + glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, + GL_UNSIGNED_BYTE,&zero); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,2,camp::localSumBuffer); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::globalSumBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,(1+gl::gs)*sizeof(GLuint),NULL, + GL_DYNAMIC_DRAW); + glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, + GL_UNSIGNED_BYTE,&zero); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,3,camp::globalSumBuffer); +} + +GLuint partialSums() +{ + GLuint fragments; + // Compute local partial sums on the GPU + glUseProgram(sum1Shader); + glUniform1ui(glGetUniformLocation(sum1Shader,"elements"),gl::pixels); + glDispatchCompute(gl::gs2,1,1); + + glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); + + glUseProgram(sum2Shader); + GLuint offset2=gl::processors+1; + glUniform1ui(glGetUniformLocation(sum2Shader,"offset2"),offset2); + glDispatchCompute(gl::gs,1,1); + + glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); + + glUseProgram(sum3Shader); + glUniform1ui(glGetUniformLocation(sum3Shader,"offset2"),offset2); + glDispatchCompute(gl::g,1,1); + + glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); + // Compute global partial sums, including number of fragments, on the CPU + GLuint *sum=(GLuint *) (glMapBuffer(GL_SHADER_STORAGE_BUFFER, + GL_READ_WRITE)); + fragments=0; + for(GLint i=1; i <= gl::gs; ++i) { + fragments += sum[i]; + sum[i]=fragments; + } + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + return fragments; +} + void refreshBuffers() { GLuint zero=0; - GLuint fragments=0; - GLuint pixels=gl::Width*gl::Height; + GLuint fragments; + gl::pixels=gl::Width*gl::Height; if(initSSBO) { glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::offsetBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER,(pixels+GPUindexing)*sizeof(GLuint), + glBufferData(GL_SHADER_STORAGE_BUFFER, + (GPUindexing ? 2:1)*gl::pixels*sizeof(GLuint), NULL,GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,1,camp::offsetBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,camp::offsetBuffer); glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, GL_UNSIGNED_BYTE,&zero); - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER,pixels*sizeof(GLuint),NULL, - GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,2,camp::countBuffer); + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::maxBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,sizeof(GLuint), + NULL,GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,1,camp::maxBuffer); glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, GL_UNSIGNED_BYTE,&zero); glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::opaqueBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER,pixels*sizeof(glm::vec4),NULL,GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,5,camp::opaqueBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,gl::pixels*sizeof(glm::vec4),NULL, + GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,6,camp::opaqueBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::opaqueDepthBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER,pixels*sizeof(GLfloat),NULL,GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,6,camp::opaqueDepthBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,gl::pixels*sizeof(GLfloat),NULL, + GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,7,camp::opaqueDepthBuffer); const GLfloat zerof=0.0; glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R32F,GL_RED,GL_FLOAT,&zerof); if(GPUindexing) { - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::sumBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER,(gl::processors+1)*sizeof(GLuint),NULL, - GL_DYNAMIC_DRAW); + double Tmin=HUGE_VAL; + GLuint G=1; + for(gl::g=2; gl::g <= gl::maxgroups; + gl::g *= 2) { + initPartialSums(); + partialSums(); + seconds(); + partialSums(); + double T=seconds(); + if(T < Tmin) { + Tmin=T; + G=gl::g; + } + } + gl::g=G; + initPartialSums(); + } else { + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,gl::pixels*sizeof(GLuint), + NULL,GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,2,camp::countBuffer); glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, GL_UNSIGNED_BYTE,&zero); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,camp::sumBuffer); } - initSSBO=false; } if(GPUindexing && gl::exporting) { - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); - glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, - GL_UNSIGNED_BYTE,&zero); - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::offsetBuffer); glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, GL_UNSIGNED_BYTE,&zero); - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::sumBuffer); + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::globalSumBuffer); } // Determine the fragment offsets @@ -2294,32 +2419,22 @@ void refreshBuffers() glEnable(GL_MULTISAMPLE); glDepthMask(GL_TRUE); // Write to depth buffer - if(GPUindexing) { // Compute partial sums directly on the GPU - glUseProgram(preSumShader); - glUniform1ui(glGetUniformLocation(preSumShader,"elements"),pixels); - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - glDispatchCompute(gl::processors,1,1); - - glUseProgram(partialSumShader); - glUniform1ui(glGetUniformLocation(partialSumShader,"elements"),pixels); - - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - glDispatchCompute(1,1,1); - - glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); - glGetBufferSubData(GL_SHADER_STORAGE_BUFFER,gl::processors*sizeof(GLuint),sizeof(GLuint),&fragments); - } else { // Compute partial sums on the CPU + if(GPUindexing) + fragments=partialSums(); + else { + // Compute partial sums on the CPU glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); - GLuint *countm1=(GLuint *) (glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY))-1; + GLuint *count=((GLuint *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, + GL_READ_ONLY)); glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::offsetBuffer); - GLuint *offset=(GLuint *) glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_WRITE_ONLY); + GLuint *offset=(GLuint *) glMapBuffer(GL_SHADER_STORAGE_BUFFER, + GL_WRITE_ONLY); - size_t Offset=0; - offset[0]=0; - for(size_t i=1; i < pixels; ++i) - offset[i]=Offset += countm1[i]; - fragments=offset[pixels-1]+countm1[pixels]; + size_t Offset=offset[0]=count[0]; + for(size_t i=1; i < gl::pixels; ++i) + offset[i]=Offset += count[i]; + fragments=Offset; glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::offsetBuffer); glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); @@ -2336,15 +2451,16 @@ void refreshBuffers() glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::fragmentBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER,maxFragments*sizeof(glm::vec4), NULL,GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,3,camp::fragmentBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,4,camp::fragmentBuffer); glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::depthBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER,maxFragments*sizeof(GLfloat), NULL,GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,4,camp::depthBuffer); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,5,camp::depthBuffer); - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::sumBuffer); + if(GPUindexing) + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::globalSumBuffer); } gl::lastshader=-1; @@ -2356,16 +2472,38 @@ void setUniforms(vertexBuffer& data, GLint shader) if(shader != gl::lastshader) { glUseProgram(shader); - gl::lastshader=shader; - if(camp::ssbo) { + if(normal) glUniform1ui(glGetUniformLocation(shader,"width"),gl::Width); - GLuint pixels=gl::Width*gl::Height; - GLuint M=GPUindexing ? pixels/gl::processors : 0; - GLuint r=pixels-M*gl::processors; - glUniform1ui(glGetUniformLocation(shader,"M"),M); + + if(camp::ssbo && GPUindexing && + (shader == transparentShader || !interlock)) { + glUniform1ui(glGetUniformLocation(shader,"pixels"),gl::pixels); + GLuint offset2=1+gl::processors; + glUniform1ui(glGetUniformLocation(shader,"offset2"),offset2); + GLuint m=GPUindexing ? gl::pixels/gl::processors : 0; + GLuint r=gl::pixels-m*gl::processors; + glUniform1ui(glGetUniformLocation(shader,"m1"),m); glUniform1ui(glGetUniformLocation(shader,"r"),r); } + } + + glUniformMatrix4fv(glGetUniformLocation(shader,"projViewMat"),1,GL_FALSE, + value_ptr(gl::projViewMat)); + + glUniformMatrix4fv(glGetUniformLocation(shader,"viewMat"),1,GL_FALSE, + value_ptr(gl::viewMat)); + if(normal) + glUniformMatrix3fv(glGetUniformLocation(shader,"normMat"),1,GL_FALSE, + value_ptr(gl::normMat)); + + if(shader == countShader) { + gl::lastshader=shader; + return; + } + + if(shader != gl::lastshader) { + gl::lastshader=shader; glUniform1ui(glGetUniformLocation(shader,"nlights"),gl::nlights); for(size_t i=0; i < gl::nlights; ++i) { @@ -2382,10 +2520,13 @@ void setUniforms(vertexBuffer& data, GLint shader) (GLfloat) gl::Diffuse[i4+2]); } - if (settings::getSetting<bool>("ibl")) { - gl::IBLbrdfTex.setUniform(glGetUniformLocation(shader,"reflBRDFSampler")); - gl::irradiance.setUniform(glGetUniformLocation(shader,"diffuseSampler")); - gl::reflTextures.setUniform(glGetUniformLocation(shader,"reflImgSampler")); + if(settings::getSetting<bool>("ibl")) { + gl::IBLbrdfTex.setUniform(glGetUniformLocation(shader, + "reflBRDFSampler")); + gl::irradiance.setUniform(glGetUniformLocation(shader, + "diffuseSampler")); + gl::reflTextures.setUniform(glGetUniformLocation(shader, + "reflImgSampler")); } } @@ -2395,15 +2536,6 @@ void setUniforms(vertexBuffer& data, GLint shader) bool copy=(gl::remesh || data.partial || !data.rendered) && !gl::copied; registerBuffer(data.materials,data.materialsBuffer,copy,GL_UNIFORM_BUFFER); glBindBufferBase(GL_UNIFORM_BUFFER,binding,data.materialsBuffer); - - glUniformMatrix4fv(glGetUniformLocation(shader,"projViewMat"),1,GL_FALSE, - value_ptr(gl::projViewMat)); - - glUniformMatrix4fv(glGetUniformLocation(shader,"viewMat"),1,GL_FALSE, - value_ptr(gl::viewMat)); - if(normal) - glUniformMatrix3fv(glGetUniformLocation(shader,"normMat"),1,GL_FALSE, - value_ptr(gl::normMat)); } void drawBuffer(vertexBuffer& data, GLint shader, bool color) @@ -2500,6 +2632,18 @@ void drawTriangle() triangleData.clear(); } +// Return the smallest power of 2 greater than or equal to n. +inline GLuint ceilpow2(GLuint n) +{ + --n; + n |= n >> 1; + n |= n >> 2; + n |= n >> 4; + n |= n >> 8; + n |= n >> 16; + return ++n; +} + void aBufferTransparency() { // Collect transparent fragments @@ -2510,21 +2654,41 @@ void aBufferTransparency() // Blend transparent fragments glDisable(GL_DEPTH_TEST); glUseProgram(blendShader); + gl::lastshader=blendShader; glUniform1ui(glGetUniformLocation(blendShader,"width"),gl::Width); - GLuint pixels=gl::Width*gl::Height; - GLuint M=GPUindexing ? pixels/gl::processors : 0; - GLuint r=pixels-M*gl::processors; - glUniform1ui(glGetUniformLocation(blendShader,"M"),M); - glUniform1ui(glGetUniformLocation(blendShader,"r"),r); + if(GPUindexing) { + glUniform1ui(glGetUniformLocation(blendShader,"pixels"),gl::pixels); + GLuint offset2=gl::processors+1; + glUniform1ui(glGetUniformLocation(blendShader,"offset2"),offset2); + GLuint m=GPUindexing ? gl::pixels/gl::processors : 0; + GLuint r=gl::pixels-m*gl::processors; + glUniform1ui(glGetUniformLocation(blendShader,"m1"),m); + glUniform1ui(glGetUniformLocation(blendShader,"r"),r); + } glUniform4f(glGetUniformLocation(blendShader,"background"), gl::Background[0],gl::Background[1],gl::Background[2], gl::Background[3]); - gl::lastshader=blendShader; fpu_trap(false); // Work around FE_INVALID glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); glDrawArrays(GL_TRIANGLES,0,3); fpu_trap(settings::trap()); transparentData.clear(); + + if(gl::maxSize > 0) { + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::maxBuffer); + GLuint *p=(GLuint *) glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_WRITE); + gl::maxSize=p[0]; + p[0]=0; + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + if(gl::maxSize > 0) { + gl::maxSize=ceilpow2(gl::maxSize); + gl::deleteBlendShader(); + gl::initBlendShader(); + } + if(GPUindexing) + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::globalSumBuffer); + } + glEnable(GL_DEPTH_TEST); } |