From b05e87dc5004f5badc02508570ddc55f31b451cc Mon Sep 17 00:00:00 2001 From: Andreas Grois Date: Sat, 17 Mar 2018 17:51:19 +0100 Subject: Correct line endings. --- BuddhaTest/src/Helpers.cpp | 832 ++++++++++++++++++++++----------------------- 1 file changed, 416 insertions(+), 416 deletions(-) (limited to 'BuddhaTest/src/Helpers.cpp') diff --git a/BuddhaTest/src/Helpers.cpp b/BuddhaTest/src/Helpers.cpp index 94c21a9..ed895c4 100644 --- a/BuddhaTest/src/Helpers.cpp +++ b/BuddhaTest/src/Helpers.cpp @@ -1,416 +1,416 @@ -#include "Helpers.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace Helpers -{ - GLuint LoadShaders(const std::string& vertex_file_path, const std::string& fragment_file_path) { - - // Create the shaders - GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); - GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); - - // Read the Vertex Shader code from the file - std::string VertexShaderCode; - std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); - if (VertexShaderStream.is_open()) { - std::stringstream sstr; - sstr << VertexShaderStream.rdbuf(); - VertexShaderCode = sstr.str(); - VertexShaderStream.close(); - } - else { - std::cerr << "Failed to load vertex shader file from " << vertex_file_path << ". Is this installed correctly?" << std::endl; - return 0; - } - - // Read the Fragment Shader code from the file - std::string FragmentShaderCode; - std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); - if (FragmentShaderStream.is_open()) { - std::stringstream sstr; - sstr << FragmentShaderStream.rdbuf(); - FragmentShaderCode = sstr.str(); - FragmentShaderStream.close(); - } - else - { - std::cerr << "Failed to load fragment shader file from " << fragment_file_path << ". Is this installed correctly?" << std::endl; - return 0; - } - - GLint Result = GL_FALSE; - int InfoLogLength; - - // Compile Vertex Shader - //std::cout << "Compiling shader : " << vertex_file_path << std::endl; - char const * VertexSourcePointer = VertexShaderCode.c_str(); - glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); - glCompileShader(VertexShaderID); - - // Check Vertex Shader - glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); - glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - std::vector VertexShaderErrorMessage(InfoLogLength + 1); - glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); - printf("%s\n", &VertexShaderErrorMessage[0]); - } - - - // Compile Fragment Shader - //std::cout << "Compiling shader : " << fragment_file_path << std::endl; - char const * FragmentSourcePointer = FragmentShaderCode.c_str(); - glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); - glCompileShader(FragmentShaderID); - - // Check Fragment Shader - glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); - glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - std::vector FragmentShaderErrorMessage(InfoLogLength + 1); - glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); - printf("%s\n", &FragmentShaderErrorMessage[0]); - } - - // Link the program - //printf("Linking program\n"); - GLuint ProgramID = glCreateProgram(); - glAttachShader(ProgramID, VertexShaderID); - glAttachShader(ProgramID, FragmentShaderID); - glLinkProgram(ProgramID); - - // Check the program - glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); - glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - std::vector ProgramErrorMessage(InfoLogLength + 1); - glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); - printf("%s\n", &ProgramErrorMessage[0]); - } - - glDetachShader(ProgramID, VertexShaderID); - glDetachShader(ProgramID, FragmentShaderID); - - glDeleteShader(VertexShaderID); - glDeleteShader(FragmentShaderID); - - return ProgramID; - } - - GLuint LoadComputeShader(const std::string& compute_file_path, unsigned int localSizeX, unsigned int localSizeY, unsigned int localSizeZ) - { - GLuint ComputeShaderID = glCreateShader(GL_COMPUTE_SHADER); - // Read the compute shader - std::string ComputeShaderCode; - { - std::ifstream ComputeShaderCodeStream(compute_file_path, std::ios::in); - if (ComputeShaderCodeStream.is_open()) { - std::stringstream sstr; - sstr << "#version 430" << - std::endl << - "layout (local_size_x = " << localSizeX << - ", local_size_y = " << localSizeY << - ", local_size_z = " << localSizeZ << ") in;" << std::endl; - sstr << ComputeShaderCodeStream.rdbuf(); - ComputeShaderCode = sstr.str(); - ComputeShaderCodeStream.close(); - } - else - { - std::cerr << "Failed to load compute shader file from " << compute_file_path << ". Is this installed correctly?" << std::endl; - return 0; - } - } - - GLint Result = GL_FALSE; - int InfoLogLength; - - { - // Compile Compute Shader - //std::cout << "Compiling shader : " << compute_file_path << std::endl; - char const * ComputeSourcePointer = ComputeShaderCode.c_str(); - glShaderSource(ComputeShaderID, 1, &ComputeSourcePointer, NULL); - glCompileShader(ComputeShaderID); - - // Check Compute Shader - glGetShaderiv(ComputeShaderID, GL_COMPILE_STATUS, &Result); - glGetShaderiv(ComputeShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - std::vector ComputeShaderErrorMessage(InfoLogLength + 1); - glGetShaderInfoLog(ComputeShaderID, InfoLogLength, NULL, &ComputeShaderErrorMessage[0]); - printf("%s\n", &ComputeShaderErrorMessage[0]); - } - } - GLuint ProgramID = glCreateProgram(); - glAttachShader(ProgramID, ComputeShaderID); - glLinkProgram(ProgramID); - - // Check the program - glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); - glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); - if (InfoLogLength > 0) { - std::vector ProgramErrorMessage(InfoLogLength + 1); - glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); - printf("%s\n", &ProgramErrorMessage[0]); - } - glDetachShader(ProgramID, ComputeShaderID); - glDeleteShader(ComputeShaderID); - return ProgramID; - } - - void WriteOutputPNG(const std::string &path, const std::vector& data, unsigned int width, unsigned int bufferHeight, double gamma, double colorScale) - { - std::vector pngData(3*width*2*bufferHeight); - std::vector rows{2*bufferHeight}; - for(unsigned int i = 0; i < 2*bufferHeight ; ++i) - { - rows[i] = pngData.data()+3*width*i; - } - - uint32_t maxValue{UINT32_C(1)}; - for(unsigned int i = 0; i < data.size();++i) - { - maxValue = std::max(maxValue,data[i]); - } - for(unsigned int i = 0; i < data.size();++i) - { - if(fabs(gamma - 1.0) > 0.0001 || fabs(colorScale - 1.0) > 0.0001) - { - pngData[data.size() + i] = static_cast(255.0 * pow(std::min(1.0,colorScale*static_cast(data[i])/static_cast(maxValue)),gamma)); - } - else - { - pngData[data.size() + i] = (255*data[i] + (maxValue/2))/maxValue; - } - } - for(unsigned int i = 0; i < bufferHeight;++i) - { - for(unsigned int j = 0; j < width*3;++j) - { - rows[i][j] =rows[2*bufferHeight-i-1][j]; - } - } - - ScopedCFileDescriptor fd(path.c_str(), "wb"); - if(!fd.IsValid()) - { - std::cerr << "Failed to open image.png for writing." << std::endl; - return; - } - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); - if(!png_ptr) - { - return; - } - png_infop info_ptr = png_create_info_struct(png_ptr); - if(!info_ptr) - { - png_destroy_write_struct(&png_ptr, (png_infopp)NULL); - return; - } - if(setjmp(png_jmpbuf(png_ptr))) - { - png_destroy_write_struct(&png_ptr, &info_ptr); - return; - } - png_init_io(png_ptr, fd.Get()); - png_set_IHDR(png_ptr, info_ptr, width, 2*bufferHeight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); - - png_write_info(png_ptr, info_ptr); - //header written. - - png_write_image(png_ptr, rows.data()); - - png_write_end(png_ptr, info_ptr); - png_destroy_write_struct(&png_ptr, &info_ptr); - } - - ScopedCFileDescriptor::ScopedCFileDescriptor(const char *path, const char *mode) - { - Descriptor = fopen(path,mode); - } - - ScopedCFileDescriptor::~ScopedCFileDescriptor() - { - if(IsValid()) - fclose(Descriptor); - } - - FILE * ScopedCFileDescriptor::Get() const - { - return Descriptor; - } - - bool ScopedCFileDescriptor::IsValid() const - { - return Descriptor != nullptr; - } - - bool RenderSettings::CheckValidity() - { - if(imageHeight%2 != 0) - { - std::cerr << "Image height has to be an even number." << std::endl; - return false; - } - int maxSSBOSize; - glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE,&maxSSBOSize); - if((static_cast(imageWidth) * static_cast(imageHeight)) > static_cast(maxSSBOSize)/2) //divided by 2, as we have 4 bytes per int, but only half the image height - { - std::cerr << "Requested buffer size is larger than maximum allowed by graphics driver. Max pixel number: " << maxSSBOSize/2 << std::endl; - std::cerr << "You can override this limit check using the --ignoreMaxBufferSize 1 command line parameter, but doing so is your own risk." << std::endl; - if(ignoreMaxBufferSize == 0) - return false; - } - int WorkGroupSizeLimitX, WorkGroupSizeLimitY, WorkGroupSizeLimitZ; - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT,0,&WorkGroupSizeLimitX); - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT,1,&WorkGroupSizeLimitY); - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT,2,&WorkGroupSizeLimitZ); - if(globalWorkGroupSizeX > static_cast(WorkGroupSizeLimitX) || - globalWorkGroupSizeY > static_cast(WorkGroupSizeLimitY) || - globalWorkGroupSizeZ > static_cast(WorkGroupSizeLimitZ)) - { - std::cerr << "Requested global work group size exceeds maximum dimension. Limits: " << WorkGroupSizeLimitX << ", " << WorkGroupSizeLimitY << ", " << WorkGroupSizeLimitZ << std::endl; - return false; - } - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE,0,&WorkGroupSizeLimitX); - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE,1,&WorkGroupSizeLimitY); - glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE,2,&WorkGroupSizeLimitZ); - if(localWorkgroupSizeX > static_cast(WorkGroupSizeLimitX) || - localWorkgroupSizeY > static_cast(WorkGroupSizeLimitY) || - localWorkgroupSizeZ > static_cast(WorkGroupSizeLimitZ)) - { - std::cerr << "Requested local work group size exceeds maximum dimension. Limits: " << WorkGroupSizeLimitX << ", " << WorkGroupSizeLimitY << ", " << WorkGroupSizeLimitZ << std::endl; - return false; - } - int maxInvocations; - glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS,&maxInvocations); - if(static_cast(localWorkgroupSizeX)*static_cast(localWorkgroupSizeY)*static_cast(localWorkgroupSizeZ) > static_cast(maxInvocations)) - { - std::cerr << "Requested local work group size exceeds maximum total count (Product of x*y*z dimensions). Limit: " << maxInvocations << std::endl; - return false; - } - return true; - } - - bool RenderSettings::ParseCommandLine(int argc, char *argv[]) - { - struct SettingsPointer - { - public: - SettingsPointer(unsigned int * ptr) : intPtr(ptr), dblPtr(nullptr), stringPtr(nullptr) {} - SettingsPointer(double * ptr) : intPtr(nullptr), dblPtr(ptr), stringPtr(nullptr) {} - SettingsPointer(std::string * ptr) : intPtr(nullptr), dblPtr(nullptr), stringPtr(ptr) {} - unsigned int * GetIntPtr() const { return intPtr; } - double * GetDblPtr() const { return dblPtr;} - std::string * GetStringPtr() const { return stringPtr;} - private: - unsigned int * intPtr = nullptr; - double * dblPtr = nullptr; - std::string * stringPtr = nullptr; - }; - std::unordered_map commandMap{ - {"--imageWidth",&imageWidth}, - {"--imageHeight",&imageHeight}, - {"--windowWidth",&windowWidth}, - {"--windowHeight",&windowHeight}, - {"--orbitLengthRed",&orbitLengthRed}, - {"--orbitLengthGreen",&orbitLengthGreen}, - {"--orbitLengthBlue",&orbitLengthBlue}, - {"--localWorkgroupSizeX", &localWorkgroupSizeX}, - {"--localWorkgroupSizeY", &localWorkgroupSizeY}, - {"--localWorkgroupSizeZ", &localWorkgroupSizeZ}, - {"--globalWorkgroupSizeX", &globalWorkGroupSizeX}, - {"--globalWorkgroupSizeY", &globalWorkGroupSizeY}, - {"--globalWorkgroupSizeZ", &globalWorkGroupSizeZ}, - {"--targetFrameRate", &targetFrameRate}, - {"--imageGamma",&pngGamma}, - {"--imageColorScale",&pngColorScale}, - {"--output", &pngFilename}, - {"--ignoreMaxBufferSize", &ignoreMaxBufferSize} - }; - - for(int i=1; i < argc;++i) - { - std::string argAsString(argv[i]); - if(argAsString == "--help") //help is a special case. - { - std::cout << "Draws a buddhabrot and iterates until the user closes the window. If a --output filename is given, a png file will afterwards be written there." <second; - if(auto intProp = ptr.GetIntPtr()) - { - *intProp = std::stoi(valueAsString); - } - else if(auto dblProp = ptr.GetDblPtr()) - { - *dblProp = std::stod(valueAsString); - } - else if(auto strPtr = ptr.GetStringPtr()) - { - *strPtr = valueAsString; - } - else - { - std::cerr << "Something went horribly wrong with command line parsing. This is a bug." << std::endl; - return false; - } - } - - return true; - } - - bool DoesFileExist(const std::string &path) - { - std::ifstream f(path); - return f.good(); - } - -} +#include "Helpers.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Helpers +{ + GLuint LoadShaders(const std::string& vertex_file_path, const std::string& fragment_file_path) { + + // Create the shaders + GLuint VertexShaderID = glCreateShader(GL_VERTEX_SHADER); + GLuint FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); + + // Read the Vertex Shader code from the file + std::string VertexShaderCode; + std::ifstream VertexShaderStream(vertex_file_path, std::ios::in); + if (VertexShaderStream.is_open()) { + std::stringstream sstr; + sstr << VertexShaderStream.rdbuf(); + VertexShaderCode = sstr.str(); + VertexShaderStream.close(); + } + else { + std::cerr << "Failed to load vertex shader file from " << vertex_file_path << ". Is this installed correctly?" << std::endl; + return 0; + } + + // Read the Fragment Shader code from the file + std::string FragmentShaderCode; + std::ifstream FragmentShaderStream(fragment_file_path, std::ios::in); + if (FragmentShaderStream.is_open()) { + std::stringstream sstr; + sstr << FragmentShaderStream.rdbuf(); + FragmentShaderCode = sstr.str(); + FragmentShaderStream.close(); + } + else + { + std::cerr << "Failed to load fragment shader file from " << fragment_file_path << ". Is this installed correctly?" << std::endl; + return 0; + } + + GLint Result = GL_FALSE; + int InfoLogLength; + + // Compile Vertex Shader + //std::cout << "Compiling shader : " << vertex_file_path << std::endl; + char const * VertexSourcePointer = VertexShaderCode.c_str(); + glShaderSource(VertexShaderID, 1, &VertexSourcePointer, NULL); + glCompileShader(VertexShaderID); + + // Check Vertex Shader + glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector VertexShaderErrorMessage(InfoLogLength + 1); + glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]); + printf("%s\n", &VertexShaderErrorMessage[0]); + } + + + // Compile Fragment Shader + //std::cout << "Compiling shader : " << fragment_file_path << std::endl; + char const * FragmentSourcePointer = FragmentShaderCode.c_str(); + glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer, NULL); + glCompileShader(FragmentShaderID); + + // Check Fragment Shader + glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector FragmentShaderErrorMessage(InfoLogLength + 1); + glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]); + printf("%s\n", &FragmentShaderErrorMessage[0]); + } + + // Link the program + //printf("Linking program\n"); + GLuint ProgramID = glCreateProgram(); + glAttachShader(ProgramID, VertexShaderID); + glAttachShader(ProgramID, FragmentShaderID); + glLinkProgram(ProgramID); + + // Check the program + glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); + glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector ProgramErrorMessage(InfoLogLength + 1); + glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); + printf("%s\n", &ProgramErrorMessage[0]); + } + + glDetachShader(ProgramID, VertexShaderID); + glDetachShader(ProgramID, FragmentShaderID); + + glDeleteShader(VertexShaderID); + glDeleteShader(FragmentShaderID); + + return ProgramID; + } + + GLuint LoadComputeShader(const std::string& compute_file_path, unsigned int localSizeX, unsigned int localSizeY, unsigned int localSizeZ) + { + GLuint ComputeShaderID = glCreateShader(GL_COMPUTE_SHADER); + // Read the compute shader + std::string ComputeShaderCode; + { + std::ifstream ComputeShaderCodeStream(compute_file_path, std::ios::in); + if (ComputeShaderCodeStream.is_open()) { + std::stringstream sstr; + sstr << "#version 430" << + std::endl << + "layout (local_size_x = " << localSizeX << + ", local_size_y = " << localSizeY << + ", local_size_z = " << localSizeZ << ") in;" << std::endl; + sstr << ComputeShaderCodeStream.rdbuf(); + ComputeShaderCode = sstr.str(); + ComputeShaderCodeStream.close(); + } + else + { + std::cerr << "Failed to load compute shader file from " << compute_file_path << ". Is this installed correctly?" << std::endl; + return 0; + } + } + + GLint Result = GL_FALSE; + int InfoLogLength; + + { + // Compile Compute Shader + //std::cout << "Compiling shader : " << compute_file_path << std::endl; + char const * ComputeSourcePointer = ComputeShaderCode.c_str(); + glShaderSource(ComputeShaderID, 1, &ComputeSourcePointer, NULL); + glCompileShader(ComputeShaderID); + + // Check Compute Shader + glGetShaderiv(ComputeShaderID, GL_COMPILE_STATUS, &Result); + glGetShaderiv(ComputeShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector ComputeShaderErrorMessage(InfoLogLength + 1); + glGetShaderInfoLog(ComputeShaderID, InfoLogLength, NULL, &ComputeShaderErrorMessage[0]); + printf("%s\n", &ComputeShaderErrorMessage[0]); + } + } + GLuint ProgramID = glCreateProgram(); + glAttachShader(ProgramID, ComputeShaderID); + glLinkProgram(ProgramID); + + // Check the program + glGetProgramiv(ProgramID, GL_LINK_STATUS, &Result); + glGetProgramiv(ProgramID, GL_INFO_LOG_LENGTH, &InfoLogLength); + if (InfoLogLength > 0) { + std::vector ProgramErrorMessage(InfoLogLength + 1); + glGetProgramInfoLog(ProgramID, InfoLogLength, NULL, &ProgramErrorMessage[0]); + printf("%s\n", &ProgramErrorMessage[0]); + } + glDetachShader(ProgramID, ComputeShaderID); + glDeleteShader(ComputeShaderID); + return ProgramID; + } + + void WriteOutputPNG(const std::string &path, const std::vector& data, unsigned int width, unsigned int bufferHeight, double gamma, double colorScale) + { + std::vector pngData(3*width*2*bufferHeight); + std::vector rows{2*bufferHeight}; + for(unsigned int i = 0; i < 2*bufferHeight ; ++i) + { + rows[i] = pngData.data()+3*width*i; + } + + uint32_t maxValue{UINT32_C(1)}; + for(unsigned int i = 0; i < data.size();++i) + { + maxValue = std::max(maxValue,data[i]); + } + for(unsigned int i = 0; i < data.size();++i) + { + if(fabs(gamma - 1.0) > 0.0001 || fabs(colorScale - 1.0) > 0.0001) + { + pngData[data.size() + i] = static_cast(255.0 * pow(std::min(1.0,colorScale*static_cast(data[i])/static_cast(maxValue)),gamma)); + } + else + { + pngData[data.size() + i] = (255*data[i] + (maxValue/2))/maxValue; + } + } + for(unsigned int i = 0; i < bufferHeight;++i) + { + for(unsigned int j = 0; j < width*3;++j) + { + rows[i][j] =rows[2*bufferHeight-i-1][j]; + } + } + + ScopedCFileDescriptor fd(path.c_str(), "wb"); + if(!fd.IsValid()) + { + std::cerr << "Failed to open image.png for writing." << std::endl; + return; + } + png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + if(!png_ptr) + { + return; + } + png_infop info_ptr = png_create_info_struct(png_ptr); + if(!info_ptr) + { + png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + return; + } + if(setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + return; + } + png_init_io(png_ptr, fd.Get()); + png_set_IHDR(png_ptr, info_ptr, width, 2*bufferHeight, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); + + png_write_info(png_ptr, info_ptr); + //header written. + + png_write_image(png_ptr, rows.data()); + + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + } + + ScopedCFileDescriptor::ScopedCFileDescriptor(const char *path, const char *mode) + { + Descriptor = fopen(path,mode); + } + + ScopedCFileDescriptor::~ScopedCFileDescriptor() + { + if(IsValid()) + fclose(Descriptor); + } + + FILE * ScopedCFileDescriptor::Get() const + { + return Descriptor; + } + + bool ScopedCFileDescriptor::IsValid() const + { + return Descriptor != nullptr; + } + + bool RenderSettings::CheckValidity() + { + if(imageHeight%2 != 0) + { + std::cerr << "Image height has to be an even number." << std::endl; + return false; + } + int maxSSBOSize; + glGetIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE,&maxSSBOSize); + if((static_cast(imageWidth) * static_cast(imageHeight)) > static_cast(maxSSBOSize)/2) //divided by 2, as we have 4 bytes per int, but only half the image height + { + std::cerr << "Requested buffer size is larger than maximum allowed by graphics driver. Max pixel number: " << maxSSBOSize/2 << std::endl; + std::cerr << "You can override this limit check using the --ignoreMaxBufferSize 1 command line parameter, but doing so is your own risk." << std::endl; + if(ignoreMaxBufferSize == 0) + return false; + } + int WorkGroupSizeLimitX, WorkGroupSizeLimitY, WorkGroupSizeLimitZ; + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT,0,&WorkGroupSizeLimitX); + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT,1,&WorkGroupSizeLimitY); + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT,2,&WorkGroupSizeLimitZ); + if(globalWorkGroupSizeX > static_cast(WorkGroupSizeLimitX) || + globalWorkGroupSizeY > static_cast(WorkGroupSizeLimitY) || + globalWorkGroupSizeZ > static_cast(WorkGroupSizeLimitZ)) + { + std::cerr << "Requested global work group size exceeds maximum dimension. Limits: " << WorkGroupSizeLimitX << ", " << WorkGroupSizeLimitY << ", " << WorkGroupSizeLimitZ << std::endl; + return false; + } + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE,0,&WorkGroupSizeLimitX); + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE,1,&WorkGroupSizeLimitY); + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE,2,&WorkGroupSizeLimitZ); + if(localWorkgroupSizeX > static_cast(WorkGroupSizeLimitX) || + localWorkgroupSizeY > static_cast(WorkGroupSizeLimitY) || + localWorkgroupSizeZ > static_cast(WorkGroupSizeLimitZ)) + { + std::cerr << "Requested local work group size exceeds maximum dimension. Limits: " << WorkGroupSizeLimitX << ", " << WorkGroupSizeLimitY << ", " << WorkGroupSizeLimitZ << std::endl; + return false; + } + int maxInvocations; + glGetIntegerv(GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS,&maxInvocations); + if(static_cast(localWorkgroupSizeX)*static_cast(localWorkgroupSizeY)*static_cast(localWorkgroupSizeZ) > static_cast(maxInvocations)) + { + std::cerr << "Requested local work group size exceeds maximum total count (Product of x*y*z dimensions). Limit: " << maxInvocations << std::endl; + return false; + } + return true; + } + + bool RenderSettings::ParseCommandLine(int argc, char *argv[]) + { + struct SettingsPointer + { + public: + SettingsPointer(unsigned int * ptr) : intPtr(ptr), dblPtr(nullptr), stringPtr(nullptr) {} + SettingsPointer(double * ptr) : intPtr(nullptr), dblPtr(ptr), stringPtr(nullptr) {} + SettingsPointer(std::string * ptr) : intPtr(nullptr), dblPtr(nullptr), stringPtr(ptr) {} + unsigned int * GetIntPtr() const { return intPtr; } + double * GetDblPtr() const { return dblPtr;} + std::string * GetStringPtr() const { return stringPtr;} + private: + unsigned int * intPtr = nullptr; + double * dblPtr = nullptr; + std::string * stringPtr = nullptr; + }; + std::unordered_map commandMap{ + {"--imageWidth",&imageWidth}, + {"--imageHeight",&imageHeight}, + {"--windowWidth",&windowWidth}, + {"--windowHeight",&windowHeight}, + {"--orbitLengthRed",&orbitLengthRed}, + {"--orbitLengthGreen",&orbitLengthGreen}, + {"--orbitLengthBlue",&orbitLengthBlue}, + {"--localWorkgroupSizeX", &localWorkgroupSizeX}, + {"--localWorkgroupSizeY", &localWorkgroupSizeY}, + {"--localWorkgroupSizeZ", &localWorkgroupSizeZ}, + {"--globalWorkgroupSizeX", &globalWorkGroupSizeX}, + {"--globalWorkgroupSizeY", &globalWorkGroupSizeY}, + {"--globalWorkgroupSizeZ", &globalWorkGroupSizeZ}, + {"--targetFrameRate", &targetFrameRate}, + {"--imageGamma",&pngGamma}, + {"--imageColorScale",&pngColorScale}, + {"--output", &pngFilename}, + {"--ignoreMaxBufferSize", &ignoreMaxBufferSize} + }; + + for(int i=1; i < argc;++i) + { + std::string argAsString(argv[i]); + if(argAsString == "--help") //help is a special case. + { + std::cout << "Draws a buddhabrot and iterates until the user closes the window. If a --output filename is given, a png file will afterwards be written there." <second; + if(auto intProp = ptr.GetIntPtr()) + { + *intProp = std::stoi(valueAsString); + } + else if(auto dblProp = ptr.GetDblPtr()) + { + *dblProp = std::stod(valueAsString); + } + else if(auto strPtr = ptr.GetStringPtr()) + { + *strPtr = valueAsString; + } + else + { + std::cerr << "Something went horribly wrong with command line parsing. This is a bug." << std::endl; + return false; + } + } + + return true; + } + + bool DoesFileExist(const std::string &path) + { + std::ifstream f(path); + return f.good(); + } + +} -- cgit v1.2.3