From 7997ead84faeec4628bebba4c05ae71ef6498f38 Mon Sep 17 00:00:00 2001 From: Samuli Vuorinen Date: Sun, 21 Feb 2021 00:31:10 +0200 Subject: [PATCH 1/5] Renew encrypted release token The access token used by AppVeyor to create releases in GitHub was deleted a while ago accidentally. A new one was generated now in GitHub and encrypted by AppVeyor, so only AppVeyor can read it and it is safe to store in a public repo. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 5c881ce..40f9c60 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,6 +24,6 @@ deploy: description: "" skip_tags: true auth_token: - secure: pb9keaNklmNgmLaw1doReZDdP5Oh/pLZPdwjt+anpcoi34MyqAbFoJbiHJMcWkgD + secure: qxadIRLRDKo8Tji0y+kZ03BIbNPJzdmp2HkzE6+G5lp1xtRCoeSpp6c4m4KU99D4 on: branch: master From eaa0aa48c4e28b5d56263e73c48c76ce03812669 Mon Sep 17 00:00:00 2001 From: Samuli Vuorinen Date: Sun, 21 Feb 2021 13:51:43 +0200 Subject: [PATCH 2/5] Improve logging and error messages when shader compilation fails --- CHANGELOG.md | 6 ++++++ src/haloray-core/gui/openGLWidget.cpp | 1 + src/haloray-core/opengl/textureRenderer.cpp | 19 +++++++++++++++++-- .../resources/shaders/raytrace.glsl | 16 ++++++++-------- .../simulation/simulationEngine.cpp | 17 +++++++++++++++-- 5 files changed, 47 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 43f1cad..f4a2b29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Improved logging and error messages in case shader compilation fails + ## 3.0.0 - 2021-02-21 ### Added diff --git a/src/haloray-core/gui/openGLWidget.cpp b/src/haloray-core/gui/openGLWidget.cpp index a52b343..0467609 100644 --- a/src/haloray-core/gui/openGLWidget.cpp +++ b/src/haloray-core/gui/openGLWidget.cpp @@ -67,6 +67,7 @@ void OpenGLWidget::initializeGL() int maxComputeGroups; glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &maxComputeGroups); + qInfo("Maximum supported number of compute shader workgroups: %i", maxComputeGroups); const int absoluteMaxRaysPerFrame = 5000000; int maxRaysPerFrame = std::min(absoluteMaxRaysPerFrame, maxComputeGroups); m_viewModel->setRaysPerFrameUpperLimit(maxRaysPerFrame); diff --git a/src/haloray-core/opengl/textureRenderer.cpp b/src/haloray-core/opengl/textureRenderer.cpp index 12b0f21..2367203 100644 --- a/src/haloray-core/opengl/textureRenderer.cpp +++ b/src/haloray-core/opengl/textureRenderer.cpp @@ -1,6 +1,7 @@ #include "textureRenderer.h" #include #include +#include #include namespace OpenGL @@ -9,11 +10,25 @@ namespace OpenGL std::unique_ptr TextureRenderer::initializeTexDrawShaderProgram() { auto program = std::make_unique(); - program->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Vertex, ":/shaders/renderer.vert"); - program->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Fragment, ":/shaders/renderer.frag"); + bool vertexShaderCompilationSucceeded = program->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Vertex, ":/shaders/renderer.vert"); + + if (vertexShaderCompilationSucceeded == false) + { + qWarning("Texture renderer vertex shader compilation failed"); + throw std::runtime_error(program->log().toUtf8()); + } + + bool fragmentShaderCompilationSucceeded = program->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Fragment, ":/shaders/renderer.frag"); + + if (fragmentShaderCompilationSucceeded == false) + { + qWarning("Texture renderer fragment shader compilation failed"); + throw std::runtime_error(program->log().toUtf8()); + } if (program->link() == false) { + qWarning("Texture renderer shader linking failed"); throw std::runtime_error(program->log().toUtf8()); } diff --git a/src/haloray-core/resources/shaders/raytrace.glsl b/src/haloray-core/resources/shaders/raytrace.glsl index 5eb16b3..abd38e7 100644 --- a/src/haloray-core/resources/shaders/raytrace.glsl +++ b/src/haloray-core/resources/shaders/raytrace.glsl @@ -142,14 +142,14 @@ vec3 triangleNormalCache[triangles.length()]; uint wang_hash(uint a) { - a -= (a << 6); - a ^= (a >> 17); - a -= (a << 9); - a ^= (a << 4); - a -= (a << 3); - a ^= (a << 10); - a ^= (a >> 15); - return a; + a -= (a << 6); + a ^= (a >> 17); + a -= (a << 9); + a ^= (a << 4); + a -= (a << 3); + a ^= (a << 10); + a ^= (a >> 15); + return a; } uint rngState = wang_hash(rngSeed + uint(gl_GlobalInvocationID.x)); diff --git a/src/haloray-core/simulation/simulationEngine.cpp b/src/haloray-core/simulation/simulationEngine.cpp index 1ab2daf..31a8af2 100644 --- a/src/haloray-core/simulation/simulationEngine.cpp +++ b/src/haloray-core/simulation/simulationEngine.cpp @@ -262,16 +262,29 @@ void SimulationEngine::initialize() void SimulationEngine::initializeShaders() { m_simulationShader = std::make_unique(); - m_simulationShader->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Compute, ":/shaders/raytrace.glsl"); + bool raytraceShaderCompilationSucceeded = m_simulationShader->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Compute, ":/shaders/raytrace.glsl"); + if (raytraceShaderCompilationSucceeded == false) + { + qWarning("Compiling raytracing shader failed"); + throw std::runtime_error(m_simulationShader->log().toUtf8()); + } + if (m_simulationShader->link() == false) { + qWarning("Linking raytracing shader failed"); throw std::runtime_error(m_simulationShader->log().toUtf8()); } m_skyShader = new QOpenGLShaderProgram(this); - m_skyShader->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Compute, ":/shaders/sky.glsl"); + bool skyShaderCompilationSucceeded = m_skyShader->addCacheableShaderFromSourceFile(QOpenGLShader::ShaderTypeBit::Compute, ":/shaders/sky.glsl"); + if (skyShaderCompilationSucceeded == false) + { + qWarning("Compiling sky shader failed"); + throw std::runtime_error(m_skyShader->log().toUtf8()); + } if (m_skyShader->link() == false) { + qWarning("Linking sky shader failed"); throw std::runtime_error(m_skyShader->log().toUtf8()); } } From 34c62344ecaeb2fe9bb9398428bb360e38e45107 Mon Sep 17 00:00:00 2001 From: Samuli Vuorinen Date: Sun, 21 Feb 2021 14:17:21 +0200 Subject: [PATCH 3/5] Log compute shader maximum workgroup size on startup --- src/haloray-core/gui/openGLWidget.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/haloray-core/gui/openGLWidget.cpp b/src/haloray-core/gui/openGLWidget.cpp index 0467609..c42a2cd 100644 --- a/src/haloray-core/gui/openGLWidget.cpp +++ b/src/haloray-core/gui/openGLWidget.cpp @@ -71,6 +71,14 @@ void OpenGLWidget::initializeGL() const int absoluteMaxRaysPerFrame = 5000000; int maxRaysPerFrame = std::min(absoluteMaxRaysPerFrame, maxComputeGroups); m_viewModel->setRaysPerFrameUpperLimit(maxRaysPerFrame); + + int maxWorkGroupSizeX; + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &maxWorkGroupSizeX); + int maxWorkGroupSizeY; + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &maxWorkGroupSizeY); + int maxWorkGroupSizeZ; + glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &maxWorkGroupSizeZ); + qInfo("Maximum supported compute shader workgroup size: %i, %i, %i", maxWorkGroupSizeX, maxWorkGroupSizeY, maxWorkGroupSizeZ); } void OpenGLWidget::mousePressEvent(QMouseEvent *event) From bf73b8d6209426f6c5c96da638e8d7034e1d35c7 Mon Sep 17 00:00:00 2001 From: Samuli Vuorinen Date: Sun, 21 Feb 2021 17:04:41 +0200 Subject: [PATCH 4/5] Change population weight from integer to decimal This allows more granular control, and now the UI widget used to change the weight is a slider, which is easier to use. --- CHANGELOG.md | 1 + README.md | 4 ++-- .../gui/crystalSettingsWidget.cpp | 10 ++++------ src/haloray-core/gui/crystalSettingsWidget.h | 2 +- src/haloray-core/gui/models/crystalModel.cpp | 4 ++-- src/haloray-core/gui/models/crystalModel.h | 2 +- src/haloray-core/gui/stateSaver.cpp | 2 +- .../crystalPopulationRepository.cpp | 20 +++++++++---------- .../simulation/crystalPopulationRepository.h | 8 ++++---- .../crystalPopulationRepositoryTests.cpp | 6 +++--- 10 files changed, 29 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a2b29..2b7e850 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Improved logging and error messages in case shader compilation fails +- Population weight was changed from an integer to a decimal number for more granular control ## 3.0.0 - 2021-02-21 diff --git a/README.md b/README.md index a012047..59bad2b 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,8 @@ Here are some general settings for the whole simulation. HaloRay allows you to simulate multiple different ice crystal populations simultaneously. You give each population a name for easier reference by typing in the **Crystal population** dropdown menu. Each population has a relative -weight, which can be changed by adjusting the **Population weight** spin box. -For example, giving weights 1 and 3 to two crystal populations respectively +weight, which can be changed by adjusting the **Population weight** slider. +For example, giving weights 1.0 and 3.0 to two crystal populations respectively would trace three times as many rays through the latter population than the former. It is also possible to enable or disable a crystal population temporarily with the **Population enabled** checkbox. diff --git a/src/haloray-core/gui/crystalSettingsWidget.cpp b/src/haloray-core/gui/crystalSettingsWidget.cpp index 8e2a30c..c86d5e0 100644 --- a/src/haloray-core/gui/crystalSettingsWidget.cpp +++ b/src/haloray-core/gui/crystalSettingsWidget.cpp @@ -53,7 +53,7 @@ CrystalSettingsWidget::CrystalSettingsWidget(CrystalModel *model, QWidget *paren m_mapper->addMapping(m_lowerApexAngleSpinBox, CrystalModel::LowerApexAngle); m_mapper->addMapping(m_lowerApexHeightAverageSlider, CrystalModel::LowerApexHeightAverage); m_mapper->addMapping(m_lowerApexHeightStdSlider, CrystalModel::LowerApexHeightStd); - m_mapper->addMapping(m_weightSpinBox, CrystalModel::PopulationWeight); + m_mapper->addMapping(m_weightSlider, CrystalModel::PopulationWeight); m_mapper->addMapping(m_populationEnabledCheckBox, CrystalModel::Enabled); m_mapper->addMapping(m_populationComboBox, CrystalModel::PopulationName, "currentText"); for (auto i = 0; i < 6; ++i) @@ -69,7 +69,7 @@ CrystalSettingsWidget::CrystalSettingsWidget(CrystalModel *model, QWidget *paren to the submit slot of the mapper. */ connect(m_populationEnabledCheckBox, &QCheckBox::toggled, m_mapper, &QDataWidgetMapper::submit, Qt::QueuedConnection); - connect(m_weightSpinBox, QOverload::of(&QSpinBox::valueChanged), m_mapper, &QDataWidgetMapper::submit, Qt::QueuedConnection); + connect(m_weightSlider, &SliderSpinBox::valueChanged, m_mapper, &QDataWidgetMapper::submit, Qt::QueuedConnection); connect(m_caRatioSlider, &SliderSpinBox::valueChanged, m_mapper, &QDataWidgetMapper::submit, Qt::QueuedConnection); connect(m_caRatioStdSlider, &SliderSpinBox::valueChanged, m_mapper, &QDataWidgetMapper::submit, Qt::QueuedConnection); connect(m_tiltDistributionComboBox, QOverload::of(&QComboBox::currentIndexChanged), m_mapper, &QDataWidgetMapper::submit, Qt::QueuedConnection); @@ -199,9 +199,7 @@ void CrystalSettingsWidget::setupUi() m_lowerApexHeightStdSlider = new SliderSpinBox(0.0, 5.0); - m_weightSpinBox = new QSpinBox(); - m_weightSpinBox->setMinimum(0); - m_weightSpinBox->setMaximum(10000); + m_weightSlider = new SliderSpinBox(0.0, 20.0); for (auto i = 0; i < 6; ++i) { @@ -221,7 +219,7 @@ void CrystalSettingsWidget::setupUi() auto populationSettingsLayout = new QFormLayout(populationSettingsWidget); populationSettingsLayout->addRow(populationManagementLayout); populationSettingsLayout->addRow(tr("Population enabled"), m_populationEnabledCheckBox); - populationSettingsLayout->addRow(tr("Population weight"), m_weightSpinBox); + populationSettingsLayout->addRow(tr("Population weight"), m_weightSlider); mainLayout->addWidget(populationSettingsWidget); mainLayout->addWidget(tabWidget); diff --git a/src/haloray-core/gui/crystalSettingsWidget.h b/src/haloray-core/gui/crystalSettingsWidget.h index c447f5f..dee442c 100644 --- a/src/haloray-core/gui/crystalSettingsWidget.h +++ b/src/haloray-core/gui/crystalSettingsWidget.h @@ -64,7 +64,7 @@ class CrystalSettingsWidget : public CollapsibleBox SliderSpinBox *m_prismFaceDistanceSliders[6]; - QSpinBox *m_weightSpinBox; + SliderSpinBox *m_weightSlider; CrystalModel *m_model; QDataWidgetMapper *m_mapper; diff --git a/src/haloray-core/gui/models/crystalModel.cpp b/src/haloray-core/gui/models/crystalModel.cpp index ed89baf..a5cc3b8 100644 --- a/src/haloray-core/gui/models/crystalModel.cpp +++ b/src/haloray-core/gui/models/crystalModel.cpp @@ -147,7 +147,7 @@ bool CrystalModel::setData(const QModelIndex &index, const QVariant &value, int crystal.lowerApexHeightStd = value.toFloat(); break; case PopulationWeight: - m_crystals->setWeight(row, value.toUInt()); + m_crystals->setWeight(row, value.toDouble()); break; case PopulationName: m_crystals->setName(row, value.toString().toStdString()); @@ -197,7 +197,7 @@ void CrystalModel::addRow(CrystalPopulationPreset preset) endInsertRows(); } -void CrystalModel::addRow(CrystalPopulation population, unsigned int weight, QString name) +void CrystalModel::addRow(CrystalPopulation population, double weight, QString name) { auto row = m_crystals->getCount(); beginInsertRows(QModelIndex(), row, row); diff --git a/src/haloray-core/gui/models/crystalModel.h b/src/haloray-core/gui/models/crystalModel.h index adf4815..15d46c5 100644 --- a/src/haloray-core/gui/models/crystalModel.h +++ b/src/haloray-core/gui/models/crystalModel.h @@ -54,7 +54,7 @@ class CrystalModel : public QAbstractTableModel Qt::ItemFlags flags(const QModelIndex &index) const override; void addRow(CrystalPopulationPreset preset = CrystalPopulationPreset::Random); - void addRow(CrystalPopulation population, unsigned int weight, QString name); + void addRow(CrystalPopulation population, double weight, QString name); bool removeRow(int row); void clear(); void setName(int row, QString name); diff --git a/src/haloray-core/gui/stateSaver.cpp b/src/haloray-core/gui/stateSaver.cpp index 441eb6c..568b2fc 100644 --- a/src/haloray-core/gui/stateSaver.cpp +++ b/src/haloray-core/gui/stateSaver.cpp @@ -96,7 +96,6 @@ void StateSaver::LoadState(QString filename, SimulationStateModel *simState, Cry { settings.setArrayIndex(i); auto pop = CrystalPopulation::createRandom(); - unsigned int weight = settings.value("Weight", 1).toUInt(); pop.enabled = settings.value("Enabled", pop.enabled).toBool(); pop.caRatioAverage = settings.value("CaRatioAverage", pop.caRatioAverage).toFloat(); @@ -119,6 +118,7 @@ void StateSaver::LoadState(QString filename, SimulationStateModel *simState, Cry pop.lowerApexHeightStd = settings.value("LowerApexHeightStd", pop.lowerApexHeightStd).toFloat(); auto name = settings.value("Name", "Default name").toString(); + double weight = settings.value("Weight", 1.0).toDouble(); crystalModel->addRow(pop, weight, name); } diff --git a/src/haloray-core/simulation/crystalPopulationRepository.cpp b/src/haloray-core/simulation/crystalPopulationRepository.cpp index 662c122..742cfdd 100644 --- a/src/haloray-core/simulation/crystalPopulationRepository.cpp +++ b/src/haloray-core/simulation/crystalPopulationRepository.cpp @@ -22,10 +22,10 @@ void CrystalPopulationRepository::add(CrystalPopulationPreset preset) m_crystals.push_back(CrystalPopulation::presetPopulation(preset)); m_names.push_back(QString("%1 population %2").arg(presetNameMap[preset]).arg(m_nextId).toStdString()); m_nextId = m_nextId + 1; - m_weights.push_back(1); + m_weights.push_back(1.0); } -void CrystalPopulationRepository::add(CrystalPopulation population, unsigned int weight, std::string name) +void CrystalPopulationRepository::add(CrystalPopulation population, double weight, std::string name) { m_crystals.push_back(population); m_names.push_back(name); @@ -36,15 +36,15 @@ void CrystalPopulationRepository::addDefaults() { m_crystals.push_back(CrystalPopulation::presetPopulation(CrystalPopulationPreset::Column)); m_names.push_back("Column"); - m_weights.push_back(1); + m_weights.push_back(1.0); m_crystals.push_back(CrystalPopulation::presetPopulation(CrystalPopulationPreset::Plate)); m_names.push_back("Plate"); - m_weights.push_back(1); + m_weights.push_back(1.0); m_crystals.push_back(CrystalPopulation::presetPopulation(CrystalPopulationPreset::Random)); m_names.push_back("Random"); - m_weights.push_back(1); + m_weights.push_back(1.0); } void CrystalPopulationRepository::remove(unsigned int index) @@ -80,20 +80,20 @@ double CrystalPopulationRepository::getProbability(unsigned int index) const { if (m_crystals[index].enabled == false) return 0.0; - auto totalWeights = 0u; + auto totalWeights = 0.0; for (auto i = 0u; i < getCount(); ++i) { - totalWeights += m_crystals[i].enabled ? m_weights[i] : 0; + totalWeights += m_crystals[i].enabled ? m_weights[i] : 0.0; } - return static_cast(m_weights[index]) / totalWeights; + return m_weights[index] / totalWeights; } -unsigned int CrystalPopulationRepository::getWeight(unsigned int index) const +double CrystalPopulationRepository::getWeight(unsigned int index) const { return m_weights[index]; } -void CrystalPopulationRepository::setWeight(unsigned int index, unsigned int weight) +void CrystalPopulationRepository::setWeight(unsigned int index, double weight) { m_weights[index] = weight; } diff --git a/src/haloray-core/simulation/crystalPopulationRepository.h b/src/haloray-core/simulation/crystalPopulationRepository.h index 2505959..06a5845 100644 --- a/src/haloray-core/simulation/crystalPopulationRepository.h +++ b/src/haloray-core/simulation/crystalPopulationRepository.h @@ -11,7 +11,7 @@ class CrystalPopulationRepository public: CrystalPopulationRepository(); void add(CrystalPopulationPreset preset = Random); - void add(CrystalPopulation population, unsigned int weight, std::string name); + void add(CrystalPopulation population, double weight, std::string name); void remove(unsigned int index); void clear(); @@ -20,8 +20,8 @@ class CrystalPopulationRepository void setName(unsigned int index, std::string name); std::string getName(unsigned int index) const; - unsigned int getWeight(unsigned int index) const; - void setWeight(unsigned int index, unsigned int weight); + double getWeight(unsigned int index) const; + void setWeight(unsigned int index, double weight); double getProbability(unsigned int index) const; unsigned int getCount() const; @@ -29,7 +29,7 @@ class CrystalPopulationRepository private: void addDefaults(); std::vector m_crystals; - std::vector m_weights; + std::vector m_weights; std::vector m_names; unsigned int m_nextId; }; diff --git a/src/tests/crystalPopulationRepositoryTests/crystalPopulationRepositoryTests.cpp b/src/tests/crystalPopulationRepositoryTests/crystalPopulationRepositoryTests.cpp index 29319d1..af2aa01 100644 --- a/src/tests/crystalPopulationRepositoryTests/crystalPopulationRepositoryTests.cpp +++ b/src/tests/crystalPopulationRepositoryTests/crystalPopulationRepositoryTests.cpp @@ -39,9 +39,9 @@ private slots: void evenWeightsByDefault() { auto repository = HaloRay::CrystalPopulationRepository(); - QCOMPARE(repository.getWeight(0), 1); - QCOMPARE(repository.getWeight(1), 1); - QCOMPARE(repository.getWeight(2), 1); + QCOMPARE(repository.getWeight(0), 1.0); + QCOMPARE(repository.getWeight(1), 1.0); + QCOMPARE(repository.getWeight(2), 1.0); } void disabledPopulationsDoNotCountTowardsProbability() From ddaec51fbbdecb88f47167410b65b9b510a63b32 Mon Sep 17 00:00:00 2001 From: Samuli Vuorinen Date: Sun, 21 Feb 2021 17:08:33 +0200 Subject: [PATCH 5/5] Bump version number --- CHANGELOG.md | 2 +- appveyor.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2b7e850..20e71c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 3.1.0 - 2021-02-21 ### Changed diff --git a/appveyor.yml b/appveyor.yml index 40f9c60..c352268 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: "3.0.0-{build}" +version: "3.1.0-{build}" branches: only: - master