diff options
author | Andreas Grois <andi@grois.info> | 2018-03-15 22:34:52 +0100 |
---|---|---|
committer | Andreas Grois <andi@grois.info> | 2018-03-15 22:34:52 +0100 |
commit | bb9b7d23a1ca8e2afa8c8636d7312adc700d9a34 (patch) | |
tree | b30bc01efe728a8b7887061b02af8e4a5af9f770 | |
parent | af0d5f4988bf94c4bf918b306f72f8604395715b (diff) |
Fix endless loop in shader and make framerate adaptive
It seems forcing points outside the cardioid and bulb with a bad random
generator can take really long...
Also, now framerate adjusts based on time it takes to render frames.
-rw-r--r-- | BuddhaTest/Shaders/BuddhaCompute.glsl | 14 | ||||
-rw-r--r-- | BuddhaTest/include/Helpers.h | 26 | ||||
-rw-r--r-- | BuddhaTest/src/BuddhaTest.cpp | 21 | ||||
-rw-r--r-- | BuddhaTest/src/Helpers.cpp | 4 |
4 files changed, 53 insertions, 12 deletions
diff --git a/BuddhaTest/Shaders/BuddhaCompute.glsl b/BuddhaTest/Shaders/BuddhaCompute.glsl index fcc9010..26c7ad0 100644 --- a/BuddhaTest/Shaders/BuddhaCompute.glsl +++ b/BuddhaTest/Shaders/BuddhaCompute.glsl @@ -172,18 +172,18 @@ bool isInMainBulb(vec2 v) vec2 getStartValue(uint seed, uint yDecoupler)
{
uint hash = seed;
- bool pointUnusable;
- vec2 point;
- do
+
+ 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);
- point = vec2(random.x * 3.5-2.5,random.y*1.55);
- pointUnusable = (isInMainBulb(point) || isInMainCardioid(point));
- }while(pointUnusable);
- return point;
+ vec2 point = vec2(random.x * 3.5-2.5,random.y*1.55);
+ if(!(isInMainBulb(point) || isInMainCardioid(point)))
+ return point;
+ }
+ return vec2(0);
}
bool isGoingToBeDrawn(in vec2 offset, in uint totalIterations, inout vec2 lastVal, inout uint iterationsLeftThisFrame, inout uint doneIterations, out bool result)
diff --git a/BuddhaTest/include/Helpers.h b/BuddhaTest/include/Helpers.h index fc63103..76f790b 100644 --- a/BuddhaTest/include/Helpers.h +++ b/BuddhaTest/include/Helpers.h @@ -46,7 +46,7 @@ namespace Helpers unsigned int globalWorkGroupSizeY = 1;
unsigned int globalWorkGroupSizeZ = 1;
- unsigned int iterationsPerFrame = 10;
+ unsigned int targetFrameRate = 60;
std::string pngFilename = "";
double pngGamma = 1.0;
@@ -57,4 +57,28 @@ namespace Helpers bool CheckValidity();
bool ParseCommandLine(int argc, char * argv[]);
};
+
+ template<typename ValueType, typename TimeType>
+ class PIDController
+ {
+ public:
+ PIDController(ValueType prop, ValueType diff, ValueType integral) : propFactor(prop), diffFactor(diff), intFactor(integral) {}
+
+ ValueType Update(TimeType dT, ValueType Error)
+ {
+ errorSum += Error * dT;
+ const auto differential{(Error - lastError)/dT};
+ lastError = Error;
+ return Error * propFactor + errorSum * intFactor + differential * diffFactor;
+ }
+
+ protected:
+ ValueType propFactor{};
+ ValueType diffFactor{};
+ ValueType intFactor{};
+
+ private:
+ ValueType errorSum{};
+ ValueType lastError{};
+ };
}
diff --git a/BuddhaTest/src/BuddhaTest.cpp b/BuddhaTest/src/BuddhaTest.cpp index 67971ea..88f9c9b 100644 --- a/BuddhaTest/src/BuddhaTest.cpp +++ b/BuddhaTest/src/BuddhaTest.cpp @@ -3,6 +3,7 @@ #include <Helpers.h>
#include <iostream>
#include <vector>
+#include <chrono>
void error_callback(int error, const char* description)
{
@@ -138,21 +139,26 @@ int main(int argc, char * argv[]) glUniform3ui(orbitLengthUniformHandle,settings.orbitLengthRed,settings.orbitLengthGreen,settings.orbitLengthBlue);
glUniform1ui(widthUniformComputeHandle, settings.imageWidth);
glUniform1ui(heightUniformComputeHandle, bufferHeight);
- glUniform1ui(iterationsPerDispatchHandle, settings.iterationsPerFrame);
glUseProgram(VertexAndFragmentShaders);
GLint widthUniformFragmentHandle = glGetUniformLocation(VertexAndFragmentShaders, "width");
GLint heightUniformFragmentHandle = glGetUniformLocation(VertexAndFragmentShaders, "height");
glUniform1ui(widthUniformFragmentHandle, settings.imageWidth);
glUniform1ui(heightUniformFragmentHandle, bufferHeight);
-
glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
+ uint32_t iterationsPerFrame = 1;
+
+ Helpers::PIDController<float, uint32_t> pid{0.0f,0.0f,1e-6f};
+ const uint32_t targetFrameDuration{1000000/settings.targetFrameRate};
+
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
+ auto frameStart{std::chrono::high_resolution_clock::now()};
//let the compute shader do something
glUseProgram(ComputeShader);
+ glUniform1ui(iterationsPerDispatchHandle, iterationsPerFrame);
glDispatchCompute(settings.globalWorkGroupSizeX, settings.globalWorkGroupSizeY, settings.globalWorkGroupSizeZ);
//before reading the values in the ssbo, we need a memory barrier:
@@ -181,6 +187,17 @@ int main(int argc, char * argv[]) /* Poll for and process events */
glfwPollEvents();
+ auto frameStop{std::chrono::high_resolution_clock::now()};
+ const auto dur{std::chrono::duration_cast<std::chrono::microseconds>(frameStop-frameStart)};
+ auto frameDuration{dur.count()};
+ if(frameDuration > 0)
+ {
+ const auto error{targetFrameDuration - frameDuration};
+ const auto pidOutput{pid.Update(frameDuration,error)};
+ iterationsPerFrame = std::max(1,static_cast<int>(pidOutput));
+
+ //std::cout << iterationsPerFrame << " " << pidOutput << std::endl;
+ }
}
if(!settings.pngFilename.empty())
diff --git a/BuddhaTest/src/Helpers.cpp b/BuddhaTest/src/Helpers.cpp index 02cc309..94c21a9 100644 --- a/BuddhaTest/src/Helpers.cpp +++ b/BuddhaTest/src/Helpers.cpp @@ -332,7 +332,7 @@ namespace Helpers {"--globalWorkgroupSizeX", &globalWorkGroupSizeX},
{"--globalWorkgroupSizeY", &globalWorkGroupSizeY},
{"--globalWorkgroupSizeZ", &globalWorkGroupSizeZ},
- {"--iterationsPerFrame", &iterationsPerFrame},
+ {"--targetFrameRate", &targetFrameRate},
{"--imageGamma",&pngGamma},
{"--imageColorScale",&pngColorScale},
{"--output", &pngFilename},
@@ -363,7 +363,7 @@ namespace Helpers "--globalWorkgroupSizeX [integer] : How often the local work group should be invoked per frame. Values up to 65535 are guaranteed to work. Default is 1024." << std::endl <<
"--globalWorkgroupSizeY [integer] : How often the local work group should be invoked per frame. Values up to 65535 are guaranteed to work. Default is 1." << std::endl <<
"--globalWorkgroupSizeZ [integer] : How often the local work group should be invoked per frame. Values up to 65535 are guaranteed to work. Default is 1." << std::endl <<
- "--iterationsPerFrame [integer] : Limit how many iteration steps the shader may make per frame. Use this to keep the desktop responsive while rendering high iteration count images. Default: 10." << std::endl <<
+ "--targetFrameRate [integer] : The number of iterations per frame will dynamically adjust to approximately reach this framerate. Default: 60." << std::endl <<
"--ignoreMaxBufferSize [0,1] : If set to 1, a failed maximum buffer size check is not treated as error. Some graphics drivers report lower values than their absolute limit. Do this on your own risk, though." << std::endl;
return false;
}
|