From b9080f108344ef8611788ec9017500af876f78ca Mon Sep 17 00:00:00 2001 From: m0dB Date: Sun, 1 Dec 2024 21:12:11 +0100 Subject: [PATCH 1/2] rendergraph library with opengl and scenegraph implementations (not linked yet) --- CMakeLists.txt | 3 + src/rendergraph/CMakeLists.txt | 10 + src/rendergraph/README | 43 +++++ src/rendergraph/common/rendergraph/assert.h | 3 + .../common/rendergraph/attributeinit.h | 18 ++ .../common/rendergraph/attributeset.h | 20 ++ src/rendergraph/common/rendergraph/geometry.h | 67 +++++++ .../common/rendergraph/geometrynode.h | 39 ++++ src/rendergraph/common/rendergraph/material.h | 71 +++++++ .../material/endoftrackmaterial.cpp | 33 ++++ .../rendergraph/material/endoftrackmaterial.h | 19 ++ .../rendergraph/material/patternmaterial.cpp | 33 ++++ .../rendergraph/material/patternmaterial.h | 32 ++++ .../rendergraph/material/rgbamaterial.cpp | 34 ++++ .../rendergraph/material/rgbamaterial.h | 19 ++ .../rendergraph/material/rgbmaterial.cpp | 33 ++++ .../common/rendergraph/material/rgbmaterial.h | 19 ++ .../rendergraph/material/texturematerial.cpp | 33 ++++ .../rendergraph/material/texturematerial.h | 32 ++++ .../rendergraph/material/unicolormaterial.cpp | 33 ++++ .../rendergraph/material/unicolormaterial.h | 19 ++ .../common/rendergraph/materialshader.h | 17 ++ .../common/rendergraph/materialtype.h | 10 + src/rendergraph/common/rendergraph/node.h | 11 ++ .../common/rendergraph/opacitynode.h | 11 ++ src/rendergraph/common/rendergraph/texture.h | 26 +++ src/rendergraph/common/rendergraph/types.h | 36 ++++ src/rendergraph/common/rendergraph/uniform.h | 28 +++ .../common/rendergraph/uniformscache.cpp | 27 +++ .../common/rendergraph/uniformscache.h | 74 ++++++++ .../common/rendergraph/uniformset.cpp | 20 ++ .../common/rendergraph/uniformset.h | 31 ++++ .../vertexupdaters/rgbavertexupdater.h | 174 ++++++++++++++++++ .../vertexupdaters/rgbvertexupdater.h | 152 +++++++++++++++ .../vertexupdaters/texturedvertexupdater.h | 70 +++++++ .../vertexupdaters/vertexupdater.h | 40 ++++ src/rendergraph/common/types.cpp | 111 +++++++++++ src/rendergraph/opengl/CMakeLists.txt | 82 +++++++++ src/rendergraph/opengl/attributeset.cpp | 8 + .../opengl/backend/baseattributeset.cpp | 18 ++ .../opengl/backend/baseattributeset.h | 28 +++ .../opengl/backend/basegeometry.cpp | 21 +++ src/rendergraph/opengl/backend/basegeometry.h | 56 ++++++ .../opengl/backend/basegeometrynode.cpp | 115 ++++++++++++ .../opengl/backend/basegeometrynode.h | 21 +++ .../opengl/backend/basematerial.cpp | 34 ++++ src/rendergraph/opengl/backend/basematerial.h | 32 ++++ .../opengl/backend/basematerialshader.cpp | 19 ++ .../opengl/backend/basematerialshader.h | 26 +++ .../opengl/backend/basematerialtype.h | 6 + src/rendergraph/opengl/backend/basenode.cpp | 62 +++++++ src/rendergraph/opengl/backend/basenode.h | 70 +++++++ .../opengl/backend/baseopacitynode.h | 23 +++ .../opengl/backend/baseopenglnode.cpp | 18 ++ .../opengl/backend/baseopenglnode.h | 27 +++ src/rendergraph/opengl/backend/basetexture.h | 7 + src/rendergraph/opengl/backend/shadercache.h | 44 +++++ src/rendergraph/opengl/engine.cpp | 98 ++++++++++ src/rendergraph/opengl/geometry.cpp | 45 +++++ src/rendergraph/opengl/geometrynode.cpp | 33 ++++ src/rendergraph/opengl/material.cpp | 9 + src/rendergraph/opengl/materialshader.cpp | 58 ++++++ src/rendergraph/opengl/rendergraph/context.h | 8 + src/rendergraph/opengl/rendergraph/engine.h | 35 ++++ .../opengl/rendergraph/nodeinterface.h | 31 ++++ .../opengl/rendergraph/openglnode.h | 7 + src/rendergraph/opengl/texture.cpp | 58 ++++++ src/rendergraph/scenegraph/CMakeLists.txt | 70 +++++++ src/rendergraph/scenegraph/attributeset.cpp | 10 + .../scenegraph/backend/baseattributeset.cpp | 27 +++ .../scenegraph/backend/baseattributeset.h | 37 ++++ .../scenegraph/backend/basegeometry.h | 9 + .../scenegraph/backend/basegeometrynode.h | 7 + .../scenegraph/backend/basematerial.cpp | 27 +++ .../scenegraph/backend/basematerial.h | 19 ++ .../scenegraph/backend/basematerialshader.cpp | 37 ++++ .../scenegraph/backend/basematerialshader.h | 24 +++ .../scenegraph/backend/basematerialtype.h | 7 + src/rendergraph/scenegraph/backend/basenode.h | 7 + .../scenegraph/backend/baseopacitynode.h | 7 + .../scenegraph/backend/basetexture.h | 7 + src/rendergraph/scenegraph/context.cpp | 11 ++ src/rendergraph/scenegraph/geometry.cpp | 70 +++++++ src/rendergraph/scenegraph/geometrynode.cpp | 35 ++++ src/rendergraph/scenegraph/material.cpp | 10 + src/rendergraph/scenegraph/materialshader.cpp | 19 ++ .../scenegraph/rendergraph/context.h | 17 ++ .../scenegraph/rendergraph/nodeinterface.h | 26 +++ src/rendergraph/scenegraph/texture.cpp | 18 ++ 89 files changed, 3051 insertions(+) create mode 100644 src/rendergraph/CMakeLists.txt create mode 100644 src/rendergraph/README create mode 100644 src/rendergraph/common/rendergraph/assert.h create mode 100644 src/rendergraph/common/rendergraph/attributeinit.h create mode 100644 src/rendergraph/common/rendergraph/attributeset.h create mode 100644 src/rendergraph/common/rendergraph/geometry.h create mode 100644 src/rendergraph/common/rendergraph/geometrynode.h create mode 100644 src/rendergraph/common/rendergraph/material.h create mode 100644 src/rendergraph/common/rendergraph/material/endoftrackmaterial.cpp create mode 100644 src/rendergraph/common/rendergraph/material/endoftrackmaterial.h create mode 100644 src/rendergraph/common/rendergraph/material/patternmaterial.cpp create mode 100644 src/rendergraph/common/rendergraph/material/patternmaterial.h create mode 100644 src/rendergraph/common/rendergraph/material/rgbamaterial.cpp create mode 100644 src/rendergraph/common/rendergraph/material/rgbamaterial.h create mode 100644 src/rendergraph/common/rendergraph/material/rgbmaterial.cpp create mode 100644 src/rendergraph/common/rendergraph/material/rgbmaterial.h create mode 100644 src/rendergraph/common/rendergraph/material/texturematerial.cpp create mode 100644 src/rendergraph/common/rendergraph/material/texturematerial.h create mode 100644 src/rendergraph/common/rendergraph/material/unicolormaterial.cpp create mode 100644 src/rendergraph/common/rendergraph/material/unicolormaterial.h create mode 100644 src/rendergraph/common/rendergraph/materialshader.h create mode 100644 src/rendergraph/common/rendergraph/materialtype.h create mode 100644 src/rendergraph/common/rendergraph/node.h create mode 100644 src/rendergraph/common/rendergraph/opacitynode.h create mode 100644 src/rendergraph/common/rendergraph/texture.h create mode 100644 src/rendergraph/common/rendergraph/types.h create mode 100644 src/rendergraph/common/rendergraph/uniform.h create mode 100644 src/rendergraph/common/rendergraph/uniformscache.cpp create mode 100644 src/rendergraph/common/rendergraph/uniformscache.h create mode 100644 src/rendergraph/common/rendergraph/uniformset.cpp create mode 100644 src/rendergraph/common/rendergraph/uniformset.h create mode 100644 src/rendergraph/common/rendergraph/vertexupdaters/rgbavertexupdater.h create mode 100644 src/rendergraph/common/rendergraph/vertexupdaters/rgbvertexupdater.h create mode 100644 src/rendergraph/common/rendergraph/vertexupdaters/texturedvertexupdater.h create mode 100644 src/rendergraph/common/rendergraph/vertexupdaters/vertexupdater.h create mode 100644 src/rendergraph/common/types.cpp create mode 100644 src/rendergraph/opengl/CMakeLists.txt create mode 100644 src/rendergraph/opengl/attributeset.cpp create mode 100644 src/rendergraph/opengl/backend/baseattributeset.cpp create mode 100644 src/rendergraph/opengl/backend/baseattributeset.h create mode 100644 src/rendergraph/opengl/backend/basegeometry.cpp create mode 100644 src/rendergraph/opengl/backend/basegeometry.h create mode 100644 src/rendergraph/opengl/backend/basegeometrynode.cpp create mode 100644 src/rendergraph/opengl/backend/basegeometrynode.h create mode 100644 src/rendergraph/opengl/backend/basematerial.cpp create mode 100644 src/rendergraph/opengl/backend/basematerial.h create mode 100644 src/rendergraph/opengl/backend/basematerialshader.cpp create mode 100644 src/rendergraph/opengl/backend/basematerialshader.h create mode 100644 src/rendergraph/opengl/backend/basematerialtype.h create mode 100644 src/rendergraph/opengl/backend/basenode.cpp create mode 100644 src/rendergraph/opengl/backend/basenode.h create mode 100644 src/rendergraph/opengl/backend/baseopacitynode.h create mode 100644 src/rendergraph/opengl/backend/baseopenglnode.cpp create mode 100644 src/rendergraph/opengl/backend/baseopenglnode.h create mode 100644 src/rendergraph/opengl/backend/basetexture.h create mode 100644 src/rendergraph/opengl/backend/shadercache.h create mode 100644 src/rendergraph/opengl/engine.cpp create mode 100644 src/rendergraph/opengl/geometry.cpp create mode 100644 src/rendergraph/opengl/geometrynode.cpp create mode 100644 src/rendergraph/opengl/material.cpp create mode 100644 src/rendergraph/opengl/materialshader.cpp create mode 100644 src/rendergraph/opengl/rendergraph/context.h create mode 100644 src/rendergraph/opengl/rendergraph/engine.h create mode 100644 src/rendergraph/opengl/rendergraph/nodeinterface.h create mode 100644 src/rendergraph/opengl/rendergraph/openglnode.h create mode 100644 src/rendergraph/opengl/texture.cpp create mode 100644 src/rendergraph/scenegraph/CMakeLists.txt create mode 100644 src/rendergraph/scenegraph/attributeset.cpp create mode 100644 src/rendergraph/scenegraph/backend/baseattributeset.cpp create mode 100644 src/rendergraph/scenegraph/backend/baseattributeset.h create mode 100644 src/rendergraph/scenegraph/backend/basegeometry.h create mode 100644 src/rendergraph/scenegraph/backend/basegeometrynode.h create mode 100644 src/rendergraph/scenegraph/backend/basematerial.cpp create mode 100644 src/rendergraph/scenegraph/backend/basematerial.h create mode 100644 src/rendergraph/scenegraph/backend/basematerialshader.cpp create mode 100644 src/rendergraph/scenegraph/backend/basematerialshader.h create mode 100644 src/rendergraph/scenegraph/backend/basematerialtype.h create mode 100644 src/rendergraph/scenegraph/backend/basenode.h create mode 100644 src/rendergraph/scenegraph/backend/baseopacitynode.h create mode 100644 src/rendergraph/scenegraph/backend/basetexture.h create mode 100644 src/rendergraph/scenegraph/context.cpp create mode 100644 src/rendergraph/scenegraph/geometry.cpp create mode 100644 src/rendergraph/scenegraph/geometrynode.cpp create mode 100644 src/rendergraph/scenegraph/material.cpp create mode 100644 src/rendergraph/scenegraph/materialshader.cpp create mode 100644 src/rendergraph/scenegraph/rendergraph/context.h create mode 100644 src/rendergraph/scenegraph/rendergraph/nodeinterface.h create mode 100644 src/rendergraph/scenegraph/texture.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index df41fa1ea7c..89b5fbaf84f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4572,6 +4572,9 @@ if(VINYLCONTROL) target_link_libraries(mixxx-lib PRIVATE mixxx-xwax) endif() +# rendergraph +add_subdirectory(src/rendergraph/opengl) + # WavPack audio file support find_package(wavpack) default_option(WAVPACK "WavPack audio file support" "wavpack_FOUND") diff --git a/src/rendergraph/CMakeLists.txt b/src/rendergraph/CMakeLists.txt new file mode 100644 index 00000000000..731c47b5122 --- /dev/null +++ b/src/rendergraph/CMakeLists.txt @@ -0,0 +1,10 @@ +find_package(QT NAMES Qt6 REQUIRED COMPONENTS Core) +message(STATUS "Qt version ${QT_VERSION_MAJOR}.${QT_VERSION_MINOR}") + +if(QT_VERSION_MINOR GREATER_EQUAL 6) + set(USE_QSHADER_FOR_GL ON) +endif() + +add_subdirectory(opengl) +add_subdirectory(scenegraph) +add_subdirectory(../../res/shaders/rendergraph shaders) diff --git a/src/rendergraph/README b/src/rendergraph/README new file mode 100644 index 00000000000..ccb176a0ae7 --- /dev/null +++ b/src/rendergraph/README @@ -0,0 +1,43 @@ +rendergraph is an abstraction layer that can be compiled with one of two backends: + +- scenegraph (QtQuick scene graph classes) +- opengl (custom classes using QOpenGL) + +This abstraction layer follows the design of the QtQuick scene graph, with classes such as Material, Geometry, Node and GeometryNode, but it only gives access to and only uses a subset of its functionality. + +The scenegraph backend class the underlying QtQuick scene graph classes directly or almost directly. The opengl layer implements classes that mimic the behaviour of the +Qt scene graph classes. + +The objective of rendergraph is to be able to write code that can be used verbatim within the context of both QWidgets applications and QML applications. This includes using the same Vulkan-style GLSL shader code for both. (The QSGMaterialShader uses the qsb files, QOpenGLShader uses the OpenGL shader code generated by qsb) + +Primarily, rendering with rendergraph uses a graph of Node's, typically of type GeometryNode. A GeometryNode uses a Geometry, which contains the vertex data of what the node renders (positional, texture coordinates, color information...) and a Material, which is the interface to the underlying shader. Uniform data is set through the Material. The QtQuick scene graph documentation is a good started point to understand the design. + +The code is organized as follows: + +common/rendergraph + Public header files. This is the primary API, identical for both backends, and the only files that should be included to write code compatible with both backends. + +common + Implementation of the functionality declared in the common/rendergraph headers that is identical for both backends. + The general guideline is "code duplicated between the backends should be in the common layer". + +common/rendergraph/material + Several basic 'materials' for common rendering operations (e.g. uniform or variying color, texture) + +scenegraph + Implementation of the functionality declared in the common/rendergraph headers that is specific to call the scenegraph backend + +scenegraph/rendergraph + Public header files specific for the opengl backend. This is the layer between QtQuick application code and the common rendergraph API. + +scenegraph/backend + The scenegraph backend implementation, the layer between the common/rendergraph API and the underlying QtQuick scene graph classes. + +opengl + Implementation of the functionality declared in the common/rendergraph headers that is specific to call the opengl backend + +opengl/rendergraph + Public header files specific for the opengl backend. This is the layer between QWidgets/QOpenGL application code and the common rendergraph API. + +opengl/backend + The opengl backend implementation, the layer between the common/rendergraph API and custom implemented classes that mimic the behaviour QtQuick scene graph classes. diff --git a/src/rendergraph/common/rendergraph/assert.h b/src/rendergraph/common/rendergraph/assert.h new file mode 100644 index 00000000000..6b47ad6a7f4 --- /dev/null +++ b/src/rendergraph/common/rendergraph/assert.h @@ -0,0 +1,3 @@ +// rendergraph is a module but we want to include util/assert.h from Mixxx, +// without adding the entire src/ dir to the include paths. +#include "../../../util/assert.h" diff --git a/src/rendergraph/common/rendergraph/attributeinit.h b/src/rendergraph/common/rendergraph/attributeinit.h new file mode 100644 index 00000000000..ccbbbf16b9b --- /dev/null +++ b/src/rendergraph/common/rendergraph/attributeinit.h @@ -0,0 +1,18 @@ +#pragma once + +#include "rendergraph/types.h" + +namespace rendergraph { +struct AttributeInit; +} + +// helper to create an AttributeSet using an initializer_list +struct rendergraph::AttributeInit { + int m_tupleSize; + PrimitiveType m_primitiveType; + + template + static AttributeInit create() { + return AttributeInit{tupleSizeOf(), primitiveTypeOf()}; + } +}; diff --git a/src/rendergraph/common/rendergraph/attributeset.h b/src/rendergraph/common/rendergraph/attributeset.h new file mode 100644 index 00000000000..a7dbab0f3c9 --- /dev/null +++ b/src/rendergraph/common/rendergraph/attributeset.h @@ -0,0 +1,20 @@ +#pragma once + +#include "backend/baseattributeset.h" +#include "rendergraph/attributeinit.h" + +namespace rendergraph { + +class AttributeSet : public BaseAttributeSet { + public: + AttributeSet(std::initializer_list list, const std::vector& names); +}; + +template +AttributeSet makeAttributeSet(const QString (&names)[N]) { + static_assert(sizeof...(Ts) == N, "Mismatch between number of attribute types and names"); + return AttributeSet({(AttributeInit::create())...}, + std::vector(std::cbegin(names), std::cend(names))); +} + +} // namespace rendergraph diff --git a/src/rendergraph/common/rendergraph/geometry.h b/src/rendergraph/common/rendergraph/geometry.h new file mode 100644 index 00000000000..47108777493 --- /dev/null +++ b/src/rendergraph/common/rendergraph/geometry.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include + +#include "backend/basegeometry.h" +#include "rendergraph/attributeset.h" + +namespace rendergraph { +class Geometry; +} // namespace rendergraph + +class rendergraph::Geometry : public rendergraph::BaseGeometry { + public: + using DrawingMode = rendergraph::DrawingMode; + + struct Point2D { + QVector2D position2D; + }; + + struct TexturedPoint2D { + QVector2D position2D; + QVector2D texcoord2D; + }; + + struct RGBColoredPoint2D { + QVector2D position2D; + QVector3D color3D; + }; + + struct RGBAColoredPoint2D { + QVector2D position2D; + QVector4D color4D; + }; + + Geometry(const rendergraph::AttributeSet& attributeSet, int vertexCount); + + const Attribute* attributes() const { + return BaseGeometry::attributes(); + } + + void setAttributeValues(int attributePosition, const float* data, int numTuples); + + int attributeCount() const { + return BaseGeometry::attributeCount(); + } + + void allocate(int vertexCount) { + BaseGeometry::allocate(vertexCount); + } + + int sizeOfVertex() const { + return BaseGeometry::sizeOfVertex(); + } + int vertexCount() const { + return BaseGeometry::vertexCount(); + } + + template + T* vertexDataAs() { + return reinterpret_cast(vertexData()); + } + + DrawingMode drawingMode() const; + + void setDrawingMode(DrawingMode mode); +}; diff --git a/src/rendergraph/common/rendergraph/geometrynode.h b/src/rendergraph/common/rendergraph/geometrynode.h new file mode 100644 index 00000000000..37db115ce40 --- /dev/null +++ b/src/rendergraph/common/rendergraph/geometrynode.h @@ -0,0 +1,39 @@ +#pragma once + +#include "backend/basegeometrynode.h" +#include "rendergraph/geometry.h" +#include "rendergraph/material.h" +#include "rendergraph/nodeinterface.h" + +namespace rendergraph { +class GeometryNode; +} // namespace rendergraph + +class rendergraph::GeometryNode : public rendergraph::NodeInterface { + public: + GeometryNode(); + virtual ~GeometryNode() = default; + + template + void initForRectangles(int numRectangles) { + const int verticesPerRectangle = 6; // 2 triangles + setGeometry(std::make_unique(T_Material::attributes(), + numRectangles * verticesPerRectangle)); + setMaterial(std::make_unique()); + geometry().setDrawingMode(DrawingMode::Triangles); + } + + void setUsePreprocess(bool value); + void setMaterial(std::unique_ptr material); + void setGeometry(std::unique_ptr geometry); + + Geometry& geometry() const; + Material& material() const; + + void markDirtyGeometry(); + void markDirtyMaterial(); + + private: + std::unique_ptr m_pMaterial; + std::unique_ptr m_pGeometry; +}; diff --git a/src/rendergraph/common/rendergraph/material.h b/src/rendergraph/common/rendergraph/material.h new file mode 100644 index 00000000000..ab18e89166a --- /dev/null +++ b/src/rendergraph/common/rendergraph/material.h @@ -0,0 +1,71 @@ +#pragma once + +#include + +#include "backend/basematerial.h" +#include "rendergraph/assert.h" +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" +#include "rendergraph/texture.h" +#include "rendergraph/uniformscache.h" +#include "rendergraph/uniformset.h" + +namespace rendergraph { +class Material; +} // namespace rendergraph + +class rendergraph::Material : public rendergraph::BaseMaterial { + public: + Material(const UniformSet& uniformSet); + virtual ~Material(); + + // see QSGMaterial::compare. + // TODO decide if this should be virtual. QSGMaterial::compare is virtual + // to concrete Material can implement a compare function, but in rendergraph + // we can compare the uniforms cache and texture already here, which seems + // sufficient. + int compare(const Material* pOther) const { + DEBUG_ASSERT(type() == pOther->type()); + int cacheCompareResult = std::memcmp(m_uniformsCache.data(), + pOther->m_uniformsCache.data(), + m_uniformsCache.size()); + if (cacheCompareResult != 0) { + return cacheCompareResult < 0 ? -1 : 1; + } + // TODO multiple textures + if (!texture(0) || !pOther->texture(0)) { + return texture(0) ? 1 : -1; + } + + const qint64 diff = texture(0)->comparisonKey() - pOther->texture(0)->comparisonKey(); + return diff < 0 ? -1 : (diff > 0 ? 1 : 0); + } + + virtual std::unique_ptr createShader() const = 0; + + template + void setUniform(int uniformIndex, const T& value) { + m_uniformsCache.set(uniformIndex, value); + m_uniformsCacheDirty = true; + } + + const UniformsCache& uniformsCache() const { + return m_uniformsCache; + } + + bool clearUniformsCacheDirty() { + if (m_uniformsCacheDirty) { + m_uniformsCacheDirty = false; + return true; + } + return false; + } + + virtual Texture* texture(int) const { + return nullptr; + } + + private: + UniformsCache m_uniformsCache; + bool m_uniformsCacheDirty{}; +}; diff --git a/src/rendergraph/common/rendergraph/material/endoftrackmaterial.cpp b/src/rendergraph/common/rendergraph/material/endoftrackmaterial.cpp new file mode 100644 index 00000000000..ee35b465934 --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/endoftrackmaterial.cpp @@ -0,0 +1,33 @@ +#include "endoftrackmaterial.h" + +#include + +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" +#include "rendergraph/uniformset.h" + +using namespace rendergraph; + +EndOfTrackMaterial::EndOfTrackMaterial() + : Material(uniforms()) { +} + +/* static */ const AttributeSet& EndOfTrackMaterial::attributes() { + static AttributeSet set = makeAttributeSet({"position", "gradient"}); + return set; +} + +/* static */ const UniformSet& EndOfTrackMaterial::uniforms() { + static UniformSet set = makeUniformSet({"ubuf.color"}); + return set; +} + +MaterialType* EndOfTrackMaterial::type() const { + static MaterialType type; + return &type; +} + +std::unique_ptr EndOfTrackMaterial::createShader() const { + return std::make_unique( + "endoftrack.vert", "endoftrack.frag", uniforms(), attributes()); +} diff --git a/src/rendergraph/common/rendergraph/material/endoftrackmaterial.h b/src/rendergraph/common/rendergraph/material/endoftrackmaterial.h new file mode 100644 index 00000000000..94c80693799 --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/endoftrackmaterial.h @@ -0,0 +1,19 @@ +#include "rendergraph/attributeset.h" +#include "rendergraph/material.h" + +namespace rendergraph { +class EndOfTrackMaterial; +} + +class rendergraph::EndOfTrackMaterial : public rendergraph::Material { + public: + EndOfTrackMaterial(); + + static const AttributeSet& attributes(); + + static const UniformSet& uniforms(); + + MaterialType* type() const override; + + std::unique_ptr createShader() const override; +}; diff --git a/src/rendergraph/common/rendergraph/material/patternmaterial.cpp b/src/rendergraph/common/rendergraph/material/patternmaterial.cpp new file mode 100644 index 00000000000..864f4a60adf --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/patternmaterial.cpp @@ -0,0 +1,33 @@ +#include "patternmaterial.h" + +#include +#include + +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" + +using namespace rendergraph; + +PatternMaterial::PatternMaterial() + : Material(uniforms()) { +} + +/* static */ const AttributeSet& PatternMaterial::attributes() { + static AttributeSet set = makeAttributeSet({"position", "texcoord"}); + return set; +} + +/* static */ const UniformSet& PatternMaterial::uniforms() { + static UniformSet set = makeUniformSet({"ubuf.matrix"}); + return set; +} + +MaterialType* PatternMaterial::type() const { + static MaterialType type; + return &type; +} + +std::unique_ptr PatternMaterial::createShader() const { + return std::make_unique( + "pattern.vert", "pattern.frag", uniforms(), attributes()); +} diff --git a/src/rendergraph/common/rendergraph/material/patternmaterial.h b/src/rendergraph/common/rendergraph/material/patternmaterial.h new file mode 100644 index 00000000000..661246abd05 --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/patternmaterial.h @@ -0,0 +1,32 @@ +#include "rendergraph/attributeset.h" +#include "rendergraph/material.h" +#include "rendergraph/texture.h" +#include "rendergraph/uniformset.h" + +namespace rendergraph { +class PatternMaterial; +} + +class rendergraph::PatternMaterial : public rendergraph::Material { + public: + PatternMaterial(); + + static const AttributeSet& attributes(); + + static const UniformSet& uniforms(); + + MaterialType* type() const override; + + std::unique_ptr createShader() const override; + + Texture* texture(int) const override { + return m_pTexture.get(); + } + + void setTexture(std::unique_ptr texture) { + m_pTexture = std::move(texture); + } + + private: + std::unique_ptr m_pTexture; +}; diff --git a/src/rendergraph/common/rendergraph/material/rgbamaterial.cpp b/src/rendergraph/common/rendergraph/material/rgbamaterial.cpp new file mode 100644 index 00000000000..e81382bf9ce --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/rgbamaterial.cpp @@ -0,0 +1,34 @@ +#include "rgbamaterial.h" + +#include + +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" +#include "rendergraph/uniformset.h" + +using namespace rendergraph; + +RGBAMaterial::RGBAMaterial() + : Material(uniforms()) { +} + +// static +const AttributeSet& RGBAMaterial::attributes() { + static AttributeSet set = makeAttributeSet({"position", "color"}); + return set; +} + +/* static */ const UniformSet& RGBAMaterial::uniforms() { + static UniformSet set = makeUniformSet({"ubuf.matrix"}); + return set; +} + +MaterialType* RGBAMaterial::type() const { + static MaterialType type; + return &type; +} + +std::unique_ptr RGBAMaterial::createShader() const { + return std::make_unique( + "rgba.vert", "rgba.frag", uniforms(), attributes()); +} diff --git a/src/rendergraph/common/rendergraph/material/rgbamaterial.h b/src/rendergraph/common/rendergraph/material/rgbamaterial.h new file mode 100644 index 00000000000..0921ebb4fae --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/rgbamaterial.h @@ -0,0 +1,19 @@ +#include "rendergraph/attributeset.h" +#include "rendergraph/material.h" + +namespace rendergraph { +class RGBAMaterial; +} + +class rendergraph::RGBAMaterial : public rendergraph::Material { + public: + RGBAMaterial(); + + static const AttributeSet& attributes(); + + static const UniformSet& uniforms(); + + MaterialType* type() const override; + + std::unique_ptr createShader() const override; +}; diff --git a/src/rendergraph/common/rendergraph/material/rgbmaterial.cpp b/src/rendergraph/common/rendergraph/material/rgbmaterial.cpp new file mode 100644 index 00000000000..455555d1e97 --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/rgbmaterial.cpp @@ -0,0 +1,33 @@ +#include "rgbmaterial.h" + +#include + +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" +#include "rendergraph/uniformset.h" + +using namespace rendergraph; + +RGBMaterial::RGBMaterial() + : Material(uniforms()) { +} + +/* static */ const AttributeSet& RGBMaterial::attributes() { + static AttributeSet set = makeAttributeSet({"position", "color"}); + return set; +} + +/* static */ const UniformSet& RGBMaterial::uniforms() { + static UniformSet set = makeUniformSet({"ubuf.matrix"}); + return set; +} + +MaterialType* RGBMaterial::type() const { + static MaterialType type; + return &type; +} + +std::unique_ptr RGBMaterial::createShader() const { + return std::make_unique( + "rgb.vert", "rgb.frag", uniforms(), attributes()); +} diff --git a/src/rendergraph/common/rendergraph/material/rgbmaterial.h b/src/rendergraph/common/rendergraph/material/rgbmaterial.h new file mode 100644 index 00000000000..cfe1fde7782 --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/rgbmaterial.h @@ -0,0 +1,19 @@ +#include "rendergraph/attributeset.h" +#include "rendergraph/material.h" + +namespace rendergraph { +class RGBMaterial; +} + +class rendergraph::RGBMaterial : public rendergraph::Material { + public: + RGBMaterial(); + + static const AttributeSet& attributes(); + + static const UniformSet& uniforms(); + + MaterialType* type() const override; + + std::unique_ptr createShader() const override; +}; diff --git a/src/rendergraph/common/rendergraph/material/texturematerial.cpp b/src/rendergraph/common/rendergraph/material/texturematerial.cpp new file mode 100644 index 00000000000..b3f61767626 --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/texturematerial.cpp @@ -0,0 +1,33 @@ +#include "texturematerial.h" + +#include +#include + +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" + +using namespace rendergraph; + +TextureMaterial::TextureMaterial() + : Material(uniforms()) { +} + +/* static */ const AttributeSet& TextureMaterial::attributes() { + static AttributeSet set = makeAttributeSet({"position", "texcoord"}); + return set; +} + +/* static */ const UniformSet& TextureMaterial::uniforms() { + static UniformSet set = makeUniformSet({"ubuf.matrix"}); + return set; +} + +MaterialType* TextureMaterial::type() const { + static MaterialType type; + return &type; +} + +std::unique_ptr TextureMaterial::createShader() const { + return std::make_unique( + "texture.vert", "texture.frag", uniforms(), attributes()); +} diff --git a/src/rendergraph/common/rendergraph/material/texturematerial.h b/src/rendergraph/common/rendergraph/material/texturematerial.h new file mode 100644 index 00000000000..2fa5a2310cc --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/texturematerial.h @@ -0,0 +1,32 @@ +#include "rendergraph/attributeset.h" +#include "rendergraph/material.h" +#include "rendergraph/texture.h" +#include "rendergraph/uniformset.h" + +namespace rendergraph { +class TextureMaterial; +} + +class rendergraph::TextureMaterial : public rendergraph::Material { + public: + TextureMaterial(); + + static const AttributeSet& attributes(); + + static const UniformSet& uniforms(); + + MaterialType* type() const override; + + std::unique_ptr createShader() const override; + + Texture* texture(int /*binding*/) const override { + return m_pTexture.get(); + } + + void setTexture(std::unique_ptr texture) { + m_pTexture = std::move(texture); + } + + private: + std::unique_ptr m_pTexture; +}; diff --git a/src/rendergraph/common/rendergraph/material/unicolormaterial.cpp b/src/rendergraph/common/rendergraph/material/unicolormaterial.cpp new file mode 100644 index 00000000000..d67fd16320c --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/unicolormaterial.cpp @@ -0,0 +1,33 @@ +#include "unicolormaterial.h" + +#include + +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" +#include "rendergraph/uniformset.h" + +using namespace rendergraph; + +UniColorMaterial::UniColorMaterial() + : Material(uniforms()) { +} + +/* static */ const AttributeSet& UniColorMaterial::attributes() { + static AttributeSet set = makeAttributeSet({"position"}); + return set; +} + +/* static */ const UniformSet& UniColorMaterial::uniforms() { + static UniformSet set = makeUniformSet({"ubuf.matrix", "ubuf.color"}); + return set; +} + +MaterialType* UniColorMaterial::type() const { + static MaterialType type; + return &type; +} + +std::unique_ptr UniColorMaterial::createShader() const { + return std::make_unique( + "unicolor.vert", "unicolor.frag", uniforms(), attributes()); +} diff --git a/src/rendergraph/common/rendergraph/material/unicolormaterial.h b/src/rendergraph/common/rendergraph/material/unicolormaterial.h new file mode 100644 index 00000000000..26225f4d3c6 --- /dev/null +++ b/src/rendergraph/common/rendergraph/material/unicolormaterial.h @@ -0,0 +1,19 @@ +#include "rendergraph/attributeset.h" +#include "rendergraph/material.h" + +namespace rendergraph { +class UniColorMaterial; +} + +class rendergraph::UniColorMaterial : public rendergraph::Material { + public: + UniColorMaterial(); + + static const AttributeSet& attributes(); + + static const UniformSet& uniforms(); + + MaterialType* type() const override; + + std::unique_ptr createShader() const override; +}; diff --git a/src/rendergraph/common/rendergraph/materialshader.h b/src/rendergraph/common/rendergraph/materialshader.h new file mode 100644 index 00000000000..43c811ebebd --- /dev/null +++ b/src/rendergraph/common/rendergraph/materialshader.h @@ -0,0 +1,17 @@ +#pragma once + +#include "backend/basematerialshader.h" +#include "rendergraph/attributeset.h" +#include "rendergraph/uniformset.h" + +namespace rendergraph { +class MaterialShader; +} // namespace rendergraph + +class rendergraph::MaterialShader : public rendergraph::BaseMaterialShader { + public: + MaterialShader(const char* vertexShaderFile, + const char* fragmentShaderFile, + const UniformSet& uniforms, + const AttributeSet& attributeSet); +}; diff --git a/src/rendergraph/common/rendergraph/materialtype.h b/src/rendergraph/common/rendergraph/materialtype.h new file mode 100644 index 00000000000..67da71e91f3 --- /dev/null +++ b/src/rendergraph/common/rendergraph/materialtype.h @@ -0,0 +1,10 @@ +#pragma once + +#include "backend/basematerialtype.h" + +namespace rendergraph { +class MaterialType; +} + +class rendergraph::MaterialType : public rendergraph::BaseMaterialType { +}; diff --git a/src/rendergraph/common/rendergraph/node.h b/src/rendergraph/common/rendergraph/node.h new file mode 100644 index 00000000000..3060648e846 --- /dev/null +++ b/src/rendergraph/common/rendergraph/node.h @@ -0,0 +1,11 @@ +#pragma once + +#include "backend/basenode.h" +#include "rendergraph/nodeinterface.h" + +namespace rendergraph { +class Node; +} // namespace rendergraph + +class rendergraph::Node : public rendergraph::NodeInterface { +}; diff --git a/src/rendergraph/common/rendergraph/opacitynode.h b/src/rendergraph/common/rendergraph/opacitynode.h new file mode 100644 index 00000000000..d69f0b1c42a --- /dev/null +++ b/src/rendergraph/common/rendergraph/opacitynode.h @@ -0,0 +1,11 @@ +#pragma once + +#include "backend/baseopacitynode.h" +#include "rendergraph/nodeinterface.h" + +namespace rendergraph { +class OpacityNode; +} // namespace rendergraph + +class rendergraph::OpacityNode : public rendergraph::NodeInterface { +}; diff --git a/src/rendergraph/common/rendergraph/texture.h b/src/rendergraph/common/rendergraph/texture.h new file mode 100644 index 00000000000..aa6bbe95ccf --- /dev/null +++ b/src/rendergraph/common/rendergraph/texture.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "backend/basetexture.h" +#include "rendergraph/context.h" + +namespace rendergraph { +class Texture; +} // namespace rendergraph + +class rendergraph::Texture { + public: + Texture(Context* pContext, const QImage& image); + + BaseTexture* backendTexture() const { + return m_pTexture.get(); + } + + // used by Material::compare + qint64 comparisonKey() const; + + private: + const std::unique_ptr m_pTexture{}; +}; diff --git a/src/rendergraph/common/rendergraph/types.h b/src/rendergraph/common/rendergraph/types.h new file mode 100644 index 00000000000..f92e8de6cda --- /dev/null +++ b/src/rendergraph/common/rendergraph/types.h @@ -0,0 +1,36 @@ +#pragma once + +namespace rendergraph { + +enum class DrawingMode { + Triangles, + TriangleStrip +}; + +enum class PrimitiveType { + UInt, + Float, +}; + +enum class Type { + UInt, + Float, + Vector2D, + Vector3D, + Vector4D, + Matrix4x4 +}; + +int sizeOf(Type type); +int sizeOf(PrimitiveType primitiveType); + +template +Type typeOf(); + +template +PrimitiveType primitiveTypeOf(); + +template +int tupleSizeOf(); + +} // namespace rendergraph diff --git a/src/rendergraph/common/rendergraph/uniform.h b/src/rendergraph/common/rendergraph/uniform.h new file mode 100644 index 00000000000..19a6a9c74a3 --- /dev/null +++ b/src/rendergraph/common/rendergraph/uniform.h @@ -0,0 +1,28 @@ +#pragma once + +#include + +#include "rendergraph/types.h" + +namespace rendergraph { +struct Uniform; +} + +struct rendergraph::Uniform { + const Type m_type; + const QString m_name; + + Uniform(Type type) + : m_type{type} { + } + + Uniform(Type type, QString name) + : m_type{type}, + m_name{std::move(name)} { + } + + template + static Uniform create() { + return Uniform(typeOf()); + } +}; diff --git a/src/rendergraph/common/rendergraph/uniformscache.cpp b/src/rendergraph/common/rendergraph/uniformscache.cpp new file mode 100644 index 00000000000..c94539631d7 --- /dev/null +++ b/src/rendergraph/common/rendergraph/uniformscache.cpp @@ -0,0 +1,27 @@ +#include "rendergraph/uniformscache.h" + +#include "rendergraph/uniformset.h" + +using namespace rendergraph; + +UniformsCache::UniformsCache(const UniformSet& uniformSet) { + int offset = 0; + m_infos.reserve(uniformSet.uniforms().size()); + for (const auto& uniform : uniformSet.uniforms()) { + const int size = sizeOf(uniform.m_type); + m_infos.push_back({uniform.m_type, offset}); + offset += size; + } + m_byteArray.resize(offset); + m_byteArray.fill('\0'); +} + +UniformsCache::~UniformsCache() = default; + +void UniformsCache::set(int uniformIndex, const void* ptr, int size) { + memcpy(m_byteArray.data() + m_infos[uniformIndex].m_offset, ptr, size); +} + +void UniformsCache::get(int uniformIndex, void* ptr, int size) const { + memcpy(ptr, m_byteArray.data() + m_infos[uniformIndex].m_offset, size); +} diff --git a/src/rendergraph/common/rendergraph/uniformscache.h b/src/rendergraph/common/rendergraph/uniformscache.h new file mode 100644 index 00000000000..045887f0c37 --- /dev/null +++ b/src/rendergraph/common/rendergraph/uniformscache.h @@ -0,0 +1,74 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "rendergraph/assert.h" +#include "rendergraph/types.h" +#include "rendergraph/uniformset.h" + +namespace rendergraph { +class UniformsCache; +} // namespace rendergraph + +class rendergraph::UniformsCache { + public: + UniformsCache(const UniformSet& uniformSet); + ~UniformsCache(); + + template + void set(int uniformIndex, const T& value) { + DEBUG_ASSERT(type(uniformIndex) == typeOf()); + DEBUG_ASSERT(std::is_trivially_copyable()); + set(uniformIndex, static_cast(&value), sizeOf(typeOf())); + } + + template + T get(int uniformIndex) const { + DEBUG_ASSERT(type(uniformIndex) == typeOf()); + DEBUG_ASSERT(std::is_trivially_copyable()); + T value; + get(uniformIndex, static_cast(&value), sizeof(T)); + return value; + } + Type type(int uniformIndex) const { + return m_infos[uniformIndex].m_type; + } + + const char* data() const { + return m_byteArray.data(); + } + qsizetype size() const { + return m_byteArray.size(); + } + int count() const { + return static_cast(m_infos.size()); + } + + private: + void set(int uniformIndex, const void* ptr, int size); + void get(int uniformIndex, void* ptr, int size) const; + + struct Info { + const Type m_type; + const int m_offset; + }; + + std::vector m_infos; + QByteArray m_byteArray; +}; + +template<> +inline void rendergraph::UniformsCache::set(int uniformIndex, const QColor& color) { + set(uniformIndex, QVector4D{color.redF(), color.greenF(), color.blueF(), color.alphaF()}); +} + +template<> +inline void rendergraph::UniformsCache::set( + int uniformIndex, const QMatrix4x4& matrix) { + DEBUG_ASSERT(type(uniformIndex) == typeOf()); + set(uniformIndex, matrix.constData(), sizeOf(typeOf())); +} diff --git a/src/rendergraph/common/rendergraph/uniformset.cpp b/src/rendergraph/common/rendergraph/uniformset.cpp new file mode 100644 index 00000000000..68e077613bd --- /dev/null +++ b/src/rendergraph/common/rendergraph/uniformset.cpp @@ -0,0 +1,20 @@ +#include "rendergraph/uniformset.h" + +using namespace rendergraph; + +UniformSet::UniformSet(std::initializer_list list, const std::vector& names) { + int i = 0; + for (auto item : list) { + add(Uniform{item.m_type, names[i++]}); + } +} + +UniformSet::~UniformSet() = default; + +void UniformSet::add(const Uniform& uniform) { + m_uniforms.push_back(uniform); +} + +const std::vector& UniformSet::uniforms() const { + return m_uniforms; +} diff --git a/src/rendergraph/common/rendergraph/uniformset.h b/src/rendergraph/common/rendergraph/uniformset.h new file mode 100644 index 00000000000..34af87e5c94 --- /dev/null +++ b/src/rendergraph/common/rendergraph/uniformset.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include + +#include "rendergraph/uniform.h" + +namespace rendergraph { +class UniformSet; +} + +class rendergraph::UniformSet { + public: + UniformSet(std::initializer_list list, const std::vector& names); + + ~UniformSet(); + + const std::vector& uniforms() const; + + private: + void add(const Uniform& uniform); + std::vector m_uniforms; +}; + +namespace rendergraph { +template +UniformSet makeUniformSet(const std::vector& names) { + return UniformSet({(Uniform::create())...}, names); +} +} // namespace rendergraph diff --git a/src/rendergraph/common/rendergraph/vertexupdaters/rgbavertexupdater.h b/src/rendergraph/common/rendergraph/vertexupdaters/rgbavertexupdater.h new file mode 100644 index 00000000000..afa7e466d1c --- /dev/null +++ b/src/rendergraph/common/rendergraph/vertexupdaters/rgbavertexupdater.h @@ -0,0 +1,174 @@ +#pragma once + +#include "rendergraph/geometry.h" + +namespace rendergraph { +class RGBAVertexUpdater; +} + +class rendergraph::RGBAVertexUpdater { + public: + RGBAVertexUpdater(Geometry::RGBAColoredPoint2D* pData) + : m_pData(pData), + m_pWrite(pData) { + } + + void addRectangle( + QVector2D lt, + QVector2D rb, + QVector4D rgba) { + addRectangle(lt.x(), lt.y(), rb.x(), rb.y(), rgba.x(), rgba.y(), rgba.z(), rgba.w()); + } + void addRectangleVGradient( + QVector2D lt, + QVector2D rb, + QVector4D rgbat, + QVector4D rgbab) { + addRectangleVGradient(lt.x(), + lt.y(), + rb.x(), + rb.y(), + rgbat.x(), + rgbat.y(), + rgbat.z(), + rgbat.w(), + rgbab.x(), + rgbab.y(), + rgbab.z(), + rgbab.w()); + } + void addRectangleHGradient( + QVector2D lt, + QVector2D rb, + QVector4D rgbal, + QVector4D rgbar) { + addRectangleHGradient(lt.x(), + lt.y(), + rb.x(), + rb.y(), + rgbal.x(), + rgbal.y(), + rgbal.z(), + rgbal.w(), + rgbar.x(), + rgbar.y(), + rgbar.z(), + rgbar.w()); + } + int index() const { + return static_cast(m_pWrite - m_pData); + } + void addTriangle(QVector2D p1, QVector2D p2, QVector2D p3, QVector4D rgba) { + addTriangle(p1.x(), + p1.y(), + p2.x(), + p2.y(), + p3.x(), + p3.y(), + rgba.x(), + rgba.y(), + rgba.z(), + rgba.w()); + } + void addTriangle(QVector2D p1, + QVector2D p2, + QVector2D p3, + QVector4D rgba1, + QVector4D rgba2, + QVector4D rgba3) { + addTriangle(p1.x(), + p1.y(), + p2.x(), + p2.y(), + p3.x(), + p3.y(), + rgba1.x(), + rgba1.y(), + rgba1.z(), + rgba1.w(), + rgba2.x(), + rgba2.y(), + rgba2.z(), + rgba2.w(), + rgba3.x(), + rgba3.y(), + rgba3.z(), + rgba3.w()); + } + + private: + void addRectangle(float x1, float y1, float x2, float y2, float r, float g, float b, float a) { + addTriangle(x1, y1, x2, y1, x1, y2, r, g, b, a); + addTriangle(x1, y2, x2, y2, x2, y1, r, g, b, a); + } + void addRectangleVGradient( + float x1, + float y1, + float x2, + float y2, + float r1, + float g1, + float b1, + float a1, + float r2, + float g2, + float b2, + float a2) { + addTriangle(x1, y1, x2, y1, x1, y2, r1, g1, b1, a1, r1, g1, b1, a1, r2, g2, b2, a2); + addTriangle(x1, y2, x2, y2, x2, y1, r2, g2, b2, a2, r2, g2, b2, a2, r1, g1, b1, a1); + } + void addRectangleHGradient( + float x1, + float y1, + float x2, + float y2, + float r1, + float g1, + float b1, + float a1, + float r2, + float g2, + float b2, + float a2) { + addTriangle(x1, y1, x2, y1, x1, y2, r1, g1, b1, a1, r2, g2, b2, a2, r1, g1, b1, a1); + addTriangle(x1, y2, x2, y2, x2, y1, r1, g1, b1, a1, r2, g2, b2, a2, r2, g2, b2, a2); + } + void addTriangle(float x1, + float y1, + float x2, + float y2, + float x3, + float y3, + float r, + float g, + float b, + float a) { + *m_pWrite++ = Geometry::RGBAColoredPoint2D{{x1, y1}, {r, g, b, a}}; + *m_pWrite++ = Geometry::RGBAColoredPoint2D{{x2, y2}, {r, g, b, a}}; + *m_pWrite++ = Geometry::RGBAColoredPoint2D{{x3, y3}, {r, g, b, a}}; + } + void addTriangle(float x1, + float y1, + float x2, + float y2, + float x3, + float y3, + float r1, + float g1, + float b1, + float a1, + float r2, + float g2, + float b2, + float a2, + float r3, + float g3, + float b3, + float a3) { + *m_pWrite++ = Geometry::RGBAColoredPoint2D{{x1, y1}, {r1, g1, b1, a1}}; + *m_pWrite++ = Geometry::RGBAColoredPoint2D{{x2, y2}, {r2, g2, b2, a2}}; + *m_pWrite++ = Geometry::RGBAColoredPoint2D{{x3, y3}, {r3, g3, b3, a3}}; + } + Geometry::RGBAColoredPoint2D* const m_pData; + Geometry::RGBAColoredPoint2D* m_pWrite; +}; diff --git a/src/rendergraph/common/rendergraph/vertexupdaters/rgbvertexupdater.h b/src/rendergraph/common/rendergraph/vertexupdaters/rgbvertexupdater.h new file mode 100644 index 00000000000..c7191e902ec --- /dev/null +++ b/src/rendergraph/common/rendergraph/vertexupdaters/rgbvertexupdater.h @@ -0,0 +1,152 @@ +#pragma once + +#include "rendergraph/geometry.h" + +namespace rendergraph { +class RGBVertexUpdater; +} + +class rendergraph::RGBVertexUpdater { + public: + RGBVertexUpdater(Geometry::RGBColoredPoint2D* pData) + : m_pData(pData), + m_pWrite(pData) { + } + + void addRectangle( + QVector2D lt, + QVector2D rb, + QVector3D rgb) { + addRectangle(lt.x(), lt.y(), rb.x(), rb.y(), rgb.x(), rgb.y(), rgb.z()); + } + void addRectangleVGradient( + QVector2D lt, + QVector2D rb, + QVector3D rgbt, + QVector3D rgbb) { + addRectangleVGradient(lt.x(), + lt.y(), + rb.x(), + rb.y(), + rgbt.x(), + rgbt.y(), + rgbt.z(), + rgbb.x(), + rgbb.y(), + rgbb.z()); + } + void addRectangleHGradient( + QVector2D lt, + QVector2D rb, + QVector3D rgbl, + QVector3D rgbr) { + addRectangleHGradient(lt.x(), + lt.y(), + rb.x(), + rb.y(), + rgbl.x(), + rgbl.y(), + rgbl.z(), + rgbr.x(), + rgbr.y(), + rgbr.z()); + } + void addTriangle(QVector2D p1, QVector2D p2, QVector2D p3, QVector3D rgb) { + addTriangle(p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y(), rgb.x(), rgb.y(), rgb.z()); + } + void addTriangle(QVector2D p1, + QVector2D p2, + QVector2D p3, + QVector3D rgb1, + QVector3D rgb2, + QVector3D rgb3) { + addTriangle(p1.x(), + p1.y(), + p2.x(), + p2.y(), + p3.x(), + p3.y(), + rgb1.x(), + rgb1.y(), + rgb1.z(), + rgb2.x(), + rgb2.y(), + rgb2.z(), + rgb3.x(), + rgb3.y(), + rgb3.z()); + } + int index() const { + return static_cast(m_pWrite - m_pData); + } + + private: + void addRectangle(float x1, float y1, float x2, float y2, float r, float g, float b) { + addTriangle(x1, y1, x2, y1, x1, y2, r, g, b); + addTriangle(x1, y2, x2, y2, x2, y1, r, g, b); + } + void addRectangleVGradient( + float x1, + float y1, + float x2, + float y2, + float r1, + float g1, + float b1, + float r2, + float g2, + float b2) { + addTriangle(x1, y1, x2, y1, x1, y2, r1, g1, b1, r1, g1, b1, r2, g2, b2); + addTriangle(x1, y2, x2, y2, x2, y1, r2, g2, b2, r2, g2, b2, r1, g1, b1); + } + void addRectangleHGradient( + float x1, + float y1, + float x2, + float y2, + float r1, + float g1, + float b1, + float r2, + float g2, + float b2) { + addTriangle(x1, y1, x2, y1, x1, y2, r1, g1, b1, r2, g2, b2, r1, g1, b1); + addTriangle(x1, y2, x2, y2, x2, y1, r1, g1, b1, r2, g2, b2, r2, g2, b2); + } + void addTriangle(float x1, + float y1, + float x2, + float y2, + float x3, + float y3, + float r, + float g, + float b) { + *m_pWrite++ = Geometry::RGBColoredPoint2D{{x1, y1}, {r, g, b}}; + *m_pWrite++ = Geometry::RGBColoredPoint2D{{x2, y2}, {r, g, b}}; + *m_pWrite++ = Geometry::RGBColoredPoint2D{{x3, y3}, {r, g, b}}; + } + void addTriangle(float x1, + float y1, + float x2, + float y2, + float x3, + float y3, + float r1, + float g1, + float b1, + float r2, + float g2, + float b2, + float r3, + float g3, + float b3) { + *m_pWrite++ = Geometry::RGBColoredPoint2D{{x1, y1}, {r1, g1, b1}}; + *m_pWrite++ = Geometry::RGBColoredPoint2D{{x2, y2}, {r2, g2, b2}}; + *m_pWrite++ = Geometry::RGBColoredPoint2D{{x3, y3}, {r3, g3, b3}}; + } + + private: + Geometry::RGBColoredPoint2D* const m_pData; + Geometry::RGBColoredPoint2D* m_pWrite; +}; diff --git a/src/rendergraph/common/rendergraph/vertexupdaters/texturedvertexupdater.h b/src/rendergraph/common/rendergraph/vertexupdaters/texturedvertexupdater.h new file mode 100644 index 00000000000..29aa5beca04 --- /dev/null +++ b/src/rendergraph/common/rendergraph/vertexupdaters/texturedvertexupdater.h @@ -0,0 +1,70 @@ +#pragma once + +#include "rendergraph/geometry.h" + +namespace rendergraph { +class TexturedVertexUpdater; +} + +class rendergraph::TexturedVertexUpdater { + public: + TexturedVertexUpdater(Geometry::TexturedPoint2D* pData) + : m_pData(pData), + m_pWrite(pData) { + } + void addRectangle( + QVector2D lt, QVector2D rb) { + addRectangle(lt.x(), lt.y(), rb.x(), rb.y(), 0.f, 0.f, 1.f, 1.f); + } + void addRectangle( + QVector2D lt, QVector2D rb, QVector2D tlr, QVector2D trb) { + addRectangle(lt.x(), lt.y(), rb.x(), rb.y(), tlr.x(), tlr.y(), trb.x(), trb.y()); + } + void addTriangle(QVector2D p1, + QVector2D p2, + QVector2D p3, + QVector2D tp1, + QVector2D tp2, + QVector2D tp3) { + addTriangle(p1.x(), + p1.y(), + p2.x(), + p2.y(), + p3.x(), + p3.y(), + tp1.x(), + tp1.y(), + tp2.x(), + tp2.y(), + tp3.x(), + tp3.y()); + } + int index() const { + return static_cast(m_pWrite - m_pData); + } + + private: + void addRectangle( + float x1, float y1, float x2, float y2, float tx1, float ty1, float tx2, float ty2) { + addTriangle(x1, y1, x2, y1, x1, y2, tx1, ty1, tx2, ty1, tx1, ty2); + addTriangle(x1, y2, x2, y2, x2, y1, tx1, ty2, tx2, ty2, tx2, ty1); + } + void addTriangle(float x1, + float y1, + float x2, + float y2, + float x3, + float y3, + float tx1, + float ty1, + float tx2, + float ty2, + float tx3, + float ty3) { + *m_pWrite++ = Geometry::TexturedPoint2D{{x1, y1}, {tx1, ty1}}; + *m_pWrite++ = Geometry::TexturedPoint2D{{x2, y2}, {tx2, ty2}}; + *m_pWrite++ = Geometry::TexturedPoint2D{{x3, y3}, {tx3, ty3}}; + } + Geometry::TexturedPoint2D* const m_pData; + Geometry::TexturedPoint2D* m_pWrite; +}; diff --git a/src/rendergraph/common/rendergraph/vertexupdaters/vertexupdater.h b/src/rendergraph/common/rendergraph/vertexupdaters/vertexupdater.h new file mode 100644 index 00000000000..4ae381db209 --- /dev/null +++ b/src/rendergraph/common/rendergraph/vertexupdaters/vertexupdater.h @@ -0,0 +1,40 @@ +#pragma once + +namespace rendergraph { +class VertexUpdater; +} + +class rendergraph::VertexUpdater { + public: + VertexUpdater(Geometry::Point2D* pData) + : m_pData(pData), + m_pWrite(pData) { + } + void addRectangle( + QVector2D lt, QVector2D rb) { + addRectangle(lt.x(), lt.y(), rb.x(), rb.y()); + } + void addTriangle(QVector2D p1, QVector2D p2, QVector2D p3) { + addTriangle(p1.x(), p1.y(), p2.x(), p2.y(), p3.x(), p3.y()); + } + int index() const { + return static_cast(m_pWrite - m_pData); + } + + private: + void addRectangle( + float x1, + float y1, + float x2, + float y2) { + addTriangle(x1, y1, x2, y1, x1, y2); + addTriangle(x1, y2, x2, y2, x2, y1); + } + void addTriangle(float x1, float y1, float x2, float y2, float x3, float y3) { + *m_pWrite++ = Geometry::Point2D{{x1, y1}}; + *m_pWrite++ = Geometry::Point2D{{x2, y2}}; + *m_pWrite++ = Geometry::Point2D{{x3, y3}}; + } + Geometry::Point2D* const m_pData; + Geometry::Point2D* m_pWrite; +}; diff --git a/src/rendergraph/common/types.cpp b/src/rendergraph/common/types.cpp new file mode 100644 index 00000000000..211538e5af4 --- /dev/null +++ b/src/rendergraph/common/types.cpp @@ -0,0 +1,111 @@ +#include "rendergraph/types.h" + +#include +#include +#include +#include +#include + +using namespace rendergraph; + +int rendergraph::sizeOf(PrimitiveType type) { + switch (type) { + case PrimitiveType::UInt: + return sizeof(uint32_t); + case PrimitiveType::Float: + return sizeof(float); + } + return 0; +} + +int rendergraph::sizeOf(Type type) { + switch (type) { + case Type::UInt: + return sizeof(uint32_t); + case Type::Float: + return sizeof(float); + case Type::Vector2D: + return sizeof(float) * 2; + case Type::Vector3D: + return sizeof(float) * 3; + case Type::Vector4D: + return sizeof(float) * 4; + case Type::Matrix4x4: + return sizeof(float) * 4 * 4; + } + return 0; +} + +template<> +Type rendergraph::typeOf() { + return Type::UInt; +} + +template<> +Type rendergraph::typeOf() { + return Type::Float; +} + +template<> +Type rendergraph::typeOf() { + return Type::Vector2D; +} + +template<> +Type rendergraph::typeOf() { + return Type::Vector3D; +} + +template<> +Type rendergraph::typeOf() { + return Type::Vector4D; +} + +template<> +Type rendergraph::typeOf() { + return Type::Matrix4x4; +} + +template<> +PrimitiveType rendergraph::primitiveTypeOf() { + return PrimitiveType::Float; +} + +template<> +PrimitiveType rendergraph::primitiveTypeOf() { + return PrimitiveType::UInt; +} + +template<> +PrimitiveType rendergraph::primitiveTypeOf() { + return PrimitiveType::Float; +} +template<> +PrimitiveType rendergraph::primitiveTypeOf() { + return PrimitiveType::Float; +} +template<> +PrimitiveType rendergraph::primitiveTypeOf() { + return PrimitiveType::Float; +} + +template<> +int rendergraph::tupleSizeOf() { + return 1; +} +template<> +int rendergraph::tupleSizeOf() { + return 1; +} +template<> +int rendergraph::tupleSizeOf() { + return 2; +} +template<> +int rendergraph::tupleSizeOf() { + return 3; +} +template<> +int rendergraph::tupleSizeOf() { + return 4; +} diff --git a/src/rendergraph/opengl/CMakeLists.txt b/src/rendergraph/opengl/CMakeLists.txt new file mode 100644 index 00000000000..c64c039b84d --- /dev/null +++ b/src/rendergraph/opengl/CMakeLists.txt @@ -0,0 +1,82 @@ +add_library( + rendergraph_gl + ../common/rendergraph/attributeinit.h + ../common/rendergraph/attributeset.h + ../common/rendergraph/geometry.h + ../common/rendergraph/geometrynode.h + ../common/rendergraph/material.h + ../common/rendergraph/material/endoftrackmaterial.cpp + ../common/rendergraph/material/endoftrackmaterial.h + ../common/rendergraph/material/patternmaterial.cpp + ../common/rendergraph/material/patternmaterial.h + ../common/rendergraph/material/rgbamaterial.cpp + ../common/rendergraph/material/rgbamaterial.h + ../common/rendergraph/material/rgbmaterial.cpp + ../common/rendergraph/material/rgbmaterial.h + ../common/rendergraph/material/texturematerial.cpp + ../common/rendergraph/material/texturematerial.h + ../common/rendergraph/material/unicolormaterial.cpp + ../common/rendergraph/material/unicolormaterial.h + ../common/rendergraph/materialshader.h + ../common/rendergraph/materialtype.h + ../common/rendergraph/node.h + ../common/rendergraph/opacitynode.h + ../common/rendergraph/texture.h + ../common/rendergraph/types.h + ../common/rendergraph/uniform.h + ../common/rendergraph/uniformscache.cpp + ../common/rendergraph/uniformscache.h + ../common/rendergraph/uniformset.cpp + ../common/rendergraph/uniformset.h + ../common/types.cpp + attributeset.cpp + backend/baseattributeset.cpp + backend/baseattributeset.h + backend/basegeometry.cpp + backend/basegeometry.h + backend/basegeometrynode.cpp + backend/basegeometrynode.h + backend/basematerial.cpp + backend/basematerial.h + backend/basematerialshader.cpp + backend/basematerialtype.h + backend/basenode.h + backend/basenode.cpp + backend/baseopacitynode.h + backend/baseopenglnode.cpp + backend/baseopenglnode.h + backend/basetexture.h + backend/shadercache.h + engine.cpp + geometry.cpp + geometrynode.cpp + material.cpp + materialshader.cpp + rendergraph/context.h + rendergraph/engine.h + rendergraph/openglnode.h + texture.cpp +) + +target_link_libraries(rendergraph_gl PUBLIC Qt6::Core Qt6::Gui Qt6::OpenGL) +find_package(Microsoft.GSL CONFIG) +if(Microsoft.GSL_FOUND) + target_link_libraries(rendergraph_gl PUBLIC Microsoft.GSL::GSL) +else() + # check if the headers have been installed without cmake config (< 3.1.0) + check_include_file_cxx(gsl/gsl HAVE_GSL_GSL) + if(NOT HAVE_GSL_GSL) + unset(HAVE_GSL_GSL CACHE) # unset cache to re-evaluate this until it succeeds. check_include_file_cxx() has no REQUIRED flag. + message(FATAL_ERROR "ms-gsl development headers (libmsgsl-dev) not found") + endif() +endif() +target_compile_definitions(rendergraph_gl PRIVATE rendergraph=rendergraph_gl) + +# USE_QSHADER_FOR_GL is set in rendergraph/CMakeLists.txt +if(USE_QSHADER_FOR_GL) + message(STATUS "Using QShader to load qsb shaders for opengl") + target_link_libraries(rendergraph_gl PUBLIC Qt6::GuiPrivate) + target_compile_definitions(rendergraph_gl PRIVATE USE_QSHADER_FOR_GL) +endif() + +target_include_directories(rendergraph_gl PUBLIC . ../common) diff --git a/src/rendergraph/opengl/attributeset.cpp b/src/rendergraph/opengl/attributeset.cpp new file mode 100644 index 00000000000..302c2ad5c9c --- /dev/null +++ b/src/rendergraph/opengl/attributeset.cpp @@ -0,0 +1,8 @@ +#include "rendergraph/attributeset.h" + +using namespace rendergraph; + +AttributeSet::AttributeSet(std::initializer_list list, + const std::vector& names) + : BaseAttributeSet(list, names) { +} diff --git a/src/rendergraph/opengl/backend/baseattributeset.cpp b/src/rendergraph/opengl/backend/baseattributeset.cpp new file mode 100644 index 00000000000..87e1ea333d0 --- /dev/null +++ b/src/rendergraph/opengl/backend/baseattributeset.cpp @@ -0,0 +1,18 @@ +#include "rendergraph/assert.h" +#include "rendergraph/attributeset.h" + +using namespace rendergraph; + +BaseAttributeSet::BaseAttributeSet(std::initializer_list list, + const std::vector& names) { + DEBUG_ASSERT(list.size() == names.size()); + int i = 0; + int offset = 0; + m_attributes.reserve(list.size()); + for (auto item : list) { + m_attributes.push_back(BaseGeometry::Attribute{ + offset, item.m_tupleSize, item.m_primitiveType, names[i++]}); + offset += item.m_tupleSize * sizeOf(item.m_primitiveType); + } + m_sizeOfVertex = offset; +} diff --git a/src/rendergraph/opengl/backend/baseattributeset.h b/src/rendergraph/opengl/backend/baseattributeset.h new file mode 100644 index 00000000000..c2c1c2cda2a --- /dev/null +++ b/src/rendergraph/opengl/backend/baseattributeset.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include "backend/basegeometry.h" +#include "rendergraph/attributeinit.h" + +namespace rendergraph { +class BaseAttributeSet; +} + +class rendergraph::BaseAttributeSet { + protected: + BaseAttributeSet(std::initializer_list list, const std::vector& names); + + public: + const std::vector& attributes() const { + return m_attributes; + } + int sizeOfVertex() const { + return m_sizeOfVertex; + } + + protected: + std::vector m_attributes; + int m_sizeOfVertex; +}; diff --git a/src/rendergraph/opengl/backend/basegeometry.cpp b/src/rendergraph/opengl/backend/basegeometry.cpp new file mode 100644 index 00000000000..09854386dbe --- /dev/null +++ b/src/rendergraph/opengl/backend/basegeometry.cpp @@ -0,0 +1,21 @@ +#include "backend/basegeometry.h" + +#include "backend/baseattributeset.h" +#include "rendergraph/geometry.h" + +using namespace rendergraph; + +namespace { +// to mimic sg default +constexpr auto defaultDrawingMode = DrawingMode::TriangleStrip; +} // namespace + +BaseGeometry::BaseGeometry( + const BaseAttributeSet& attributeSet, int vertexCount) + : m_pAttributes(attributeSet.attributes().data()), + m_attributeCount(attributeSet.attributes().size()), + m_sizeOfVertex(attributeSet.sizeOfVertex()), + m_drawingMode(defaultDrawingMode), + m_vertexCount(vertexCount), + m_vertexData(m_vertexCount * m_sizeOfVertex / sizeof(float)) { +} diff --git a/src/rendergraph/opengl/backend/basegeometry.h b/src/rendergraph/opengl/backend/basegeometry.h new file mode 100644 index 00000000000..f3575adaa14 --- /dev/null +++ b/src/rendergraph/opengl/backend/basegeometry.h @@ -0,0 +1,56 @@ +#pragma once + +#include +#include + +#include "rendergraph/types.h" + +namespace rendergraph { +class BaseAttributeSet; // fwd decl to avoid circular dependency +class BaseGeometry; +} // namespace rendergraph + +// TODO this assumes all vertices consist of floats +class rendergraph::BaseGeometry { + protected: + BaseGeometry(const BaseAttributeSet& attributeSet, int vertexCount); + + public: + struct Attribute { + const int m_offset; + const int m_tupleSize; + const PrimitiveType m_primitiveType; + const QString m_name; + }; + + float* vertexData() { + return m_vertexData.data(); + } + const float* vertexData() const { + return m_vertexData.data(); + } + const Attribute* attributes() const { + return m_pAttributes; + } + int attributeCount() const { + return m_attributeCount; + } + int vertexCount() const { + return m_vertexCount; + } + int sizeOfVertex() const { // in bytes + return m_sizeOfVertex; + } + void allocate(int vertexCount) { + m_vertexCount = vertexCount; + m_vertexData.resize(m_vertexCount * sizeOfVertex() / sizeof(float)); + } + + protected: + const Attribute* m_pAttributes; + const int m_attributeCount; + const int m_sizeOfVertex; + DrawingMode m_drawingMode; + int m_vertexCount; + std::vector m_vertexData; +}; diff --git a/src/rendergraph/opengl/backend/basegeometrynode.cpp b/src/rendergraph/opengl/backend/basegeometrynode.cpp new file mode 100644 index 00000000000..31075d5f873 --- /dev/null +++ b/src/rendergraph/opengl/backend/basegeometrynode.cpp @@ -0,0 +1,115 @@ +#include "backend/basegeometrynode.h" + +#include +#include + +#include "backend/shadercache.h" +#include "rendergraph/engine.h" +#include "rendergraph/geometrynode.h" +#include "rendergraph/texture.h" + +using namespace rendergraph; + +namespace { +GLenum toGlDrawingMode(DrawingMode mode) { + switch (mode) { + case DrawingMode::Triangles: + return GL_TRIANGLES; + case DrawingMode::TriangleStrip: + return GL_TRIANGLE_STRIP; + default: + throw std::runtime_error("not implemented"); + } +} +} // namespace + +void BaseGeometryNode::initialize() { + initializeOpenGLFunctions(); + GeometryNode* pThis = static_cast(this); + pThis->material().setShader(ShaderCache::getShaderForMaterial(&pThis->material())); + pThis->material().setUniform(0, engine()->matrix()); +} + +void BaseGeometryNode::render() { + GeometryNode* pThis = static_cast(this); + Geometry& geometry = pThis->geometry(); + Material& material = pThis->material(); + + if (geometry.vertexCount() == 0) { + return; + } + + glEnable(GL_BLEND); + // qt scene graph uses premultiplied alpha color in the shader, + // so we need to do the same + glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); + + QOpenGLShaderProgram& shader = material.shader(); + shader.bind(); + + if (material.clearUniformsCacheDirty() || !material.isLastModifierOfShader()) { + material.modifyShader(); + const UniformsCache& cache = material.uniformsCache(); + for (int i = 0; i < cache.count(); i++) { + int location = material.uniformLocation(i); + switch (cache.type(i)) { + case Type::UInt: + shader.setUniformValue(location, cache.get(i)); + break; + case Type::Float: + shader.setUniformValue(location, cache.get(i)); + break; + case Type::Vector2D: + shader.setUniformValue(location, cache.get(i)); + break; + case Type::Vector3D: + shader.setUniformValue(location, cache.get(i)); + break; + case Type::Vector4D: + shader.setUniformValue(location, cache.get(i)); + break; + case Type::Matrix4x4: + shader.setUniformValue(location, cache.get(i)); + break; + } + } + } + + // TODO this code assumes all vertices are floats + int vertexOffset = 0; + for (int i = 0; i < geometry.attributeCount(); i++) { + const Geometry::Attribute& attribute = geometry.attributes()[i]; + int location = material.attributeLocation(i); + shader.enableAttributeArray(location); + shader.setAttributeArray(location, + geometry.vertexDataAs() + vertexOffset, + attribute.m_tupleSize, + geometry.sizeOfVertex()); + vertexOffset += attribute.m_tupleSize; + } + + // TODO multiple textures + auto pTexture = material.texture(1); + if (pTexture) { + pTexture->backendTexture()->bind(); + } + + glDrawArrays(toGlDrawingMode(geometry.drawingMode()), 0, geometry.vertexCount()); + + if (pTexture) { + pTexture->backendTexture()->release(); + } + + for (int i = 0; i < geometry.attributeCount(); i++) { + int location = material.attributeLocation(i); + shader.disableAttributeArray(location); + } + + shader.release(); +} + +void BaseGeometryNode::resize(int, int) { + assert(engine() != nullptr); + GeometryNode* pThis = static_cast(this); + pThis->material().setUniform(0, engine()->matrix()); +} diff --git a/src/rendergraph/opengl/backend/basegeometrynode.h b/src/rendergraph/opengl/backend/basegeometrynode.h new file mode 100644 index 00000000000..a4a7f609c4a --- /dev/null +++ b/src/rendergraph/opengl/backend/basegeometrynode.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +#include "backend/basenode.h" + +namespace rendergraph { +class BaseGeometryNode; +} + +class rendergraph::BaseGeometryNode : public rendergraph::BaseNode, + public QOpenGLFunctions { + public: + BaseGeometryNode() = default; + virtual ~BaseGeometryNode() = default; + + // called by Engine + void initialize() override; + void render() override; + void resize(int w, int h) override; +}; diff --git a/src/rendergraph/opengl/backend/basematerial.cpp b/src/rendergraph/opengl/backend/basematerial.cpp new file mode 100644 index 00000000000..ae6817ce878 --- /dev/null +++ b/src/rendergraph/opengl/backend/basematerial.cpp @@ -0,0 +1,34 @@ +#include "backend/basematerial.h" + +#include "rendergraph/material.h" + +using namespace rendergraph; + +void BaseMaterial::setShader(std::shared_ptr pShader) { + m_pShader = pShader; +} + +MaterialShader& BaseMaterial::shader() const { + return *m_pShader; +} + +int BaseMaterial::uniformLocation(int uniformIndex) const { + return m_pShader->uniformLocation(uniformIndex); +} + +int BaseMaterial::attributeLocation(int attributeIndex) const { + return m_pShader->attributeLocation(attributeIndex); +} + +void BaseMaterial::modifyShader() { + m_pShader->setLastModifiedByMaterial(this); +} + +bool BaseMaterial::isLastModifierOfShader() const { + return this == m_pShader->lastModifiedByMaterial(); +} + +int BaseMaterial::compare(const BaseMaterial* other) const { + auto pThis = static_cast(this); + return pThis->compare(static_cast(other)); +} diff --git a/src/rendergraph/opengl/backend/basematerial.h b/src/rendergraph/opengl/backend/basematerial.h new file mode 100644 index 00000000000..6f2a22ccba2 --- /dev/null +++ b/src/rendergraph/opengl/backend/basematerial.h @@ -0,0 +1,32 @@ +#pragma once + +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" + +namespace rendergraph { +class BaseMaterial; +} + +class rendergraph::BaseMaterial { + protected: + BaseMaterial() = default; + + public: + virtual MaterialType* type() const = 0; + + // For parity with QSGMaterial, not used yet + int compare(const BaseMaterial* other) const; + + void setShader(std::shared_ptr pShader); + + MaterialShader& shader() const; + + int uniformLocation(int uniformIndex) const; + int attributeLocation(int attributeIndex) const; + + void modifyShader(); + bool isLastModifierOfShader() const; + + private: + std::shared_ptr m_pShader; +}; diff --git a/src/rendergraph/opengl/backend/basematerialshader.cpp b/src/rendergraph/opengl/backend/basematerialshader.cpp new file mode 100644 index 00000000000..498ed8fbe4f --- /dev/null +++ b/src/rendergraph/opengl/backend/basematerialshader.cpp @@ -0,0 +1,19 @@ +#include "backend/basematerialshader.h" + +using namespace rendergraph; + +int BaseMaterialShader::attributeLocation(int attributeIndex) const { + return m_attributeLocations[attributeIndex]; +} + +int BaseMaterialShader::uniformLocation(int uniformIndex) const { + return m_uniformLocations[uniformIndex]; +} + +BaseMaterial* BaseMaterialShader::lastModifiedByMaterial() const { + return m_pLastModifiedByMaterial; +} + +void BaseMaterialShader::setLastModifiedByMaterial(BaseMaterial* pMaterial) { + m_pLastModifiedByMaterial = pMaterial; +} diff --git a/src/rendergraph/opengl/backend/basematerialshader.h b/src/rendergraph/opengl/backend/basematerialshader.h new file mode 100644 index 00000000000..f5e1b3e195e --- /dev/null +++ b/src/rendergraph/opengl/backend/basematerialshader.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +namespace rendergraph { +class BaseMaterial; // fwd decl to avoid circular dependency +class BaseMaterialShader; +} // namespace rendergraph + +class rendergraph::BaseMaterialShader : public QOpenGLShaderProgram { + protected: + BaseMaterialShader() = default; + + public: + int attributeLocation(int attributeIndex) const; + int uniformLocation(int uniformIndex) const; + + BaseMaterial* lastModifiedByMaterial() const; + void setLastModifiedByMaterial(BaseMaterial* pMaterial); + + protected: + std::vector m_attributeLocations; + std::vector m_uniformLocations; + BaseMaterial* m_pLastModifiedByMaterial{}; +}; diff --git a/src/rendergraph/opengl/backend/basematerialtype.h b/src/rendergraph/opengl/backend/basematerialtype.h new file mode 100644 index 00000000000..50b925d0bf4 --- /dev/null +++ b/src/rendergraph/opengl/backend/basematerialtype.h @@ -0,0 +1,6 @@ +#pragma once + +namespace rendergraph { +class BaseMaterialType { +}; +} // namespace rendergraph diff --git a/src/rendergraph/opengl/backend/basenode.cpp b/src/rendergraph/opengl/backend/basenode.cpp new file mode 100644 index 00000000000..a413325ee29 --- /dev/null +++ b/src/rendergraph/opengl/backend/basenode.cpp @@ -0,0 +1,62 @@ +#include "backend/basenode.h" + +#include "rendergraph/assert.h" +#include "rendergraph/engine.h" + +using namespace rendergraph; + +BaseNode::~BaseNode() { + DEBUG_ASSERT(m_pParent == nullptr); + DEBUG_ASSERT(m_pEngine == nullptr); + + while (m_pFirstChild) { + auto pChild = m_pFirstChild; + removeChildNode(pChild); + delete pChild; + } +} + +// This mimics QSGNode::appendChildNode. +// Use NodeInterface::appendChildNode(std::unique_ptr pNode) +// for a more clear transfer of ownership. pChild is considered owned by +// this at this point. +void BaseNode::appendChildNode(BaseNode* pChild) { + if (m_pLastChild) { + pChild->m_pPreviousSibling = m_pLastChild; + m_pLastChild->m_pNextSibling = pChild; + } else { + m_pFirstChild = pChild; + } + m_pLastChild = pChild; + m_pLastChild->m_pParent = this; + + DEBUG_ASSERT(m_pLastChild->m_pNextSibling == nullptr); + + if (m_pEngine) { + m_pEngine->add(pChild); + } +} + +// This mimics QSGNode::removeChildNode. +// Use NodeInterface::detachChildNode(BaseNode* pNode) +// for a more clear transfer of ownership. Otherwise, +// deleting pChild is responsibility of the caller. +void BaseNode::removeChildNode(BaseNode* pChild) { + if (pChild == m_pFirstChild) { + m_pFirstChild = pChild->m_pNextSibling; + } else { + pChild->m_pPreviousSibling->m_pNextSibling = pChild->m_pNextSibling; + } + + if (pChild == m_pLastChild) { + m_pLastChild = nullptr; + } + + if (pChild->m_pEngine) { + pChild->m_pEngine->remove(pChild); + } + + pChild->m_pNextSibling = nullptr; + pChild->m_pPreviousSibling = nullptr; + pChild->m_pParent = nullptr; +} diff --git a/src/rendergraph/opengl/backend/basenode.h b/src/rendergraph/opengl/backend/basenode.h new file mode 100644 index 00000000000..b0079954697 --- /dev/null +++ b/src/rendergraph/opengl/backend/basenode.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +namespace rendergraph { +class BaseNode; +class Engine; +} // namespace rendergraph + +class rendergraph::BaseNode { + public: + BaseNode() = default; + virtual ~BaseNode(); + + void setUsePreprocess(bool value) { + m_usePreprocess = value; + } + bool usePreprocess() const { + return m_usePreprocess; + } + virtual bool isSubtreeBlocked() const { + return false; + } + virtual void preprocess() { + } + virtual void render() { + } + virtual void initialize() { + } + virtual void resize(int, int) { + } + void setEngine(Engine* engine) { + m_pEngine = engine; + } + Engine* engine() const { + return m_pEngine; + } + + // Prefer using NodeInterface::appendChildNode(std::unique_ptr pNode); + void appendChildNode(BaseNode* pChild); + // Prefer using std::unique_ptr NodeInterface::detachChildNode(BaseNode* pNode); + void removeChildNode(BaseNode* pChild); + + BaseNode* parent() const { + return m_pParent; + } + BaseNode* firstChild() const { + return m_pFirstChild; + } + BaseNode* lastChild() const { + return m_pLastChild; + } + BaseNode* nextSibling() const { + return m_pNextSibling; + } + BaseNode* previousSibling() const { + return m_pPreviousSibling; + } + + private: + Engine* m_pEngine{}; + bool m_usePreprocess{}; + + // Mimicking scenegraph node hierarchy. A parent owns its children. + BaseNode* m_pParent{}; + BaseNode* m_pFirstChild{}; + BaseNode* m_pLastChild{}; + BaseNode* m_pNextSibling{}; + BaseNode* m_pPreviousSibling{}; +}; diff --git a/src/rendergraph/opengl/backend/baseopacitynode.h b/src/rendergraph/opengl/backend/baseopacitynode.h new file mode 100644 index 00000000000..1bd11da2fe0 --- /dev/null +++ b/src/rendergraph/opengl/backend/baseopacitynode.h @@ -0,0 +1,23 @@ +#pragma once + +#include "backend/basenode.h" + +namespace rendergraph { +class BaseOpacityNode; +} // namespace rendergraph + +class rendergraph::BaseOpacityNode : public rendergraph::BaseNode { + public: + BaseOpacityNode() = default; + virtual ~BaseOpacityNode() = default; + + void setOpacity(float opacity) { + m_opacity = opacity; + } + bool isSubtreeBlocked() const override { + return m_opacity == 0.f; + } + + private: + float m_opacity{1.f}; +}; diff --git a/src/rendergraph/opengl/backend/baseopenglnode.cpp b/src/rendergraph/opengl/backend/baseopenglnode.cpp new file mode 100644 index 00000000000..13c3bdfc783 --- /dev/null +++ b/src/rendergraph/opengl/backend/baseopenglnode.cpp @@ -0,0 +1,18 @@ +#include "backend/baseopenglnode.h" + +#include "rendergraph/openglnode.h" + +using namespace rendergraph; + +void BaseOpenGLNode::initialize() { + initializeOpenGLFunctions(); + initializeGL(); +} + +void BaseOpenGLNode::render() { + paintGL(); +} + +void BaseOpenGLNode::resize(int w, int h) { + resizeGL(w, h); +} diff --git a/src/rendergraph/opengl/backend/baseopenglnode.h b/src/rendergraph/opengl/backend/baseopenglnode.h new file mode 100644 index 00000000000..545f5381630 --- /dev/null +++ b/src/rendergraph/opengl/backend/baseopenglnode.h @@ -0,0 +1,27 @@ +#pragma once + +#include + +#include "backend/basenode.h" + +namespace rendergraph { +class BaseOpenGLNode; +} // namespace rendergraph + +class rendergraph::BaseOpenGLNode : public rendergraph::BaseNode, + public QOpenGLFunctions { + public: + BaseOpenGLNode() = default; + virtual ~BaseOpenGLNode() = default; + + void initialize() override; + void render() override; + void resize(int w, int h) override; + + virtual void initializeGL() { + } + virtual void paintGL() { + } + virtual void resizeGL(int, int) { + } +}; diff --git a/src/rendergraph/opengl/backend/basetexture.h b/src/rendergraph/opengl/backend/basetexture.h new file mode 100644 index 00000000000..1a47541fe24 --- /dev/null +++ b/src/rendergraph/opengl/backend/basetexture.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace rendergraph { +using BaseTexture = QOpenGLTexture; +} // namespace rendergraph diff --git a/src/rendergraph/opengl/backend/shadercache.h b/src/rendergraph/opengl/backend/shadercache.h new file mode 100644 index 00000000000..557a0b6a582 --- /dev/null +++ b/src/rendergraph/opengl/backend/shadercache.h @@ -0,0 +1,44 @@ +#pragma once + +#include + +#include "rendergraph/material.h" +#include "rendergraph/materialshader.h" +#include "rendergraph/materialtype.h" + +namespace rendergraph { +class ShaderCache; +} // namespace rendergraph + +class rendergraph::ShaderCache { + private: + static std::unordered_map>& + map() { + static std::unordered_map> + s_map; + return s_map; + } + + public: + static std::shared_ptr getShaderForMaterial( + Material* pMaterial) { + auto iter = map().find(pMaterial->type()); + if (iter != map().end()) { + return iter->second; + } + auto pResult = std::shared_ptr( + pMaterial->createShader()); + map().insert(std::pair>{ + pMaterial->type(), pResult}); + return pResult; + } + static void purge() { + std::erase_if(map(), [](const auto& item) { + auto const& [key, value] = item; + return value.use_count() == 1; + }); + } +}; diff --git a/src/rendergraph/opengl/engine.cpp b/src/rendergraph/opengl/engine.cpp new file mode 100644 index 00000000000..f8188375e36 --- /dev/null +++ b/src/rendergraph/opengl/engine.cpp @@ -0,0 +1,98 @@ +#include "rendergraph/engine.h" + +#include +#include + +using namespace rendergraph; + +Engine::Engine(std::unique_ptr pRootNode) + : m_pRootNode(std::move(pRootNode)) { + add(m_pRootNode.get()); +} + +Engine::~Engine() { + // Explicitly remove the root node (and tree from the engine before deallocating its vectors) + remove(m_pRootNode.get()); +} + +void Engine::add(BaseNode* pNode) { + assert(pNode->engine() == nullptr || pNode->engine() == this); + if (pNode->engine() == nullptr) { + pNode->setEngine(this); + m_pInitializeNodes.push_back(pNode); + if (pNode->usePreprocess()) { + m_pPreprocessNodes.push_back(pNode); + } + pNode = pNode->firstChild(); + while (pNode) { + add(pNode); + pNode = pNode->nextSibling(); + } + } +} + +void Engine::remove(BaseNode* pNode) { + assert(pNode->engine() == this); + pNode->setEngine(nullptr); + + std::erase(m_pInitializeNodes, pNode); + std::erase(m_pPreprocessNodes, pNode); + + if (m_pRootNode.get() == pNode) { + m_pRootNode.reset(); + } +} + +void Engine::render() { + if (!m_pInitializeNodes.empty()) { + for (auto pNode : m_pInitializeNodes) { + pNode->initialize(); + } + m_pInitializeNodes.clear(); + } + if (m_pRootNode && !m_pRootNode->isSubtreeBlocked()) { + render(m_pRootNode.get()); + } +} + +void Engine::render(BaseNode* pNode) { + pNode->render(); + pNode = pNode->firstChild(); + while (pNode) { + if (!pNode->isSubtreeBlocked()) { + render(pNode); + } + pNode = pNode->nextSibling(); + } +} + +void Engine::preprocess() { + for (auto pNode : m_pPreprocessNodes) { + if (!pNode->isSubtreeBlocked()) { + pNode->preprocess(); + } + } +} + +void Engine::resize(int w, int h) { + m_matrix.setToIdentity(); + m_matrix.ortho(QRectF(0.0f, 0.0f, w, h)); + // TODO + // if (waveformRenderer->getOrientation() == Qt::Vertical) { + // matrix.rotate(90.f, 0.0f, 0.0f, 1.0f); + // matrix.translate(0.f, -waveformRenderer->getWidth() * ratio, 0.f); + //} + + if (m_pRootNode) { + resize(m_pRootNode.get(), w, h); + } +} + +void Engine::resize(BaseNode* pNode, int w, int h) { + pNode->resize(w, h); + pNode = pNode->firstChild(); + while (pNode) { + resize(pNode, w, h); + pNode = pNode->nextSibling(); + } +} diff --git a/src/rendergraph/opengl/geometry.cpp b/src/rendergraph/opengl/geometry.cpp new file mode 100644 index 00000000000..b2fbfbbcd2a --- /dev/null +++ b/src/rendergraph/opengl/geometry.cpp @@ -0,0 +1,45 @@ +#include "rendergraph/geometry.h" + +#include "rendergraph/assert.h" +#include "rendergraph/attributeset.h" + +using namespace rendergraph; + +Geometry::Geometry(const AttributeSet& attributeSet, int vertexCount) + : BaseGeometry(attributeSet, vertexCount) { +} + +void Geometry::setAttributeValues(int attributePosition, const float* from, int numTuples) { + // TODO this code assumes all vertices are floats + VERIFY_OR_DEBUG_ASSERT(attributePosition < attributeCount()) { + return; + } + const int vertexOffset = attributes()[attributePosition].m_offset / sizeof(float); + const int tupleSize = attributes()[attributePosition].m_tupleSize; + const int vertexStride = sizeOfVertex() / sizeof(float); + const int vertexSkip = vertexStride - tupleSize; + + VERIFY_OR_DEBUG_ASSERT(vertexOffset + numTuples * vertexStride - vertexSkip <= + static_cast(m_vertexData.size())) { + return; + } + + float* to = m_vertexData.data(); + to += vertexOffset; + + while (numTuples--) { + int k = tupleSize; + while (k--) { + *to++ = *from++; + } + to += vertexSkip; + } +} + +void Geometry::setDrawingMode(DrawingMode mode) { + m_drawingMode = mode; +} + +DrawingMode Geometry::drawingMode() const { + return m_drawingMode; +} diff --git a/src/rendergraph/opengl/geometrynode.cpp b/src/rendergraph/opengl/geometrynode.cpp new file mode 100644 index 00000000000..7c5020974bc --- /dev/null +++ b/src/rendergraph/opengl/geometrynode.cpp @@ -0,0 +1,33 @@ +#include "rendergraph/geometrynode.h" + +using namespace rendergraph; + +GeometryNode::GeometryNode() = default; + +void GeometryNode::setUsePreprocess(bool value) { + BaseNode::setUsePreprocess(value); +} + +void GeometryNode::setGeometry(std::unique_ptr pGeometry) { + m_pGeometry = std::move(pGeometry); +} + +void GeometryNode::setMaterial(std::unique_ptr pMaterial) { + m_pMaterial = std::move(pMaterial); +} + +Geometry& GeometryNode::geometry() const { + return *m_pGeometry; +} + +Material& GeometryNode::material() const { + return *m_pMaterial; +} + +void GeometryNode::markDirtyGeometry() { + // not (yet) needed for opengl +} + +void GeometryNode::markDirtyMaterial() { + // not (yet) needed for opengl +} diff --git a/src/rendergraph/opengl/material.cpp b/src/rendergraph/opengl/material.cpp new file mode 100644 index 00000000000..4913e8d5b61 --- /dev/null +++ b/src/rendergraph/opengl/material.cpp @@ -0,0 +1,9 @@ +#include "rendergraph/material.h" + +using namespace rendergraph; + +Material::Material(const UniformSet& uniformSet) + : m_uniformsCache(uniformSet) { +} + +Material::~Material() = default; diff --git a/src/rendergraph/opengl/materialshader.cpp b/src/rendergraph/opengl/materialshader.cpp new file mode 100644 index 00000000000..e8fd233a21d --- /dev/null +++ b/src/rendergraph/opengl/materialshader.cpp @@ -0,0 +1,58 @@ +#include "rendergraph/materialshader.h" + +#include +#ifdef USE_QSHADER_FOR_GL +#include +#endif + +using namespace rendergraph; + +namespace { +#ifdef USE_QSHADER_FOR_GL +QString resource(const QString& filename) { + return QStringLiteral(":/shaders/rendergraph/%1.qsb").arg(filename); +} + +QByteArray loadShaderCodeFromFile(const QString& path) { + QFile file(path); + file.open(QIODeviceBase::ReadOnly); + QShader qsbShader = QShader::fromSerialized(file.readAll()); + QShaderKey key(QShader::GlslShader, 120); + return qsbShader.shader(key).shader(); +} +#else +QString resource(const QString& filename) { + return QStringLiteral(":/shaders/rendergraph/%1.gl").arg(filename); +} + +QByteArray loadShaderCodeFromFile(const QString& path) { + QFile file(path); + file.open(QIODeviceBase::ReadOnly); + return file.readAll(); +} +#endif +} // namespace + +MaterialShader::MaterialShader(const char* vertexShaderFilename, + const char* fragmentShaderFilename, + const UniformSet& uniformSet, + const AttributeSet& attributeSet) { + const QString vertexShaderFileFullPath = resource(vertexShaderFilename); + const QString fragmentShaderFileFullPath = resource(fragmentShaderFilename); + + addShaderFromSourceCode(QOpenGLShader::Vertex, + loadShaderCodeFromFile(vertexShaderFileFullPath)); + addShaderFromSourceCode(QOpenGLShader::Fragment, + loadShaderCodeFromFile(fragmentShaderFileFullPath)); + + link(); + + for (const auto& attribute : attributeSet.attributes()) { + int location = QOpenGLShaderProgram::attributeLocation(attribute.m_name); + m_attributeLocations.push_back(location); + } + for (const auto& uniform : uniformSet.uniforms()) { + int location = QOpenGLShaderProgram::uniformLocation(uniform.m_name); + m_uniformLocations.push_back(location); + } +} diff --git a/src/rendergraph/opengl/rendergraph/context.h b/src/rendergraph/opengl/rendergraph/context.h new file mode 100644 index 00000000000..d5d0611408f --- /dev/null +++ b/src/rendergraph/opengl/rendergraph/context.h @@ -0,0 +1,8 @@ +#pragma once + +namespace rendergraph { +class Context; +} + +class rendergraph::Context { +}; diff --git a/src/rendergraph/opengl/rendergraph/engine.h b/src/rendergraph/opengl/rendergraph/engine.h new file mode 100644 index 00000000000..83e480727e0 --- /dev/null +++ b/src/rendergraph/opengl/rendergraph/engine.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include +#include + +#include "rendergraph/node.h" + +namespace rendergraph { +class Engine; +} // namespace rendergraph + +class rendergraph::Engine { + public: + Engine(std::unique_ptr pRootNode); + ~Engine(); + + void render(); + void resize(int w, int h); + void preprocess(); + void add(BaseNode* pNode); + void remove(BaseNode* pNode); + const QMatrix4x4& matrix() const { + return m_matrix; + } + + private: + void render(BaseNode* pNode); + void resize(BaseNode* pNode, int, int); + + QMatrix4x4 m_matrix; + std::unique_ptr m_pRootNode; + std::vector m_pPreprocessNodes; + std::vector m_pInitializeNodes; +}; diff --git a/src/rendergraph/opengl/rendergraph/nodeinterface.h b/src/rendergraph/opengl/rendergraph/nodeinterface.h new file mode 100644 index 00000000000..45159724c49 --- /dev/null +++ b/src/rendergraph/opengl/rendergraph/nodeinterface.h @@ -0,0 +1,31 @@ +#pragma once + +#include "backend/basenode.h" + +namespace rendergraph { + +template +class NodeInterface : public T_Node { + public: + void appendChildNode(std::unique_ptr pNode) { + // Transfers ownership to this. + BaseNode* pRawNode = pNode.release(); + // Note: Ideally we would use unique_ptrs internally, but + // Qt uses raw pointers for QSGNode hierarchy. For simplicity + // we mimic this. + + T_Node::appendChildNode(pRawNode); + } + + std::unique_ptr detachChildNode(BaseNode* pNode) { + // After removeChildNode, the caller has the responsibility + // to deal with the child node. By returning a unique_ptr + // we preoprtly transfer ownership to the caller (which + // can result in deleting pNode if the caller doesn't + // take the unique_ptr). + T_Node::removeChildNode(pNode); + return std::unique_ptr(pNode); + } +}; + +} // namespace rendergraph diff --git a/src/rendergraph/opengl/rendergraph/openglnode.h b/src/rendergraph/opengl/rendergraph/openglnode.h new file mode 100644 index 00000000000..7499312cb08 --- /dev/null +++ b/src/rendergraph/opengl/rendergraph/openglnode.h @@ -0,0 +1,7 @@ +#pragma once + +#include "backend/baseopenglnode.h" + +namespace rendergraph { +using OpenGLNode = BaseOpenGLNode; +} // namespace rendergraph diff --git a/src/rendergraph/opengl/texture.cpp b/src/rendergraph/opengl/texture.cpp new file mode 100644 index 00000000000..88921bde9df --- /dev/null +++ b/src/rendergraph/opengl/texture.cpp @@ -0,0 +1,58 @@ +#include "rendergraph/texture.h" + +#include +#include + +#include "rendergraph/assert.h" +#include "rendergraph/context.h" + +using namespace rendergraph; + +namespace { +QImage premultiplyAlpha(const QImage& image) { + // Since the image is passed by const reference, implicit copy cannot be + // used, and this Qimage::bits will return a ref the QImage buffer, which + // may have a shorter lifecycle that the texture buffer. In order to + // workaround this, and because we cannot copy the image as we need to use + // the raw bitmap with an explicit image format, we make a manual copy of + // the buffer + QImage result(image.width(), image.height(), QImage::Format_RGBA8888); + if (image.format() == QImage::Format_RGBA8888_Premultiplied) { + VERIFY_OR_DEBUG_ASSERT(result.sizeInBytes() == image.sizeInBytes()) { + result.fill(QColor(Qt::transparent).rgba()); + return result; + } + std::memcpy(result.bits(), image.bits(), result.sizeInBytes()); + } else { + auto convertedImage = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied); + VERIFY_OR_DEBUG_ASSERT(result.sizeInBytes() == convertedImage.sizeInBytes()) { + result.fill(QColor(Qt::transparent).rgba()); + return result; + } + std::memcpy(result.bits(), convertedImage.bits(), result.sizeInBytes()); + } + return result; + /* TODO rendergraph ASK @acolombier to try if the following works as well + * (added the .copy()) + if (image.format() == QImage::Format_RGBA8888_Premultiplied) { + return QImage(image.bits(), image.width(), image.height(), QImage::Format_RGBA8888).copy(); + } + return QImage( + image.convertToFormat(QImage::Format_RGBA8888_Premultiplied) + .bits(), + image.width(), + image.height(), + QImage::Format_RGBA8888).copy(); + */ +} +} // namespace + +Texture::Texture(Context*, const QImage& image) + : m_pTexture(std::make_unique(premultiplyAlpha(image))) { + m_pTexture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear); + m_pTexture->setWrapMode(QOpenGLTexture::ClampToEdge); +} + +qint64 Texture::comparisonKey() const { + return static_cast(m_pTexture->textureId()); +} diff --git a/src/rendergraph/scenegraph/CMakeLists.txt b/src/rendergraph/scenegraph/CMakeLists.txt new file mode 100644 index 00000000000..e33747a22e7 --- /dev/null +++ b/src/rendergraph/scenegraph/CMakeLists.txt @@ -0,0 +1,70 @@ +add_library( + rendergraph_sg + ../common/rendergraph/attributeinit.h + ../common/rendergraph/attributeset.h + ../common/rendergraph/geometry.h + ../common/rendergraph/geometrynode.h + ../common/rendergraph/material.h + ../common/rendergraph/material/endoftrackmaterial.cpp + ../common/rendergraph/material/endoftrackmaterial.h + ../common/rendergraph/material/patternmaterial.cpp + ../common/rendergraph/material/patternmaterial.h + ../common/rendergraph/material/rgbamaterial.cpp + ../common/rendergraph/material/rgbamaterial.h + ../common/rendergraph/material/rgbmaterial.cpp + ../common/rendergraph/material/rgbmaterial.h + ../common/rendergraph/material/texturematerial.cpp + ../common/rendergraph/material/texturematerial.h + ../common/rendergraph/material/unicolormaterial.cpp + ../common/rendergraph/material/unicolormaterial.h + ../common/rendergraph/materialshader.h + ../common/rendergraph/materialtype.h + ../common/rendergraph/node.h + ../common/rendergraph/opacitynode.h + ../common/rendergraph/texture.h + ../common/rendergraph/types.h + ../common/rendergraph/uniform.h + ../common/rendergraph/uniformscache.cpp + ../common/rendergraph/uniformscache.h + ../common/rendergraph/uniformset.cpp + ../common/rendergraph/uniformset.h + ../common/types.cpp + attributeset.cpp + backend/baseattributeset.cpp + backend/baseattributeset.h + backend/basegeometry.h + backend/basegeometrynode.h + backend/basematerial.cpp + backend/basematerial.h + backend/basematerialshader.cpp + backend/basematerialtype.h + backend/basenode.h + backend/baseopacitynode.h + backend/basetexture.h + context.cpp + geometry.cpp + geometrynode.cpp + material.cpp + materialshader.cpp + rendergraph/context.h + texture.cpp +) + +target_link_libraries( + rendergraph_sg + PUBLIC Qt6::Core Qt6::Gui Qt6::Qml Qt6::Quick +) +find_package(Microsoft.GSL CONFIG) +if(Microsoft.GSL_FOUND) + target_link_libraries(rendergraph_sg PUBLIC Microsoft.GSL::GSL) +else() + # check if the headers have been installed without cmake config (< 3.1.0) + check_include_file_cxx(gsl/gsl HAVE_GSL_GSL) + if(NOT HAVE_GSL_GSL) + unset(HAVE_GSL_GSL CACHE) # unset cache to re-evaluate this until it succeeds. check_include_file_cxx() has no REQUIRED flag. + message(FATAL_ERROR "ms-gsl development headers (libmsgsl-dev) not found") + endif() +endif() +target_compile_definitions(rendergraph_sg PRIVATE rendergraph=rendergraph_sg) + +target_include_directories(rendergraph_sg PUBLIC . ../common) diff --git a/src/rendergraph/scenegraph/attributeset.cpp b/src/rendergraph/scenegraph/attributeset.cpp new file mode 100644 index 00000000000..04d55fcae8f --- /dev/null +++ b/src/rendergraph/scenegraph/attributeset.cpp @@ -0,0 +1,10 @@ +#include "rendergraph/attributeset.h" + +#include "backend/baseattributeset.h" + +using namespace rendergraph; + +AttributeSet::AttributeSet(std::initializer_list list, const std::vector&) + : BaseAttributeSet(list) { + // names are not used in scenegraph +} diff --git a/src/rendergraph/scenegraph/backend/baseattributeset.cpp b/src/rendergraph/scenegraph/backend/baseattributeset.cpp new file mode 100644 index 00000000000..0f0bf0b8e7a --- /dev/null +++ b/src/rendergraph/scenegraph/backend/baseattributeset.cpp @@ -0,0 +1,27 @@ +#include "backend/baseattributeset.h" + +using namespace rendergraph; + +namespace { +int toQSGGeometryType(const PrimitiveType& t) { + switch (t) { + case PrimitiveType::Float: + return QSGGeometry::FloatType; + case PrimitiveType::UInt: + return QSGGeometry::UnsignedIntType; + } +} +} // namespace + +BaseAttributeSetHelper::BaseAttributeSetHelper(std::initializer_list list) { + int i = 0; + m_sgAttributes.reserve(list.size()); + for (auto item : list) { + const int count = static_cast(m_sgAttributes.size()); + const bool isPosition = count == 0; + m_sgAttributes.push_back(QSGGeometry::Attribute::create(count, + item.m_tupleSize, + toQSGGeometryType(item.m_primitiveType), + isPosition)); + } +} diff --git a/src/rendergraph/scenegraph/backend/baseattributeset.h b/src/rendergraph/scenegraph/backend/baseattributeset.h new file mode 100644 index 00000000000..7c33e25192a --- /dev/null +++ b/src/rendergraph/scenegraph/backend/baseattributeset.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +#include "rendergraph/attributeinit.h" + +namespace rendergraph { +class BaseAttributeSet; +class BaseAttributeSetHelper; +} // namespace rendergraph + +class rendergraph::BaseAttributeSetHelper { + protected: + BaseAttributeSetHelper(std::initializer_list list); + std::vector m_sgAttributes; +}; + +class rendergraph::BaseAttributeSet + : protected rendergraph::BaseAttributeSetHelper, + public QSGGeometry::AttributeSet { + protected: + BaseAttributeSet(std::initializer_list list) + : BaseAttributeSetHelper(list), + QSGGeometry::AttributeSet{static_cast(m_sgAttributes.size()), + calculateSizeOfVertex(list), + m_sgAttributes.data()} { + } + static int calculateSizeOfVertex(std::initializer_list list) { + int numBytes = 0; + for (auto item : list) { + numBytes += item.m_tupleSize * sizeOf(item.m_primitiveType); + } + return numBytes; + } +}; diff --git a/src/rendergraph/scenegraph/backend/basegeometry.h b/src/rendergraph/scenegraph/backend/basegeometry.h new file mode 100644 index 00000000000..6d15a9f49dd --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basegeometry.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#include "rendergraph/attributeset.h" + +namespace rendergraph { +using BaseGeometry = QSGGeometry; +} // namespace rendergraph diff --git a/src/rendergraph/scenegraph/backend/basegeometrynode.h b/src/rendergraph/scenegraph/backend/basegeometrynode.h new file mode 100644 index 00000000000..26dd0b323bc --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basegeometrynode.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace rendergraph { +using BaseGeometryNode = QSGGeometryNode; +} // namespace rendergraph diff --git a/src/rendergraph/scenegraph/backend/basematerial.cpp b/src/rendergraph/scenegraph/backend/basematerial.cpp new file mode 100644 index 00000000000..6c882d5e759 --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basematerial.cpp @@ -0,0 +1,27 @@ +#include "rendergraph/material.h" +#include "rendergraph/materialshader.h" + +using namespace rendergraph; + +bool BaseMaterial::updateUniformsByteArray(QByteArray* buf) { + auto pThis = static_cast(this); + if (pThis->clearUniformsCacheDirty()) { + memcpy(buf->data(), pThis->uniformsCache().data(), pThis->uniformsCache().size()); + return true; + } + return false; +} + +int BaseMaterial::compare(const QSGMaterial* other) const { + auto pThis = static_cast(this); + return pThis->compare(static_cast(other)); +} + +QSGMaterialShader* BaseMaterial::createShader(QSGRendererInterface::RenderMode) const { + // This looks like a leak but it isn't: we pass ownership to Qt. Qt will + // cache and reuse the shader for all Material of the same type. + // TODO make sure that RenderMode is always the same. + auto pThis = static_cast(this); + auto pShader = pThis->createShader().release(); + return pShader; +} diff --git a/src/rendergraph/scenegraph/backend/basematerial.h b/src/rendergraph/scenegraph/backend/basematerial.h new file mode 100644 index 00000000000..ac434248d2f --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basematerial.h @@ -0,0 +1,19 @@ +#pragma once + +#include + +namespace rendergraph { +class BaseMaterial; +} // namespace rendergraph + +class rendergraph::BaseMaterial : public QSGMaterial { + protected: + BaseMaterial() = default; + + public: + QSGMaterialShader* createShader(QSGRendererInterface::RenderMode) const override; + + int compare(const QSGMaterial* other) const override; + + bool updateUniformsByteArray(QByteArray* buf); +}; diff --git a/src/rendergraph/scenegraph/backend/basematerialshader.cpp b/src/rendergraph/scenegraph/backend/basematerialshader.cpp new file mode 100644 index 00000000000..7a49a3d5afd --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basematerialshader.cpp @@ -0,0 +1,37 @@ +#include "backend/basematerialshader.h" + +#include + +#include "rendergraph/material.h" + +using namespace rendergraph; + +bool BaseMaterialShader::updateUniformData(RenderState& state, + QSGMaterial* newMaterial, + QSGMaterial* oldMaterial) { + bool result = static_cast(newMaterial)->updateUniformsByteArray(state.uniformData()); + QByteArray* buf = state.uniformData(); + + if (state.isMatrixDirty()) { + const QMatrix4x4 m = state.combinedMatrix(); + memcpy(buf->data(), m.constData(), 64); + result = true; + } + + return result; +} + +// override for QSGMaterialShader; this function is called by the Qt scene graph to prepare use of +// sampled images in the shader, typically in the form of combined image samplers. +void BaseMaterialShader::updateSampledImage(RenderState& state, + int binding, + QSGTexture** texture, + QSGMaterial* newMaterial, + QSGMaterial* oldMaterial) { + if (!newMaterial || !static_cast(newMaterial)->texture(binding)) { + *texture = nullptr; + return; + } + *texture = static_cast(newMaterial)->texture(binding)->backendTexture(); + (*texture)->commitTextureOperations(state.rhi(), state.resourceUpdateBatch()); +} diff --git a/src/rendergraph/scenegraph/backend/basematerialshader.h b/src/rendergraph/scenegraph/backend/basematerialshader.h new file mode 100644 index 00000000000..ac2ee3cbb6e --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basematerialshader.h @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +namespace rendergraph { +class BaseMaterialShader; +} // namespace rendergraph + +class rendergraph::BaseMaterialShader : public QSGMaterialShader { + protected: + BaseMaterialShader() = default; + + public: + bool updateUniformData(RenderState& state, + QSGMaterial* newMaterial, + QSGMaterial* oldMaterial) override; + + void updateSampledImage(RenderState& state, + int binding, + QSGTexture** texture, + QSGMaterial* newMaterial, + QSGMaterial* oldMaterial) override; +}; diff --git a/src/rendergraph/scenegraph/backend/basematerialtype.h b/src/rendergraph/scenegraph/backend/basematerialtype.h new file mode 100644 index 00000000000..3bcefcf54e6 --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basematerialtype.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace rendergraph { +using BaseMaterialType = QSGMaterialType; +} // namespace rendergraph diff --git a/src/rendergraph/scenegraph/backend/basenode.h b/src/rendergraph/scenegraph/backend/basenode.h new file mode 100644 index 00000000000..0eac56e1e0e --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basenode.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace rendergraph { +using BaseNode = QSGNode; +} // namespace rendergraph diff --git a/src/rendergraph/scenegraph/backend/baseopacitynode.h b/src/rendergraph/scenegraph/backend/baseopacitynode.h new file mode 100644 index 00000000000..14ea7e9d75f --- /dev/null +++ b/src/rendergraph/scenegraph/backend/baseopacitynode.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace rendergraph { +using BaseOpacityNode = QSGOpacityNode; +} // namespace rendergraph diff --git a/src/rendergraph/scenegraph/backend/basetexture.h b/src/rendergraph/scenegraph/backend/basetexture.h new file mode 100644 index 00000000000..287319af829 --- /dev/null +++ b/src/rendergraph/scenegraph/backend/basetexture.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +namespace rendergraph { +using BaseTexture = QSGTexture; +} // namespace rendergraph diff --git a/src/rendergraph/scenegraph/context.cpp b/src/rendergraph/scenegraph/context.cpp new file mode 100644 index 00000000000..29c3f567e25 --- /dev/null +++ b/src/rendergraph/scenegraph/context.cpp @@ -0,0 +1,11 @@ +#include "rendergraph/context.h" + +using namespace rendergraph; + +Context::Context(gsl::not_null pWindow) + : m_pWindow(pWindow) { +} + +gsl::not_null Context::window() const { + return m_pWindow; +} diff --git a/src/rendergraph/scenegraph/geometry.cpp b/src/rendergraph/scenegraph/geometry.cpp new file mode 100644 index 00000000000..fcc63f030ff --- /dev/null +++ b/src/rendergraph/scenegraph/geometry.cpp @@ -0,0 +1,70 @@ +#include "rendergraph/geometry.h" + +#include + +#include "rendergraph/assert.h" + +using namespace rendergraph; + +namespace { +QSGGeometry::DrawingMode toSgDrawingMode(DrawingMode mode) { + switch (mode) { + case DrawingMode::Triangles: + return QSGGeometry::DrawTriangles; + case DrawingMode::TriangleStrip: + return QSGGeometry::DrawTriangleStrip; + default: + throw std::runtime_error("not implemented"); + } +} + +DrawingMode fromSgDrawingMode(unsigned int mode) { + switch (mode) { + case QSGGeometry::DrawTriangles: + return DrawingMode::Triangles; + case QSGGeometry::DrawTriangleStrip: + return DrawingMode::TriangleStrip; + default: + throw std::runtime_error("not implemented"); + } +} +} // namespace + +Geometry::Geometry(const rendergraph::AttributeSet& attributeSet, int vertexCount) + : BaseGeometry(attributeSet, vertexCount) { +} + +void Geometry::setAttributeValues(int attributePosition, const float* from, int numTuples) { + // TODO this code assumes all vertices are floats + const auto attributeArray = QSGGeometry::attributes(); + int vertexOffset = 0; + for (int i = 0; i < attributePosition; i++) { + vertexOffset += attributeArray[i].tupleSize; + } + const int tupleSize = attributeArray[attributePosition].tupleSize; + const int vertexStride = sizeOfVertex() / sizeof(float); + const int vertexSkip = vertexStride - tupleSize; + + VERIFY_OR_DEBUG_ASSERT(vertexOffset + numTuples * vertexStride - vertexSkip <= + vertexCount() * vertexStride) { + return; + } + + float* to = static_cast(QSGGeometry::vertexData()); + to += vertexOffset; + while (numTuples--) { + int k = tupleSize; + while (k--) { + *to++ = *from++; + } + to += vertexSkip; + } +} + +void Geometry::setDrawingMode(DrawingMode mode) { + QSGGeometry::setDrawingMode(toSgDrawingMode(mode)); +} + +DrawingMode Geometry::drawingMode() const { + return fromSgDrawingMode(QSGGeometry::drawingMode()); +} diff --git a/src/rendergraph/scenegraph/geometrynode.cpp b/src/rendergraph/scenegraph/geometrynode.cpp new file mode 100644 index 00000000000..21196f2b8a3 --- /dev/null +++ b/src/rendergraph/scenegraph/geometrynode.cpp @@ -0,0 +1,35 @@ +#include "rendergraph/geometrynode.h" + +using namespace rendergraph; + +GeometryNode::GeometryNode() = default; + +void GeometryNode::setUsePreprocess(bool value) { + setFlag(QSGNode::UsePreprocess, value); +} + +void GeometryNode::setGeometry(std::unique_ptr pGeometry) { + m_pGeometry = std::move(pGeometry); + QSGGeometryNode::setGeometry(m_pGeometry.get()); +} + +void GeometryNode::setMaterial(std::unique_ptr pMaterial) { + m_pMaterial = std::move(pMaterial); + QSGGeometryNode::setMaterial(m_pMaterial.get()); +} + +Geometry& GeometryNode::geometry() const { + return *m_pGeometry; +} + +Material& GeometryNode::material() const { + return *m_pMaterial; +} + +void GeometryNode::markDirtyMaterial() { + markDirty(QSGNode::DirtyMaterial); +} + +void GeometryNode::markDirtyGeometry() { + markDirty(QSGNode::DirtyGeometry); +} diff --git a/src/rendergraph/scenegraph/material.cpp b/src/rendergraph/scenegraph/material.cpp new file mode 100644 index 00000000000..79cd048b011 --- /dev/null +++ b/src/rendergraph/scenegraph/material.cpp @@ -0,0 +1,10 @@ +#include "rendergraph/material.h" + +using namespace rendergraph; + +Material::Material(const UniformSet& uniformSet) + : m_uniformsCache(uniformSet) { + setFlag(QSGMaterial::Blending); +} + +Material::~Material() = default; diff --git a/src/rendergraph/scenegraph/materialshader.cpp b/src/rendergraph/scenegraph/materialshader.cpp new file mode 100644 index 00000000000..3a34c80274d --- /dev/null +++ b/src/rendergraph/scenegraph/materialshader.cpp @@ -0,0 +1,19 @@ +#include "rendergraph/materialshader.h" + +using namespace rendergraph; + +namespace { +static QString resource(const QString& filename) { + return QStringLiteral(":/shaders/rendergraph/%1.qsb").arg(filename); +} +} // namespace + +MaterialShader::MaterialShader(const char* vertexShaderFile, + const char* fragmentShaderFile, + const UniformSet& uniformSet, + const AttributeSet& attributeSet) { + (void)uniformSet; + (void)attributeSet; + setShaderFileName(VertexStage, resource(vertexShaderFile)); + setShaderFileName(FragmentStage, resource(fragmentShaderFile)); +} diff --git a/src/rendergraph/scenegraph/rendergraph/context.h b/src/rendergraph/scenegraph/rendergraph/context.h new file mode 100644 index 00000000000..431b41d027b --- /dev/null +++ b/src/rendergraph/scenegraph/rendergraph/context.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +namespace rendergraph { +class Context; +} + +class rendergraph::Context { + public: + Context(gsl::not_null pWindow); + gsl::not_null window() const; + + private: + QQuickWindow* m_pWindow; +}; diff --git a/src/rendergraph/scenegraph/rendergraph/nodeinterface.h b/src/rendergraph/scenegraph/rendergraph/nodeinterface.h new file mode 100644 index 00000000000..f5c42cadf46 --- /dev/null +++ b/src/rendergraph/scenegraph/rendergraph/nodeinterface.h @@ -0,0 +1,26 @@ +#pragma once + +#include "backend/basenode.h" +#include "rendergraph/assert.h" + +namespace rendergraph { + +template +class NodeInterface : public T_Node { + public: + void appendChildNode(std::unique_ptr pNode) { + BaseNode* pRawNode = pNode.release(); + pRawNode->setFlag(QSGNode::OwnedByParent, true); + T_Node::appendChildNode(pRawNode); + DEBUG_ASSERT(pRawNode->flags() & QSGNode::OwnedByParent); + } + std::unique_ptr detachChildNode(BaseNode* pNode) { + DEBUG_ASSERT(pNode->flags() & QSGNode::OwnedByParent); + pNode->setFlag(QSGNode::OwnedByParent, false); + T_Node::removeChildNode(pNode); + DEBUG_ASSERT(!pNode->flags() & QSGNode::OwnedByParent); + return std::unique_ptr(pNode); + } +}; + +} // namespace rendergraph diff --git a/src/rendergraph/scenegraph/texture.cpp b/src/rendergraph/scenegraph/texture.cpp new file mode 100644 index 00000000000..130d10df821 --- /dev/null +++ b/src/rendergraph/scenegraph/texture.cpp @@ -0,0 +1,18 @@ +#include "rendergraph/texture.h" + +#include "rendergraph/assert.h" +#include "rendergraph/context.h" + +using namespace rendergraph; + +Texture::Texture(Context* pContext, const QImage& image) + : m_pTexture(pContext->window()->createTextureFromImage(image)) { + VERIFY_OR_DEBUG_ASSERT(pContext->window() != nullptr) { + return; + } + DEBUG_ASSERT(!m_pTexture->textureSize().isNull()); +} + +qint64 Texture::comparisonKey() const { + return m_pTexture->comparisonKey(); +} From 89bf0a23bfa795cb4b002f5443a8079ea0797de4 Mon Sep 17 00:00:00 2001 From: m0dB Date: Sat, 14 Dec 2024 05:38:44 +0100 Subject: [PATCH 2/2] add on review --- src/rendergraph/CMakeLists.txt | 35 ++++++++++++++++++- src/rendergraph/common/rendergraph/assert.h | 5 +-- .../common/rendergraph/attributeinit.h | 2 +- src/rendergraph/common/rendergraph/material.h | 12 +++---- .../rendergraph/material/rgbamaterial.cpp | 3 +- src/rendergraph/opengl/CMakeLists.txt | 30 +--------------- .../opengl/backend/basegeometry.cpp | 2 +- src/rendergraph/opengl/backend/basegeometry.h | 2 +- .../opengl/backend/basegeometrynode.cpp | 4 +-- .../opengl/backend/basegeometrynode.h | 2 +- src/rendergraph/opengl/backend/basematerial.h | 2 +- src/rendergraph/opengl/backend/basenode.cpp | 16 ++++----- src/rendergraph/opengl/backend/basenode.h | 8 +++-- src/rendergraph/opengl/geometry.cpp | 3 +- src/rendergraph/scenegraph/CMakeLists.txt | 30 +--------------- src/rendergraph/scenegraph/attributeset.cpp | 2 +- .../scenegraph/backend/basematerial.cpp | 4 +-- .../scenegraph/backend/basematerialshader.cpp | 4 +-- src/rendergraph/scenegraph/geometry.cpp | 3 +- 19 files changed, 76 insertions(+), 93 deletions(-) diff --git a/src/rendergraph/CMakeLists.txt b/src/rendergraph/CMakeLists.txt index 731c47b5122..8f14cb2f313 100644 --- a/src/rendergraph/CMakeLists.txt +++ b/src/rendergraph/CMakeLists.txt @@ -5,6 +5,39 @@ if(QT_VERSION_MINOR GREATER_EQUAL 6) set(USE_QSHADER_FOR_GL ON) endif() +set( + COMMON_RENDERGRAPH_FILES + ../common/rendergraph/attributeinit.h + ../common/rendergraph/attributeset.h + ../common/rendergraph/geometry.h + ../common/rendergraph/geometrynode.h + ../common/rendergraph/material.h + ../common/rendergraph/material/endoftrackmaterial.cpp + ../common/rendergraph/material/endoftrackmaterial.h + ../common/rendergraph/material/patternmaterial.cpp + ../common/rendergraph/material/patternmaterial.h + ../common/rendergraph/material/rgbamaterial.cpp + ../common/rendergraph/material/rgbamaterial.h + ../common/rendergraph/material/rgbmaterial.cpp + ../common/rendergraph/material/rgbmaterial.h + ../common/rendergraph/material/texturematerial.cpp + ../common/rendergraph/material/texturematerial.h + ../common/rendergraph/material/unicolormaterial.cpp + ../common/rendergraph/material/unicolormaterial.h + ../common/rendergraph/materialshader.h + ../common/rendergraph/materialtype.h + ../common/rendergraph/node.h + ../common/rendergraph/opacitynode.h + ../common/rendergraph/texture.h + ../common/rendergraph/types.h + ../common/rendergraph/uniform.h + ../common/rendergraph/uniformscache.cpp + ../common/rendergraph/uniformscache.h + ../common/rendergraph/uniformset.cpp + ../common/rendergraph/uniformset.h + ../common/types.cpp +) + add_subdirectory(opengl) add_subdirectory(scenegraph) -add_subdirectory(../../res/shaders/rendergraph shaders) +add_subdirectory(shaders) diff --git a/src/rendergraph/common/rendergraph/assert.h b/src/rendergraph/common/rendergraph/assert.h index 6b47ad6a7f4..4a72e0f6db4 100644 --- a/src/rendergraph/common/rendergraph/assert.h +++ b/src/rendergraph/common/rendergraph/assert.h @@ -1,3 +1,4 @@ -// rendergraph is a module but we want to include util/assert.h from Mixxx, -// without adding the entire src/ dir to the include paths. +// Note: in principal, rendergraph is a module independent of Mixxx, but we +// do want to include util/assert.h from Mixxx here, using a relative path +// so we avoid adding the entire Mixxx src/ dir to the include paths. #include "../../../util/assert.h" diff --git a/src/rendergraph/common/rendergraph/attributeinit.h b/src/rendergraph/common/rendergraph/attributeinit.h index ccbbbf16b9b..d774386de70 100644 --- a/src/rendergraph/common/rendergraph/attributeinit.h +++ b/src/rendergraph/common/rendergraph/attributeinit.h @@ -6,7 +6,7 @@ namespace rendergraph { struct AttributeInit; } -// helper to create an AttributeSet using an initializer_list +/// Helper to create an AttributeSet using an initializer_list. struct rendergraph::AttributeInit { int m_tupleSize; PrimitiveType m_primitiveType; diff --git a/src/rendergraph/common/rendergraph/material.h b/src/rendergraph/common/rendergraph/material.h index ab18e89166a..4073111e1ce 100644 --- a/src/rendergraph/common/rendergraph/material.h +++ b/src/rendergraph/common/rendergraph/material.h @@ -19,11 +19,11 @@ class rendergraph::Material : public rendergraph::BaseMaterial { Material(const UniformSet& uniformSet); virtual ~Material(); - // see QSGMaterial::compare. - // TODO decide if this should be virtual. QSGMaterial::compare is virtual - // to concrete Material can implement a compare function, but in rendergraph - // we can compare the uniforms cache and texture already here, which seems - // sufficient. + /// See QSGMaterial::compare. + // Note: QSGMaterial::compare is virtual, so that a concrete Material can + // implement a custom compare function. But in rendergraph we can always + // compare the uniforms cache and texture already, and this is sufficient + // for our purpose. int compare(const Material* pOther) const { DEBUG_ASSERT(type() == pOther->type()); int cacheCompareResult = std::memcmp(m_uniformsCache.data(), @@ -32,7 +32,7 @@ class rendergraph::Material : public rendergraph::BaseMaterial { if (cacheCompareResult != 0) { return cacheCompareResult < 0 ? -1 : 1; } - // TODO multiple textures + // Note: we currently support only a single texture per material if (!texture(0) || !pOther->texture(0)) { return texture(0) ? 1 : -1; } diff --git a/src/rendergraph/common/rendergraph/material/rgbamaterial.cpp b/src/rendergraph/common/rendergraph/material/rgbamaterial.cpp index e81382bf9ce..4ad2d92bb48 100644 --- a/src/rendergraph/common/rendergraph/material/rgbamaterial.cpp +++ b/src/rendergraph/common/rendergraph/material/rgbamaterial.cpp @@ -18,7 +18,8 @@ const AttributeSet& RGBAMaterial::attributes() { return set; } -/* static */ const UniformSet& RGBAMaterial::uniforms() { +// static +const UniformSet& RGBAMaterial::uniforms() { static UniformSet set = makeUniformSet({"ubuf.matrix"}); return set; } diff --git a/src/rendergraph/opengl/CMakeLists.txt b/src/rendergraph/opengl/CMakeLists.txt index c64c039b84d..67de29950a8 100644 --- a/src/rendergraph/opengl/CMakeLists.txt +++ b/src/rendergraph/opengl/CMakeLists.txt @@ -1,34 +1,6 @@ add_library( rendergraph_gl - ../common/rendergraph/attributeinit.h - ../common/rendergraph/attributeset.h - ../common/rendergraph/geometry.h - ../common/rendergraph/geometrynode.h - ../common/rendergraph/material.h - ../common/rendergraph/material/endoftrackmaterial.cpp - ../common/rendergraph/material/endoftrackmaterial.h - ../common/rendergraph/material/patternmaterial.cpp - ../common/rendergraph/material/patternmaterial.h - ../common/rendergraph/material/rgbamaterial.cpp - ../common/rendergraph/material/rgbamaterial.h - ../common/rendergraph/material/rgbmaterial.cpp - ../common/rendergraph/material/rgbmaterial.h - ../common/rendergraph/material/texturematerial.cpp - ../common/rendergraph/material/texturematerial.h - ../common/rendergraph/material/unicolormaterial.cpp - ../common/rendergraph/material/unicolormaterial.h - ../common/rendergraph/materialshader.h - ../common/rendergraph/materialtype.h - ../common/rendergraph/node.h - ../common/rendergraph/opacitynode.h - ../common/rendergraph/texture.h - ../common/rendergraph/types.h - ../common/rendergraph/uniform.h - ../common/rendergraph/uniformscache.cpp - ../common/rendergraph/uniformscache.h - ../common/rendergraph/uniformset.cpp - ../common/rendergraph/uniformset.h - ../common/types.cpp + ${COMMON_RENDERGRAPH_FILES} attributeset.cpp backend/baseattributeset.cpp backend/baseattributeset.h diff --git a/src/rendergraph/opengl/backend/basegeometry.cpp b/src/rendergraph/opengl/backend/basegeometry.cpp index 09854386dbe..f2074d3fe6a 100644 --- a/src/rendergraph/opengl/backend/basegeometry.cpp +++ b/src/rendergraph/opengl/backend/basegeometry.cpp @@ -6,7 +6,7 @@ using namespace rendergraph; namespace { -// to mimic sg default +// This mimics the scenegraph default. constexpr auto defaultDrawingMode = DrawingMode::TriangleStrip; } // namespace diff --git a/src/rendergraph/opengl/backend/basegeometry.h b/src/rendergraph/opengl/backend/basegeometry.h index f3575adaa14..86c0e41e9ae 100644 --- a/src/rendergraph/opengl/backend/basegeometry.h +++ b/src/rendergraph/opengl/backend/basegeometry.h @@ -10,7 +10,7 @@ class BaseAttributeSet; // fwd decl to avoid circular dependency class BaseGeometry; } // namespace rendergraph -// TODO this assumes all vertices consist of floats +// Note: this assumes all vertices consist of floats, which is sufficient for our purposes class rendergraph::BaseGeometry { protected: BaseGeometry(const BaseAttributeSet& attributeSet, int vertexCount); diff --git a/src/rendergraph/opengl/backend/basegeometrynode.cpp b/src/rendergraph/opengl/backend/basegeometrynode.cpp index 31075d5f873..cf318725b7b 100644 --- a/src/rendergraph/opengl/backend/basegeometrynode.cpp +++ b/src/rendergraph/opengl/backend/basegeometrynode.cpp @@ -40,8 +40,8 @@ void BaseGeometryNode::render() { } glEnable(GL_BLEND); - // qt scene graph uses premultiplied alpha color in the shader, - // so we need to do the same + // Note: Qt scenegraph uses premultiplied alpha color in the shader, + // so we need to do the same. glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); QOpenGLShaderProgram& shader = material.shader(); diff --git a/src/rendergraph/opengl/backend/basegeometrynode.h b/src/rendergraph/opengl/backend/basegeometrynode.h index a4a7f609c4a..50535cab1c9 100644 --- a/src/rendergraph/opengl/backend/basegeometrynode.h +++ b/src/rendergraph/opengl/backend/basegeometrynode.h @@ -14,7 +14,7 @@ class rendergraph::BaseGeometryNode : public rendergraph::BaseNode, BaseGeometryNode() = default; virtual ~BaseGeometryNode() = default; - // called by Engine + // Called by Engine. void initialize() override; void render() override; void resize(int w, int h) override; diff --git a/src/rendergraph/opengl/backend/basematerial.h b/src/rendergraph/opengl/backend/basematerial.h index 6f2a22ccba2..6c1507cb422 100644 --- a/src/rendergraph/opengl/backend/basematerial.h +++ b/src/rendergraph/opengl/backend/basematerial.h @@ -14,7 +14,7 @@ class rendergraph::BaseMaterial { public: virtual MaterialType* type() const = 0; - // For parity with QSGMaterial, not used yet + // For parity with QSGMaterial, not used yet. int compare(const BaseMaterial* other) const; void setShader(std::shared_ptr pShader); diff --git a/src/rendergraph/opengl/backend/basenode.cpp b/src/rendergraph/opengl/backend/basenode.cpp index a413325ee29..c771b5beca4 100644 --- a/src/rendergraph/opengl/backend/basenode.cpp +++ b/src/rendergraph/opengl/backend/basenode.cpp @@ -16,10 +16,10 @@ BaseNode::~BaseNode() { } } -// This mimics QSGNode::appendChildNode. -// Use NodeInterface::appendChildNode(std::unique_ptr pNode) -// for a more clear transfer of ownership. pChild is considered owned by -// this at this point. +/// This mimics QSGNode::appendChildNode. +/// Use NodeInterface::appendChildNode(std::unique_ptr pNode) +/// for a more clear transfer of ownership. pChild is considered owned by +/// this at this point. void BaseNode::appendChildNode(BaseNode* pChild) { if (m_pLastChild) { pChild->m_pPreviousSibling = m_pLastChild; @@ -37,10 +37,10 @@ void BaseNode::appendChildNode(BaseNode* pChild) { } } -// This mimics QSGNode::removeChildNode. -// Use NodeInterface::detachChildNode(BaseNode* pNode) -// for a more clear transfer of ownership. Otherwise, -// deleting pChild is responsibility of the caller. +/// This mimics QSGNode::removeChildNode. +/// Use NodeInterface::detachChildNode(BaseNode* pNode) +/// for a more clear transfer of ownership. Otherwise, +/// deleting pChild is responsibility of the caller. void BaseNode::removeChildNode(BaseNode* pChild) { if (pChild == m_pFirstChild) { m_pFirstChild = pChild->m_pNextSibling; diff --git a/src/rendergraph/opengl/backend/basenode.h b/src/rendergraph/opengl/backend/basenode.h index b0079954697..6e5730eb1af 100644 --- a/src/rendergraph/opengl/backend/basenode.h +++ b/src/rendergraph/opengl/backend/basenode.h @@ -36,9 +36,11 @@ class rendergraph::BaseNode { return m_pEngine; } - // Prefer using NodeInterface::appendChildNode(std::unique_ptr pNode); + /// Mimicking scenegraph node API. + /// Prefer using NodeInterface::appendChildNode(std::unique_ptr pNode); void appendChildNode(BaseNode* pChild); - // Prefer using std::unique_ptr NodeInterface::detachChildNode(BaseNode* pNode); + /// Mimicking scenegraph node API. + /// Prefer using std::unique_ptr NodeInterface::detachChildNode(BaseNode* pNode); void removeChildNode(BaseNode* pChild); BaseNode* parent() const { @@ -61,7 +63,7 @@ class rendergraph::BaseNode { Engine* m_pEngine{}; bool m_usePreprocess{}; - // Mimicking scenegraph node hierarchy. A parent owns its children. + /// Mimicking scenegraph node hierarchy. A parent owns its children. BaseNode* m_pParent{}; BaseNode* m_pFirstChild{}; BaseNode* m_pLastChild{}; diff --git a/src/rendergraph/opengl/geometry.cpp b/src/rendergraph/opengl/geometry.cpp index b2fbfbbcd2a..26a316509ad 100644 --- a/src/rendergraph/opengl/geometry.cpp +++ b/src/rendergraph/opengl/geometry.cpp @@ -10,7 +10,8 @@ Geometry::Geometry(const AttributeSet& attributeSet, int vertexCount) } void Geometry::setAttributeValues(int attributePosition, const float* from, int numTuples) { - // TODO this code assumes all vertices are floats + // Note: this code assumes all vertices are floats, which is sufficient for + // our purpose. VERIFY_OR_DEBUG_ASSERT(attributePosition < attributeCount()) { return; } diff --git a/src/rendergraph/scenegraph/CMakeLists.txt b/src/rendergraph/scenegraph/CMakeLists.txt index e33747a22e7..1e52790a94c 100644 --- a/src/rendergraph/scenegraph/CMakeLists.txt +++ b/src/rendergraph/scenegraph/CMakeLists.txt @@ -1,34 +1,6 @@ add_library( rendergraph_sg - ../common/rendergraph/attributeinit.h - ../common/rendergraph/attributeset.h - ../common/rendergraph/geometry.h - ../common/rendergraph/geometrynode.h - ../common/rendergraph/material.h - ../common/rendergraph/material/endoftrackmaterial.cpp - ../common/rendergraph/material/endoftrackmaterial.h - ../common/rendergraph/material/patternmaterial.cpp - ../common/rendergraph/material/patternmaterial.h - ../common/rendergraph/material/rgbamaterial.cpp - ../common/rendergraph/material/rgbamaterial.h - ../common/rendergraph/material/rgbmaterial.cpp - ../common/rendergraph/material/rgbmaterial.h - ../common/rendergraph/material/texturematerial.cpp - ../common/rendergraph/material/texturematerial.h - ../common/rendergraph/material/unicolormaterial.cpp - ../common/rendergraph/material/unicolormaterial.h - ../common/rendergraph/materialshader.h - ../common/rendergraph/materialtype.h - ../common/rendergraph/node.h - ../common/rendergraph/opacitynode.h - ../common/rendergraph/texture.h - ../common/rendergraph/types.h - ../common/rendergraph/uniform.h - ../common/rendergraph/uniformscache.cpp - ../common/rendergraph/uniformscache.h - ../common/rendergraph/uniformset.cpp - ../common/rendergraph/uniformset.h - ../common/types.cpp + ${COMMON_RENDERGRAPH_FILES} attributeset.cpp backend/baseattributeset.cpp backend/baseattributeset.h diff --git a/src/rendergraph/scenegraph/attributeset.cpp b/src/rendergraph/scenegraph/attributeset.cpp index 04d55fcae8f..72621f82c69 100644 --- a/src/rendergraph/scenegraph/attributeset.cpp +++ b/src/rendergraph/scenegraph/attributeset.cpp @@ -6,5 +6,5 @@ using namespace rendergraph; AttributeSet::AttributeSet(std::initializer_list list, const std::vector&) : BaseAttributeSet(list) { - // names are not used in scenegraph + // names are not used in scenegraph, but needed in the API for the opengl backend } diff --git a/src/rendergraph/scenegraph/backend/basematerial.cpp b/src/rendergraph/scenegraph/backend/basematerial.cpp index 6c882d5e759..27be8bbdeec 100644 --- a/src/rendergraph/scenegraph/backend/basematerial.cpp +++ b/src/rendergraph/scenegraph/backend/basematerial.cpp @@ -18,8 +18,8 @@ int BaseMaterial::compare(const QSGMaterial* other) const { } QSGMaterialShader* BaseMaterial::createShader(QSGRendererInterface::RenderMode) const { - // This looks like a leak but it isn't: we pass ownership to Qt. Qt will - // cache and reuse the shader for all Material of the same type. + // Note: this looks like a leak but it isn't: we pass ownership to Qt. + // Qt will cache and reuse the shader for all Material of the same type. // TODO make sure that RenderMode is always the same. auto pThis = static_cast(this); auto pShader = pThis->createShader().release(); diff --git a/src/rendergraph/scenegraph/backend/basematerialshader.cpp b/src/rendergraph/scenegraph/backend/basematerialshader.cpp index 7a49a3d5afd..dc6b562e74a 100644 --- a/src/rendergraph/scenegraph/backend/basematerialshader.cpp +++ b/src/rendergraph/scenegraph/backend/basematerialshader.cpp @@ -21,8 +21,8 @@ bool BaseMaterialShader::updateUniformData(RenderState& state, return result; } -// override for QSGMaterialShader; this function is called by the Qt scene graph to prepare use of -// sampled images in the shader, typically in the form of combined image samplers. +/// Override for QSGMaterialShader; this function is called by the Qt scene graph to prepare use of +/// sampled images in the shader, typically in the form of combined image samplers. void BaseMaterialShader::updateSampledImage(RenderState& state, int binding, QSGTexture** texture, diff --git a/src/rendergraph/scenegraph/geometry.cpp b/src/rendergraph/scenegraph/geometry.cpp index fcc63f030ff..bcaa6eec048 100644 --- a/src/rendergraph/scenegraph/geometry.cpp +++ b/src/rendergraph/scenegraph/geometry.cpp @@ -35,7 +35,8 @@ Geometry::Geometry(const rendergraph::AttributeSet& attributeSet, int vertexCoun } void Geometry::setAttributeValues(int attributePosition, const float* from, int numTuples) { - // TODO this code assumes all vertices are floats + // Note: this code assumes all vertices are floats, which is sufficient for our + // purpose. const auto attributeArray = QSGGeometry::attributes(); int vertexOffset = 0; for (int i = 0; i < attributePosition; i++) {