diff options
Diffstat (limited to 'BuddhaTest/Shaders/BuddhaCompute.glsl')
-rw-r--r-- | BuddhaTest/Shaders/BuddhaCompute.glsl | 173 |
1 files changed, 133 insertions, 40 deletions
diff --git a/BuddhaTest/Shaders/BuddhaCompute.glsl b/BuddhaTest/Shaders/BuddhaCompute.glsl index bca9025..b1ce2bc 100644 --- a/BuddhaTest/Shaders/BuddhaCompute.glsl +++ b/BuddhaTest/Shaders/BuddhaCompute.glsl @@ -2,25 +2,60 @@ //#version 430
//layout (local_size_x = 1024) in; //to be safe, we limit our local work group size to 1024. That's the minimum a GL 4.3 capable driver must support.
-layout(std430, binding=2) buffer renderedDataRed
+layout(std430, binding=2) restrict buffer renderedDataRed
{
- uint counts_SSBORed[];
+ restrict uint counts_SSBORed[];
};
-layout(std430, binding=3) buffer renderedDataGreen
+layout(std430, binding=3) restrict buffer renderedDataGreen
{
- uint counts_SSBOGreen[];
+ restrict uint counts_SSBOGreen[];
};
-layout(std430, binding=4) buffer renderedDataBlue
+layout(std430, binding=4) restrict buffer renderedDataBlue
{
- uint counts_SSBOBlue[];
+ restrict uint counts_SSBOBlue[];
+};
+layout(std430, binding=5) restrict buffer statusBuffer
+{
+ restrict uint individualState[];
};
uniform uint width;
uniform uint height;
-uniform uint iterationCount;
uniform uvec3 orbitLength;
+uniform uint iterationsPerDispatch;
+
+void getIndividualState(in uint CellID, out vec2 offset, out vec2 coordinates, out uint phase, out uint orbitNumber, out uint doneIterations)
+{
+ uint startIndex = 7*CellID;
+ uint x = individualState[startIndex];
+ uint y = individualState[startIndex+1];
+ phase = individualState[startIndex+2];
+ orbitNumber = individualState[startIndex+3];
+ doneIterations = individualState[startIndex+4];
+ uint offx = individualState[startIndex+5];
+ uint offy = individualState[startIndex+6];
+ coordinates = vec2(uintBitsToFloat(x),uintBitsToFloat(y));
+ offset = vec2(uintBitsToFloat(offx),uintBitsToFloat(offy));
+}
+
+void setIndividualState(in uint CellID, in vec2 offset, in vec2 coordinates, in uint phase, in uint orbitNumber, in uint doneIterations)
+{
+ uint startIndex = 7*CellID;
+ uint x=floatBitsToUint(coordinates.x);
+ uint y=floatBitsToUint(coordinates.y);
+ uint offx = floatBitsToUint(offset.x);
+ uint offy = floatBitsToUint(offset.y);
+ atomicExchange(individualState[startIndex],x);
+ atomicExchange(individualState[startIndex+1],y);
+ atomicExchange(individualState[startIndex+2],phase);
+ atomicExchange(individualState[startIndex+3],orbitNumber);
+ atomicExchange(individualState[startIndex+4],doneIterations);
+ atomicExchange(individualState[startIndex+5],offx);
+ atomicExchange(individualState[startIndex+6],offy);
+}
+
void addToColorOfCell(uvec2 cell, uvec3 toAdd)
{
uint firstIndex = (cell.x + cell.y * width);
@@ -59,7 +94,7 @@ vec2 compSqr(in vec2 v) return vec2(v.x*v.x-v.y*v.y, 2.0*v.x*v.y);
}
-float isInMainCardioid(vec2 v)
+bool isInMainCardioid(vec2 v)
{
/*
The condition that a point c is in the main cardioid is that its orbit has
@@ -117,10 +152,10 @@ float isInMainCardioid(vec2 v) vec2 z = vec2(1.0,0.0)-4.0*v;
float zNormSqr = dot(z,z);
float rhsSqrt = 0.5*zNormSqr - z.x;
- return step(rhsSqrt*rhsSqrt,zNormSqr);
+ return rhsSqrt*rhsSqrt<zNormSqr;
}
-float isInMainBulb(vec2 v)
+bool isInMainBulb(vec2 v)
{
//The condition for this is that f(f(z)) = z
//where f(z) = z*z+v
@@ -131,60 +166,66 @@ float isInMainBulb(vec2 v) //Well, after a bit of magic one finds out it's a circle around -1, radius 1/4.
vec2 shifted = v + vec2(1,0);
float sqrRadius = dot(shifted,shifted);
- return step(sqrRadius,0.062499999);
+ return sqrRadius<0.062499999;
}
vec2 getStartValue(uint seed, uint yDecoupler)
{
uint hash = seed;
- vec2 retval = vec2(0);
- for(int i = 0; i < 5; ++i)
+ for(uint i = 0; i < 5;++i)
{
float x = hash1(hash,hash);
hash = (hash ^ intHash(yDecoupler));
float y = hash1(hash,hash);
vec2 random = vec2(x,y);
vec2 point = vec2(random.x * 3.5-2.5,random.y*1.55);
- float useThisPoint =1.0-(isInMainBulb(point) + isInMainCardioid(point));
- retval = mix(retval,point,useThisPoint);
+ if(!(isInMainBulb(point) || isInMainCardioid(point)))
+ return point;
}
- return retval;
+ return vec2(0);
}
-bool isGoingToBeDrawn(vec2 offset)
+bool isGoingToBeDrawn(in vec2 offset, in uint totalIterations, inout vec2 lastVal, inout uint iterationsLeftThisFrame, inout uint doneIterations, out bool result)
{
- vec2 val = vec2(0);
- uint limit = orbitLength.x > orbitLength.y ? orbitLength.x : orbitLength.y;
- limit = limit > orbitLength.z ? limit : orbitLength.z;
- for(uint i = 0; i < limit;++i)
+ uint endCount = doneIterations + iterationsLeftThisFrame > totalIterations ? totalIterations : doneIterations + iterationsLeftThisFrame;
+ for(uint i = doneIterations; i < endCount;++i)
{
- val = compSqr(val) + offset;
- if(dot(val,val) > 4.0)
+ lastVal = compSqr(lastVal) + offset;
+ if(dot(lastVal,lastVal) > 4.0)
{
+ result = true;
+ iterationsLeftThisFrame -= i+1-doneIterations;
+ doneIterations = i+1;
return true;
}
}
- return false;
+ doneIterations = endCount;
+ iterationsLeftThisFrame = 0;
+ result = false;
+ return endCount == totalIterations;
}
-void drawOrbit(vec2 offset)
+bool drawOrbit(in vec2 offset, in uint totalIterations, inout vec2 lastVal, inout uint iterationsLeftThisFrame, inout uint doneIterations)
{
- vec2 val = vec2(0);
- uint limit = orbitLength.x > orbitLength.y ? orbitLength.x : orbitLength.y;
- limit = limit > orbitLength.z ? limit : orbitLength.z;
- for(uint i = 0; i < limit;++i)
+ uint endCount = doneIterations + iterationsLeftThisFrame > totalIterations ? totalIterations : doneIterations + iterationsLeftThisFrame;
+ for(uint i = doneIterations; i < endCount;++i)
{
- val = compSqr(val) + offset;
- if(dot(val,val) > 20.0)
+ lastVal = compSqr(lastVal) + offset;
+ if(dot(lastVal,lastVal) > 20.0)
{
- return;
+ iterationsLeftThisFrame -= i+1-doneIterations;
+ doneIterations = i+1;
+ return true; //done.
}
- if(val.x > -2.5 && val.x < 1.0 && val.y > -1.0 && val.y < 1.0)
+ if(lastVal.x > -2.5 && lastVal.x < 1.0 && lastVal.y > -1.0 && lastVal.y < 1.0)
{
- addToColorAt(val,uvec3(i < orbitLength.r,i < orbitLength.g,i < orbitLength.b));
+ addToColorAt(lastVal,uvec3(i < orbitLength.r,i < orbitLength.g,i < orbitLength.b));
}
}
+ doneIterations = endCount;
+ iterationsLeftThisFrame = 0;
+ return endCount == totalIterations;
}
void main() {
@@ -193,12 +234,64 @@ void main() { uvec3 totalWorkersPerDimension = gl_WorkGroupSize * gl_NumWorkGroups;
uint totalWorkers = totalWorkersPerDimension.x*totalWorkersPerDimension.y*totalWorkersPerDimension.z;
- uint seed = iterationCount * totalWorkers + gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*totalWorkersPerDimension.x + gl_GlobalInvocationID.z*(totalWorkersPerDimension.x * totalWorkersPerDimension.y);
- uint yDecoupler = iterationCount;
- vec2 offset = getStartValue(seed, yDecoupler);
+ //TODO: Check this once I've had some sleep. Anyhow, I'm using 1D, so y and z components globalInfocationID should be zero anyhow.
+ uint uniqueWorkerID = gl_GlobalInvocationID.x + gl_GlobalInvocationID.y*totalWorkersPerDimension.x + gl_GlobalInvocationID.z*(totalWorkersPerDimension.x * totalWorkersPerDimension.y);
+
+ uint totalIterations = orbitLength.x > orbitLength.y ? orbitLength.x : orbitLength.y;
+ totalIterations = totalIterations > orbitLength.z ? totalIterations : orbitLength.z;
+
+ //getIndividualState(in uint CellID, out vec2 coordinates, out uint phase, out uint remainingIterations)
+ vec2 lastPosition;
+ uint phase;
+ uint doneIterations;
+ uint orbitNumber;
+ vec2 offset;
+ //getIndividualState(in uint CellID, out vec2 offset, out vec2 coordinates, out uint phase, out uint orbitNumber, out uint doneIterations)
+ getIndividualState(uniqueWorkerID, offset, lastPosition, phase, orbitNumber, doneIterations);
+ uint iterationsLeftToDo = iterationsPerDispatch;
+ while(iterationsLeftToDo != 0)
+ {
+ if(phase == 0)
+ {
+ //new orbit:
+ uint seed = orbitNumber * totalWorkers + uniqueWorkerID;
+ uint yDecoupler = orbitNumber;
+ offset = getStartValue(seed, yDecoupler);
+ lastPosition = vec2(0);
+ phase = 1;
+ doneIterations = 0;
+ }
+ if(phase == 1)
+ {
+ //check if this orbit is going to be drawn
+ bool result;
+ if(isGoingToBeDrawn(offset,totalIterations, lastPosition, iterationsLeftToDo, doneIterations , result))
+ {
+ if(result)
+ {
+ //on to step 2: drawing
+ phase = 2;
+ lastPosition = vec2(0);
+ doneIterations = 0;
+ }
+ else
+ {
+ //back to step 0
+ ++orbitNumber;
+ phase = 0;
+ }
+ }
+ }
+ else if(phase == 2)
+ {
+ if(drawOrbit(offset, totalIterations, lastPosition, iterationsLeftToDo, doneIterations))
+ {
+ ++orbitNumber;
+ phase = 0;
+ }
+ }
+ }
- if(!isGoingToBeDrawn(offset))
- return;
- drawOrbit(offset);
+ setIndividualState(uniqueWorkerID, offset, lastPosition, phase, orbitNumber, doneIterations);
}
|