summaryrefslogtreecommitdiff
path: root/graphics/asymptote/base/shaders/sum3.glsl
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/asymptote/base/shaders/sum3.glsl')
-rw-r--r--graphics/asymptote/base/shaders/sum3.glsl85
1 files changed, 63 insertions, 22 deletions
diff --git a/graphics/asymptote/base/shaders/sum3.glsl b/graphics/asymptote/base/shaders/sum3.glsl
index 8e6e94bf45..4ee5203060 100644
--- a/graphics/asymptote/base/shaders/sum3.glsl
+++ b/graphics/asymptote/base/shaders/sum3.glsl
@@ -1,11 +1,19 @@
-layout(local_size_x=LOCAL_SIZE_X) in;
+layout(local_size_x=LOCALSIZE) in;
+
+const uint groupSize=LOCALSIZE*BLOCKSIZE;
-uniform uint offset2;
uniform uint final;
-layout(binding=2, std430) buffer localSumBuffer
+layout(binding=0, std430) buffer offsetBuffer
+{
+ uint maxDepth;
+ uint offset[];
+};
+
+layout(binding=2, std430) buffer countBuffer
{
- uint localSum[];
+ uint maxSize;
+ uint count[];
};
layout(binding=3, std430) buffer globalSumBuffer
@@ -13,27 +21,60 @@ layout(binding=3, std430) buffer globalSumBuffer
uint globalSum[];
};
-layout(binding=7, std430) buffer opaqueDepthBuffer
+layout(binding=8, std430) buffer feedbackBuffer
{
- uint maxSize;
- float opaqueDepth[];
+ uint size;
+ uint fragments;
};
-void main(void)
+shared uint shuffle[groupSize+LOCALSIZE-1u];
+shared uint groupSum[LOCALSIZE+1u];
+
+void main()
{
- uint id=gl_GlobalInvocationID.x;
- uint row=offset2+LOCAL_SIZE_X*id;
- uint stop=row+LOCAL_SIZE_X;
-
- uint Sum=localSum[row];
- for(uint i=row+1u; i < stop; ++i)
- localSum[i]=Sum += localSum[i];
-
- uint id1=id+1u;
- if(id1 < gl_WorkGroupSize.x*gl_NumWorkGroups.x)
- globalSum[id1]=Sum;
- else {
- globalSum[0]=maxSize;
- globalSum[id1]=Sum+localSum[offset2-1u]+localSum[final];
+ uint id=gl_LocalInvocationID.x;
+
+// avoid bank conflicts and coalesce global memory accesses
+ uint dataOffset=gl_WorkGroupID.x*groupSize+id;
+ uint shuffleOffset=id/BLOCKSIZE+id;
+ const uint stride=LOCALSIZE/BLOCKSIZE+LOCALSIZE;
+ for(uint i=0u; i < BLOCKSIZE; i++)
+ shuffle[shuffleOffset+i*stride]=count[dataOffset+i*LOCALSIZE];
+
+ barrier();
+
+ uint Offset=id*BLOCKSIZE+id;
+ uint stop=Offset+BLOCKSIZE;
+
+ uint sum=0u;
+ for(uint i=Offset; i < stop; ++i)
+ shuffle[i]=sum += shuffle[i];
+
+ if(id == 0u)
+ groupSum[0u]=0u;
+ groupSum[id+1u]=sum;
+ barrier();
+
+ // Apply Hillis-Steele algorithm over all sums in workgroup
+ for(uint shift=1u; shift < LOCALSIZE; shift *= 2u) {
+ uint read;
+ if(shift <= id)
+ read=groupSum[id]+groupSum[id-shift];
+ barrier();
+ if(shift <= id)
+ groupSum[id]=read;
+ barrier();
+ }
+
+ uint groupOffset=globalSum[gl_WorkGroupID.x];
+ for(uint i=0u; i < BLOCKSIZE; ++i)
+ offset[dataOffset+i*LOCALSIZE]=shuffle[shuffleOffset+i*stride]+
+ groupSum[(i*LOCALSIZE+id)/BLOCKSIZE]+groupOffset;
+
+ uint diff=final-dataOffset;
+ if(diff < groupSize && diff % LOCALSIZE == 0) {
+ size=maxDepth;
+ maxDepth=0u;
+ fragments=offset[final+1u]=offset[final];
}
}