diff options
Diffstat (limited to 'graphics/asymptote/glrender.cc')
-rw-r--r-- | graphics/asymptote/glrender.cc | 317 |
1 files changed, 146 insertions, 171 deletions
diff --git a/graphics/asymptote/glrender.cc b/graphics/asymptote/glrender.cc index 9b60846784..18d72d5c4d 100644 --- a/graphics/asymptote/glrender.cc +++ b/graphics/asymptote/glrender.cc @@ -88,18 +88,21 @@ GLint zeroShader; GLint compressShader; GLint sum1Shader; GLint sum2Shader; +GLint sum2fastShader; GLint sum3Shader; +GLuint fragments; + GLuint offsetBuffer; GLuint indexBuffer; GLuint elementsBuffer; GLuint countBuffer; -GLuint localSumBuffer; GLuint globalSumBuffer; GLuint fragmentBuffer; GLuint depthBuffer; GLuint opaqueBuffer; GLuint opaqueDepthBuffer; +GLuint feedbackBuffer; bool ssbo; bool interlock; @@ -167,11 +170,11 @@ GLint gs2; GLint gs; GLint g; GLuint processors; -GLuint localsize; -GLuint lastlocalsize; -GLint maxgroups; +GLuint localSize; +GLuint blockSize; +GLuint groupSize; +//GLint maxgroups; GLuint maxSize; -GLuint lastSize; bool outlinemode=false; bool ibl=false; @@ -543,30 +546,38 @@ void initComputeShaders() { string sum1=locateFile("shaders/sum1.glsl"); string sum2=locateFile("shaders/sum2.glsl"); + string sum2fast=locateFile("shaders/sum2fast.glsl"); string sum3=locateFile("shaders/sum3.glsl"); - if(sum1.empty() || sum2.empty() || sum3.empty()) + if(sum1.empty() || sum2.empty() || sum2fast.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; + ostringstream s,s2; + s << "LOCALSIZE " << gl::localSize << "u" << endl; shaderParams.push_back(s.str().c_str()); + s2 << "BLOCKSIZE " << gl::blockSize << "u" << endl; + shaderParams.push_back(s2.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)); +// 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); + camp::sum2Shader=compileAndLinkShader(shaders,shaderParams,true,false, + true); + + shaders[0]=ShaderfileModePair(sum2fast.c_str(),GL_COMPUTE_SHADER); + camp::sum2fastShader=compileAndLinkShader(shaders,shaderParams,true,false, + true); shaders[0]=ShaderfileModePair(sum3.c_str(),GL_COMPUTE_SHADER); camp::sum3Shader=compileAndLinkShader(shaders,shaderParams,true,false, @@ -701,7 +712,7 @@ void initShaders() shaderParams.pop_back(); shaderParams.push_back("GENERAL"); - if(Mode == 2) + if(Mode != 0) shaderParams.push_back("WIREFRAME"); camp::generalShader[0]=compileAndLinkShader(shaders,shaderParams,ssbo, interlock); @@ -717,10 +728,10 @@ void initShaders() if(ssbo) { if(GPUindexing) shaderParams.push_back("GPUINDEXING"); - shaders[0]=ShaderfileModePair(screen.c_str(),GL_VERTEX_SHADER); + shaders[0]=ShaderfileModePair(screen.c_str(),GL_VERTEX_SHADER); shaders[1]=ShaderfileModePair(compress.c_str(),GL_FRAGMENT_SHADER); camp::compressShader=compileAndLinkShader(shaders,shaderParams,ssbo); - if(GPUindexing) + if(GPUindexing) shaderParams.pop_back(); else { shaders[1]=ShaderfileModePair(zero.c_str(),GL_FRAGMENT_SHADER); @@ -736,6 +747,7 @@ void deleteComputeShaders() { glDeleteProgram(camp::sum1Shader); glDeleteProgram(camp::sum2Shader); + glDeleteProgram(camp::sum2fastShader); glDeleteProgram(camp::sum3Shader); } @@ -765,12 +777,11 @@ void deleteShaders() glDeleteProgram(camp::pixelShader); } -void resizeBlendShader() +void resizeBlendShader(uint maxsize) { - gl::maxSize=ceilpow2(gl::maxSize); + gl::maxSize=ceilpow2(maxsize); gl::deleteBlendShader(); gl::initBlendShader(); - gl::lastSize=gl::maxSize; } void setBuffers() @@ -788,10 +799,10 @@ void setBuffers() #ifdef HAVE_SSBO glGenBuffers(1, &camp::offsetBuffer); if(GPUindexing) { - glGenBuffers(1, &camp::localSumBuffer); glGenBuffers(1, &camp::globalSumBuffer); - } else - glGenBuffers(1, &camp::countBuffer); + glGenBuffers(1, &camp::feedbackBuffer); + } + glGenBuffers(1, &camp::countBuffer); if(GPUcompress) { glGenBuffers(1, &camp::indexBuffer); glGenBuffers(1, &camp::elementsBuffer); @@ -2155,7 +2166,7 @@ void glrender(const string& prefix, const picture *pic, const string& format, #if defined(HAVE_COMPUTE_SHADER) && !defined(HAVE_LIBOSMESA) GPUindexing=getSetting<bool>("GPUindexing"); - GPUcompress=NVIDIA() || getSetting<bool>("GPUcompress"); + GPUcompress=getSetting<bool>("GPUcompress"); #else GPUindexing=false; GPUcompress=false; @@ -2164,8 +2175,11 @@ void glrender(const string& prefix, const picture *pic, const string& format, GLint val; glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE,&val); - if(GPUindexing) - lastlocalsize=localsize=getSetting<Int>("GPUlocalSize"); + if(GPUindexing) { + gl::localSize=getSetting<Int>("GPUlocalSize"); + gl::blockSize=getSetting<Int>("GPUblockSize"); + gl::groupSize=gl::localSize*gl::blockSize; + } Maxmaterials=val/sizeof(Material); if(nmaterials > Maxmaterials) nmaterials=Maxmaterials; @@ -2328,108 +2342,108 @@ void compressCount() glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); } -void initPartialSums() +void partialSums(bool readSize=false) { - 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_R32UI,GL_RED_INTEGER, - GL_UNSIGNED_INT,&zero); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,2,camp::localSumBuffer); - - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::globalSumBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER,(gl::gs+1)*sizeof(GLuint),NULL, - GL_DYNAMIC_DRAW); - glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R32UI,GL_RED_INTEGER, - GL_UNSIGNED_INT,&zero); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,3,camp::globalSumBuffer); -} - -GLuint partialSums(bool readSize=false) -{ - GLuint fragments; - // Compute local partial sums on the GPU + // Compute partial sums on the GPU glUseProgram(sum1Shader); - glUniform1ui(glGetUniformLocation(sum1Shader,"elements"),gl::elements); - - 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); + glDispatchCompute(gl::g,1,1); - glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); + if(gl::elements <= gl::groupSize*gl::groupSize) + glUseProgram(sum2fastShader); + else { + glUseProgram(sum2Shader); + glUniform1ui(glGetUniformLocation(sum2Shader,"blockSize"), + gl::ceilquotient(gl::g,gl::localSize)); + } + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); + glDispatchCompute(1,1,1); glUseProgram(sum3Shader); - glUniform1ui(glGetUniformLocation(sum3Shader,"offset2"),offset2); - glUniform1ui(glGetUniformLocation(sum3Shader,"final"),offset2+gl::gs2); + glUniform1ui(glGetUniformLocation(sum3Shader,"final"),gl::elements-1); + glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT); 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); +void resizeFragmentBuffer() +{ + if(GPUindexing) { + glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::feedbackBuffer); + GLuint *feedback=(GLuint *) glMapBuffer(GL_SHADER_STORAGE_BUFFER,GL_READ_ONLY); - if(readSize) { - gl::maxSize=sum[0]; - sum[0]=0; - if(gl::maxSize > gl::lastSize) - gl::resizeBlendShader(); + GLuint maxDepth=feedback[0]; + if(maxDepth > gl::maxSize) + gl::resizeBlendShader(maxDepth); + + fragments=feedback[1]; + glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); } - fragments=sum[1]; - for(GLint i=2; i < gl::gs; ++i) - sum[i]=fragments += sum[i]; - fragments += sum[gl::gs]; + if(fragments > maxFragments) { + // Initialize the alpha buffer + maxFragments=11*fragments/10; + 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,4,camp::fragmentBuffer); + - glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::depthBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,maxFragments*sizeof(GLfloat), + NULL,GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,5,camp::depthBuffer); - return fragments; + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::feedbackBuffer); + } } void refreshBuffers() { GLuint zero=0; - GLuint fragments; - gl::pixels=gl::Width*gl::Height; + gl::pixels=(gl::Width+1)*(gl::Height+1); if(initSSBO) { gl::processors=1; + GLuint Pixels; + if(GPUindexing) { + GLuint G=gl::ceilquotient(gl::pixels,gl::groupSize); + Pixels=gl::groupSize*G; + + GLuint globalSize=gl::localSize*gl::ceilquotient(G,gl::localSize); + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::globalSumBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,globalSize*sizeof(GLuint),NULL, + GL_DYNAMIC_READ); + glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R32UI,GL_RED_INTEGER, + GL_UNSIGNED_INT,&zero); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,3,camp::globalSumBuffer); + } else Pixels=gl::pixels; + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::offsetBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER, - (GPUindexing ? 2 : 1)*(gl::pixels+1)*sizeof(GLuint), + glBufferData(GL_SHADER_STORAGE_BUFFER,(Pixels+2)*sizeof(GLuint), NULL,GL_DYNAMIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER,0,camp::offsetBuffer); + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,(Pixels+2)*sizeof(GLuint), + NULL,GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,2,camp::countBuffer); + if(GPUcompress) { glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::indexBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER,gl::pixels*sizeof(GLuint), NULL,GL_DYNAMIC_DRAW); glBindBufferBase(GL_SHADER_STORAGE_BUFFER,1,camp::indexBuffer); - glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R32UI,GL_RED_INTEGER, - GL_UNSIGNED_INT,&zero); GLuint one=1; glBindBuffer(GL_ATOMIC_COUNTER_BUFFER,camp::elementsBuffer); glBufferData(GL_ATOMIC_COUNTER_BUFFER,sizeof(GLuint),&one, GL_DYNAMIC_DRAW); glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER,0,camp::elementsBuffer); - } - - if(!GPUindexing) { - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); - glBufferData(GL_SHADER_STORAGE_BUFFER,(gl::pixels+1)*sizeof(GLuint), - NULL,GL_DYNAMIC_DRAW); - glBindBufferBase(GL_SHADER_STORAGE_BUFFER,2,camp::countBuffer); - } + } else + glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R8UI,GL_RED_INTEGER, + GL_UNSIGNED_BYTE,&zero); // Clear the count buffer glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::opaqueBuffer); glBufferData(GL_SHADER_STORAGE_BUFFER,gl::pixels*sizeof(glm::vec4),NULL, @@ -2443,10 +2457,25 @@ void refreshBuffers() 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); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::feedbackBuffer); + glBufferData(GL_SHADER_STORAGE_BUFFER,2*sizeof(GLuint),NULL, + GL_DYNAMIC_DRAW); + glBindBufferBase(GL_SHADER_STORAGE_BUFFER,8,camp::feedbackBuffer); + + glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::feedbackBuffer); + initSSBO=false; } // Determine the fragment offsets + if(gl::exporting && GPUindexing && !GPUcompress) { + 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::feedbackBuffer); + } + if(!interlock) { drawBuffer(material1Data,countShader); drawBuffer(materialData,countShader); @@ -2462,7 +2491,6 @@ void refreshBuffers() if(GPUcompress) { compressCount(); - GLuint *p=(GLuint *) glMapBuffer(GL_ATOMIC_COUNTER_BUFFER,GL_READ_WRITE); gl::elements=GPUindexing ? p[0] : p[0]-1; p[0]=1; @@ -2471,52 +2499,37 @@ void refreshBuffers() } else gl::elements=gl::pixels; - if(initSSBO) { - if(GPUindexing) { - double Tmin=HUGE_VAL; - GLuint G=1; - GLuint twos3=2*gl::localsize*gl::localsize*gl::localsize; - - if(twos3 > gl::elements) { - gl::localsize=1; - twos3=2; - } else gl::localsize=settings::getSetting<Int>("GPUlocalSize"); - - if(gl::localsize != gl::lastlocalsize) { - gl::deleteComputeShaders(); - gl::initComputeShaders(); - gl::lastlocalsize=gl::localsize; - } + if(GPUindexing) { + gl::g=gl::ceilquotient(gl::elements,gl::groupSize); + gl::elements=gl::groupSize*gl::g; - GLint stop=min(gl::maxgroups,(GLint) (gl::elements/twos3)); - for(gl::g=2; gl::g <= stop; gl::g *= 2) { - initPartialSums(); - partialSums(); - seconds(); + if(settings::verbose > 3) { + static bool first=true; + if(first) { partialSums(); - double T=seconds(); - if(T < Tmin) { - Tmin=T; - G=gl::g; - } + first=false; } - gl::g=G; - initPartialSums(); + unsigned int N=10000; + seconds(); + for(unsigned int i=0; i < N; ++i) + partialSums(); + glFinish(); + double T=seconds()/N; + cout << "elements=" << gl::elements << endl; + cout << "Tmin (ms)=" << T*1e3 << endl; + cout << "Megapixels/second=" << gl::elements/T/1e6 << endl; } - initSSBO=false; - } - if(GPUindexing) - fragments=partialSums(true); - else { + partialSums(true); + } else { size_t size=gl::elements*sizeof(GLuint); // Compute partial sums on the CPU glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); GLuint *p=(GLuint *) glMapBufferRange(GL_SHADER_STORAGE_BUFFER, - 0,size+sizeof(GLuint), + 0,size+sizeof(GLuint), GL_MAP_READ_BIT); - gl::maxSize=p[0]; + GLuint maxsize=p[0]; GLuint *count=p+1; glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::offsetBuffer); @@ -2535,36 +2548,16 @@ void refreshBuffers() glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); glUnmapBuffer(GL_SHADER_STORAGE_BUFFER); - if(gl::exporting && !GPUindexing) { - GLuint zero=0; + if(gl::exporting) { glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::countBuffer); glClearBufferData(GL_SHADER_STORAGE_BUFFER,GL_R32UI,GL_RED_INTEGER, GL_UNSIGNED_INT,&zero); } else clearCount(); - if(gl::maxSize > gl::lastSize) - gl::resizeBlendShader(); - } - - if(fragments > maxFragments) { - // Initialize the alpha buffer - maxFragments=11*fragments/10; - 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,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,5,camp::depthBuffer); - - if(GPUindexing) - glBindBuffer(GL_SHADER_STORAGE_BUFFER,camp::globalSumBuffer); + if(maxsize > gl::maxSize) + gl::resizeBlendShader(maxsize); } - gl::lastshader=-1; } @@ -2577,18 +2570,6 @@ void setUniforms(vertexBuffer& data, GLint shader) if(normal) glUniform1ui(glGetUniformLocation(shader,"width"),gl::Width); - - if(camp::ssbo && GPUindexing && - (shader == transparentShader || !interlock)) { - GLuint offset2=1+gl::processors; - glUniform1ui(glGetUniformLocation(shader,"elements"),gl::elements); - glUniform1ui(glGetUniformLocation(shader,"offset2"),offset2); - GLuint m=gl::elements/gl::processors; - GLuint r=gl::elements-m*gl::processors; - glUniform1ui(glGetUniformLocation(shader,"m1"),m); - glUniform1ui(glGetUniformLocation(shader,"m2"),gl::localsize); - glUniform1ui(glGetUniformLocation(shader,"r"),r); - } } glUniformMatrix4fv(glGetUniformLocation(shader,"projViewMat"),1,GL_FALSE, @@ -2747,16 +2728,6 @@ void aBufferTransparency() glUseProgram(blendShader); gl::lastshader=blendShader; glUniform1ui(glGetUniformLocation(blendShader,"width"),gl::Width); - if(GPUindexing) { - GLuint offset2=gl::processors+1; - glUniform1ui(glGetUniformLocation(blendShader,"elements"),gl::elements); - glUniform1ui(glGetUniformLocation(blendShader,"offset2"),offset2); - GLuint m=gl::elements/gl::processors; - GLuint r=gl::elements-m*gl::processors; - glUniform1ui(glGetUniformLocation(blendShader,"m1"),m); - glUniform1ui(glGetUniformLocation(blendShader,"m2"),gl::localsize); - glUniform1ui(glGetUniformLocation(blendShader,"r"),r); - } glUniform4f(glGetUniformLocation(blendShader,"background"), gl::Background[0],gl::Background[1],gl::Background[2], gl::Background[3]); @@ -2792,7 +2763,10 @@ void drawBuffers() if(camp::ssbo) { if(transparent) { refreshBuffers(); - if(!interlock) gl::copied=true; + if(!interlock) { + resizeFragmentBuffer(); + gl::copied=true; + } } } @@ -2804,6 +2778,7 @@ void drawBuffers() if(transparent) { gl::copied=true; + if(interlock) resizeFragmentBuffer(); drawTransparent(); } Opaque=0; |