diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 325241d33..603becb45 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: target-platform: [host-os] - os: [ubuntu-20.04, ubuntu-22.04, windows-2022, macos-12] + os: [ubuntu-20.04, ubuntu-22.04, windows-2019, macos-12] type: [Debug, Release] compiler: [default] include: @@ -38,7 +38,7 @@ jobs: compiler: clang # on Windows we skip Debug because otherwise the hosted runner runs out of space exclude: - - os: windows-2022 + - os: windows-2019 type: Debug steps: diff --git a/.gitignore b/.gitignore index 82fff4431..82ebdb02b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ /build*/ *~ .vscode/ +.cache/ *.swp *.orig *.pyc diff --git a/CHANGELOG.md b/CHANGELOG.md index b51218229..caff7542f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,69 @@ # Ramses Changelog +28.2.0 +------------------- + +### Added +- Added feature level 02 + - Note that EFeatureLevel_Latest now points to EFeatureLevel_02 + - New features: + - Added support for Uniform Buffer Objects (Uniform Blocks) in shaders + - Added semantics for UBO: + - `EEffectUniformSemantic::ModelBlock`, `EEffectUniformSemantic::CameraBlock`, `EEffectUniformSemantic::ModelCameraBlock` (fully implemented) + - `EEffectUniformSemantic::FramebufferBlock`, `EEffectUniformSemantic::SceneBlock` (not yet implemented on renderer side) + - Added support for merging content into an existing scene + - Added support for merging content of several files to ramses-viewer + - Add experimental support for Vulkan: + - Building vulkan device needs to be explicitly enabled using cmake option `ramses-sdk_ENABLE_DEVICE_TYPE_VULKAN` + - Added new enum value `EDeviceType::Vulkan` + - Scene can be configured to specify render backend compatibility using `SceneConfig::setRenderBackendCompatibility` +- Added glad (OpenGL loader library) + +### Changed +- Redesigned CMake build option for freetype/harfbuzz. Bundled package is used by default unless `ramses-sdk_USE_PLATFORM_FREETYPE` is ON. + - Removed `ramses-sdk_ALLOW_PLATFORM_FREETYPE` and `ramses-sdk_ALLOW_CUSTOM_FREETYPE` + - Replaced with `ramses-sdk_USE_PLATFORM_FREETYPE` for system package, and set to `OFF` by default +- SkinBindings are now updated at the end of logic update +- Upgraded internal abseil to 20240116.1 +- Upgraded glslang to 14.1.0 +- Allow embedded compositing using DMA buffers even if EGL extension `EGL_WL_bind_wayland_display` is not available +- Mark APIs related to system compositor controller on renderer side as deprecated + +### Fixed +- SkinBinding update order bug where skin bindings use old values in update +- SkinBinding serializing inverse binding matrices in wrong order +- Fixed scene locked in subscription requested state, when + - Scene is created in LocalOnly mode + - Display is destroyed, before the scene entered Ready state +- Can create display with wayland IVI window without setting IVI layer if system compositor controller not enabled +- Fixed possible crash when statistics logs are enabled +- EGLContext for async effect uploader is no longer created if feature is disabled in DisplayConfig +- Improved validation messages for RenderBuffers +- Removed warning for empty render group + +28.1.1 +------------------- +### Added +- added ramsh commands to modify some object parameters (visibility, uniform inputs) + +### Fixed +- Attempt to read pixels from multisampled offscreen buffer no longer crashes but fails with an event +- Removed `ramses-sdk_ENABLE_LOGIC` flag, logic cannot be excluded from build anymore + +28.1.0 +------------------- +### Added + +- Added `DisplayConfig::setWindowTitle()` +- `ramses-viewer`: show scenes that are published remotely +- `ramses-viewer`: show stream surfaces + +### Fixed +- Handle time overflow when calculating watchdog notification intervals (IThreadWatchdogNotification) +- Added sanity check for display thread sleep timeout (skub mode) +- Fixed missing watchdog callbacks if notification interval is set to 1ms (RamsesFrameworkConfig::setWatchdogNotificationInterval) +- Instance prefix for logging (RamsesFrameworkConfig::setLoggingInstanceName) now works also for dynamically linked renderer library + 28.0.0 ------------------- ### Added diff --git a/CMakeLists.txt b/CMakeLists.txt index a6e74d0cd..0b1ddb24a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 3.13) set(RAMSES_VERSION_MAJOR 28) -set(RAMSES_VERSION_MINOR 0) +set(RAMSES_VERSION_MINOR 2) set(RAMSES_VERSION_PATCH 0) set(RAMSES_VERSION_POSTFIX "") set(RAMSES_VERSION "${RAMSES_VERSION_MAJOR}.${RAMSES_VERSION_MINOR}.${RAMSES_VERSION_PATCH}${RAMSES_VERSION_POSTFIX}") @@ -43,12 +43,12 @@ option(ramses-sdk_ENABLE_WINDOW_TYPE_ANDROID "Enable building for And option(ramses-sdk_ENABLE_WINDOW_TYPE_IOS "Enable building for iOS window" OFF) option(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_IVI "Enable building for Wayland ivi window" OFF) option(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL "Enable building for Wayland wl_shell window" OFF) +option(ramses-sdk_ENABLE_DEVICE_TYPE_VULKAN "Enable building for an EXPERIMENTAL vulkan device" OFF) # shared lib options option(ramses-sdk_BUILD_FULL_SHARED_LIB "Build full shared libraries (with renderer)." ON) # optional components -option(ramses-sdk_ENABLE_LOGIC "Enable ramses logic - a component for scripting and animation." ON) option(ramses-sdk_TEXT_SUPPORT "Enable/disable the ramses text API." ON) option(ramses-sdk_ENABLE_TCP_SUPPORT "Enable use of TCP communication." ON) option(ramses-sdk_ENABLE_DLT "Enable DLT logging support." ON) @@ -66,11 +66,10 @@ option(ramses-sdk_ENABLE_FLATBUFFERS_GENERATION "Enable generation of fl option(ramses-sdk_USE_IMAGEMAGICK "Enable tests depending on image magick compare" OFF) # find options -option(ramses-sdk_ALLOW_PLATFORM_GLM "Enable to search for platform provided OpenGL Math library (glm)." ON) -option(ramses-sdk_ALLOW_PLATFORM_FREETYPE "Enable to search for platform provided freetype and harfbuzz." ON) -option(ramses-sdk_ALLOW_CUSTOM_FREETYPE "Allow usage of custom freetype and harfbuzz if platform provided one was not found." ON) -option(ramses-sdk_ALLOW_PLATFORM_LZ4 "Enable to search for platform provided lz4" ON) -option(ramses-sdk_USE_PLATFORM_LUAJIT "Uses platform provided luajit instead of internal lua" OFF) +option(ramses-sdk_ALLOW_PLATFORM_GLM "Enable to search for platform-provided OpenGL Math library (glm)." ON) +option(ramses-sdk_ALLOW_PLATFORM_LZ4 "Enable to search for platform-provided lz4" ON) +option(ramses-sdk_USE_PLATFORM_FREETYPE "Use platform-provided freetype and harfbuzz package instead of bundled package." OFF) +option(ramses-sdk_USE_PLATFORM_LUAJIT "Use platform-provided luajit instead of internal lua" OFF) # other options set(ramses-sdk_FOLDER_PREFIX "" CACHE STRING "Optional folder prefix for targets in visual studio.") diff --git a/cmake/modules/FindOpenGL.cmake b/cmake/modules/FindOpenGL.cmake index 89b32ff13..178d66811 100644 --- a/cmake/modules/FindOpenGL.cmake +++ b/cmake/modules/FindOpenGL.cmake @@ -6,75 +6,27 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. # ------------------------------------------------------------------------- -IF(CMAKE_SYSTEM_NAME MATCHES "Windows") - - # we always use the Khronos reference headers - SET(OpenGL_INCLUDE_DIRS - ${ramses-sdk_SOURCE_DIR}/external/khronos - ) - - # Windows has all OpenGL/WGL symbols in one lib - opengl32.lib - SET(OpenGL_LIBRARIES opengl32) - set(OpenGL_DEFINITIONS "-DDESKTOP_GL") - - MARK_AS_ADVANCED( - OpenGL_INCLUDE_DIRS - OpenGL_LIBRARIES - OpenGL_DEFINITIONS - ) - - SET(OpenGL_FOUND TRUE) - -ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Linux") - - # we always use the Khronos reference headers - SET(OpenGL_INCLUDE_DIRS - ${ramses-sdk_SOURCE_DIR}/external/khronos - ) - - # only check, if systems has GLESv3 headers, if yes we - # assume the system is GLESv3 enabled. - # we still use the included khronos GLESv3 headers. - FIND_PATH(GLESv3_INCLUDE_DIRS_IN_SYSROOT GLES3/gl3.h - /usr/include - ) - - # GL ES 3 is implemented in GLESv2 (in mesa) - FIND_LIBRARY(OpenGL_LIBRARIES - NAMES GLESv2 - PATHS - ) - - IF(OpenGL_LIBRARIES AND GLESv3_INCLUDE_DIRS_IN_SYSROOT) - SET(OpenGL_FOUND TRUE) - ENDIF() - - MARK_AS_ADVANCED( - OpenGL_INCLUDE_DIRS - OpenGL_LIBRARIES - ) - -ELSEIF(CMAKE_SYSTEM_NAME MATCHES "Android") - - # only check, if systems has GLESv3 headers, if yes we - # assume the system is GLESv3 enabled. - # we still use the included khronos GLESv3 headers. - FIND_PATH(OpenGL_INCLUDE_DIRS_IN_SYSROOT GLES3/gl3.h - /usr/include - ) - - FIND_LIBRARY(OpenGL_LIBRARIES - NAMES GLESv3 - PATHS - ) - - IF(OpenGL_LIBRARIES AND OpenGL_INCLUDE_DIRS_IN_SYSROOT) - SET(OpenGL_FOUND TRUE) - ENDIF() - - MARK_AS_ADVANCED( - OpenGL_INCLUDE_DIRS - OpenGL_LIBRARIES - ) - -ENDIF() +find_path(GLES3_INCLUDE_DIRS GLES3/gl3.h + PATHS + /usr/include +) + +find_library(GLES3_LIBRARIES + NAMES GLESv3 GLESv2 +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OpenGL DEFAULT_MSG GLES3_LIBRARIES GLES3_INCLUDE_DIRS) + +if (OpenGL_FOUND) + add_library(OpenGL::GLES3 UNKNOWN IMPORTED) + set_target_properties(OpenGL::GLES3 PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${GLES3_INCLUDE_DIRS}" + IMPORTED_LOCATION "${GLES3_LIBRARIES}" + ) + + mark_as_advanced( + GLES3_INCLUDE_DIRS + GLES3_LIBRARIES + ) +endif() diff --git a/cmake/ramses/platformConfig.cmake b/cmake/ramses/platformConfig.cmake index 1e3ab2ee9..e960f6717 100644 --- a/cmake/ramses/platformConfig.cmake +++ b/cmake/ramses/platformConfig.cmake @@ -74,7 +74,7 @@ endif() # gcc specific if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") # optimize for debuggability - addFlags(RAMSES_DEBUG_FLAGS "-Og") + addFlags(RAMSES_DEBUG_FLAGS "-O0") # remap GOT readonly after resolving addFlags(RAMSES_C_CXX_FLAGS "-Wl,-z,relro,-z,now") diff --git a/examples/ramses-example-local-scene-referencing/CMakeLists.txt b/cmake/toolchain/Linux_X86_64_clang15.toolchain similarity index 64% rename from examples/ramses-example-local-scene-referencing/CMakeLists.txt rename to cmake/toolchain/Linux_X86_64_clang15.toolchain index 5c85db2d2..06a4e389c 100644 --- a/examples/ramses-example-local-scene-referencing/CMakeLists.txt +++ b/cmake/toolchain/Linux_X86_64_clang15.toolchain @@ -1,15 +1,13 @@ # ------------------------------------------------------------------------- -# Copyright (C) 2020 BMW AG +# Copyright (C) 2024 BMW AG # ------------------------------------------------------------------------- # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at https://mozilla.org/MPL/2.0/. # ------------------------------------------------------------------------- -createModule( - NAME ramses-example-local-scene-referencing - TYPE BINARY - ENABLE_INSTALL ON - SRC_FILES src/* - DEPENDENCIES ramses-shared-lib -) +SET(CMAKE_C_COMPILER clang-15) +SET(CMAKE_CXX_COMPILER clang++-15) + +SET(CMAKE_C_FLAGS "-m64 -fdiagnostics-color" CACHE STRING "") +SET(CMAKE_CXX_FLAGS "-m64 -fdiagnostics-color" CACHE STRING "") diff --git a/doc/sphinx/_static/style.css b/doc/sphinx/_static/style.css new file mode 100644 index 000000000..1f1b6c4f9 --- /dev/null +++ b/doc/sphinx/_static/style.css @@ -0,0 +1,13 @@ +/* + ------------------------------------------------------------------------- + Copyright (C) 2024 BMW AG + ------------------------------------------------------------------------- + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + ------------------------------------------------------------------------- +*/ + +.wy-nav-content { + max-width: none; +} diff --git a/doc/sphinx/_templates/layout.html b/doc/sphinx/_templates/layout.html new file mode 100644 index 000000000..dd5570fc6 --- /dev/null +++ b/doc/sphinx/_templates/layout.html @@ -0,0 +1,13 @@ + +{% extends "!layout.html" %} +{% block extrahead %} + +{% endblock %} diff --git a/doc/sphinx/build.rst b/doc/sphinx/build.rst index eae96ff12..5c87f1065 100644 --- a/doc/sphinx/build.rst +++ b/doc/sphinx/build.rst @@ -133,11 +133,6 @@ Supported window types can be controlled with the cmake options below: You can use the following options to disable some of the Ramses features: -* -Dramses-sdk_ENABLE_LOGIC - * options: ON/OFF - * default: ON - * Enables the logic subsystem of ramses alongside its dependencies (Lua, Sol, ...). - * -Dramses-sdk_TEXT_SUPPORT * options: ON/OFF * default: ON diff --git a/doc/sphinx/core.rst b/doc/sphinx/core.rst index de8fdafe3..55a22baa7 100644 --- a/doc/sphinx/core.rst +++ b/doc/sphinx/core.rst @@ -613,12 +613,6 @@ this in most cases means to render the scene(s) assigned to an offscreen buffer the consumer scene using the contents of the offscreen buffer. -^^^^^^^^^^^^^^^^^^^^^^ -ContentExpiration -^^^^^^^^^^^^^^^^^^^^^^ - -.. TODO - ------------------------ The Daemon component ------------------------ diff --git a/doc/sphinx/index.rst b/doc/sphinx/index.rst index eec65b74e..806458fd4 100644 --- a/doc/sphinx/index.rst +++ b/doc/sphinx/index.rst @@ -47,6 +47,12 @@ Ramses documentation viewer +.. toctree:: + :maxdepth: 3 + :caption: Performance and Profiling + + profiling + .. toctree:: :maxdepth: 3 :caption: Class Index diff --git a/doc/sphinx/profiling.rst b/doc/sphinx/profiling.rst new file mode 100644 index 000000000..51b22a0f8 --- /dev/null +++ b/doc/sphinx/profiling.rst @@ -0,0 +1,253 @@ +.. + ------------------------------------------------------------------------- + Copyright (C) 2024 BMW AG + ------------------------------------------------------------------------- + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + ------------------------------------------------------------------------- + +========================================================= +Performance and Profiling +========================================================= + +There are multiple ways to find bottlenecks in your assets, your code using Ramses, or Ramses itself. + + +========================================================= +Inspecting the contents of your scene and optimizing it +========================================================= + +The first source of performance problems in a 3D application is usually the content. Having large textures or geometry, +heavy shaders, or simply rendering suboptimally - those are all things that can be easily solved in the content/scene directly +by a skilled technical artist. + +Ramses provides a tool to perform such analysis, called the ramses scene viewer (see its documentation in :ref:`ramses-viewer `). + +========================================================= +Looking at the Ramses periodic performance logs +========================================================= + +A great source of information about what's going on in the Ramses threads (specifically when having network involved) are +the ramses periodic logs (RPER). See below how +to read and use these logs. + +-------------------------------------------------------- +General periodic logs +-------------------------------------------------------- + +Any Ramses application (regardless if it has a client, a renderer, or both) has a periodic log whichs looks like this: + +.. code-block:: text + + 20240311-18:10:14.378 | Info | RPER | R.PerLogger: Version: 28.0.0 Hash:bfadebe40e Commit:40378 Type:RelWithDebInfo Env:(unknown) SyncT:1710177014378ms (dtSteady:2001 - dtSync:2001 -> 0) PUp:2002 RUp:2002 RInit:1 RParallel:1 + 20240311-18:10:14.378 | Info | RPER | R.TCP_ConnSys: Connected Participant(s): 8649-E0139E8AE986; + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line-by-line explanation of the logs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +First line: + * Version: Ramses version + * Hash: Commit hash + * Commit: Commit Count + * Type: Build type (e.g. Debug) + * Env: Build environment version + * SyncT: Current time (ms) from synchronized clock + * (dtSteady - dtSync -> DIFF) + + * dtSteady: difference between current time and previous time from steady clock + * dtSync: difference between current time and previous time from synchronized clock + * DIFF: Difference between dtSteady and dtSync + + * PUp: Uptime since process started + * RUp: Uptime since ramses started + * RInit: 1 instance of ramses initialized (framework) + * RParallel: 1 instance of ramses running now + + + +Second line: + * Participants connected to this instance of ramses + + +-------------------------------------------------------- +Client periodic logs +-------------------------------------------------------- + +A Ramses client typically reports logs like this: + +.. code-block:: text + + 20240311-18:10:14.378 | Info | RPER | R.PerLogger: Client: 1 scene(s): 123 Published + 20240311-18:10:14.378 | Info | RPER | R.PerLogger: msgIn (3/5/4) msgO (0/1/0) res+ (0/5/2) res- (0) resNr (5) resF (0) resFS (0) + 20240311-18:10:14.378 | Info | RPER | R.PerLogger: scene: 123 flush (0/1/0) obj+ (0/12/6) obj- (0) objNr (12) actG (0/46/23) actGS (0/878/439) actO (0) actSkp (0) suG (0) suGS (0) suX (0/0) ar# (0/3/1) aras (0/30/15) arms (0/48/24) er# (0/1/0) eras (0/385/192) erms (0/385/192) tr# (0/1/0) tras (0/1048576/524288) trms (0/1048576/524288) + + +^^^^^^^^^^^^^^^^^^^^^^ +General Explanation +^^^^^^^^^^^^^^^^^^^^^^ + +The client-side periodic logger collects the stats values (flush, obj+, etc) every second. However the time interval +for logging output is configurable and by default set to 2 seconds. + +The collected values are printed in two fashions depending on the stat value: + * `suX` lists the largest collected values of the last logging period (value1, value2, ..., valueN) + * For all other stats there are typically 3 values printed (min/max/avg): + + * min: the smallest value that was collected since the last log output + * max: the largest value that was collected since the last log output + * avg: the average of all collected values since the last log output: ((value1 + value2 + ..valueN) / n) + +If the smallest and the largest value are equal (min == max), only 1 value will be printed: (value) + ++--------------------------------+------------------+-----------+ +| | Example 1 | Example 2 | ++================================+==================+===========+ +| Logging output time interval | 4 seconds | 2 seconds | ++--------------------------------+------------------+-----------+ +| Number of values collected | 4 | 2 | ++--------------------------------+------------------+-----------+ +| Values collected in the logger | `20, 25, 21, 55` | `42, 42` | ++--------------------------------+------------------+-----------+ +| Values printed in logs | `(20/55/30)` | `(42)` | ++--------------------------------+------------------+-----------+ + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line-by-line explanation of client logs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +First line: + * Client participant id + * List of scenes owned by the client and their status + + +Second line (General client performance stats): + * msgIn: Number of messages received + * msgO: Number of message sent + * res+: Client Resources created + * res-: Client Resources destroyed + * resNr: Client Resource Count + * resF: Number of Client Resources loaded from File + * resFS: Size of Client Resources loaded from file + + +Third line and over (Scene related stats): + * scene: scene id + * flush: Number of flushes triggered per second + * obj+: Number of scene objects created (ramses::SceneObject) per second + * obj-: Number of scene objects destroyed (ramses::SceneObject) per second + * objNr: Number of currently existing scene objects (ramses::SceneObject) + * actG: Number of scene actions generated per second + * actGS: Size of scene actions generated per second + * actO: Number of scene actions sent to renderer(s) per second (will be counted for each scene subscriber) + * actSkp: Number of skipped scene actions per second (usually an optimization to avoid empty updates) + * suG: Scene updates generated per second. Number of scene update packages generated for network send (might be more than # of sceneupdates) + * suGS: Scene update generated size per second. Accumulated size of scene update packages generated for network send + * suX: Shows the n largest scene updated packets in the logging interval (to identify peaks in network load) + * ar#: Number of currently used array resources + * aras: Average size of a single array resource ((totalSize of currently used array resources) / ar#) + * arms: Largest currently used array resource + * er#: Number of currently used Effects + * eras: Average size of a single effect resource ((totalSize of currently used effects) / er#) + * erms: Largest currently used effect resource + * tr#: Number of currently used texture resources + * tras: Average size of a single texture resource ((totalSize of currently used textures) / tr#) + * trms: Largest currently used texture resource + + +.. warning:: + Some stats describe changes/deltas to the scene: flush, obj+, obj-, act*, su*; others describe a snapshot of the current scene state: objNr, ar*, er* tr*. + Resource stats (ar*,er*, tr*) are only logged if there was a flush during the logging interval. + + +-------------------------------------------------------- +Renderer periodic logs +-------------------------------------------------------- + +A Ramses application which also contains a renderer component has periodic logs which look like this: + +.. code-block:: text + + 20240311-16:33:23.008 | Info | RPER | R.DispThrd0: Display: threaded=true dispThreadsRunning=true loopMode=UpdAndRnd targetFPS=60 skub=true + 2 scene(s): 123 Rendered 124 Rendered + Avg framerate: 21.775545 FPS [minFrameTime 9431us, maxFrameTime 35222us], drawCalls (0/4/1), numFrames 13, resUploaded 11 (2160319 B), RC VRAM usage/cache (2/0 MB) + FB: 7 + Scene 123: rendered 4, framesFArrived 2, framesFApplied 2, framesFBlocked 0, maxFramesWithNoFApplied 5, maxFramesFBlocked 0, FArrived 2, FApplied 2, actions/F (4/96/50), dt/F (13/766/389.5), RC+/F (0/2/1), RC-/F (0/0/0), RS/F (0/1/0.5), RSUploaded 1 (1024 B) + Scene 124: rendered 3, framesFArrived 3, framesFApplied 2, framesFBlocked 1, maxFramesWithNoFApplied 7, maxFramesFBlocked 1, FArrived 3, FApplied 3, actions/F (44/72/56.666668), dt/F (12/33/24.666666), RC+/F (0/6/3), RC-/F (0/0/0), RS/F (0/0/0) + + Time budgets: sceneResourceUpload 315360000000000us resourceUpload 315360000000000us obRender 315360000000000us + Longest frame(us)[avg]:229046 RendererCommands:205638 [15529] UpdateClientResources:13 [767] ApplySceneActions:1 [101] UpdateSceneResources:1 [4] UpdateEmbeddedCompositingResources:7 [3] UpdateStreamTextures:1 [0] UpdateScenesToBeMapped:6 [604] UpdateResourceCache:1 [47] UpdateTransformations:5 [12] UpdateDataLinks:13 [13] HandleDisplayEvents:42 [63] DrawScenes:21792 [1802] SwapBuffersNotifyClients:1526 [329] MaxFramerateSleep:0 [8714] + + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Line-by-line explanation of renderer logs +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +First line: + * Whether display threaded + * Whether display thread running + * Renderer Loop Mode ( `UpdateAndRender` or `UpdateOnly` ) + * Target FPS + * Whether unmodified scenes skipped + +Second line: + * Renderer participant id + * List of scenes known to renderer and status + +Third line (General renderer performance stats): + * Number of frames per second + * minimal and maximal frame time within time period + * drawcalls per frame + * Number of frames rendered in time period + * resources uploaded in time period + * Size of the uploaded client resources / Cache Size of GPU (in MB) + +Fourth line and over (Scene-related stats): + * Scene id + * rendered: Number of frames rendered + * FrameFArrived: Number of frames where flushes arrived + * FramesFApplied: Number of frames where flushes applied + * FrameFBlocked: Number of frames where applying a flush was blocked + * maxFramesWithNoFApplied: How many consecutive frame there was no flush applied + * maxFramesFBlocked: How many consecutive frames flushes were blocked from applying + * FArrived: Number of flushes arrived + * FApplied: Number of flushes applied + * actions/F: number of scene actions per flush + * dt/F: flush latency + * RC+/F RC-/F: Number of client resources added/removed per flush + * RS/F: Number of scene resource actions per flush + * RSUploaded: Size of scene resources uploaded + +Second-last line (Time budgets): + * Information about how much time per frame an action may take as a maximum, set by application + +Last line (Advanced stats): + * Longest Frame: How long did the longest frame take to render altogether + * Rest: Advanced stats for profiling renderer which need internal understanding of the Ramses renderer. + +.. note:: + RC stands for client resources - legacy name for immutable/static resources - textures, static geometry buffers, shaders + + RS stands for scene resources - legacy name for dynamic resources - render buffers/targets and dynamic geometry buffers + + +===================================================== +Using specialized tools +===================================================== + +If the above methods didn't yield the results you expected, or you still think your application can perform better, +you can also use some of the professional tools for profiling: + + * NVidia NSight - a great tool by NVidia which can analyze any OpenGL-based application. Limitation: requires an NVidia graphics card. + * Standard profilers like the MSVC Profiler or gprof - great for finding CPU bottlenecks or memory attrition issues. + * Android Profiler - a great all-round tool for finding issues, also in native libs such as Ramses. Works only on Android. + + +-------------------------------------------------------- +Logic Update Cycle Profiling +-------------------------------------------------------- + +The SDK also provides basic measuring. Please see :ref:`Logic API/Performance ` for details. diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 7c68b22c8..6634cad3a 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -20,11 +20,12 @@ add_subdirectory(ramses-example-data-buffers-vertices) add_subdirectory(ramses-example-data-buffers-texture) add_subdirectory(ramses-example-geometry-instancing) add_subdirectory(ramses-example-renderonce) +add_subdirectory(ramses-example-interleaved-vertex-buffers) + if(ramses-sdk_TEXT_SUPPORT) add_subdirectory(ramses-example-text-basic) add_subdirectory(ramses-example-text-languages) endif() -add_subdirectory(ramses-example-interleaved-vertex-buffers) if(ramses-sdk_BUILD_FULL_SHARED_LIB) add_subdirectory(ramses-example-local-client) @@ -34,11 +35,9 @@ if(ramses-sdk_BUILD_FULL_SHARED_LIB) add_subdirectory(ramses-example-local-dma-offscreenbuffer) add_subdirectory(ramses-example-local-viewport-link) add_subdirectory(ramses-example-local-pick-handling) - add_subdirectory(ramses-example-local-scene-referencing) add_subdirectory(ramses-example-local-geometry-shaders) add_subdirectory(ramses-example-local-compositing) + add_subdirectory(ramses-example-local-scene-merge) endif() -if(ramses-sdk_ENABLE_LOGIC) - add_subdirectory(logic) -endif() +add_subdirectory(logic) diff --git a/examples/ramses-example-local-client/res/ramses-local-client-test.frag b/examples/ramses-example-local-client/res/ramses-local-client-test.frag index 21f831cc3..50cdd8b2e 100644 --- a/examples/ramses-example-local-client/res/ramses-local-client-test.frag +++ b/examples/ramses-example-local-client/res/ramses-local-client-test.frag @@ -6,10 +6,14 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#version 100 +#version 310 es + +precision highp float; +uniform vec4 color; + +out vec4 fragColor; -uniform highp vec4 color; void main(void) { - gl_FragColor = color + vec4(0.1); + fragColor = color + vec4(0.1); } diff --git a/examples/ramses-example-local-client/res/ramses-local-client-test.vert b/examples/ramses-example-local-client/res/ramses-local-client-test.vert index d36728575..16ca010d9 100644 --- a/examples/ramses-example-local-client/res/ramses-local-client-test.vert +++ b/examples/ramses-example-local-client/res/ramses-local-client-test.vert @@ -6,13 +6,20 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#version 100 +#version 310 es -uniform highp mat4 mvpMatrix; +precision highp float; -attribute vec3 a_position; +layout(std140,binding=1) uniform modelCameraBlock_t +{ + mat4 mvpMatrix; + mat4 mvMatrix; + mat4 normalMatrix; +} modelCameraBlock; + +in vec3 a_position; void main() { - gl_Position = mvpMatrix * vec4(a_position, 1.0); + gl_Position = modelCameraBlock.mvpMatrix * vec4(a_position, 1.0); } diff --git a/examples/ramses-example-local-client/src/main.cpp b/examples/ramses-example-local-client/src/main.cpp index 9a863a076..1ed85ecab 100644 --- a/examples/ramses-example-local-client/src/main.cpp +++ b/examples/ramses-example-local-client/src/main.cpp @@ -81,7 +81,8 @@ int main() ramses::EffectDescription effectDesc; effectDesc.setVertexShaderFromFile("res/ramses-local-client-test.vert"); effectDesc.setFragmentShaderFromFile("res/ramses-local-client-test.frag"); - effectDesc.setUniformSemantic("mvpMatrix", ramses::EEffectUniformSemantic::ModelViewProjectionMatrix); + // tell Ramses that the shader uniform block is meant to be automatically filled with model/camera matrices + effectDesc.setUniformSemantic("modelCameraBlock", ramses::EEffectUniformSemantic::ModelCameraBlock); ramses::Effect* effect = clientScene->createEffect(effectDesc, "glsl shader"); ramses::Appearance* appearance = clientScene->createAppearance(*effect, "triangle appearance"); @@ -124,5 +125,7 @@ int main() meshNode->setRotation(glm::mix(q1, q2, factor)); clientScene->flush(); if (factor >= 1.f || factor <= 0.f) step = -step; + + renderer.dispatchEvents(eventHandler); } } diff --git a/examples/ramses-example-local-scene-merge/CMakeLists.txt b/examples/ramses-example-local-scene-merge/CMakeLists.txt new file mode 100644 index 000000000..23d729972 --- /dev/null +++ b/examples/ramses-example-local-scene-merge/CMakeLists.txt @@ -0,0 +1,17 @@ +# ------------------------------------------------------------------------- +# Copyright (C) 2018 BMW Car IT GmbH +# ------------------------------------------------------------------------- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# ------------------------------------------------------------------------- + +createModule( + NAME ramses-example-local-scene-merge + TYPE BINARY + ENABLE_INSTALL ON + SRC_FILES include/*.h + src/*.cpp + RESOURCE_FOLDERS res + DEPENDENCIES ramses-shared-lib +) diff --git a/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texture-inverted.png b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texture-inverted.png new file mode 100644 index 000000000..9efd252c9 Binary files /dev/null and b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texture-inverted.png differ diff --git a/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texture.png b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texture.png new file mode 100644 index 000000000..e7ad227ed Binary files /dev/null and b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texture.png differ diff --git a/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texturing.frag b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texturing.frag new file mode 100644 index 000000000..367be321d --- /dev/null +++ b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texturing.frag @@ -0,0 +1,26 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 310 es + +precision highp float; + +uniform sampler2D textureSampler; + +layout(std140,binding=1) uniform ub_t +{ + highp vec4 color; +} uniformBlock; + +in lowp vec2 v_texcoord; +out vec4 fragColor; + +void main(void) +{ + fragColor = uniformBlock.color * texture(textureSampler, v_texcoord); +} diff --git a/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texturing.vert b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texturing.vert new file mode 100644 index 000000000..76426cf27 --- /dev/null +++ b/examples/ramses-example-local-scene-merge/res/ramses-example-local-scene-merge-texturing.vert @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 310 es + +precision highp float; + +uniform highp mat4 mvpMatrix; + +in vec3 a_position; +in vec2 a_texcoord; + +out vec2 v_texcoord; + +void main() +{ + gl_Position = mvpMatrix * vec4(a_position, 1.0); + v_texcoord = a_texcoord; +} diff --git a/examples/ramses-example-local-scene-merge/src/main.cpp b/examples/ramses-example-local-scene-merge/src/main.cpp new file mode 100644 index 000000000..3172beecf --- /dev/null +++ b/examples/ramses-example-local-scene-merge/src/main.cpp @@ -0,0 +1,312 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "ramses/framework/EFeatureLevel.h" +#include "ramses/framework/DataTypes.h" +#include "ramses/framework/RamsesFrameworkTypes.h" +#include "ramses/framework/RamsesObjectTypes.h" +#include "ramses/client/ramses-client.h" +#include "ramses/client/ramses-utils.h" +#include "ramses/client/Node.h" +#include "ramses/client/RenderPass.h" +#include "ramses/client/RenderTarget.h" +#include "ramses/client/SceneObjectIterator.h" +#include "ramses/client/logic/AppearanceBinding.h" +#include "ramses/client/logic/LogicEngine.h" +#include "ramses/client/logic/NodeBinding.h" +#include "ramses/client/logic/LuaScript.h" +#include "ramses/client/logic/LuaInterface.h" +#include "ramses/client/logic/Property.h" +#include "ramses/renderer/RamsesRenderer.h" +#include "ramses/renderer/IRendererEventHandler.h" +#include "ramses/renderer/IRendererSceneControlEventHandler.h" +#include "ramses/renderer/DisplayConfig.h" +#include "ramses/renderer/RendererConfig.h" +#include "ramses/renderer/RendererSceneControl.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +const ramses::sceneId_t SCENE_ID{123}; +constexpr int SCENE_COUNT = 3; +const std::array FILE_NAMES{"tempfileA.ramses", "tempfileB.ramses", "tempfileC.ramses"}; +const std::array COLORS{ramses::vec4f{1.0f, 0.0f, 0.0f, 1.0f}, ramses::vec4f{0.0f, 1.0f, 0.0f, 1.0f}, ramses::vec4f{0.0f, 0.0f, 1.0f, 1.0f}}; +const std::array TRANSLATIONS{ramses::vec3f{-1.0f, 0.0f, 0.0f}, ramses::vec3f{1.0f, 0.0f, 0.0f}, ramses::vec3f{0.0f, 0.0f, 0.0f}}; +const std::array ROTATIONS{45.0f, -20.0f, 5.0f}; +const std::chrono::seconds DELAY{5}; + + +bool createScene(int sceneNumber); +bool mergeScenes(const std::vector& files); + + +class RendererEventHandler : public ramses::RendererEventHandlerEmpty +{ +public: + void windowClosed(ramses::displayId_t /*displayId*/) override + { + m_windowClosed = true; + } + + [[nodiscard]] bool isWindowClosed() const + { + return m_windowClosed; + } + +private: + bool m_windowClosed = false; +}; + + +/** + * @example ramses-example-local-scene-merge/src/main.cpp + * @brief Scene Merging Example + */ +int main() +{ + std::vector fileNames; + + for (int i = 0; i < SCENE_COUNT; ++i) + { + if (!createScene(i)) + { + return EXIT_FAILURE; + } + fileNames.push_back(FILE_NAMES[i]); + } + + if (!mergeScenes(fileNames)) + { + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +std::string generateName(std::string const & str, int sceneNumber) +{ + return str + "_" + std::to_string(sceneNumber); +} + +bool createScene(int sceneNumber) +{ + constexpr uint32_t width = 1280u; + constexpr uint32_t height = 480u; + ramses::RamsesFrameworkConfig config{ramses::EFeatureLevel_Latest}; + config.setLogLevelConsole(ramses::ELogLevel::Trace); + config.setLoggingInstanceName(generateName("Scene", sceneNumber)); + ramses::RamsesFramework framework(config); + ramses::RamsesClient& ramses(*framework.createClient("ramses-example-local-scene-merge")); + const ramses::SceneConfig sceneConfig(SCENE_ID); + ramses::Scene* scene = ramses.createScene(sceneConfig, "scene merging from file"); + + // every scene needs a render pass with camera + auto* camera = scene->createPerspectiveCamera(generateName("my camera", sceneNumber)); + camera->setViewport(0, 0, 1280u, 480u); + camera->setFrustum(19.f, 1280.f / 480.f, 0.1f, 1500.f); + camera->setTranslation({0.0f, 0.0f, 5.0f}); + ramses::RenderPass* renderPass = scene->createRenderPass(generateName("my render pass", sceneNumber)); + renderPass->setClearFlags(ramses::EClearFlag::None); + renderPass->setCamera(*camera); + ramses::RenderGroup* renderGroup = scene->createRenderGroup(generateName("group", sceneNumber)); + renderPass->addRenderGroup(*renderGroup); + + const std::array vertexPositionsArray{ ramses::vec3f{-0.5f, -0.5f, -1.f}, ramses::vec3f{0.5f, -0.5f, -1.f}, ramses::vec3f{-0.5f, 0.5f, -1.f}, ramses::vec3f{0.5f, 0.5f, -1.f} }; + ramses::ArrayResource* vertexPositions = scene->createArrayResource(4u, vertexPositionsArray.data()); + + const std::array textureCoordsArray{ ramses::vec2f{0.f, 1.f}, ramses::vec2f{1.f, 1.f}, ramses::vec2f{0.f, 0.f}, ramses::vec2f{1.f, 0.f} }; + ramses::ArrayResource* textureCoords = scene->createArrayResource(4u, textureCoordsArray.data()); + + const std::array indicesArray{ 0, 1, 2, 2, 1, 3 }; + ramses::ArrayResource* indices = scene->createArrayResource(6u, indicesArray.data()); + + char const * const fileNameTexture = "res/ramses-example-local-scene-merge-texture.png"; + char const * const fileNameTextureInverted = "res/ramses-example-local-scene-merge-texture-inverted.png"; + + ramses::Texture2D* texture = ramses::RamsesUtils::CreateTextureResourceFromPng(sceneNumber == 0 ? fileNameTexture : fileNameTextureInverted, *scene); + ramses::TextureSampler* sampler = scene->createTextureSampler( + ramses::ETextureAddressMode::Repeat, + ramses::ETextureAddressMode::Repeat, + ramses::ETextureSamplingMethod::Linear, + ramses::ETextureSamplingMethod::Linear, + *texture); + + ramses::EffectDescription effectDesc; + effectDesc.setVertexShaderFromFile("res/ramses-example-local-scene-merge-texturing.vert"); + effectDesc.setFragmentShaderFromFile("res/ramses-example-local-scene-merge-texturing.frag"); + effectDesc.setUniformSemantic("mvpMatrix", ramses::EEffectUniformSemantic::ModelViewProjectionMatrix); + + ramses::Effect* effectTex = scene->createEffect(effectDesc, generateName("glsl shader", sceneNumber)); + + ramses::Appearance* appearance = scene->createAppearance(*effectTex, generateName("triangle appearance", sceneNumber)); + auto colorUniform = effectTex->findUniformInput("uniformBlock.color"); + appearance->setInputValue(colorUniform.value(), ramses::vec4f{1.0f, 1.0f, 0.0f, 1.0f}); + + ramses::Geometry* geometry = scene->createGeometry(*effectTex, generateName("triangle geometry", sceneNumber)); + + geometry->setIndices(*indices); + std::optional positionsInput = effectTex->findAttributeInput("a_position"); + std::optional texcoordsInput = effectTex->findAttributeInput("a_texcoord"); + std::optional textureInput = effectTex->findUniformInput("textureSampler"); + assert(positionsInput.has_value() && texcoordsInput.has_value() && textureInput.has_value()); + geometry->setInputBuffer(*positionsInput, *vertexPositions); + geometry->setInputBuffer(*texcoordsInput, *textureCoords); + appearance->setInputTexture(*textureInput, *sampler); + + ramses::Node* scaleNode = scene->createNode(generateName("scale node", sceneNumber)); + scaleNode->setScaling({2.0f, 2.0f, 2.0f}); + + ramses::MeshNode* meshNode = scene->createMeshNode(generateName("textured triangle mesh node", sceneNumber)); + meshNode->setAppearance(*appearance); + meshNode->setGeometry(*geometry); + + meshNode->setTranslation(TRANSLATIONS[sceneNumber]); + // mesh needs to be added to a render group that belongs to a render pass with camera in order to be rendered + renderGroup->addMeshNode(*meshNode); + + scaleNode->addChild(*meshNode); + + scene->flush(); + + // create logic engine that sets the rotation of the meshes + ramses::LogicEngine& logicEngine{ *scene->createLogicEngine(generateName("example logic", sceneNumber))}; + ramses::NodeBinding* nodeBinding = logicEngine.createNodeBinding(*meshNode, ramses::ERotationType::Euler_XYZ, "link to node"); + + auto* appearanceBinding = logicEngine.createAppearanceBinding(*appearance, generateName("appearance binding", sceneNumber)); + + ramses::LuaScript* simpleScript = logicEngine.createLuaScript(R"( + function interface(IN,OUT) + IN.rotationZ = Type:Float() + OUT.rotationZ = Type:Vec3f() + end + + function run(IN,OUT) + -- Rotate around Z axis with 100 degrees per second + OUT.rotationZ = {0, 0, IN.rotationZ} + end + )", {}, "simple rotation script"); + + const std::string_view interfaceSrc = R"( + function interface(inout_params) + inout_params.rotationZ = Type:Float() + inout_params.color = Type:Vec4f() + end + )"; + + ramses::LuaInterface* intf = logicEngine.createLuaInterface(interfaceSrc, "Interface"); + logicEngine.link(*simpleScript->getOutputs()->getChild("rotationZ"), *nodeBinding->getInputs()->getChild("rotation")); + logicEngine.link( + *intf->getOutputs()->getChild("rotationZ"), + *simpleScript->getInputs()->getChild("rotationZ")); + + logicEngine.link(*intf->getOutputs()->getChild("color"), *appearanceBinding->getInputs()->getChild("uniformBlock.color")); + + // Let's initialize the interface's input with some value + intf->getInputs()->getChild("rotationZ")->set(ROTATIONS[sceneNumber]); + intf->getInputs()->getChild("color")->set(COLORS[sceneNumber]); + + /** + * Call update() before saving to ensure the ramses scene is in a state where all settings (in this case, the node's rotation) + * have been set once before saving + */ + logicEngine.update(); + + bool result = scene->saveToFile(FILE_NAMES[sceneNumber], {}); + + ramses.destroy(*scene); + + return result; +} + +bool mergeScenes(const std::vector& files) +{ + if (files.empty()) + { + return false; + } + + ramses::EFeatureLevel featureLevel = ramses::EFeatureLevel_Latest; + if (!ramses::RamsesClient::GetFeatureLevelFromFile(files[0], featureLevel)) + { + return false; + } + + // load the saved file + ramses::RamsesFrameworkConfig config{featureLevel}; + config.setRequestedRamsesShellType(ramses::ERamsesShellType::Console); + config.setLogLevel(ramses::ELogLevel::Info); + config.setPeriodicLogInterval(std::chrono::seconds(0)); + config.setLoggingInstanceName("Merge"); + ramses::RamsesFramework framework(config); + ramses::RamsesClient& ramses(*framework.createClient("ramses-example-local-scene-merge")); + + ramses::RendererConfig rendererConfig; + ramses::RamsesRenderer& renderer(*framework.createRenderer(rendererConfig)); + ramses::RendererSceneControl& sceneControlAPI = *renderer.getSceneControlAPI(); + renderer.startThread(); + + ramses::DisplayConfig displayConfig; + const ramses::displayId_t display = renderer.createDisplay(displayConfig); + renderer.flush(); + + RendererEventHandler eventHandler; + ramses::RendererSceneControlEventHandlerEmpty sceneControlEventHandler; + + ramses::Scene* loadedScene = nullptr; + for (size_t sceneIndex = 0; sceneIndex < files.size(); ++sceneIndex) + { + if (sceneIndex == 0) + { + // load scene from first file + loadedScene = ramses.loadSceneFromFile(files[0], ramses::SceneConfig(SCENE_ID, ramses::EScenePublicationMode::LocalOnly)); + if (!loadedScene) + { + return false; + } + + loadedScene->publish(ramses::EScenePublicationMode::LocalOnly); + + // show the scene on the renderer + sceneControlAPI.setSceneMapping(SCENE_ID, display); + sceneControlAPI.setSceneState(SCENE_ID, ramses::RendererSceneState::Rendered); + sceneControlAPI.flush(); + } + else + { + // merge the remaining files into the scene one by one + ramses.mergeSceneFromFile(*loadedScene, files[sceneIndex]); + loadedScene->flush(); + } + + const auto startTime = std::chrono::steady_clock::now(); + while (!eventHandler.isWindowClosed() && (std::chrono::steady_clock::now() - startTime) < DELAY) + { + std::this_thread::sleep_for(std::chrono::milliseconds(16)); + loadedScene->flush(); + renderer.dispatchEvents(eventHandler); + sceneControlAPI.dispatchEvents(sceneControlEventHandler); + } + } + + if (!loadedScene) + { + return false; + } + + loadedScene->unpublish(); + ramses.destroy(*loadedScene); + + return true; +} diff --git a/examples/ramses-example-local-scene-referencing/src/main.cpp b/examples/ramses-example-local-scene-referencing/src/main.cpp deleted file mode 100644 index 48f976574..000000000 --- a/examples/ramses-example-local-scene-referencing/src/main.cpp +++ /dev/null @@ -1,332 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (C) 2020 BMW AG -// ------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// ------------------------------------------------------------------------- - -#include "ramses/client/ramses-client.h" - -#include "ramses/client/SceneReference.h" - -#include "ramses/renderer/RamsesRenderer.h" -#include "ramses/renderer/IRendererEventHandler.h" -#include "ramses/renderer/DisplayConfig.h" -#include "ramses/renderer/RendererSceneControl.h" - -#include "ramses/client/ramses-utils.h" - -#include -#include -#include - -class RendererEventHandler : public ramses::RendererEventHandlerEmpty -{ -public: - void windowClosed(ramses::displayId_t /*displayId*/) override - { - m_windowClosed = true; - } - - [[nodiscard]] bool isWindowClosed() const - { - return m_windowClosed; - } - -private: - bool m_windowClosed = false; -}; - - -/** \cond HIDDEN_SYMBOLS */ -class SceneReferenceEventHandler final : public ramses::IClientEventHandler -{ -public: - explicit SceneReferenceEventHandler(ramses::RamsesClient& client) - : m_client(client) - {} - - void sceneFileLoadFailed(std::string_view /*filename*/) override {} - void sceneFileLoadSucceeded(std::string_view /*filename*/, ramses::Scene* /*loadedScene*/) override {} - void sceneReferenceFlushed(ramses::SceneReference& /*sceneRef*/, ramses::sceneVersionTag_t /*versionTag*/) override {} - void dataLinked(ramses::sceneId_t /*providerScene*/, ramses::dataProviderId_t /*providerId*/, ramses::sceneId_t /*consumerScene*/, ramses::dataConsumerId_t /*consumerId*/, bool /*success*/) override {} - void dataUnlinked(ramses::sceneId_t /*consumerScene*/, ramses::dataConsumerId_t /*consumerId*/, bool /*success*/) override {} - - void sceneReferenceStateChanged(ramses::SceneReference& sceneRef, ramses::RendererSceneState state) override - { - m_sceneRefState[sceneRef.getReferencedSceneId()] = state; - } - - void waitForSceneRefState(ramses::sceneId_t sceneId, ramses::RendererSceneState state) - { - while (m_sceneRefState.count(sceneId) == 0 || m_sceneRefState.find(sceneId)->second != state) - { - ramses::SceneIterator sceneIter{ m_client }; - while (auto scene = sceneIter.getNext()) - scene->flush(); // local only scenes have to be flushed periodically when getting scene to READY state - - std::this_thread::sleep_for(std::chrono::milliseconds(5)); - m_client.dispatchEvents(*this); - } - } - -private: - ramses::RamsesClient& m_client; - std::unordered_map m_sceneRefState; -}; -/** \endcond */ - -static constexpr int32_t VPWidth = 600; -static constexpr int32_t VPHeight = 400; -static constexpr int32_t DispWidth = 1280; -static constexpr int32_t DispHeight = 480; - -// Master scene's data provider IDs -static constexpr ramses::dataProviderId_t VP1OffsetProviderId{ 333 }; -static constexpr ramses::dataProviderId_t VP1SizeProviderId{ 334 }; -static constexpr ramses::dataProviderId_t VP2OffsetProviderId{ 335 }; -static constexpr ramses::dataProviderId_t VP2SizeProviderId{ 336 }; -static constexpr ramses::dataProviderId_t Color1ProviderId{ 337 }; -static constexpr ramses::dataProviderId_t Color2ProviderId{ 338 }; -static constexpr ramses::dataProviderId_t Color3ProviderId{ 339 }; -static constexpr ramses::dataProviderId_t Color4ProviderId{ 340 }; - -// Content scene's data consumer IDs -static constexpr ramses::dataConsumerId_t VPOffsetConsumerId{ 350 }; -static constexpr ramses::dataConsumerId_t VPSizeConsumerId{ 351 }; -static constexpr ramses::dataConsumerId_t Color1ConsumerId{ 352 }; -static constexpr ramses::dataConsumerId_t Color2ConsumerId{ 353 }; - -void createContentProviderScene(ramses::RamsesClient& client, ramses::sceneId_t sceneId) -{ - ramses::Scene* clientScene = client.createScene(sceneId); - - ramses::PerspectiveCamera* camera = clientScene->createPerspectiveCamera("camera"); - camera->setFrustum(19.f, 1280.f / 480.f, 0.1f, 1500.f); - camera->setTranslation({0.0f, 0.0f, 5.0f}); - - // Bind data objects to scene's camera viewport offset/size and mark as data consumers - const auto vpOffsetData = clientScene->createDataObject(ramses::EDataType::Vector2I, "vpOffset"); - const auto vpSizeData = clientScene->createDataObject(ramses::EDataType::Vector2I, "vpSize"); - vpOffsetData->setValue(ramses::vec2i{ 0, 0 }); - vpSizeData->setValue(ramses::vec2i{ VPWidth, VPHeight }); - camera->bindViewportOffset(*vpOffsetData); - camera->bindViewportSize(*vpSizeData); - clientScene->createDataConsumer(*vpOffsetData, VPOffsetConsumerId); - clientScene->createDataConsumer(*vpSizeData, VPSizeConsumerId); - - ramses::RenderPass* renderPass = clientScene->createRenderPass("my render pass"); - renderPass->setClearFlags(ramses::EClearFlag::None); - renderPass->setCamera(*camera); - ramses::RenderGroup* renderGroup = clientScene->createRenderGroup(); - renderPass->addRenderGroup(*renderGroup); - - const std::array vertexPositionsData{ ramses::vec3f{-1.f, 0.f, -6.f}, ramses::vec3f{1.f, 0.f, -6.f}, ramses::vec3f{0.f, 1.f, -6.f} }; - ramses::ArrayResource* vertexPositions = clientScene->createArrayResource(3u, vertexPositionsData.data()); - const std::array indexData{ 0, 1, 2 }; - ramses::ArrayResource* indices = clientScene->createArrayResource(3u, indexData.data()); - - ramses::EffectDescription effectDesc; - effectDesc.setVertexShader(R"glsl(#version 100 -uniform highp mat4 mvpMatrix; -attribute vec3 a_position; -void main() { - gl_Position = mvpMatrix * vec4(a_position, 1.0); -})glsl"); - effectDesc.setFragmentShader(R"glsl(#version 100 -uniform highp vec4 color; -void main(void) { - gl_FragColor = color + vec4(0.1); -})glsl"); - effectDesc.setUniformSemantic("mvpMatrix", ramses::EEffectUniformSemantic::ModelViewProjectionMatrix); - - ramses::Effect* effect = clientScene->createEffect(effectDesc, "glsl shader"); - ramses::Appearance* appearance = clientScene->createAppearance(*effect, "triangle appearance"); - ramses::Geometry* geometry = clientScene->createGeometry(*effect, "triangle geometry"); - - geometry->setIndices(*indices); - std::optional positionsInput = effect->findAttributeInput("a_position"); - assert(positionsInput.has_value()); - geometry->setInputBuffer(*positionsInput, *vertexPositions); - - ramses::MeshNode* meshNode = clientScene->createMeshNode("triangle mesh node"); - meshNode->setAppearance(*appearance); - meshNode->setGeometry(*geometry); - renderGroup->addMeshNode(*meshNode); - - ramses::MeshNode* meshNode2 = clientScene->createMeshNode("triangle mesh node 2"); - ramses::Appearance* appearance2 = clientScene->createAppearance(*effect, "triangle appearance"); - meshNode2->setAppearance(*appearance2); - meshNode2->setGeometry(*geometry); - renderGroup->addMeshNode(*meshNode2); - meshNode2->setTranslation({0, -10, -5}); - meshNode2->setScaling({100, 100, 1}); - - std::optional colorInput = effect->findUniformInput("color"); - assert(colorInput.has_value()); - - // Create data objects to hold color and bind them to appearance inputs - auto color1 = clientScene->createDataObject(ramses::EDataType::Vector4F); - auto color2 = clientScene->createDataObject(ramses::EDataType::Vector4F); - color1->setValue(ramses::vec4f{ 1.f, 1.f, 1.f, 1.f }); - color1->setValue(ramses::vec4f{ 0.5f, 0.5f, 0.5f, 1.f }); - appearance->bindInput(*colorInput, *color1); - appearance2->bindInput(*colorInput, *color2); - clientScene->createDataConsumer(*color1, Color1ConsumerId); - clientScene->createDataConsumer(*color2, Color2ConsumerId); - - clientScene->flush(); - clientScene->publish(); -} - -ramses::Scene* createSceneMaster(ramses::RamsesClient& client, ramses::sceneId_t sceneId) -{ - ramses::Scene* clientScene = client.createScene(sceneId); - - // In master scene create data objects and mark them as providers to control other scenes' viewports - const auto vp1offset = clientScene->createDataObject(ramses::EDataType::Vector2I, "vp1offset"); - const auto vp1size = clientScene->createDataObject(ramses::EDataType::Vector2I, "vp1size"); - const auto vp2offset = clientScene->createDataObject(ramses::EDataType::Vector2I, "vp2offset"); - const auto vp2size = clientScene->createDataObject(ramses::EDataType::Vector2I, "vp2size"); - - vp1offset->setValue(ramses::vec2i{ 0, 0 }); - vp1size->setValue(ramses::vec2i{ DispWidth, DispHeight }); - vp2offset->setValue(ramses::vec2i{ 0, 0 }); - vp2size->setValue(ramses::vec2i{ DispWidth, DispHeight }); - - clientScene->createDataProvider(*vp1offset, VP1OffsetProviderId); - clientScene->createDataProvider(*vp1size, VP1SizeProviderId); - clientScene->createDataProvider(*vp2offset, VP2OffsetProviderId); - clientScene->createDataProvider(*vp2size, VP2SizeProviderId); - - // Create data objects and mark them as providers to control content scenes colors - const auto color1 = clientScene->createDataObject(ramses::EDataType::Vector4F, "color1"); - const auto color2 = clientScene->createDataObject(ramses::EDataType::Vector4F, "color2"); - const auto color3 = clientScene->createDataObject(ramses::EDataType::Vector4F, "color3"); - const auto color4 = clientScene->createDataObject(ramses::EDataType::Vector4F, "color4"); - - color1->setValue(ramses::vec4f{ 1.f, 1.f, 0.3f, 1.f }); - color2->setValue(ramses::vec4f{ 0.f, 0.3f, 0.5f, 1.f }); - color3->setValue(ramses::vec4f{ 1.f, 0.f, 0.5f, 1.f }); - color4->setValue(ramses::vec4f{ 0.5f, 0.3f, 0.f, 1.f }); - - clientScene->createDataProvider(*color1, Color1ProviderId); - clientScene->createDataProvider(*color2, Color2ProviderId); - clientScene->createDataProvider(*color3, Color3ProviderId); - clientScene->createDataProvider(*color4, Color4ProviderId); - - clientScene->flush(); - clientScene->publish(); - - return clientScene; -} - -/** - * @example ramses-example-local-scene-referencing/src/main.cpp - * @brief Example for controlling scene state and data linking of scenes via scene referencing instead of renderer API. - */ -int main() -{ - // create a renderer and a client locally, open a display - ramses::RamsesFrameworkConfig config{ramses::EFeatureLevel_Latest}; - config.setRequestedRamsesShellType(ramses::ERamsesShellType::Console); //needed for automated test of examples - ramses::RamsesFramework framework(config); - ramses::RamsesClient& client(*framework.createClient("ExampleSceneReferencing")); - - ramses::RendererConfig rendererConfig; - ramses::RamsesRenderer& renderer(*framework.createRenderer(rendererConfig)); - renderer.startThread(); - - ramses::DisplayConfig displayConfig; - const ramses::displayId_t display = renderer.createDisplay(displayConfig); - renderer.flush(); - - framework.connect(); - - // prepare a master scene and two scenes, which are to be referenced - const ramses::sceneId_t refSceneId1(1u); - const ramses::sceneId_t refSceneId2(2u); - const ramses::sceneId_t sceneIdMaster(3u); - - createContentProviderScene(client, refSceneId1); - createContentProviderScene(client, refSceneId2); - - ramses::Scene* masterScene = createSceneMaster(client, sceneIdMaster); - ramses::RendererSceneControl& sceneControlAPI = *renderer.getSceneControlAPI(); - sceneControlAPI.setSceneMapping(sceneIdMaster, display); - sceneControlAPI.flush(); - - /// [Scene referencing setup] - // create a scene reference for both scenes - ramses::SceneReference* sceneRef1 = masterScene->createSceneReference(refSceneId1); - ramses::SceneReference* sceneRef2 = masterScene->createSceneReference(refSceneId2); - - // request scene references state to rendered, they will be brought to state rendered alongside with master scene - sceneRef1->requestState(ramses::RendererSceneState::Rendered); - sceneRef2->requestState(ramses::RendererSceneState::Rendered); - masterScene->flush(); - /// [Scene referencing setup] - - // request master scene to be ready, so scene references can become ready as well - sceneControlAPI.setSceneState(sceneIdMaster, ramses::RendererSceneState::Ready); - sceneControlAPI.flush(); - - /// [Scene referencing data linking] - // wait for referenced scene to be available, before trying to data link - SceneReferenceEventHandler eventHandler(client); - eventHandler.waitForSceneRefState(refSceneId1, ramses::RendererSceneState::Ready); - eventHandler.waitForSceneRefState(refSceneId2, ramses::RendererSceneState::Ready); - - // Link master scene's data objects to other scenes cameras' viewports - masterScene->linkData(nullptr, VP1OffsetProviderId, sceneRef1, VPOffsetConsumerId); - masterScene->linkData(nullptr, VP1SizeProviderId, sceneRef1, VPSizeConsumerId); - masterScene->linkData(nullptr, VP2OffsetProviderId, sceneRef2, VPOffsetConsumerId); - masterScene->linkData(nullptr, VP2SizeProviderId, sceneRef2, VPSizeConsumerId); - masterScene->flush(); - /// [Scene referencing data linking] - - // Link master scene's data objects to scene1 and scene2 colors - masterScene->linkData(nullptr, Color1ProviderId, sceneRef1, Color1ConsumerId); - masterScene->linkData(nullptr, Color2ProviderId, sceneRef1, Color2ConsumerId); - masterScene->linkData(nullptr, Color3ProviderId, sceneRef2, Color1ConsumerId); - masterScene->linkData(nullptr, Color4ProviderId, sceneRef2, Color2ConsumerId); - masterScene->flush(); - - // wait and check for data link result events for all links, skipped here for example simplicity - - // Now that everything is set up properly, bring master scene to a rendered state - sceneControlAPI.setSceneState(sceneIdMaster, ramses::RendererSceneState::Rendered); - sceneControlAPI.flush(); - - // These are master scene's data objects linked to scene1 and scene2 cameras' viewports - auto scene1vpOffset = masterScene->findObject("vp1offset"); - auto scene1vpSize = masterScene->findObject("vp1size"); - auto scene2vpOffset = masterScene->findObject("vp2offset"); - auto scene2vpSize = masterScene->findObject("vp2size"); - - // start animating data provider values after scenes are being rendered - eventHandler.waitForSceneRefState(refSceneId1, ramses::RendererSceneState::Rendered); - eventHandler.waitForSceneRefState(refSceneId2, ramses::RendererSceneState::Rendered); - - int animParam = 0; - bool animInc = true; - RendererEventHandler rendererEventHandler; - while (!rendererEventHandler.isWindowClosed()) - { - renderer.dispatchEvents(rendererEventHandler); - // animate master scene - scene1vpOffset->setValue(ramses::vec2i{ VPWidth / 8 + VPWidth / 2 * animParam / 100, VPHeight / 8 + VPHeight / 4 * animParam / 100 }); - scene1vpSize->setValue(ramses::vec2i{ VPWidth / 4 + VPWidth / 2 * animParam / 100, VPHeight / 4 + VPHeight / 4 * animParam / 100 }); - const auto invAnimParam = 100 - animParam; - scene2vpOffset->setValue(ramses::vec2i{ DispWidth / 2 - VPWidth / 2 * invAnimParam / 100, DispHeight - DispHeight / 4 - VPHeight / 4 * invAnimParam / 100 }); - scene2vpSize->setValue(ramses::vec2i{ VPWidth / 2 + VPWidth / 2 * invAnimParam / 100, VPHeight / 4 + VPHeight / 4 * invAnimParam / 100 }); - masterScene->flush(); - - animParam = (animInc ? animParam + 1 : animParam - 1); - if (animParam == 0 || animParam == 100) - animInc = !animInc; - - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } -} diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index bfcf48f4a..5b20bb0d9 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -83,6 +83,21 @@ else() endif() endif() +add_library(ramses-glad + glad/src/gles2.c +) +target_include_directories(ramses-glad PUBLIC + glad/include/ +) +folderizeTarget(ramses-glad) + +if(WIN32) + target_include_directories(ramses-glad PUBLIC + khronos # find wgl.h/wglext.h + ) + target_link_libraries(ramses-glad PUBLIC opengl32) +endif() + # abseil library function(add_abseil_scope) set(BUILD_TESTING OFF) @@ -131,7 +146,63 @@ foreach(lib target_link_libraries(ramses-abseil INTERFACE absl::${lib}) endforeach() +# glslang +macro(configureGlslangGeneratedBuildHeader) + # This block is originally taken and adapted from glslang's CMakeLists.txt + # and licensed as follows: + # Copyright (C) 2020-2023 The Khronos Group Inc. + # + # All rights reserved. + # + # Redistribution and use in source and binary forms, with or without + # modification, are permitted provided that the following conditions + # are met: + # + # Redistributions of source code must retain the above copyright + # notice, this list of conditions and the following disclaimer. + # + # Redistributions in binary form must reproduce the above + # copyright notice, this list of conditions and the following + # disclaimer in the documentation and/or other materials provided + # with the distribution. + # + # Neither the name of The Khronos Group Inc. nor the names of its + # contributors may be used to endorse or promote products derived + # from this software without specific prior written permission. + # + # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + # COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + # POSSIBILITY OF SUCH DAMAGE. + + set(GLSLANG_CHANGES_FILE "${CMAKE_CURRENT_SOURCE_DIR}/glslang/CHANGES.md") + set(GLSLANG_BUILD_INFO_H_TMPL "${CMAKE_CURRENT_SOURCE_DIR}/glslang/build_info.h.tmpl") + set(GLSLANG_GENERATED_INCLUDEDIR "${CMAKE_BINARY_DIR}/include/glslang") + set(GLSLANG_BUILD_INFO_H "${GLSLANG_GENERATED_INCLUDEDIR}/glslang/build_info.h") + + include(glslang/parse_version.cmake) + parse_version(${GLSLANG_CHANGES_FILE} GLSLANG) + + function(configurate_version) + set(major ${GLSLANG_VERSION_MAJOR}) + set(minor ${GLSLANG_VERSION_MINOR}) + set(patch ${GLSLANG_VERSION_PATCH}) + set(flavor ${GLSLANG_VERSION_FLAVOR}) + configure_file(${GLSLANG_BUILD_INFO_H_TMPL} ${GLSLANG_BUILD_INFO_H} @ONLY) + endfunction() + + configurate_version() +endmacro() +configureGlslangGeneratedBuildHeader() createModule( NAME ramses-glslang TYPE STATIC_LIBRARY @@ -139,18 +210,27 @@ createModule( INCLUDE_PATHS glslang/glslang glslang/glslang/MachineIndependent glslang + ${GLSLANG_GENERATED_INCLUDEDIR} SRC_FILES glslang/glslang/Include/*.h glslang/glslang/Public/*.h glslang/glslang/OSDependent/*.h glslang/glslang/MachineIndependent/*.h glslang/OGLCompilersDLL/*.h + glslang/SPIRV/*.h + glslang/SPIRV*.hpp glslang/glslang/MachineIndependent/*.cpp glslang/glslang/MachineIndependent/preprocessor/*.cpp glslang/glslang/GenericCodeGen/*.cpp glslang/OGLCompilersDLL/*.cpp - glslang-os-dep/GenericSingleThreaded/ossource.cpp + glslang/SPIRV/*.cpp ) +if(WIN32) + target_sources(ramses-glslang PRIVATE glslang/glslang/OSDependent/Windows/ossource.cpp) +else() + target_sources(ramses-glslang PRIVATE glslang/glslang/OSDependent/Unix/ossource.cpp) +endif() + createModule( NAME lodepng TYPE STATIC_LIBRARY @@ -171,10 +251,12 @@ createModule( if(ramses-sdk_TEXT_SUPPORT) # find freetype with harfbuzz support - if (ramses-sdk_ALLOW_PLATFORM_FREETYPE) - find_package(FreetypeAndHarfbuzz QUIET) - endif() - if (ramses-sdk_ALLOW_CUSTOM_FREETYPE AND NOT freetype_FOUND) + if (ramses-sdk_USE_PLATFORM_FREETYPE) + find_package(FreetypeAndHarfbuzz REQUIRED) + if (NOT freetype_FOUND) + message(FATAL_ERROR "Freetype package is not found on the system. Please make sure it is available or use bundled package instead.") + endif() + else() set(SKIP_INSTALL_ALL ON) # no 'd' suffix on debug libs @@ -202,6 +284,11 @@ if(ramses-sdk_TEXT_SUPPORT) endif() endif() else() + if (ramses-sdk_USE_PLATFORM_FREETYPE) + message(WARNING "ramses-sdk_USE_PLATFORM_FREETYPE is set to ${ramses-sdk_USE_PLATFORM_FREETYPE} but ramses-sdk_TEXT_SUPPORT is ${ramses-sdk_TEXT_SUPPORT}. ramses-sdk_USE_PLATFORM_FREETYPE will not take effect. Please set it to OFF or check the configuration.") + set(ramses-sdk_USE_PLATFORM_FREETYPE OFF) + message(VERBOSE "ramses-sdk_USE_PLATFORM_FREETYPE is now ${ramses-sdk_USE_PLATFORM_FREETYPE}.") + endif() message(STATUS "- harfbuzz/freetype (text support disabled)") endif() @@ -237,6 +324,8 @@ ELSEIF (wayland-client_FOUND AND wayland-server_FOUND) ) ENDIF() +find_package(OpenGL QUIET) + importDependenciesAndCheckMissing(WAYLAND_IVI_EXT_MISSING wayland-ivi-extension) if (ramses-sdk_BUILD_TOOLS AND (NOT WAYLAND_IVI_EXT_MISSING)) # wayland ivi example/test application @@ -246,7 +335,7 @@ if (ramses-sdk_BUILD_TOOLS AND (NOT WAYLAND_IVI_EXT_MISSING)) ENABLE_INSTALL ON SRC_FILES wayland-ivi-example-client/gears.c DEPENDENCIES EGL - OpenGL + OpenGL::GLES3 wayland-client wayland-egl wayland-ivi-extension @@ -279,7 +368,7 @@ if (ramses-sdk_BUILD_TOOLS AND (NOT MISSING_DEPENDENCY)) ENABLE_INSTALL ON SRC_FILES wayland-ivi-example-client/simple-dmabuf-egl.c DEPENDENCIES EGL - OpenGL + OpenGL::GLES3 wayland-client wayland-egl wayland-ivi-extension @@ -346,138 +435,136 @@ ELSE() ENDIF() # Ramses logic specific dependencies -if(ramses-sdk_ENABLE_LOGIC) - ################################################ - ################ Google Benchmark ########### - ################################################ +################################################ +################ Google Benchmark ########### +################################################ - #project specific setup for google benchmark - if(ramses-sdk_BUILD_TESTS AND NOT TARGET benchmark::benchmark) - set(BENCHMARK_ENABLE_TESTING OFF CACHE INTERNAL "") - set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE INTERNAL "") - set(BENCHMARK_ENABLE_INSTALL OFF CACHE INTERNAL "") +#project specific setup for google benchmark +if(ramses-sdk_BUILD_TESTS AND NOT TARGET benchmark::benchmark) + set(BENCHMARK_ENABLE_TESTING OFF CACHE INTERNAL "") + set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE INTERNAL "") + set(BENCHMARK_ENABLE_INSTALL OFF CACHE INTERNAL "") - ensureSubmoduleExists(google-benchmark) + ensureSubmoduleExists(google-benchmark) - add_subdirectory(google-benchmark) + add_subdirectory(google-benchmark) - folderizeTarget(benchmark) - folderizeTarget(benchmark_main) - endif() + folderizeTarget(benchmark) + folderizeTarget(benchmark_main) +endif() - add_library(ramses-google-benchmark-main INTERFACE) - target_link_libraries(ramses-google-benchmark-main INTERFACE benchmark_main) - add_library(ramses::google-benchmark-main ALIAS ramses-google-benchmark-main) +add_library(ramses-google-benchmark-main INTERFACE) +target_link_libraries(ramses-google-benchmark-main INTERFACE benchmark_main) +add_library(ramses::google-benchmark-main ALIAS ramses-google-benchmark-main) - ################################################ - ################ Lua ################## - ################################################ +################################################ +################ Lua ################## +################################################ - if(NOT TARGET lua::lua) - message(STATUS "+ lua (internal) (STATIC_LIBRARY)") - ensureSubmoduleExists(lua) +if(NOT TARGET lua::lua) + message(STATUS "+ lua (internal) (STATIC_LIBRARY)") + ensureSubmoduleExists(lua) - # Collect all source and header files - file(GLOB LUA_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/lua/*.c) - file(GLOB LUA_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/lua/*.h) + # Collect all source and header files + file(GLOB LUA_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/lua/*.c) + file(GLOB LUA_HEADER ${CMAKE_CURRENT_SOURCE_DIR}/lua/*.h) - # Remove luac from the list, because it contains a main function - list(REMOVE_ITEM LUA_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/lua/lua.c) + # Remove luac from the list, because it contains a main function + list(REMOVE_ITEM LUA_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/lua/lua.c) - set_source_files_properties(${LUA_SOURCE} PROPERTIES LANGUAGE CXX) + set_source_files_properties(${LUA_SOURCE} PROPERTIES LANGUAGE CXX) - # Create library for lua - add_library(lua STATIC ${LUA_SOURCE} ${LUA_HEADER}) + # Create library for lua + add_library(lua STATIC ${LUA_SOURCE} ${LUA_HEADER}) - # This is required for Lua on Android to suppress a false-positive fortification trigger when - # the garbage collector is invoked - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") - target_compile_options(lua PRIVATE -fno-stack-protector -U_FORTIFY_SOURCE -Wno-deprecated-declarations) - endif() + # This is required for Lua on Android to suppress a false-positive fortification trigger when + # the garbage collector is invoked + if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU") + target_compile_options(lua PRIVATE -fno-stack-protector -U_FORTIFY_SOURCE -Wno-deprecated-declarations) + endif() - if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") - # We compile lua as c++ even though it has .c files. convince clang to just do it without complaining - target_compile_options(lua PRIVATE -x c++) - endif() + if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + # We compile lua as c++ even though it has .c files. convince clang to just do it without complaining + target_compile_options(lua PRIVATE -x c++) + endif() - target_include_directories(lua - PUBLIC - $ - ) + target_include_directories(lua + PUBLIC + $ + ) - folderizeTarget(lua) - add_library(lua::lua ALIAS lua) - endif() + folderizeTarget(lua) + add_library(lua::lua ALIAS lua) +endif() - ################################################ - ################ Sol ################## - ################################################ - - if(NOT TARGET sol2) - set(SOL2_LUA_VERSION "5.1.1" CACHE STRING "" FORCE) - set(INSTALL_SOL2 OFF CACHE INTERNAL "") - - ensureSubmoduleExists(sol) - - # TODO Violin remove EXCLUDE_FROM_ALL when upgrading to the next official sol version - # Currently its's needed because otherwise sol is installed automatically and also - # lands in the packaged version of ramses - add_subdirectory(sol EXCLUDE_FROM_ALL) - - # Ensure sol is expecting c++ compiled lua - target_compile_definitions(sol2 INTERFACE - # catch and redirect exception to user handler func instead of - # prapagating them directly through lua - SOL_EXCEPTIONS_ALWAYS_UNSAFE=1 - # check if types are numbers before using them as numbers - SOL_SAFE_NUMERICS=1 - # ensure sol calls luaL_checkstack to avoid stack overflows - SOL_SAFE_STACK_CHECK=1 - # Make sure Debug flags are equivalent to Release flags in terms of behavior - SOL_IN_DEBUG_DETECTED=0 - ) +################################################ +################ Sol ################## +################################################ + +if(NOT TARGET sol2) + set(SOL2_LUA_VERSION "5.1.1" CACHE STRING "" FORCE) + set(INSTALL_SOL2 OFF CACHE INTERNAL "") + + ensureSubmoduleExists(sol) + + # TODO Violin remove EXCLUDE_FROM_ALL when upgrading to the next official sol version + # Currently its's needed because otherwise sol is installed automatically and also + # lands in the packaged version of ramses + add_subdirectory(sol EXCLUDE_FROM_ALL) + + # Ensure sol is expecting c++ compiled lua + target_compile_definitions(sol2 INTERFACE + # catch and redirect exception to user handler func instead of + # prapagating them directly through lua + SOL_EXCEPTIONS_ALWAYS_UNSAFE=1 + # check if types are numbers before using them as numbers + SOL_SAFE_NUMERICS=1 + # ensure sol calls luaL_checkstack to avoid stack overflows + SOL_SAFE_STACK_CHECK=1 + # Make sure Debug flags are equivalent to Release flags in terms of behavior + SOL_IN_DEBUG_DETECTED=0 + ) + + if(NOT ramses-sdk_USE_PLATFORM_LUAJIT) + target_compile_definitions(sol2 INTERFACE + # we compile lua with c++, make sol not use extern C etc + SOL_USING_CXX_LUA=1 + ) + endif() +endif() - if(NOT ramses-sdk_USE_PLATFORM_LUAJIT) - target_compile_definitions(sol2 INTERFACE - # we compile lua with c++, make sol not use extern C etc - SOL_USING_CXX_LUA=1 - ) - endif() - endif() +################################################ +################ Flatbuffers ################## +################################################ - ################################################ - ################ Flatbuffers ################## - ################################################ - - if(NOT TARGET flatbuffers) - # Don't build flatbuf targets we don't need - set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "" FORCE) - set(FLATBUFFERS_INSTALL OFF CACHE BOOL "" FORCE) - set(FLATBUFFERS_BUILD_FLATHASH OFF CACHE BOOL "" FORCE) - - # Only add flatc target if flatbuffers header generation needed - if(ramses-sdk_ENABLE_FLATBUFFERS_GENERATION) - set(FLATBUFFERS_BUILD_FLATC ON CACHE BOOL "Build flatbuffers compiler" FORCE) - else() - set(FLATBUFFERS_BUILD_FLATC OFF CACHE BOOL "Build flatbuffers compiler" FORCE) - endif() +if(NOT TARGET flatbuffers) + # Don't build flatbuf targets we don't need + set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "" FORCE) + set(FLATBUFFERS_INSTALL OFF CACHE BOOL "" FORCE) + set(FLATBUFFERS_BUILD_FLATHASH OFF CACHE BOOL "" FORCE) - ensureSubmoduleExists(flatbuffers) + # Only add flatc target if flatbuffers header generation needed + if(ramses-sdk_ENABLE_FLATBUFFERS_GENERATION) + set(FLATBUFFERS_BUILD_FLATC ON CACHE BOOL "Build flatbuffers compiler" FORCE) + else() + set(FLATBUFFERS_BUILD_FLATC OFF CACHE BOOL "Build flatbuffers compiler" FORCE) + endif() - add_subdirectory(flatbuffers) - folderizeTarget(flatbuffers) - endif() + ensureSubmoduleExists(flatbuffers) - add_library(ramses::flatbuffers ALIAS flatbuffers) + add_subdirectory(flatbuffers) + folderizeTarget(flatbuffers) +endif() - if(ramses-sdk_ENABLE_FLATBUFFERS_GENERATION) - folderizeTarget(flatc) - endif() +add_library(ramses::flatbuffers ALIAS flatbuffers) + +if(ramses-sdk_ENABLE_FLATBUFFERS_GENERATION) + folderizeTarget(flatc) endif() # ANGLE - Build for iOS support only -IF((${CMAKE_SYSTEM_NAME} MATCHES "iOS")) +if((${CMAKE_SYSTEM_NAME} MATCHES "iOS")) # Define File Copy Function that WebKit ANGLE build expects to be there function(WEBKIT_COPY_FILES target_name) # This CMake macro is from the WebKit Repository and licensed as follows: @@ -587,5 +674,20 @@ IF((${CMAKE_SYSTEM_NAME} MATCHES "iOS")) target_include_directories(EGL INTERFACE ANGLE/include) # Alias ANGLE as OpenGL, so it is a drop in replacement. - add_library(OpenGL ALIAS GLESv2) -ENDIF() + target_link_libraries(ramses-glad PUBLIC GLESv2) +endif() + + +if(ramses-sdk_ENABLE_DEVICE_TYPE_VULKAN) + message(STATUS "Environment VULKAN_SDK: $ENV{VULKAN_SDK}") + + find_package(Vulkan REQUIRED) + message(STATUS "+ Vulkan ${Vulkan_VERSION}") + add_library(ramses-vulkan INTERFACE) + target_link_libraries(ramses-vulkan INTERFACE ${Vulkan_LIBRARIES}) + target_include_directories(ramses-vulkan INTERFACE ${Vulkan_INCLUDE_DIR}) + + # add headers as sources to enable IntelliSense and other code completion features + file(GLOB VULKAN_HEADERS ${Vulkan_INCLUDE_DIR}/vulkan/*.h) + target_sources(ramses-vulkan INTERFACE ${VULKAN_HEADERS}) +endif() diff --git a/external/abseil b/external/abseil index 8c0b94e79..2f9e432cc 160000 --- a/external/abseil +++ b/external/abseil @@ -1 +1 @@ -Subproject commit 8c0b94e793a66495e0b1f34a5eb26bd7dc672db0 +Subproject commit 2f9e432cce407ce0ae50676696666f33a77d42ac diff --git a/external/glad/include/KHR/khrplatform.h b/external/glad/include/KHR/khrplatform.h new file mode 100644 index 000000000..01646449c --- /dev/null +++ b/external/glad/include/KHR/khrplatform.h @@ -0,0 +1,311 @@ +#ifndef __khrplatform_h_ +#define __khrplatform_h_ + +/* +** Copyright (c) 2008-2018 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/* Khronos platform-specific types and definitions. + * + * The master copy of khrplatform.h is maintained in the Khronos EGL + * Registry repository at https://github.com/KhronosGroup/EGL-Registry + * The last semantic modification to khrplatform.h was at commit ID: + * 67a3e0864c2d75ea5287b9f3d2eb74a745936692 + * + * Adopters may modify this file to suit their platform. Adopters are + * encouraged to submit platform specific modifications to the Khronos + * group so that they can be included in future versions of this file. + * Please submit changes by filing pull requests or issues on + * the EGL Registry repository linked above. + * + * + * See the Implementer's Guidelines for information about where this file + * should be located on your system and for more details of its use: + * http://www.khronos.org/registry/implementers_guide.pdf + * + * This file should be included as + * #include + * by Khronos client API header files that use its types and defines. + * + * The types in khrplatform.h should only be used to define API-specific types. + * + * Types defined in khrplatform.h: + * khronos_int8_t signed 8 bit + * khronos_uint8_t unsigned 8 bit + * khronos_int16_t signed 16 bit + * khronos_uint16_t unsigned 16 bit + * khronos_int32_t signed 32 bit + * khronos_uint32_t unsigned 32 bit + * khronos_int64_t signed 64 bit + * khronos_uint64_t unsigned 64 bit + * khronos_intptr_t signed same number of bits as a pointer + * khronos_uintptr_t unsigned same number of bits as a pointer + * khronos_ssize_t signed size + * khronos_usize_t unsigned size + * khronos_float_t signed 32 bit floating point + * khronos_time_ns_t unsigned 64 bit time in nanoseconds + * khronos_utime_nanoseconds_t unsigned time interval or absolute time in + * nanoseconds + * khronos_stime_nanoseconds_t signed time interval in nanoseconds + * khronos_boolean_enum_t enumerated boolean type. This should + * only be used as a base type when a client API's boolean type is + * an enum. Client APIs which use an integer or other type for + * booleans cannot use this as the base type for their boolean. + * + * Tokens defined in khrplatform.h: + * + * KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values. + * + * KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0. + * KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0. + * + * Calling convention macros defined in this file: + * KHRONOS_APICALL + * KHRONOS_APIENTRY + * KHRONOS_APIATTRIBUTES + * + * These may be used in function prototypes as: + * + * KHRONOS_APICALL void KHRONOS_APIENTRY funcname( + * int arg1, + * int arg2) KHRONOS_APIATTRIBUTES; + */ + +#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC) +# define KHRONOS_STATIC 1 +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APICALL + *------------------------------------------------------------------------- + * This precedes the return type of the function in the function prototype. + */ +#if defined(KHRONOS_STATIC) + /* If the preprocessor constant KHRONOS_STATIC is defined, make the + * header compatible with static linking. */ +# define KHRONOS_APICALL +#elif defined(_WIN32) +# define KHRONOS_APICALL __declspec(dllimport) +#elif defined (__SYMBIAN32__) +# define KHRONOS_APICALL IMPORT_C +#elif defined(__ANDROID__) +# define KHRONOS_APICALL __attribute__((visibility("default"))) +#else +# define KHRONOS_APICALL +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIENTRY + *------------------------------------------------------------------------- + * This follows the return type of the function and precedes the function + * name in the function prototype. + */ +#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__) + /* Win32 but not WinCE */ +# define KHRONOS_APIENTRY __stdcall +#else +# define KHRONOS_APIENTRY +#endif + +/*------------------------------------------------------------------------- + * Definition of KHRONOS_APIATTRIBUTES + *------------------------------------------------------------------------- + * This follows the closing parenthesis of the function prototype arguments. + */ +#if defined (__ARMCC_2__) +#define KHRONOS_APIATTRIBUTES __softfp +#else +#define KHRONOS_APIATTRIBUTES +#endif + +/*------------------------------------------------------------------------- + * basic type definitions + *-----------------------------------------------------------------------*/ +#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__) + + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 +/* + * To support platform where unsigned long cannot be used interchangeably with + * inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t. + * Ideally, we could just use (u)intptr_t everywhere, but this could result in + * ABI breakage if khronos_uintptr_t is changed from unsigned long to + * unsigned long long or similar (this results in different C++ name mangling). + * To avoid changes for existing platforms, we restrict usage of intptr_t to + * platforms where the size of a pointer is larger than the size of long. + */ +#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__) +#if __SIZEOF_POINTER__ > __SIZEOF_LONG__ +#define KHRONOS_USE_INTPTR_T +#endif +#endif + +#elif defined(__VMS ) || defined(__sgi) + +/* + * Using + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(_WIN32) && !defined(__SCITECH_SNAP__) + +/* + * Win32 + */ +typedef __int32 khronos_int32_t; +typedef unsigned __int32 khronos_uint32_t; +typedef __int64 khronos_int64_t; +typedef unsigned __int64 khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif defined(__sun__) || defined(__digital__) + +/* + * Sun or Digital + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#if defined(__arch64__) || defined(_LP64) +typedef long int khronos_int64_t; +typedef unsigned long int khronos_uint64_t; +#else +typedef long long int khronos_int64_t; +typedef unsigned long long int khronos_uint64_t; +#endif /* __arch64__ */ +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#elif 0 + +/* + * Hypothetical platform with no float or int64 support + */ +typedef int khronos_int32_t; +typedef unsigned int khronos_uint32_t; +#define KHRONOS_SUPPORT_INT64 0 +#define KHRONOS_SUPPORT_FLOAT 0 + +#else + +/* + * Generic fallback + */ +#include +typedef int32_t khronos_int32_t; +typedef uint32_t khronos_uint32_t; +typedef int64_t khronos_int64_t; +typedef uint64_t khronos_uint64_t; +#define KHRONOS_SUPPORT_INT64 1 +#define KHRONOS_SUPPORT_FLOAT 1 + +#endif + + +/* + * Types that are (so far) the same on all platforms + */ +typedef signed char khronos_int8_t; +typedef unsigned char khronos_uint8_t; +typedef signed short int khronos_int16_t; +typedef unsigned short int khronos_uint16_t; + +/* + * Types that differ between LLP64 and LP64 architectures - in LLP64, + * pointers are 64 bits, but 'long' is still 32 bits. Win64 appears + * to be the only LLP64 architecture in current use. + */ +#ifdef KHRONOS_USE_INTPTR_T +typedef intptr_t khronos_intptr_t; +typedef uintptr_t khronos_uintptr_t; +#elif defined(_WIN64) +typedef signed long long int khronos_intptr_t; +typedef unsigned long long int khronos_uintptr_t; +#else +typedef signed long int khronos_intptr_t; +typedef unsigned long int khronos_uintptr_t; +#endif + +#if defined(_WIN64) +typedef signed long long int khronos_ssize_t; +typedef unsigned long long int khronos_usize_t; +#else +typedef signed long int khronos_ssize_t; +typedef unsigned long int khronos_usize_t; +#endif + +#if KHRONOS_SUPPORT_FLOAT +/* + * Float type + */ +typedef float khronos_float_t; +#endif + +#if KHRONOS_SUPPORT_INT64 +/* Time types + * + * These types can be used to represent a time interval in nanoseconds or + * an absolute Unadjusted System Time. Unadjusted System Time is the number + * of nanoseconds since some arbitrary system event (e.g. since the last + * time the system booted). The Unadjusted System Time is an unsigned + * 64 bit value that wraps back to 0 every 584 years. Time intervals + * may be either signed or unsigned. + */ +typedef khronos_uint64_t khronos_utime_nanoseconds_t; +typedef khronos_int64_t khronos_stime_nanoseconds_t; +#endif + +/* + * Dummy value used to pad enum types to 32 bits. + */ +#ifndef KHRONOS_MAX_ENUM +#define KHRONOS_MAX_ENUM 0x7FFFFFFF +#endif + +/* + * Enumerated boolean type + * + * Values other than zero should be considered to be true. Therefore + * comparisons should not be made against KHRONOS_TRUE. + */ +typedef enum { + KHRONOS_FALSE = 0, + KHRONOS_TRUE = 1, + KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM +} khronos_boolean_enum_t; + +#endif /* __khrplatform_h_ */ diff --git a/external/glad/include/glad/gles2.h b/external/glad/include/glad/gles2.h new file mode 100644 index 000000000..af186d7eb --- /dev/null +++ b/external/glad/include/glad/gles2.h @@ -0,0 +1,2463 @@ +/** + * Loader generated by glad 2.0.6 on Wed May 22 21:17:21 2024 + * + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + * + * Generator: C/C++ + * Specification: gl + * Extensions: 7 + * + * APIs: + * - gles2=3.2 + * + * Options: + * - ALIAS = False + * - DEBUG = False + * - HEADER_ONLY = False + * - LOADER = False + * - MX = False + * - ON_DEMAND = False + * + * Commandline: + * --api='gles2=3.2' --extensions='GL_EXT_geometry_shader,GL_EXT_texture_compression_dxt1,GL_EXT_texture_filter_anisotropic,GL_OES_EGL_image,GL_OES_EGL_image_external,GL_OES_EGL_image_external_essl3,GL_OES_texture_compression_astc' c + * + * Online: + * http://glad.sh/#api=gles2%3D3.2&extensions=GL_EXT_geometry_shader%2CGL_EXT_texture_compression_dxt1%2CGL_EXT_texture_filter_anisotropic%2CGL_OES_EGL_image%2CGL_OES_EGL_image_external%2CGL_OES_EGL_image_external_essl3%2CGL_OES_texture_compression_astc&generator=c&options= + * + */ + +#ifndef GLAD_GLES2_H_ +#define GLAD_GLES2_H_ + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif +#ifdef __gl2_h_ + #error OpenGL ES 2 header already included (API: gles2), remove previous include! +#endif +#define __gl2_h_ 1 +#ifdef __gles2_gl2_h_ + #error OpenGL ES 2 header already included (API: gles2), remove previous include! +#endif +#define __gles2_gl2_h_ 1 +#ifdef __gl3_h_ + #error OpenGL ES 3 header already included (API: gles2), remove previous include! +#endif +#define __gl3_h_ 1 +#ifdef __gles2_gl3_h_ + #error OpenGL ES 3 header already included (API: gles2), remove previous include! +#endif +#define __gles2_gl3_h_ 1 +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#define GLAD_GLES2 + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef GLAD_PLATFORM_H_ +#define GLAD_PLATFORM_H_ + +#ifndef GLAD_PLATFORM_WIN32 + #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) || defined(__MINGW32__) + #define GLAD_PLATFORM_WIN32 1 + #else + #define GLAD_PLATFORM_WIN32 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_APPLE + #ifdef __APPLE__ + #define GLAD_PLATFORM_APPLE 1 + #else + #define GLAD_PLATFORM_APPLE 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_EMSCRIPTEN + #ifdef __EMSCRIPTEN__ + #define GLAD_PLATFORM_EMSCRIPTEN 1 + #else + #define GLAD_PLATFORM_EMSCRIPTEN 0 + #endif +#endif + +#ifndef GLAD_PLATFORM_UWP + #if defined(_MSC_VER) && !defined(GLAD_INTERNAL_HAVE_WINAPIFAMILY) + #ifdef __has_include + #if __has_include() + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #elif _MSC_VER >= 1700 && !_USING_V110_SDK71_ + #define GLAD_INTERNAL_HAVE_WINAPIFAMILY 1 + #endif + #endif + + #ifdef GLAD_INTERNAL_HAVE_WINAPIFAMILY + #include + #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) && WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) + #define GLAD_PLATFORM_UWP 1 + #endif + #endif + + #ifndef GLAD_PLATFORM_UWP + #define GLAD_PLATFORM_UWP 0 + #endif +#endif + +#ifdef __GNUC__ + #define GLAD_GNUC_EXTENSION __extension__ +#else + #define GLAD_GNUC_EXTENSION +#endif + +#define GLAD_UNUSED(x) (void)(x) + +#ifndef GLAD_API_CALL + #if defined(GLAD_API_CALL_EXPORT) + #if GLAD_PLATFORM_WIN32 || defined(__CYGWIN__) + #if defined(GLAD_API_CALL_EXPORT_BUILD) + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllexport)) extern + #else + #define GLAD_API_CALL __declspec(dllexport) extern + #endif + #else + #if defined(__GNUC__) + #define GLAD_API_CALL __attribute__ ((dllimport)) extern + #else + #define GLAD_API_CALL __declspec(dllimport) extern + #endif + #endif + #elif defined(__GNUC__) && defined(GLAD_API_CALL_EXPORT_BUILD) + #define GLAD_API_CALL __attribute__ ((visibility ("default"))) extern + #else + #define GLAD_API_CALL extern + #endif + #else + #define GLAD_API_CALL extern + #endif +#endif + +#ifdef APIENTRY + #define GLAD_API_PTR APIENTRY +#elif GLAD_PLATFORM_WIN32 + #define GLAD_API_PTR __stdcall +#else + #define GLAD_API_PTR +#endif + +#ifndef GLAPI +#define GLAPI GLAD_API_CALL +#endif + +#ifndef GLAPIENTRY +#define GLAPIENTRY GLAD_API_PTR +#endif + +#define GLAD_MAKE_VERSION(major, minor) (major * 10000 + minor) +#define GLAD_VERSION_MAJOR(version) (version / 10000) +#define GLAD_VERSION_MINOR(version) (version % 10000) + +#define GLAD_GENERATOR_VERSION "2.0.6" + +typedef void (*GLADapiproc)(void); + +typedef GLADapiproc (*GLADloadfunc)(const char *name); +typedef GLADapiproc (*GLADuserptrloadfunc)(void *userptr, const char *name); + +typedef void (*GLADprecallback)(const char *name, GLADapiproc apiproc, int len_args, ...); +typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apiproc, int len_args, ...); + +#endif /* GLAD_PLATFORM_H_ */ + +#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_ACTIVE_PROGRAM 0x8259 +#define GL_ACTIVE_RESOURCES 0x92F5 +#define GL_ACTIVE_TEXTURE 0x84E0 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_VARIABLES 0x9305 +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALL_BARRIER_BITS 0xFFFFFFFF +#define GL_ALL_SHADER_BITS 0xFFFFFFFF +#define GL_ALPHA 0x1906 +#define GL_ALPHA_BITS 0x0D55 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_ALWAYS 0x0207 +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ARRAY_SIZE 0x92FB +#define GL_ARRAY_STRIDE 0x92FE +#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 +#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 +#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 +#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 +#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 +#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_BACK 0x0405 +#define GL_BLEND 0x0BE2 +#define GL_BLEND_COLOR 0x8005 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_ALPHA 0x883D +#define GL_BLEND_EQUATION_RGB 0x8009 +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLOCK_INDEX 0x92FD +#define GL_BLUE 0x1905 +#define GL_BLUE_BITS 0x0D54 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_BUFFER 0x82E0 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_BINDING 0x9302 +#define GL_BUFFER_DATA_SIZE 0x9303 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 +#define GL_BUFFER_USAGE 0x8765 +#define GL_BUFFER_VARIABLE 0x92E5 +#define GL_BYTE 0x1400 +#define GL_CCW 0x0901 +#define GL_CLAMP_TO_BORDER 0x812D +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_COLOR 0x1800 +#define GL_COLORBURN 0x929A +#define GL_COLORDODGE 0x9299 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_COLOR_ATTACHMENT16 0x8CF0 +#define GL_COLOR_ATTACHMENT17 0x8CF1 +#define GL_COLOR_ATTACHMENT18 0x8CF2 +#define GL_COLOR_ATTACHMENT19 0x8CF3 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT20 0x8CF4 +#define GL_COLOR_ATTACHMENT21 0x8CF5 +#define GL_COLOR_ATTACHMENT22 0x8CF6 +#define GL_COLOR_ATTACHMENT23 0x8CF7 +#define GL_COLOR_ATTACHMENT24 0x8CF8 +#define GL_COLOR_ATTACHMENT25 0x8CF9 +#define GL_COLOR_ATTACHMENT26 0x8CFA +#define GL_COLOR_ATTACHMENT27 0x8CFB +#define GL_COLOR_ATTACHMENT28 0x8CFC +#define GL_COLOR_ATTACHMENT29 0x8CFD +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT30 0x8CFE +#define GL_COLOR_ATTACHMENT31 0x8CFF +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_BUFFER_BIT 0x00004000 +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_COMMAND_BARRIER_BIT 0x00000040 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_COMPARE_R_TO_TEXTURE 0x884E +#define GL_COMPILE_STATUS 0x8B81 +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_RGBA_ASTC_10x10 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_10x5 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_12x10 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12 0x93BD +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0 +#define GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1 +#define GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2 +#define GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3 +#define GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4 +#define GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5 +#define GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6 +#define GL_COMPRESSED_RGBA_ASTC_6x5 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7 +#define GL_COMPRESSED_RGBA_ASTC_6x6 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8 +#define GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9 +#define GL_COMPRESSED_RGBA_ASTC_8x5 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 +#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12 0x93DD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 +#define GL_COMPUTE_SHADER 0x91B9 +#define GL_COMPUTE_SHADER_BIT 0x00000020 +#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 +#define GL_CONDITION_SATISFIED 0x911C +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_CONSTANT_COLOR 0x8001 +#define GL_CONTEXT_FLAGS 0x821E +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004 +#define GL_CONTEXT_LOST 0x0507 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_READ_BUFFER_BINDING 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 +#define GL_CULL_FACE 0x0B44 +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_CURRENT_PROGRAM 0x8B8D +#define GL_CURRENT_QUERY 0x8865 +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 +#define GL_CW 0x0900 +#define GL_DARKEN 0x9297 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DECR 0x1E03 +#define GL_DECR_WRAP 0x8508 +#define GL_DELETE_STATUS 0x8B80 +#define GL_DEPTH 0x1801 +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_DEPTH_BITS 0x0D56 +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH_FUNC 0x0B74 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA +#define GL_DEPTH_TEST 0x0B71 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DIFFERENCE 0x929E +#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE +#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF +#define GL_DITHER 0x0BD0 +#define GL_DONT_CARE 0x1100 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 +#define GL_DST_ALPHA 0x0304 +#define GL_DST_COLOR 0x0306 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_DYNAMIC_DRAW 0x88E8 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 +#define GL_EQUAL 0x0202 +#define GL_EXCLUSION 0x92A0 +#define GL_EXTENSIONS 0x1F03 +#define GL_FALSE 0 +#define GL_FASTEST 0x1101 +#define GL_FIRST_VERTEX_CONVENTION 0x8E4D +#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D +#define GL_FIXED 0x140C +#define GL_FLOAT 0x1406 +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4 0x8B5C +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_FRACTIONAL_EVEN 0x8E7C +#define GL_FRACTIONAL_ODD 0x8E7B +#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS 0x8E5D +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_FRAGMENT_SHADER_BIT 0x00000002 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_FRAMEBUFFER 0x8D40 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 +#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312 +#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 +#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD +#define GL_FRONT 0x0404 +#define GL_FRONT_AND_BACK 0x0408 +#define GL_FRONT_FACE 0x0B46 +#define GL_FUNC_ADD 0x8006 +#define GL_FUNC_REVERSE_SUBTRACT 0x800B +#define GL_FUNC_SUBTRACT 0x800A +#define GL_GENERATE_MIPMAP_HINT 0x8192 +#define GL_GEOMETRY_INPUT_TYPE 0x8917 +#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917 +#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918 +#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916 +#define GL_GEOMETRY_OUTPUT_TYPE 0x8918 +#define GL_GEOMETRY_SHADER 0x8DD9 +#define GL_GEOMETRY_SHADER_BIT 0x00000004 +#define GL_GEOMETRY_SHADER_BIT_EXT 0x00000004 +#define GL_GEOMETRY_SHADER_EXT 0x8DD9 +#define GL_GEOMETRY_SHADER_INVOCATIONS 0x887F +#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F +#define GL_GEOMETRY_VERTICES_OUT 0x8916 +#define GL_GEQUAL 0x0206 +#define GL_GREATER 0x0204 +#define GL_GREEN 0x1904 +#define GL_GREEN_BITS 0x0D53 +#define GL_GUILTY_CONTEXT_RESET 0x8253 +#define GL_HALF_FLOAT 0x140B +#define GL_HARDLIGHT 0x929B +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_HIGH_INT 0x8DF5 +#define GL_HSL_COLOR 0x92AF +#define GL_HSL_HUE 0x92AD +#define GL_HSL_LUMINOSITY 0x92B0 +#define GL_HSL_SATURATION 0x92AE +#define GL_IMAGE_2D 0x904D +#define GL_IMAGE_2D_ARRAY 0x9053 +#define GL_IMAGE_3D 0x904E +#define GL_IMAGE_BINDING_ACCESS 0x8F3E +#define GL_IMAGE_BINDING_FORMAT 0x906E +#define GL_IMAGE_BINDING_LAYER 0x8F3D +#define GL_IMAGE_BINDING_LAYERED 0x8F3C +#define GL_IMAGE_BINDING_LEVEL 0x8F3B +#define GL_IMAGE_BINDING_NAME 0x8F3A +#define GL_IMAGE_BUFFER 0x9051 +#define GL_IMAGE_CUBE 0x9050 +#define GL_IMAGE_CUBE_MAP_ARRAY 0x9054 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 +#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 +#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_INCR 0x1E02 +#define GL_INCR_WRAP 0x8507 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_INNOCENT_CONTEXT_RESET 0x8254 +#define GL_INT 0x1404 +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_INT_IMAGE_2D 0x9058 +#define GL_INT_IMAGE_2D_ARRAY 0x905E +#define GL_INT_IMAGE_3D 0x9059 +#define GL_INT_IMAGE_BUFFER 0x905C +#define GL_INT_IMAGE_CUBE 0x905B +#define GL_INT_IMAGE_CUBE_MAP_ARRAY 0x905F +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 +#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910C +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_BUFFER 0x8DD0 +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_CUBE_MAP_ARRAY 0x900E +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#define GL_INVALID_INDEX 0xFFFFFFFF +#define GL_INVALID_OPERATION 0x0502 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVERT 0x150A +#define GL_ISOLINES 0x8E7A +#define GL_IS_PER_PATCH 0x92E7 +#define GL_IS_ROW_MAJOR 0x9300 +#define GL_KEEP 0x1E00 +#define GL_LAST_VERTEX_CONVENTION 0x8E4E +#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E +#define GL_LAYER_PROVOKING_VERTEX 0x825E +#define GL_LAYER_PROVOKING_VERTEX_EXT 0x825E +#define GL_LEQUAL 0x0203 +#define GL_LESS 0x0201 +#define GL_LIGHTEN 0x9298 +#define GL_LINEAR 0x2601 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_LINES 0x0001 +#define GL_LINES_ADJACENCY 0x000A +#define GL_LINES_ADJACENCY_EXT 0x000A +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_LINE_STRIP_ADJACENCY 0x000B +#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B +#define GL_LINE_WIDTH 0x0B21 +#define GL_LINK_STATUS 0x8B82 +#define GL_LOCATION 0x930E +#define GL_LOSE_CONTEXT_ON_RESET 0x8252 +#define GL_LOW_FLOAT 0x8DF0 +#define GL_LOW_INT 0x8DF3 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A +#define GL_MAJOR_VERSION 0x821B +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MATRIX_STRIDE 0x92FF +#define GL_MAX 0x8008 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC +#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E +#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 +#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 +#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32 +#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32 +#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF +#define GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39 +#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 +#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC +#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E +#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 +#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 +#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD +#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB +#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 +#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC +#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB +#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 +#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE +#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB +#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 +#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 +#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET 0x8E5C +#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 +#define GL_MAX_FRAMEBUFFER_LAYERS 0x9317 +#define GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317 +#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 +#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5 +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF +#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS 0x90CD +#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS 0x9123 +#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES 0x8DE0 +#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS 0x8E5A +#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS 0x90D7 +#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS 0x8C29 +#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS 0x8DE1 +#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS 0x8A2C +#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS 0x8DDF +#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF +#define GL_MAX_IMAGE_UNITS 0x8F38 +#define GL_MAX_INTEGER_SAMPLES 0x9110 +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_MAX_NAME_LENGTH 0x92F6 +#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 +#define GL_MAX_PATCH_VERTICES 0x8E7D +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE +#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 +#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD +#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS 0x90CB +#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS 0x886C +#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS 0x8E83 +#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS 0x90D8 +#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS 0x8E81 +#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS 0x8E85 +#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS 0x8E89 +#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E7F +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 +#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE +#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS 0x90CC +#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS 0x886D +#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS 0x8E86 +#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS 0x90D9 +#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS 0x8E82 +#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS 0x8E8A +#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E80 +#define GL_MAX_TESS_GEN_LEVEL 0x8E7E +#define GL_MAX_TESS_PATCH_COMPONENTS 0x8E84 +#define GL_MAX_TEXTURE_BUFFER_SIZE 0x8C2B +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF +#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_LOCATIONS 0x826E +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_MAX_VARYING_FLOATS 0x8B4B +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 +#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA +#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 +#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 +#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_MIN 0x8007 +#define GL_MINOR_VERSION 0x821C +#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET 0x8E5B +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E +#define GL_MIN_SAMPLE_SHADING_VALUE 0x8C37 +#define GL_MIRRORED_REPEAT 0x8370 +#define GL_MULTIPLY 0x9294 +#define GL_MULTISAMPLE_LINE_WIDTH_GRANULARITY 0x9382 +#define GL_MULTISAMPLE_LINE_WIDTH_RANGE 0x9381 +#define GL_NAME_LENGTH 0x92F9 +#define GL_NEAREST 0x2600 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_NEVER 0x0200 +#define GL_NICEST 0x1102 +#define GL_NONE 0 +#define GL_NOTEQUAL 0x0205 +#define GL_NO_ERROR 0 +#define GL_NO_RESET_NOTIFICATION 0x8261 +#define GL_NUM_ACTIVE_VARIABLES 0x9304 +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_NUM_EXTENSIONS 0x821D +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 +#define GL_OBJECT_TYPE 0x9112 +#define GL_OFFSET 0x92FC +#define GL_ONE 1 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_OUT_OF_MEMORY 0x0505 +#define GL_OVERLAY 0x9296 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PATCHES 0x000E +#define GL_PATCH_VERTICES 0x8E72 +#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_POINTS 0x0000 +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +#define GL_PRIMITIVES_GENERATED 0x8C87 +#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 +#define GL_PRIMITIVE_BOUNDING_BOX 0x92BE +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 +#define GL_PROGRAM 0x82E2 +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_INPUT 0x92E3 +#define GL_PROGRAM_OUTPUT 0x92E4 +#define GL_PROGRAM_PIPELINE 0x82E4 +#define GL_PROGRAM_PIPELINE_BINDING 0x825A +#define GL_PROGRAM_SEPARABLE 0x8258 +#define GL_QUADS 0x0007 +#define GL_QUERY 0x82E3 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_R16F 0x822D +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32F 0x822E +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_R8 0x8229 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R8_SNORM 0x8F94 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_READ_BUFFER 0x0C02 +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_READ_ONLY 0x88B8 +#define GL_READ_WRITE 0x88BA +#define GL_RED 0x1903 +#define GL_RED_BITS 0x0D52 +#define GL_RED_INTEGER 0x8D94 +#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B +#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A +#define GL_REFERENCED_BY_GEOMETRY_SHADER 0x9309 +#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309 +#define GL_REFERENCED_BY_TESS_CONTROL_SHADER 0x9307 +#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER 0x9308 +#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 +#define GL_RENDERBUFFER 0x8D41 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERER 0x1F01 +#define GL_REPEAT 0x2901 +#define GL_REPLACE 0x1E01 +#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68 +#define GL_RESET_NOTIFICATION_STRATEGY 0x8256 +#define GL_RG 0x8227 +#define GL_RG16F 0x822F +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32F 0x8230 +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_RG8 0x822B +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB 0x1907 +#define GL_RGB10_A2 0x8059 +#define GL_RGB10_A2UI 0x906F +#define GL_RGB16F 0x881B +#define GL_RGB16I 0x8D89 +#define GL_RGB16UI 0x8D77 +#define GL_RGB32F 0x8815 +#define GL_RGB32I 0x8D83 +#define GL_RGB32UI 0x8D71 +#define GL_RGB565 0x8D62 +#define GL_RGB5_A1 0x8057 +#define GL_RGB8 0x8051 +#define GL_RGB8I 0x8D8F +#define GL_RGB8UI 0x8D7D +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGB9_E5 0x8C3D +#define GL_RGBA 0x1908 +#define GL_RGBA16F 0x881A +#define GL_RGBA16I 0x8D88 +#define GL_RGBA16UI 0x8D76 +#define GL_RGBA32F 0x8814 +#define GL_RGBA32I 0x8D82 +#define GL_RGBA32UI 0x8D70 +#define GL_RGBA4 0x8056 +#define GL_RGBA8 0x8058 +#define GL_RGBA8I 0x8D8E +#define GL_RGBA8UI 0x8D7C +#define GL_RGBA8_SNORM 0x8F97 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RG_INTEGER 0x8228 +#define GL_SAMPLER 0x82E6 +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 +#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910B +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_BINDING 0x8919 +#define GL_SAMPLER_BUFFER 0x8DC2 +#define GL_SAMPLER_CUBE 0x8B60 +#define GL_SAMPLER_CUBE_MAP_ARRAY 0x900C +#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW 0x900D +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_SAMPLER_EXTERNAL_OES 0x8D66 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLE_COVERAGE 0x80A0 +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_MASK 0x8E51 +#define GL_SAMPLE_MASK_VALUE 0x8E52 +#define GL_SAMPLE_POSITION 0x8E50 +#define GL_SAMPLE_SHADING 0x8C36 +#define GL_SCISSOR_BOX 0x0C10 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_SCREEN 0x9295 +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_SHADER 0x82E1 +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_SHADER_COMPILER 0x8DFA +#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 +#define GL_SHADER_STORAGE_BLOCK 0x92E6 +#define GL_SHADER_STORAGE_BUFFER 0x90D2 +#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 +#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF +#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 +#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 +#define GL_SHADER_TYPE 0x8B4F +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_SHORT 0x1402 +#define GL_SIGNALED 0x9119 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_SOFTLIGHT 0x929C +#define GL_SRC_ALPHA 0x0302 +#define GL_SRC_ALPHA_SATURATE 0x0308 +#define GL_SRC_COLOR 0x0300 +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#define GL_STATIC_COPY 0x88E6 +#define GL_STATIC_DRAW 0x88E4 +#define GL_STATIC_READ 0x88E5 +#define GL_STENCIL 0x1802 +#define GL_STENCIL_ATTACHMENT 0x8D20 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_STENCIL_BITS 0x0D57 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_INDEX 0x1901 +#define GL_STENCIL_INDEX8 0x8D48 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_TEST 0x0B90 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STREAM_COPY 0x88E2 +#define GL_STREAM_DRAW 0x88E0 +#define GL_STREAM_READ 0x88E1 +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_SYNC_STATUS 0x9114 +#define GL_TESS_CONTROL_OUTPUT_VERTICES 0x8E75 +#define GL_TESS_CONTROL_SHADER 0x8E88 +#define GL_TESS_CONTROL_SHADER_BIT 0x00000008 +#define GL_TESS_EVALUATION_SHADER 0x8E87 +#define GL_TESS_EVALUATION_SHADER_BIT 0x00000010 +#define GL_TESS_GEN_MODE 0x8E76 +#define GL_TESS_GEN_POINT_MODE 0x8E79 +#define GL_TESS_GEN_SPACING 0x8E77 +#define GL_TESS_GEN_VERTEX_ORDER 0x8E78 +#define GL_TEXTURE 0x1702 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE_2D 0x0DE1 +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 +#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_ALPHA_SIZE 0x805F +#define GL_TEXTURE_ALPHA_TYPE 0x8C13 +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 +#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY 0x9105 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_TEXTURE_BINDING_BUFFER 0x8C2C +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY 0x900A +#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 +#define GL_TEXTURE_BLUE_SIZE 0x805E +#define GL_TEXTURE_BLUE_TYPE 0x8C12 +#define GL_TEXTURE_BORDER_COLOR 0x1004 +#define GL_TEXTURE_BUFFER 0x8C2A +#define GL_TEXTURE_BUFFER_BINDING 0x8C2A +#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING 0x8C2D +#define GL_TEXTURE_BUFFER_OFFSET 0x919D +#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT 0x919F +#define GL_TEXTURE_BUFFER_SIZE 0x919E +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPRESSED 0x86A1 +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_CUBE_MAP_ARRAY 0x9009 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_DEPTH 0x8071 +#define GL_TEXTURE_DEPTH_SIZE 0x884A +#define GL_TEXTURE_DEPTH_TYPE 0x8C16 +#define GL_TEXTURE_EXTERNAL_OES 0x8D65 +#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 +#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 +#define GL_TEXTURE_GREEN_SIZE 0x805D +#define GL_TEXTURE_GREEN_TYPE 0x8C11 +#define GL_TEXTURE_HEIGHT 0x1001 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF +#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE +#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_RED_SIZE 0x805C +#define GL_TEXTURE_RED_TYPE 0x8C10 +#define GL_TEXTURE_SAMPLES 0x9106 +#define GL_TEXTURE_SHARED_SIZE 0x8C3F +#define GL_TEXTURE_STENCIL_SIZE 0x88F1 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 +#define GL_TEXTURE_WIDTH 0x1000 +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFF +#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C +#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_TRANSFORM_FEEDBACK_BUFFER_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLES_ADJACENCY 0x000C +#define GL_TRIANGLES_ADJACENCY_EXT 0x000C +#define GL_TRIANGLE_FAN 0x0006 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_STRIP_ADJACENCY 0x000D +#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D +#define GL_TRUE 1 +#define GL_TYPE 0x92FA +#define GL_UNDEFINED_VERTEX 0x8260 +#define GL_UNDEFINED_VERTEX_EXT 0x8260 +#define GL_UNIFORM 0x92E1 +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_BARRIER_BIT 0x00000004 +#define GL_UNIFORM_BLOCK 0x92E2 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNKNOWN_CONTEXT_RESET 0x8255 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNSIGNALED 0x9118 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB +#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 +#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 +#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 +#define GL_UNSIGNED_INT_IMAGE_BUFFER 0x9067 +#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 +#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY 0x906A +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A +#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY 0x910D +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_BUFFER 0x8DD8 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY 0x900F +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_VENDOR 0x1F00 +#define GL_VERSION 0x1F02 +#define GL_VERTEX_ARRAY 0x8074 +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_BINDING 0x82D4 +#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 +#define GL_VERTEX_BINDING_BUFFER 0x8F4F +#define GL_VERTEX_BINDING_DIVISOR 0x82D6 +#define GL_VERTEX_BINDING_OFFSET 0x82D7 +#define GL_VERTEX_BINDING_STRIDE 0x82D8 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_VERTEX_SHADER_BIT 0x00000001 +#define GL_VIEWPORT 0x0BA2 +#define GL_WAIT_FAILED 0x911D +#define GL_WRITE_ONLY 0x88B9 +#define GL_ZERO 0 + + +#include +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef void GLvoid; +typedef khronos_int8_t GLbyte; +typedef khronos_uint8_t GLubyte; +typedef khronos_int16_t GLshort; +typedef khronos_uint16_t GLushort; +typedef int GLint; +typedef unsigned int GLuint; +typedef khronos_int32_t GLclampx; +typedef int GLsizei; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef double GLdouble; +typedef double GLclampd; +typedef void *GLeglClientBufferEXT; +typedef void *GLeglImageOES; +typedef char GLchar; +typedef char GLcharARB; +#ifdef __APPLE__ +typedef void *GLhandleARB; +#else +typedef unsigned int GLhandleARB; +#endif +typedef khronos_uint16_t GLhalf; +typedef khronos_uint16_t GLhalfARB; +typedef khronos_int32_t GLfixed; +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptr; +#else +typedef khronos_intptr_t GLintptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_intptr_t GLintptrARB; +#else +typedef khronos_intptr_t GLintptrARB; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptr; +#else +typedef khronos_ssize_t GLsizeiptr; +#endif +#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) && (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ > 1060) +typedef khronos_ssize_t GLsizeiptrARB; +#else +typedef khronos_ssize_t GLsizeiptrARB; +#endif +typedef khronos_int64_t GLint64; +typedef khronos_int64_t GLint64EXT; +typedef khronos_uint64_t GLuint64; +typedef khronos_uint64_t GLuint64EXT; +typedef struct __GLsync *GLsync; +struct _cl_context; +struct _cl_event; +typedef void (GLAD_API_PTR *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCARB)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); +typedef void (GLAD_API_PTR *GLDEBUGPROCAMD)(GLuint id,GLenum category,GLenum severity,GLsizei length,const GLchar *message,void *userParam); +typedef unsigned short GLhalfNV; +typedef GLintptr GLvdpauSurfaceNV; +typedef void (GLAD_API_PTR *GLVULKANPROCNV)(void); + + +#define GL_ES_VERSION_2_0 1 +GLAD_API_CALL int GLAD_GL_ES_VERSION_2_0; +#define GL_ES_VERSION_3_0 1 +GLAD_API_CALL int GLAD_GL_ES_VERSION_3_0; +#define GL_ES_VERSION_3_1 1 +GLAD_API_CALL int GLAD_GL_ES_VERSION_3_1; +#define GL_ES_VERSION_3_2 1 +GLAD_API_CALL int GLAD_GL_ES_VERSION_3_2; +#define GL_EXT_geometry_shader 1 +GLAD_API_CALL int GLAD_GL_EXT_geometry_shader; +#define GL_EXT_texture_compression_dxt1 1 +GLAD_API_CALL int GLAD_GL_EXT_texture_compression_dxt1; +#define GL_EXT_texture_filter_anisotropic 1 +GLAD_API_CALL int GLAD_GL_EXT_texture_filter_anisotropic; +#define GL_OES_EGL_image 1 +GLAD_API_CALL int GLAD_GL_OES_EGL_image; +#define GL_OES_EGL_image_external 1 +GLAD_API_CALL int GLAD_GL_OES_EGL_image_external; +#define GL_OES_EGL_image_external_essl3 1 +GLAD_API_CALL int GLAD_GL_OES_EGL_image_external_essl3; +#define GL_OES_texture_compression_astc 1 +GLAD_API_CALL int GLAD_GL_OES_texture_compression_astc; + + +typedef void (GLAD_API_PTR *PFNGLACTIVESHADERPROGRAMPROC)(GLuint pipeline, GLuint program); +typedef void (GLAD_API_PTR *PFNGLACTIVETEXTUREPROC)(GLenum texture); +typedef void (GLAD_API_PTR *PFNGLATTACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLBEGINQUERYPROC)(GLenum target, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBEGINTRANSFORMFEEDBACKPROC)(GLenum primitiveMode); +typedef void (GLAD_API_PTR *PFNGLBINDATTRIBLOCATIONPROC)(GLuint program, GLuint index, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERPROC)(GLenum target, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERBASEPROC)(GLenum target, GLuint index, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLBINDBUFFERRANGEPROC)(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLBINDFRAMEBUFFERPROC)(GLenum target, GLuint framebuffer); +typedef void (GLAD_API_PTR *PFNGLBINDIMAGETEXTUREPROC)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); +typedef void (GLAD_API_PTR *PFNGLBINDPROGRAMPIPELINEPROC)(GLuint pipeline); +typedef void (GLAD_API_PTR *PFNGLBINDRENDERBUFFERPROC)(GLenum target, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLBINDSAMPLERPROC)(GLuint unit, GLuint sampler); +typedef void (GLAD_API_PTR *PFNGLBINDTEXTUREPROC)(GLenum target, GLuint texture); +typedef void (GLAD_API_PTR *PFNGLBINDTRANSFORMFEEDBACKPROC)(GLenum target, GLuint id); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXARRAYPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLBINDVERTEXBUFFERPROC)(GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); +typedef void (GLAD_API_PTR *PFNGLBLENDBARRIERPROC)(void); +typedef void (GLAD_API_PTR *PFNGLBLENDCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEPROC)(GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONSEPARATEIPROC)(GLuint buf, GLenum modeRGB, GLenum modeAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDEQUATIONIPROC)(GLuint buf, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCPROC)(GLenum sfactor, GLenum dfactor); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEPROC)(GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCSEPARATEIPROC)(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +typedef void (GLAD_API_PTR *PFNGLBLENDFUNCIPROC)(GLuint buf, GLenum src, GLenum dst); +typedef void (GLAD_API_PTR *PFNGLBLITFRAMEBUFFERPROC)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +typedef void (GLAD_API_PTR *PFNGLBUFFERDATAPROC)(GLenum target, GLsizeiptr size, const void * data, GLenum usage); +typedef void (GLAD_API_PTR *PFNGLBUFFERSUBDATAPROC)(GLenum target, GLintptr offset, GLsizeiptr size, const void * data); +typedef GLenum (GLAD_API_PTR *PFNGLCHECKFRAMEBUFFERSTATUSPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLCLEARPROC)(GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFIPROC)(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERFVPROC)(GLenum buffer, GLint drawbuffer, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERIVPROC)(GLenum buffer, GLint drawbuffer, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARBUFFERUIVPROC)(GLenum buffer, GLint drawbuffer, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLCLEARCOLORPROC)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +typedef void (GLAD_API_PTR *PFNGLCLEARDEPTHFPROC)(GLfloat d); +typedef void (GLAD_API_PTR *PFNGLCLEARSTENCILPROC)(GLint s); +typedef GLenum (GLAD_API_PTR *PFNGLCLIENTWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKPROC)(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +typedef void (GLAD_API_PTR *PFNGLCOLORMASKIPROC)(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); +typedef void (GLAD_API_PTR *PFNGLCOMPILESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXIMAGE3DPROC)(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void * data); +typedef void (GLAD_API_PTR *PFNGLCOPYBUFFERSUBDATAPROC)(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLCOPYIMAGESUBDATAPROC)(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXIMAGE2DPROC)(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLCOPYTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLuint (GLAD_API_PTR *PFNGLCREATEPROGRAMPROC)(void); +typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROC)(GLenum type); +typedef GLuint (GLAD_API_PTR *PFNGLCREATESHADERPROGRAMVPROC)(GLenum type, GLsizei count, const GLchar *const* strings); +typedef void (GLAD_API_PTR *PFNGLCULLFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECALLBACKPROC)(GLDEBUGPROC callback, const void * userParam); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGECONTROLPROC)(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled); +typedef void (GLAD_API_PTR *PFNGLDEBUGMESSAGEINSERTPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf); +typedef void (GLAD_API_PTR *PFNGLDELETEBUFFERSPROC)(GLsizei n, const GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLDELETEFRAMEBUFFERSPROC)(GLsizei n, const GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLDELETEPROGRAMPIPELINESPROC)(GLsizei n, const GLuint * pipelines); +typedef void (GLAD_API_PTR *PFNGLDELETEQUERIESPROC)(GLsizei n, const GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLDELETERENDERBUFFERSPROC)(GLsizei n, const GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLDELETESAMPLERSPROC)(GLsizei count, const GLuint * samplers); +typedef void (GLAD_API_PTR *PFNGLDELETESHADERPROC)(GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDELETESYNCPROC)(GLsync sync); +typedef void (GLAD_API_PTR *PFNGLDELETETEXTURESPROC)(GLsizei n, const GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLDELETETRANSFORMFEEDBACKSPROC)(GLsizei n, const GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLDELETEVERTEXARRAYSPROC)(GLsizei n, const GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLDEPTHFUNCPROC)(GLenum func); +typedef void (GLAD_API_PTR *PFNGLDEPTHMASKPROC)(GLboolean flag); +typedef void (GLAD_API_PTR *PFNGLDEPTHRANGEFPROC)(GLfloat n, GLfloat f); +typedef void (GLAD_API_PTR *PFNGLDETACHSHADERPROC)(GLuint program, GLuint shader); +typedef void (GLAD_API_PTR *PFNGLDISABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLDISABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLDISPATCHCOMPUTEPROC)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); +typedef void (GLAD_API_PTR *PFNGLDISPATCHCOMPUTEINDIRECTPROC)(GLintptr indirect); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSPROC)(GLenum mode, GLint first, GLsizei count); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINDIRECTPROC)(GLenum mode, const void * indirect); +typedef void (GLAD_API_PTR *PFNGLDRAWARRAYSINSTANCEDPROC)(GLenum mode, GLint first, GLsizei count, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWBUFFERSPROC)(GLsizei n, const GLenum * bufs); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINDIRECTPROC)(GLenum mode, GLenum type, const void * indirect); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount); +typedef void (GLAD_API_PTR *PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC)(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices); +typedef void (GLAD_API_PTR *PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC)(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex); +typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC)(GLenum target, GLeglImageOES image); +typedef void (GLAD_API_PTR *PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)(GLenum target, GLeglImageOES image); +typedef void (GLAD_API_PTR *PFNGLENABLEPROC)(GLenum cap); +typedef void (GLAD_API_PTR *PFNGLENABLEVERTEXATTRIBARRAYPROC)(GLuint index); +typedef void (GLAD_API_PTR *PFNGLENABLEIPROC)(GLenum target, GLuint index); +typedef void (GLAD_API_PTR *PFNGLENDQUERYPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLENDTRANSFORMFEEDBACKPROC)(void); +typedef GLsync (GLAD_API_PTR *PFNGLFENCESYNCPROC)(GLenum condition, GLbitfield flags); +typedef void (GLAD_API_PTR *PFNGLFINISHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFLUSHPROC)(void); +typedef void (GLAD_API_PTR *PFNGLFLUSHMAPPEDBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERRENDERBUFFERPROC)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURE2DPROC)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTUREEXTPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level); +typedef void (GLAD_API_PTR *PFNGLFRAMEBUFFERTEXTURELAYERPROC)(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +typedef void (GLAD_API_PTR *PFNGLFRONTFACEPROC)(GLenum mode); +typedef void (GLAD_API_PTR *PFNGLGENBUFFERSPROC)(GLsizei n, GLuint * buffers); +typedef void (GLAD_API_PTR *PFNGLGENFRAMEBUFFERSPROC)(GLsizei n, GLuint * framebuffers); +typedef void (GLAD_API_PTR *PFNGLGENPROGRAMPIPELINESPROC)(GLsizei n, GLuint * pipelines); +typedef void (GLAD_API_PTR *PFNGLGENQUERIESPROC)(GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLGENRENDERBUFFERSPROC)(GLsizei n, GLuint * renderbuffers); +typedef void (GLAD_API_PTR *PFNGLGENSAMPLERSPROC)(GLsizei count, GLuint * samplers); +typedef void (GLAD_API_PTR *PFNGLGENTEXTURESPROC)(GLsizei n, GLuint * textures); +typedef void (GLAD_API_PTR *PFNGLGENTRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint * ids); +typedef void (GLAD_API_PTR *PFNGLGENVERTEXARRAYSPROC)(GLsizei n, GLuint * arrays); +typedef void (GLAD_API_PTR *PFNGLGENERATEMIPMAPPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEATTRIBPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLint * size, GLenum * type, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC)(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei * length, GLchar * uniformBlockName); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMBLOCKIVPROC)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETACTIVEUNIFORMSIVPROC)(GLuint program, GLsizei uniformCount, const GLuint * uniformIndices, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETATTACHEDSHADERSPROC)(GLuint program, GLsizei maxCount, GLsizei * count, GLuint * shaders); +typedef GLint (GLAD_API_PTR *PFNGLGETATTRIBLOCATIONPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANI_VPROC)(GLenum target, GLuint index, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBOOLEANVPROC)(GLenum pname, GLboolean * data); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERI64VPROC)(GLenum target, GLenum pname, GLint64 * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETBUFFERPOINTERVPROC)(GLenum target, GLenum pname, void ** params); +typedef GLuint (GLAD_API_PTR *PFNGLGETDEBUGMESSAGELOGPROC)(GLuint count, GLsizei bufSize, GLenum * sources, GLenum * types, GLuint * ids, GLenum * severities, GLsizei * lengths, GLchar * messageLog); +typedef GLenum (GLAD_API_PTR *PFNGLGETERRORPROC)(void); +typedef void (GLAD_API_PTR *PFNGLGETFLOATVPROC)(GLenum pname, GLfloat * data); +typedef GLint (GLAD_API_PTR *PFNGLGETFRAGDATALOCATIONPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC)(GLenum target, GLenum attachment, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETFRAMEBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef GLenum (GLAD_API_PTR *PFNGLGETGRAPHICSRESETSTATUSPROC)(void); +typedef void (GLAD_API_PTR *PFNGLGETINTEGER64I_VPROC)(GLenum target, GLuint index, GLint64 * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGER64VPROC)(GLenum pname, GLint64 * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERI_VPROC)(GLenum target, GLuint index, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTEGERVPROC)(GLenum pname, GLint * data); +typedef void (GLAD_API_PTR *PFNGLGETINTERNALFORMATIVPROC)(GLenum target, GLenum internalformat, GLenum pname, GLsizei count, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETMULTISAMPLEFVPROC)(GLenum pname, GLuint index, GLfloat * val); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei * length, GLchar * label); +typedef void (GLAD_API_PTR *PFNGLGETOBJECTPTRLABELPROC)(const void * ptr, GLsizei bufSize, GLsizei * length, GLchar * label); +typedef void (GLAD_API_PTR *PFNGLGETPOINTERVPROC)(GLenum pname, void ** params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMBINARYPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLenum * binaryFormat, void * binary); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINFOLOGPROC)(GLuint program, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMINTERFACEIVPROC)(GLuint program, GLenum programInterface, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEINFOLOGPROC)(GLuint pipeline, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMPIPELINEIVPROC)(GLuint pipeline, GLenum pname, GLint * params); +typedef GLuint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCEINDEXPROC)(GLuint program, GLenum programInterface, const GLchar * name); +typedef GLint (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCELOCATIONPROC)(GLuint program, GLenum programInterface, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCENAMEPROC)(GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei * length, GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMRESOURCEIVPROC)(GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum * props, GLsizei count, GLsizei * length, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETPROGRAMIVPROC)(GLuint program, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYOBJECTUIVPROC)(GLuint id, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETQUERYIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETRENDERBUFFERPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETSHADERINFOLOGPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * infoLog); +typedef void (GLAD_API_PTR *PFNGLGETSHADERPRECISIONFORMATPROC)(GLenum shadertype, GLenum precisiontype, GLint * range, GLint * precision); +typedef void (GLAD_API_PTR *PFNGLGETSHADERSOURCEPROC)(GLuint shader, GLsizei bufSize, GLsizei * length, GLchar * source); +typedef void (GLAD_API_PTR *PFNGLGETSHADERIVPROC)(GLuint shader, GLenum pname, GLint * params); +typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGPROC)(GLenum name); +typedef const GLubyte * (GLAD_API_PTR *PFNGLGETSTRINGIPROC)(GLenum name, GLuint index); +typedef void (GLAD_API_PTR *PFNGLGETSYNCIVPROC)(GLsync sync, GLenum pname, GLsizei count, GLsizei * length, GLint * values); +typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERFVPROC)(GLenum target, GLint level, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXLEVELPARAMETERIVPROC)(GLenum target, GLint level, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERFVPROC)(GLenum target, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETTEXPARAMETERIVPROC)(GLenum target, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETTRANSFORMFEEDBACKVARYINGPROC)(GLuint program, GLuint index, GLsizei bufSize, GLsizei * length, GLsizei * size, GLenum * type, GLchar * name); +typedef GLuint (GLAD_API_PTR *PFNGLGETUNIFORMBLOCKINDEXPROC)(GLuint program, const GLchar * uniformBlockName); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMINDICESPROC)(GLuint program, GLsizei uniformCount, const GLchar *const* uniformNames, GLuint * uniformIndices); +typedef GLint (GLAD_API_PTR *PFNGLGETUNIFORMLOCATIONPROC)(GLuint program, const GLchar * name); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMFVPROC)(GLuint program, GLint location, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMIVPROC)(GLuint program, GLint location, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETUNIFORMUIVPROC)(GLuint program, GLint location, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIUIVPROC)(GLuint index, GLenum pname, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBPOINTERVPROC)(GLuint index, GLenum pname, void ** pointer); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBFVPROC)(GLuint index, GLenum pname, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETVERTEXATTRIBIVPROC)(GLuint index, GLenum pname, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMFVPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLint * params); +typedef void (GLAD_API_PTR *PFNGLGETNUNIFORMUIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint * params); +typedef void (GLAD_API_PTR *PFNGLHINTPROC)(GLenum target, GLenum mode); +typedef void (GLAD_API_PTR *PFNGLINVALIDATEFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments); +typedef void (GLAD_API_PTR *PFNGLINVALIDATESUBFRAMEBUFFERPROC)(GLenum target, GLsizei numAttachments, const GLenum * attachments, GLint x, GLint y, GLsizei width, GLsizei height); +typedef GLboolean (GLAD_API_PTR *PFNGLISBUFFERPROC)(GLuint buffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDPROC)(GLenum cap); +typedef GLboolean (GLAD_API_PTR *PFNGLISENABLEDIPROC)(GLenum target, GLuint index); +typedef GLboolean (GLAD_API_PTR *PFNGLISFRAMEBUFFERPROC)(GLuint framebuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPROC)(GLuint program); +typedef GLboolean (GLAD_API_PTR *PFNGLISPROGRAMPIPELINEPROC)(GLuint pipeline); +typedef GLboolean (GLAD_API_PTR *PFNGLISQUERYPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISRENDERBUFFERPROC)(GLuint renderbuffer); +typedef GLboolean (GLAD_API_PTR *PFNGLISSAMPLERPROC)(GLuint sampler); +typedef GLboolean (GLAD_API_PTR *PFNGLISSHADERPROC)(GLuint shader); +typedef GLboolean (GLAD_API_PTR *PFNGLISSYNCPROC)(GLsync sync); +typedef GLboolean (GLAD_API_PTR *PFNGLISTEXTUREPROC)(GLuint texture); +typedef GLboolean (GLAD_API_PTR *PFNGLISTRANSFORMFEEDBACKPROC)(GLuint id); +typedef GLboolean (GLAD_API_PTR *PFNGLISVERTEXARRAYPROC)(GLuint array); +typedef void (GLAD_API_PTR *PFNGLLINEWIDTHPROC)(GLfloat width); +typedef void (GLAD_API_PTR *PFNGLLINKPROGRAMPROC)(GLuint program); +typedef void * (GLAD_API_PTR *PFNGLMAPBUFFERRANGEPROC)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GLAD_API_PTR *PFNGLMEMORYBARRIERPROC)(GLbitfield barriers); +typedef void (GLAD_API_PTR *PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield barriers); +typedef void (GLAD_API_PTR *PFNGLMINSAMPLESHADINGPROC)(GLfloat value); +typedef void (GLAD_API_PTR *PFNGLOBJECTLABELPROC)(GLenum identifier, GLuint name, GLsizei length, const GLchar * label); +typedef void (GLAD_API_PTR *PFNGLOBJECTPTRLABELPROC)(const void * ptr, GLsizei length, const GLchar * label); +typedef void (GLAD_API_PTR *PFNGLPATCHPARAMETERIPROC)(GLenum pname, GLint value); +typedef void (GLAD_API_PTR *PFNGLPAUSETRANSFORMFEEDBACKPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPIXELSTOREIPROC)(GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLPOLYGONOFFSETPROC)(GLfloat factor, GLfloat units); +typedef void (GLAD_API_PTR *PFNGLPOPDEBUGGROUPPROC)(void); +typedef void (GLAD_API_PTR *PFNGLPRIMITIVEBOUNDINGBOXPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); +typedef void (GLAD_API_PTR *PFNGLPROGRAMBINARYPROC)(GLuint program, GLenum binaryFormat, const void * binary, GLsizei length); +typedef void (GLAD_API_PTR *PFNGLPROGRAMPARAMETERIPROC)(GLuint program, GLenum pname, GLint value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FPROC)(GLuint program, GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IPROC)(GLuint program, GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIPROC)(GLuint program, GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM1UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IPROC)(GLuint program, GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM2UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM3UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FPROC)(GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4FVPROC)(GLuint program, GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IPROC)(GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4IVPROC)(GLuint program, GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIPROC)(GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORM4UIVPROC)(GLuint program, GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC)(GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLPUSHDEBUGGROUPPROC)(GLenum source, GLuint id, GLsizei length, const GLchar * message); +typedef void (GLAD_API_PTR *PFNGLREADBUFFERPROC)(GLenum src); +typedef void (GLAD_API_PTR *PFNGLREADPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void * pixels); +typedef void (GLAD_API_PTR *PFNGLREADNPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data); +typedef void (GLAD_API_PTR *PFNGLRELEASESHADERCOMPILERPROC)(void); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEPROC)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLRESUMETRANSFORMFEEDBACKPROC)(void); +typedef void (GLAD_API_PTR *PFNGLSAMPLECOVERAGEPROC)(GLfloat value, GLboolean invert); +typedef void (GLAD_API_PTR *PFNGLSAMPLEMASKIPROC)(GLuint maskNumber, GLbitfield mask); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIIVPROC)(GLuint sampler, GLenum pname, const GLint * param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIUIVPROC)(GLuint sampler, GLenum pname, const GLuint * param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFPROC)(GLuint sampler, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERFVPROC)(GLuint sampler, GLenum pname, const GLfloat * param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIPROC)(GLuint sampler, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLSAMPLERPARAMETERIVPROC)(GLuint sampler, GLenum pname, const GLint * param); +typedef void (GLAD_API_PTR *PFNGLSCISSORPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLSHADERBINARYPROC)(GLsizei count, const GLuint * shaders, GLenum binaryFormat, const void * binary, GLsizei length); +typedef void (GLAD_API_PTR *PFNGLSHADERSOURCEPROC)(GLuint shader, GLsizei count, const GLchar *const* string, const GLint * length); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCPROC)(GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILFUNCSEPARATEPROC)(GLenum face, GLenum func, GLint ref, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKPROC)(GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILMASKSEPARATEPROC)(GLenum face, GLuint mask); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPPROC)(GLenum fail, GLenum zfail, GLenum zpass); +typedef void (GLAD_API_PTR *PFNGLSTENCILOPSEPARATEPROC)(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); +typedef void (GLAD_API_PTR *PFNGLTEXBUFFERPROC)(GLenum target, GLenum internalformat, GLuint buffer); +typedef void (GLAD_API_PTR *PFNGLTEXBUFFERRANGEPROC)(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE2DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXIMAGE3DPROC)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIUIVPROC)(GLenum target, GLenum pname, const GLuint * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFPROC)(GLenum target, GLenum pname, GLfloat param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERFVPROC)(GLenum target, GLenum pname, const GLfloat * params); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIPROC)(GLenum target, GLenum pname, GLint param); +typedef void (GLAD_API_PTR *PFNGLTEXPARAMETERIVPROC)(GLenum target, GLenum pname, const GLint * params); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE2DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DPROC)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +typedef void (GLAD_API_PTR *PFNGLTEXSTORAGE3DMULTISAMPLEPROC)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE2DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTEXSUBIMAGE3DPROC)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void * pixels); +typedef void (GLAD_API_PTR *PFNGLTRANSFORMFEEDBACKVARYINGSPROC)(GLuint program, GLsizei count, const GLchar *const* varyings, GLenum bufferMode); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FPROC)(GLint location, GLfloat v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IPROC)(GLint location, GLint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIPROC)(GLint location, GLuint v0); +typedef void (GLAD_API_PTR *PFNGLUNIFORM1UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FPROC)(GLint location, GLfloat v0, GLfloat v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IPROC)(GLint location, GLint v0, GLint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIPROC)(GLint location, GLuint v0, GLuint v1); +typedef void (GLAD_API_PTR *PFNGLUNIFORM2UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IPROC)(GLint location, GLint v0, GLint v1, GLint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2); +typedef void (GLAD_API_PTR *PFNGLUNIFORM3UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FPROC)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4FVPROC)(GLint location, GLsizei count, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IPROC)(GLint location, GLint v0, GLint v1, GLint v2, GLint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4IVPROC)(GLint location, GLsizei count, const GLint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIPROC)(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +typedef void (GLAD_API_PTR *PFNGLUNIFORM4UIVPROC)(GLint location, GLsizei count, const GLuint * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMBLOCKBINDINGPROC)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX2X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX3X4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X2FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef void (GLAD_API_PTR *PFNGLUNIFORMMATRIX4X3FVPROC)(GLint location, GLsizei count, GLboolean transpose, const GLfloat * value); +typedef GLboolean (GLAD_API_PTR *PFNGLUNMAPBUFFERPROC)(GLenum target); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLUSEPROGRAMSTAGESPROC)(GLuint pipeline, GLbitfield stages, GLuint program); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPROC)(GLuint program); +typedef void (GLAD_API_PTR *PFNGLVALIDATEPROGRAMPIPELINEPROC)(GLuint pipeline); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FPROC)(GLuint index, GLfloat x); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB1FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FPROC)(GLuint index, GLfloat x, GLfloat y); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB2FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB3FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FPROC)(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIB4FVPROC)(GLuint index, const GLfloat * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBBINDINGPROC)(GLuint attribindex, GLuint bindingindex); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBDIVISORPROC)(GLuint index, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IPROC)(GLuint index, GLint x, GLint y, GLint z, GLint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4IVPROC)(GLuint index, const GLint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIPROC)(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBI4UIVPROC)(GLuint index, const GLuint * v); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIFORMATPROC)(GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBIPOINTERPROC)(GLuint index, GLint size, GLenum type, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXATTRIBPOINTERPROC)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void * pointer); +typedef void (GLAD_API_PTR *PFNGLVERTEXBINDINGDIVISORPROC)(GLuint bindingindex, GLuint divisor); +typedef void (GLAD_API_PTR *PFNGLVIEWPORTPROC)(GLint x, GLint y, GLsizei width, GLsizei height); +typedef void (GLAD_API_PTR *PFNGLWAITSYNCPROC)(GLsync sync, GLbitfield flags, GLuint64 timeout); + +GLAD_API_CALL PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram; +#define glActiveShaderProgram glad_glActiveShaderProgram +GLAD_API_CALL PFNGLACTIVETEXTUREPROC glad_glActiveTexture; +#define glActiveTexture glad_glActiveTexture +GLAD_API_CALL PFNGLATTACHSHADERPROC glad_glAttachShader; +#define glAttachShader glad_glAttachShader +GLAD_API_CALL PFNGLBEGINQUERYPROC glad_glBeginQuery; +#define glBeginQuery glad_glBeginQuery +GLAD_API_CALL PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback; +#define glBeginTransformFeedback glad_glBeginTransformFeedback +GLAD_API_CALL PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation; +#define glBindAttribLocation glad_glBindAttribLocation +GLAD_API_CALL PFNGLBINDBUFFERPROC glad_glBindBuffer; +#define glBindBuffer glad_glBindBuffer +GLAD_API_CALL PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase; +#define glBindBufferBase glad_glBindBufferBase +GLAD_API_CALL PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange; +#define glBindBufferRange glad_glBindBufferRange +GLAD_API_CALL PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer; +#define glBindFramebuffer glad_glBindFramebuffer +GLAD_API_CALL PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture; +#define glBindImageTexture glad_glBindImageTexture +GLAD_API_CALL PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline; +#define glBindProgramPipeline glad_glBindProgramPipeline +GLAD_API_CALL PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer; +#define glBindRenderbuffer glad_glBindRenderbuffer +GLAD_API_CALL PFNGLBINDSAMPLERPROC glad_glBindSampler; +#define glBindSampler glad_glBindSampler +GLAD_API_CALL PFNGLBINDTEXTUREPROC glad_glBindTexture; +#define glBindTexture glad_glBindTexture +GLAD_API_CALL PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback; +#define glBindTransformFeedback glad_glBindTransformFeedback +GLAD_API_CALL PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray; +#define glBindVertexArray glad_glBindVertexArray +GLAD_API_CALL PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer; +#define glBindVertexBuffer glad_glBindVertexBuffer +GLAD_API_CALL PFNGLBLENDBARRIERPROC glad_glBlendBarrier; +#define glBlendBarrier glad_glBlendBarrier +GLAD_API_CALL PFNGLBLENDCOLORPROC glad_glBlendColor; +#define glBlendColor glad_glBlendColor +GLAD_API_CALL PFNGLBLENDEQUATIONPROC glad_glBlendEquation; +#define glBlendEquation glad_glBlendEquation +GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate; +#define glBlendEquationSeparate glad_glBlendEquationSeparate +GLAD_API_CALL PFNGLBLENDEQUATIONSEPARATEIPROC glad_glBlendEquationSeparatei; +#define glBlendEquationSeparatei glad_glBlendEquationSeparatei +GLAD_API_CALL PFNGLBLENDEQUATIONIPROC glad_glBlendEquationi; +#define glBlendEquationi glad_glBlendEquationi +GLAD_API_CALL PFNGLBLENDFUNCPROC glad_glBlendFunc; +#define glBlendFunc glad_glBlendFunc +GLAD_API_CALL PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate; +#define glBlendFuncSeparate glad_glBlendFuncSeparate +GLAD_API_CALL PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei; +#define glBlendFuncSeparatei glad_glBlendFuncSeparatei +GLAD_API_CALL PFNGLBLENDFUNCIPROC glad_glBlendFunci; +#define glBlendFunci glad_glBlendFunci +GLAD_API_CALL PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer; +#define glBlitFramebuffer glad_glBlitFramebuffer +GLAD_API_CALL PFNGLBUFFERDATAPROC glad_glBufferData; +#define glBufferData glad_glBufferData +GLAD_API_CALL PFNGLBUFFERSUBDATAPROC glad_glBufferSubData; +#define glBufferSubData glad_glBufferSubData +GLAD_API_CALL PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus; +#define glCheckFramebufferStatus glad_glCheckFramebufferStatus +GLAD_API_CALL PFNGLCLEARPROC glad_glClear; +#define glClear glad_glClear +GLAD_API_CALL PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi; +#define glClearBufferfi glad_glClearBufferfi +GLAD_API_CALL PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv; +#define glClearBufferfv glad_glClearBufferfv +GLAD_API_CALL PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv; +#define glClearBufferiv glad_glClearBufferiv +GLAD_API_CALL PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv; +#define glClearBufferuiv glad_glClearBufferuiv +GLAD_API_CALL PFNGLCLEARCOLORPROC glad_glClearColor; +#define glClearColor glad_glClearColor +GLAD_API_CALL PFNGLCLEARDEPTHFPROC glad_glClearDepthf; +#define glClearDepthf glad_glClearDepthf +GLAD_API_CALL PFNGLCLEARSTENCILPROC glad_glClearStencil; +#define glClearStencil glad_glClearStencil +GLAD_API_CALL PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync; +#define glClientWaitSync glad_glClientWaitSync +GLAD_API_CALL PFNGLCOLORMASKPROC glad_glColorMask; +#define glColorMask glad_glColorMask +GLAD_API_CALL PFNGLCOLORMASKIPROC glad_glColorMaski; +#define glColorMaski glad_glColorMaski +GLAD_API_CALL PFNGLCOMPILESHADERPROC glad_glCompileShader; +#define glCompileShader glad_glCompileShader +GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D; +#define glCompressedTexImage2D glad_glCompressedTexImage2D +GLAD_API_CALL PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D; +#define glCompressedTexImage3D glad_glCompressedTexImage3D +GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D; +#define glCompressedTexSubImage2D glad_glCompressedTexSubImage2D +GLAD_API_CALL PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D; +#define glCompressedTexSubImage3D glad_glCompressedTexSubImage3D +GLAD_API_CALL PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData; +#define glCopyBufferSubData glad_glCopyBufferSubData +GLAD_API_CALL PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData; +#define glCopyImageSubData glad_glCopyImageSubData +GLAD_API_CALL PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D; +#define glCopyTexImage2D glad_glCopyTexImage2D +GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D; +#define glCopyTexSubImage2D glad_glCopyTexSubImage2D +GLAD_API_CALL PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D; +#define glCopyTexSubImage3D glad_glCopyTexSubImage3D +GLAD_API_CALL PFNGLCREATEPROGRAMPROC glad_glCreateProgram; +#define glCreateProgram glad_glCreateProgram +GLAD_API_CALL PFNGLCREATESHADERPROC glad_glCreateShader; +#define glCreateShader glad_glCreateShader +GLAD_API_CALL PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv; +#define glCreateShaderProgramv glad_glCreateShaderProgramv +GLAD_API_CALL PFNGLCULLFACEPROC glad_glCullFace; +#define glCullFace glad_glCullFace +GLAD_API_CALL PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback; +#define glDebugMessageCallback glad_glDebugMessageCallback +GLAD_API_CALL PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl; +#define glDebugMessageControl glad_glDebugMessageControl +GLAD_API_CALL PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert; +#define glDebugMessageInsert glad_glDebugMessageInsert +GLAD_API_CALL PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers; +#define glDeleteBuffers glad_glDeleteBuffers +GLAD_API_CALL PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers; +#define glDeleteFramebuffers glad_glDeleteFramebuffers +GLAD_API_CALL PFNGLDELETEPROGRAMPROC glad_glDeleteProgram; +#define glDeleteProgram glad_glDeleteProgram +GLAD_API_CALL PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines; +#define glDeleteProgramPipelines glad_glDeleteProgramPipelines +GLAD_API_CALL PFNGLDELETEQUERIESPROC glad_glDeleteQueries; +#define glDeleteQueries glad_glDeleteQueries +GLAD_API_CALL PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers; +#define glDeleteRenderbuffers glad_glDeleteRenderbuffers +GLAD_API_CALL PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers; +#define glDeleteSamplers glad_glDeleteSamplers +GLAD_API_CALL PFNGLDELETESHADERPROC glad_glDeleteShader; +#define glDeleteShader glad_glDeleteShader +GLAD_API_CALL PFNGLDELETESYNCPROC glad_glDeleteSync; +#define glDeleteSync glad_glDeleteSync +GLAD_API_CALL PFNGLDELETETEXTURESPROC glad_glDeleteTextures; +#define glDeleteTextures glad_glDeleteTextures +GLAD_API_CALL PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks; +#define glDeleteTransformFeedbacks glad_glDeleteTransformFeedbacks +GLAD_API_CALL PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays; +#define glDeleteVertexArrays glad_glDeleteVertexArrays +GLAD_API_CALL PFNGLDEPTHFUNCPROC glad_glDepthFunc; +#define glDepthFunc glad_glDepthFunc +GLAD_API_CALL PFNGLDEPTHMASKPROC glad_glDepthMask; +#define glDepthMask glad_glDepthMask +GLAD_API_CALL PFNGLDEPTHRANGEFPROC glad_glDepthRangef; +#define glDepthRangef glad_glDepthRangef +GLAD_API_CALL PFNGLDETACHSHADERPROC glad_glDetachShader; +#define glDetachShader glad_glDetachShader +GLAD_API_CALL PFNGLDISABLEPROC glad_glDisable; +#define glDisable glad_glDisable +GLAD_API_CALL PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray; +#define glDisableVertexAttribArray glad_glDisableVertexAttribArray +GLAD_API_CALL PFNGLDISABLEIPROC glad_glDisablei; +#define glDisablei glad_glDisablei +GLAD_API_CALL PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute; +#define glDispatchCompute glad_glDispatchCompute +GLAD_API_CALL PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect; +#define glDispatchComputeIndirect glad_glDispatchComputeIndirect +GLAD_API_CALL PFNGLDRAWARRAYSPROC glad_glDrawArrays; +#define glDrawArrays glad_glDrawArrays +GLAD_API_CALL PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect; +#define glDrawArraysIndirect glad_glDrawArraysIndirect +GLAD_API_CALL PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced; +#define glDrawArraysInstanced glad_glDrawArraysInstanced +GLAD_API_CALL PFNGLDRAWBUFFERSPROC glad_glDrawBuffers; +#define glDrawBuffers glad_glDrawBuffers +GLAD_API_CALL PFNGLDRAWELEMENTSPROC glad_glDrawElements; +#define glDrawElements glad_glDrawElements +GLAD_API_CALL PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex; +#define glDrawElementsBaseVertex glad_glDrawElementsBaseVertex +GLAD_API_CALL PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect; +#define glDrawElementsIndirect glad_glDrawElementsIndirect +GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced; +#define glDrawElementsInstanced glad_glDrawElementsInstanced +GLAD_API_CALL PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex; +#define glDrawElementsInstancedBaseVertex glad_glDrawElementsInstancedBaseVertex +GLAD_API_CALL PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements; +#define glDrawRangeElements glad_glDrawRangeElements +GLAD_API_CALL PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex; +#define glDrawRangeElementsBaseVertex glad_glDrawRangeElementsBaseVertex +GLAD_API_CALL PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glad_glEGLImageTargetRenderbufferStorageOES; +#define glEGLImageTargetRenderbufferStorageOES glad_glEGLImageTargetRenderbufferStorageOES +GLAD_API_CALL PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glad_glEGLImageTargetTexture2DOES; +#define glEGLImageTargetTexture2DOES glad_glEGLImageTargetTexture2DOES +GLAD_API_CALL PFNGLENABLEPROC glad_glEnable; +#define glEnable glad_glEnable +GLAD_API_CALL PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray; +#define glEnableVertexAttribArray glad_glEnableVertexAttribArray +GLAD_API_CALL PFNGLENABLEIPROC glad_glEnablei; +#define glEnablei glad_glEnablei +GLAD_API_CALL PFNGLENDQUERYPROC glad_glEndQuery; +#define glEndQuery glad_glEndQuery +GLAD_API_CALL PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback; +#define glEndTransformFeedback glad_glEndTransformFeedback +GLAD_API_CALL PFNGLFENCESYNCPROC glad_glFenceSync; +#define glFenceSync glad_glFenceSync +GLAD_API_CALL PFNGLFINISHPROC glad_glFinish; +#define glFinish glad_glFinish +GLAD_API_CALL PFNGLFLUSHPROC glad_glFlush; +#define glFlush glad_glFlush +GLAD_API_CALL PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange; +#define glFlushMappedBufferRange glad_glFlushMappedBufferRange +GLAD_API_CALL PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri; +#define glFramebufferParameteri glad_glFramebufferParameteri +GLAD_API_CALL PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer; +#define glFramebufferRenderbuffer glad_glFramebufferRenderbuffer +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture; +#define glFramebufferTexture glad_glFramebufferTexture +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D; +#define glFramebufferTexture2D glad_glFramebufferTexture2D +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT; +#define glFramebufferTextureEXT glad_glFramebufferTextureEXT +GLAD_API_CALL PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer; +#define glFramebufferTextureLayer glad_glFramebufferTextureLayer +GLAD_API_CALL PFNGLFRONTFACEPROC glad_glFrontFace; +#define glFrontFace glad_glFrontFace +GLAD_API_CALL PFNGLGENBUFFERSPROC glad_glGenBuffers; +#define glGenBuffers glad_glGenBuffers +GLAD_API_CALL PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers; +#define glGenFramebuffers glad_glGenFramebuffers +GLAD_API_CALL PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines; +#define glGenProgramPipelines glad_glGenProgramPipelines +GLAD_API_CALL PFNGLGENQUERIESPROC glad_glGenQueries; +#define glGenQueries glad_glGenQueries +GLAD_API_CALL PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers; +#define glGenRenderbuffers glad_glGenRenderbuffers +GLAD_API_CALL PFNGLGENSAMPLERSPROC glad_glGenSamplers; +#define glGenSamplers glad_glGenSamplers +GLAD_API_CALL PFNGLGENTEXTURESPROC glad_glGenTextures; +#define glGenTextures glad_glGenTextures +GLAD_API_CALL PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks; +#define glGenTransformFeedbacks glad_glGenTransformFeedbacks +GLAD_API_CALL PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays; +#define glGenVertexArrays glad_glGenVertexArrays +GLAD_API_CALL PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap; +#define glGenerateMipmap glad_glGenerateMipmap +GLAD_API_CALL PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib; +#define glGetActiveAttrib glad_glGetActiveAttrib +GLAD_API_CALL PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform; +#define glGetActiveUniform glad_glGetActiveUniform +GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName; +#define glGetActiveUniformBlockName glad_glGetActiveUniformBlockName +GLAD_API_CALL PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv; +#define glGetActiveUniformBlockiv glad_glGetActiveUniformBlockiv +GLAD_API_CALL PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv; +#define glGetActiveUniformsiv glad_glGetActiveUniformsiv +GLAD_API_CALL PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders; +#define glGetAttachedShaders glad_glGetAttachedShaders +GLAD_API_CALL PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation; +#define glGetAttribLocation glad_glGetAttribLocation +GLAD_API_CALL PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v; +#define glGetBooleani_v glad_glGetBooleani_v +GLAD_API_CALL PFNGLGETBOOLEANVPROC glad_glGetBooleanv; +#define glGetBooleanv glad_glGetBooleanv +GLAD_API_CALL PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v; +#define glGetBufferParameteri64v glad_glGetBufferParameteri64v +GLAD_API_CALL PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv; +#define glGetBufferParameteriv glad_glGetBufferParameteriv +GLAD_API_CALL PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv; +#define glGetBufferPointerv glad_glGetBufferPointerv +GLAD_API_CALL PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog; +#define glGetDebugMessageLog glad_glGetDebugMessageLog +GLAD_API_CALL PFNGLGETERRORPROC glad_glGetError; +#define glGetError glad_glGetError +GLAD_API_CALL PFNGLGETFLOATVPROC glad_glGetFloatv; +#define glGetFloatv glad_glGetFloatv +GLAD_API_CALL PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation; +#define glGetFragDataLocation glad_glGetFragDataLocation +GLAD_API_CALL PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv; +#define glGetFramebufferAttachmentParameteriv glad_glGetFramebufferAttachmentParameteriv +GLAD_API_CALL PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv; +#define glGetFramebufferParameteriv glad_glGetFramebufferParameteriv +GLAD_API_CALL PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus; +#define glGetGraphicsResetStatus glad_glGetGraphicsResetStatus +GLAD_API_CALL PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v; +#define glGetInteger64i_v glad_glGetInteger64i_v +GLAD_API_CALL PFNGLGETINTEGER64VPROC glad_glGetInteger64v; +#define glGetInteger64v glad_glGetInteger64v +GLAD_API_CALL PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v; +#define glGetIntegeri_v glad_glGetIntegeri_v +GLAD_API_CALL PFNGLGETINTEGERVPROC glad_glGetIntegerv; +#define glGetIntegerv glad_glGetIntegerv +GLAD_API_CALL PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ; +#define glGetInternalformativ glad_glGetInternalformativ +GLAD_API_CALL PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv; +#define glGetMultisamplefv glad_glGetMultisamplefv +GLAD_API_CALL PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel; +#define glGetObjectLabel glad_glGetObjectLabel +GLAD_API_CALL PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel; +#define glGetObjectPtrLabel glad_glGetObjectPtrLabel +GLAD_API_CALL PFNGLGETPOINTERVPROC glad_glGetPointerv; +#define glGetPointerv glad_glGetPointerv +GLAD_API_CALL PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary; +#define glGetProgramBinary glad_glGetProgramBinary +GLAD_API_CALL PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog; +#define glGetProgramInfoLog glad_glGetProgramInfoLog +GLAD_API_CALL PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv; +#define glGetProgramInterfaceiv glad_glGetProgramInterfaceiv +GLAD_API_CALL PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog; +#define glGetProgramPipelineInfoLog glad_glGetProgramPipelineInfoLog +GLAD_API_CALL PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv; +#define glGetProgramPipelineiv glad_glGetProgramPipelineiv +GLAD_API_CALL PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex; +#define glGetProgramResourceIndex glad_glGetProgramResourceIndex +GLAD_API_CALL PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation; +#define glGetProgramResourceLocation glad_glGetProgramResourceLocation +GLAD_API_CALL PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName; +#define glGetProgramResourceName glad_glGetProgramResourceName +GLAD_API_CALL PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv; +#define glGetProgramResourceiv glad_glGetProgramResourceiv +GLAD_API_CALL PFNGLGETPROGRAMIVPROC glad_glGetProgramiv; +#define glGetProgramiv glad_glGetProgramiv +GLAD_API_CALL PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv; +#define glGetQueryObjectuiv glad_glGetQueryObjectuiv +GLAD_API_CALL PFNGLGETQUERYIVPROC glad_glGetQueryiv; +#define glGetQueryiv glad_glGetQueryiv +GLAD_API_CALL PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv; +#define glGetRenderbufferParameteriv glad_glGetRenderbufferParameteriv +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv; +#define glGetSamplerParameterIiv glad_glGetSamplerParameterIiv +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv; +#define glGetSamplerParameterIuiv glad_glGetSamplerParameterIuiv +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv; +#define glGetSamplerParameterfv glad_glGetSamplerParameterfv +GLAD_API_CALL PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv; +#define glGetSamplerParameteriv glad_glGetSamplerParameteriv +GLAD_API_CALL PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog; +#define glGetShaderInfoLog glad_glGetShaderInfoLog +GLAD_API_CALL PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat; +#define glGetShaderPrecisionFormat glad_glGetShaderPrecisionFormat +GLAD_API_CALL PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource; +#define glGetShaderSource glad_glGetShaderSource +GLAD_API_CALL PFNGLGETSHADERIVPROC glad_glGetShaderiv; +#define glGetShaderiv glad_glGetShaderiv +GLAD_API_CALL PFNGLGETSTRINGPROC glad_glGetString; +#define glGetString glad_glGetString +GLAD_API_CALL PFNGLGETSTRINGIPROC glad_glGetStringi; +#define glGetStringi glad_glGetStringi +GLAD_API_CALL PFNGLGETSYNCIVPROC glad_glGetSynciv; +#define glGetSynciv glad_glGetSynciv +GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv; +#define glGetTexLevelParameterfv glad_glGetTexLevelParameterfv +GLAD_API_CALL PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv; +#define glGetTexLevelParameteriv glad_glGetTexLevelParameteriv +GLAD_API_CALL PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv; +#define glGetTexParameterIiv glad_glGetTexParameterIiv +GLAD_API_CALL PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv; +#define glGetTexParameterIuiv glad_glGetTexParameterIuiv +GLAD_API_CALL PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv; +#define glGetTexParameterfv glad_glGetTexParameterfv +GLAD_API_CALL PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv; +#define glGetTexParameteriv glad_glGetTexParameteriv +GLAD_API_CALL PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying; +#define glGetTransformFeedbackVarying glad_glGetTransformFeedbackVarying +GLAD_API_CALL PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex; +#define glGetUniformBlockIndex glad_glGetUniformBlockIndex +GLAD_API_CALL PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices; +#define glGetUniformIndices glad_glGetUniformIndices +GLAD_API_CALL PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation; +#define glGetUniformLocation glad_glGetUniformLocation +GLAD_API_CALL PFNGLGETUNIFORMFVPROC glad_glGetUniformfv; +#define glGetUniformfv glad_glGetUniformfv +GLAD_API_CALL PFNGLGETUNIFORMIVPROC glad_glGetUniformiv; +#define glGetUniformiv glad_glGetUniformiv +GLAD_API_CALL PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv; +#define glGetUniformuiv glad_glGetUniformuiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv; +#define glGetVertexAttribIiv glad_glGetVertexAttribIiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv; +#define glGetVertexAttribIuiv glad_glGetVertexAttribIuiv +GLAD_API_CALL PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv; +#define glGetVertexAttribPointerv glad_glGetVertexAttribPointerv +GLAD_API_CALL PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv; +#define glGetVertexAttribfv glad_glGetVertexAttribfv +GLAD_API_CALL PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv; +#define glGetVertexAttribiv glad_glGetVertexAttribiv +GLAD_API_CALL PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv; +#define glGetnUniformfv glad_glGetnUniformfv +GLAD_API_CALL PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv; +#define glGetnUniformiv glad_glGetnUniformiv +GLAD_API_CALL PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv; +#define glGetnUniformuiv glad_glGetnUniformuiv +GLAD_API_CALL PFNGLHINTPROC glad_glHint; +#define glHint glad_glHint +GLAD_API_CALL PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer; +#define glInvalidateFramebuffer glad_glInvalidateFramebuffer +GLAD_API_CALL PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer; +#define glInvalidateSubFramebuffer glad_glInvalidateSubFramebuffer +GLAD_API_CALL PFNGLISBUFFERPROC glad_glIsBuffer; +#define glIsBuffer glad_glIsBuffer +GLAD_API_CALL PFNGLISENABLEDPROC glad_glIsEnabled; +#define glIsEnabled glad_glIsEnabled +GLAD_API_CALL PFNGLISENABLEDIPROC glad_glIsEnabledi; +#define glIsEnabledi glad_glIsEnabledi +GLAD_API_CALL PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer; +#define glIsFramebuffer glad_glIsFramebuffer +GLAD_API_CALL PFNGLISPROGRAMPROC glad_glIsProgram; +#define glIsProgram glad_glIsProgram +GLAD_API_CALL PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline; +#define glIsProgramPipeline glad_glIsProgramPipeline +GLAD_API_CALL PFNGLISQUERYPROC glad_glIsQuery; +#define glIsQuery glad_glIsQuery +GLAD_API_CALL PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer; +#define glIsRenderbuffer glad_glIsRenderbuffer +GLAD_API_CALL PFNGLISSAMPLERPROC glad_glIsSampler; +#define glIsSampler glad_glIsSampler +GLAD_API_CALL PFNGLISSHADERPROC glad_glIsShader; +#define glIsShader glad_glIsShader +GLAD_API_CALL PFNGLISSYNCPROC glad_glIsSync; +#define glIsSync glad_glIsSync +GLAD_API_CALL PFNGLISTEXTUREPROC glad_glIsTexture; +#define glIsTexture glad_glIsTexture +GLAD_API_CALL PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback; +#define glIsTransformFeedback glad_glIsTransformFeedback +GLAD_API_CALL PFNGLISVERTEXARRAYPROC glad_glIsVertexArray; +#define glIsVertexArray glad_glIsVertexArray +GLAD_API_CALL PFNGLLINEWIDTHPROC glad_glLineWidth; +#define glLineWidth glad_glLineWidth +GLAD_API_CALL PFNGLLINKPROGRAMPROC glad_glLinkProgram; +#define glLinkProgram glad_glLinkProgram +GLAD_API_CALL PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange; +#define glMapBufferRange glad_glMapBufferRange +GLAD_API_CALL PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier; +#define glMemoryBarrier glad_glMemoryBarrier +GLAD_API_CALL PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion; +#define glMemoryBarrierByRegion glad_glMemoryBarrierByRegion +GLAD_API_CALL PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading; +#define glMinSampleShading glad_glMinSampleShading +GLAD_API_CALL PFNGLOBJECTLABELPROC glad_glObjectLabel; +#define glObjectLabel glad_glObjectLabel +GLAD_API_CALL PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel; +#define glObjectPtrLabel glad_glObjectPtrLabel +GLAD_API_CALL PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri; +#define glPatchParameteri glad_glPatchParameteri +GLAD_API_CALL PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback; +#define glPauseTransformFeedback glad_glPauseTransformFeedback +GLAD_API_CALL PFNGLPIXELSTOREIPROC glad_glPixelStorei; +#define glPixelStorei glad_glPixelStorei +GLAD_API_CALL PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset; +#define glPolygonOffset glad_glPolygonOffset +GLAD_API_CALL PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup; +#define glPopDebugGroup glad_glPopDebugGroup +GLAD_API_CALL PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox; +#define glPrimitiveBoundingBox glad_glPrimitiveBoundingBox +GLAD_API_CALL PFNGLPROGRAMBINARYPROC glad_glProgramBinary; +#define glProgramBinary glad_glProgramBinary +GLAD_API_CALL PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri; +#define glProgramParameteri glad_glProgramParameteri +GLAD_API_CALL PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f; +#define glProgramUniform1f glad_glProgramUniform1f +GLAD_API_CALL PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv; +#define glProgramUniform1fv glad_glProgramUniform1fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i; +#define glProgramUniform1i glad_glProgramUniform1i +GLAD_API_CALL PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv; +#define glProgramUniform1iv glad_glProgramUniform1iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui; +#define glProgramUniform1ui glad_glProgramUniform1ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv; +#define glProgramUniform1uiv glad_glProgramUniform1uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f; +#define glProgramUniform2f glad_glProgramUniform2f +GLAD_API_CALL PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv; +#define glProgramUniform2fv glad_glProgramUniform2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i; +#define glProgramUniform2i glad_glProgramUniform2i +GLAD_API_CALL PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv; +#define glProgramUniform2iv glad_glProgramUniform2iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui; +#define glProgramUniform2ui glad_glProgramUniform2ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv; +#define glProgramUniform2uiv glad_glProgramUniform2uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f; +#define glProgramUniform3f glad_glProgramUniform3f +GLAD_API_CALL PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv; +#define glProgramUniform3fv glad_glProgramUniform3fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i; +#define glProgramUniform3i glad_glProgramUniform3i +GLAD_API_CALL PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv; +#define glProgramUniform3iv glad_glProgramUniform3iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui; +#define glProgramUniform3ui glad_glProgramUniform3ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv; +#define glProgramUniform3uiv glad_glProgramUniform3uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f; +#define glProgramUniform4f glad_glProgramUniform4f +GLAD_API_CALL PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv; +#define glProgramUniform4fv glad_glProgramUniform4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i; +#define glProgramUniform4i glad_glProgramUniform4i +GLAD_API_CALL PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv; +#define glProgramUniform4iv glad_glProgramUniform4iv +GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui; +#define glProgramUniform4ui glad_glProgramUniform4ui +GLAD_API_CALL PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv; +#define glProgramUniform4uiv glad_glProgramUniform4uiv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv; +#define glProgramUniformMatrix2fv glad_glProgramUniformMatrix2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv; +#define glProgramUniformMatrix2x3fv glad_glProgramUniformMatrix2x3fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv; +#define glProgramUniformMatrix2x4fv glad_glProgramUniformMatrix2x4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv; +#define glProgramUniformMatrix3fv glad_glProgramUniformMatrix3fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv; +#define glProgramUniformMatrix3x2fv glad_glProgramUniformMatrix3x2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv; +#define glProgramUniformMatrix3x4fv glad_glProgramUniformMatrix3x4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv; +#define glProgramUniformMatrix4fv glad_glProgramUniformMatrix4fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv; +#define glProgramUniformMatrix4x2fv glad_glProgramUniformMatrix4x2fv +GLAD_API_CALL PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv; +#define glProgramUniformMatrix4x3fv glad_glProgramUniformMatrix4x3fv +GLAD_API_CALL PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup; +#define glPushDebugGroup glad_glPushDebugGroup +GLAD_API_CALL PFNGLREADBUFFERPROC glad_glReadBuffer; +#define glReadBuffer glad_glReadBuffer +GLAD_API_CALL PFNGLREADPIXELSPROC glad_glReadPixels; +#define glReadPixels glad_glReadPixels +GLAD_API_CALL PFNGLREADNPIXELSPROC glad_glReadnPixels; +#define glReadnPixels glad_glReadnPixels +GLAD_API_CALL PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler; +#define glReleaseShaderCompiler glad_glReleaseShaderCompiler +GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage; +#define glRenderbufferStorage glad_glRenderbufferStorage +GLAD_API_CALL PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample; +#define glRenderbufferStorageMultisample glad_glRenderbufferStorageMultisample +GLAD_API_CALL PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback; +#define glResumeTransformFeedback glad_glResumeTransformFeedback +GLAD_API_CALL PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage; +#define glSampleCoverage glad_glSampleCoverage +GLAD_API_CALL PFNGLSAMPLEMASKIPROC glad_glSampleMaski; +#define glSampleMaski glad_glSampleMaski +GLAD_API_CALL PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv; +#define glSamplerParameterIiv glad_glSamplerParameterIiv +GLAD_API_CALL PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv; +#define glSamplerParameterIuiv glad_glSamplerParameterIuiv +GLAD_API_CALL PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf; +#define glSamplerParameterf glad_glSamplerParameterf +GLAD_API_CALL PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv; +#define glSamplerParameterfv glad_glSamplerParameterfv +GLAD_API_CALL PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri; +#define glSamplerParameteri glad_glSamplerParameteri +GLAD_API_CALL PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv; +#define glSamplerParameteriv glad_glSamplerParameteriv +GLAD_API_CALL PFNGLSCISSORPROC glad_glScissor; +#define glScissor glad_glScissor +GLAD_API_CALL PFNGLSHADERBINARYPROC glad_glShaderBinary; +#define glShaderBinary glad_glShaderBinary +GLAD_API_CALL PFNGLSHADERSOURCEPROC glad_glShaderSource; +#define glShaderSource glad_glShaderSource +GLAD_API_CALL PFNGLSTENCILFUNCPROC glad_glStencilFunc; +#define glStencilFunc glad_glStencilFunc +GLAD_API_CALL PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate; +#define glStencilFuncSeparate glad_glStencilFuncSeparate +GLAD_API_CALL PFNGLSTENCILMASKPROC glad_glStencilMask; +#define glStencilMask glad_glStencilMask +GLAD_API_CALL PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate; +#define glStencilMaskSeparate glad_glStencilMaskSeparate +GLAD_API_CALL PFNGLSTENCILOPPROC glad_glStencilOp; +#define glStencilOp glad_glStencilOp +GLAD_API_CALL PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate; +#define glStencilOpSeparate glad_glStencilOpSeparate +GLAD_API_CALL PFNGLTEXBUFFERPROC glad_glTexBuffer; +#define glTexBuffer glad_glTexBuffer +GLAD_API_CALL PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange; +#define glTexBufferRange glad_glTexBufferRange +GLAD_API_CALL PFNGLTEXIMAGE2DPROC glad_glTexImage2D; +#define glTexImage2D glad_glTexImage2D +GLAD_API_CALL PFNGLTEXIMAGE3DPROC glad_glTexImage3D; +#define glTexImage3D glad_glTexImage3D +GLAD_API_CALL PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv; +#define glTexParameterIiv glad_glTexParameterIiv +GLAD_API_CALL PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv; +#define glTexParameterIuiv glad_glTexParameterIuiv +GLAD_API_CALL PFNGLTEXPARAMETERFPROC glad_glTexParameterf; +#define glTexParameterf glad_glTexParameterf +GLAD_API_CALL PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv; +#define glTexParameterfv glad_glTexParameterfv +GLAD_API_CALL PFNGLTEXPARAMETERIPROC glad_glTexParameteri; +#define glTexParameteri glad_glTexParameteri +GLAD_API_CALL PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv; +#define glTexParameteriv glad_glTexParameteriv +GLAD_API_CALL PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D; +#define glTexStorage2D glad_glTexStorage2D +GLAD_API_CALL PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample; +#define glTexStorage2DMultisample glad_glTexStorage2DMultisample +GLAD_API_CALL PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D; +#define glTexStorage3D glad_glTexStorage3D +GLAD_API_CALL PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample; +#define glTexStorage3DMultisample glad_glTexStorage3DMultisample +GLAD_API_CALL PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D; +#define glTexSubImage2D glad_glTexSubImage2D +GLAD_API_CALL PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D; +#define glTexSubImage3D glad_glTexSubImage3D +GLAD_API_CALL PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings; +#define glTransformFeedbackVaryings glad_glTransformFeedbackVaryings +GLAD_API_CALL PFNGLUNIFORM1FPROC glad_glUniform1f; +#define glUniform1f glad_glUniform1f +GLAD_API_CALL PFNGLUNIFORM1FVPROC glad_glUniform1fv; +#define glUniform1fv glad_glUniform1fv +GLAD_API_CALL PFNGLUNIFORM1IPROC glad_glUniform1i; +#define glUniform1i glad_glUniform1i +GLAD_API_CALL PFNGLUNIFORM1IVPROC glad_glUniform1iv; +#define glUniform1iv glad_glUniform1iv +GLAD_API_CALL PFNGLUNIFORM1UIPROC glad_glUniform1ui; +#define glUniform1ui glad_glUniform1ui +GLAD_API_CALL PFNGLUNIFORM1UIVPROC glad_glUniform1uiv; +#define glUniform1uiv glad_glUniform1uiv +GLAD_API_CALL PFNGLUNIFORM2FPROC glad_glUniform2f; +#define glUniform2f glad_glUniform2f +GLAD_API_CALL PFNGLUNIFORM2FVPROC glad_glUniform2fv; +#define glUniform2fv glad_glUniform2fv +GLAD_API_CALL PFNGLUNIFORM2IPROC glad_glUniform2i; +#define glUniform2i glad_glUniform2i +GLAD_API_CALL PFNGLUNIFORM2IVPROC glad_glUniform2iv; +#define glUniform2iv glad_glUniform2iv +GLAD_API_CALL PFNGLUNIFORM2UIPROC glad_glUniform2ui; +#define glUniform2ui glad_glUniform2ui +GLAD_API_CALL PFNGLUNIFORM2UIVPROC glad_glUniform2uiv; +#define glUniform2uiv glad_glUniform2uiv +GLAD_API_CALL PFNGLUNIFORM3FPROC glad_glUniform3f; +#define glUniform3f glad_glUniform3f +GLAD_API_CALL PFNGLUNIFORM3FVPROC glad_glUniform3fv; +#define glUniform3fv glad_glUniform3fv +GLAD_API_CALL PFNGLUNIFORM3IPROC glad_glUniform3i; +#define glUniform3i glad_glUniform3i +GLAD_API_CALL PFNGLUNIFORM3IVPROC glad_glUniform3iv; +#define glUniform3iv glad_glUniform3iv +GLAD_API_CALL PFNGLUNIFORM3UIPROC glad_glUniform3ui; +#define glUniform3ui glad_glUniform3ui +GLAD_API_CALL PFNGLUNIFORM3UIVPROC glad_glUniform3uiv; +#define glUniform3uiv glad_glUniform3uiv +GLAD_API_CALL PFNGLUNIFORM4FPROC glad_glUniform4f; +#define glUniform4f glad_glUniform4f +GLAD_API_CALL PFNGLUNIFORM4FVPROC glad_glUniform4fv; +#define glUniform4fv glad_glUniform4fv +GLAD_API_CALL PFNGLUNIFORM4IPROC glad_glUniform4i; +#define glUniform4i glad_glUniform4i +GLAD_API_CALL PFNGLUNIFORM4IVPROC glad_glUniform4iv; +#define glUniform4iv glad_glUniform4iv +GLAD_API_CALL PFNGLUNIFORM4UIPROC glad_glUniform4ui; +#define glUniform4ui glad_glUniform4ui +GLAD_API_CALL PFNGLUNIFORM4UIVPROC glad_glUniform4uiv; +#define glUniform4uiv glad_glUniform4uiv +GLAD_API_CALL PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding; +#define glUniformBlockBinding glad_glUniformBlockBinding +GLAD_API_CALL PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv; +#define glUniformMatrix2fv glad_glUniformMatrix2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv; +#define glUniformMatrix2x3fv glad_glUniformMatrix2x3fv +GLAD_API_CALL PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv; +#define glUniformMatrix2x4fv glad_glUniformMatrix2x4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv; +#define glUniformMatrix3fv glad_glUniformMatrix3fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv; +#define glUniformMatrix3x2fv glad_glUniformMatrix3x2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv; +#define glUniformMatrix3x4fv glad_glUniformMatrix3x4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv; +#define glUniformMatrix4fv glad_glUniformMatrix4fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv; +#define glUniformMatrix4x2fv glad_glUniformMatrix4x2fv +GLAD_API_CALL PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv; +#define glUniformMatrix4x3fv glad_glUniformMatrix4x3fv +GLAD_API_CALL PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer; +#define glUnmapBuffer glad_glUnmapBuffer +GLAD_API_CALL PFNGLUSEPROGRAMPROC glad_glUseProgram; +#define glUseProgram glad_glUseProgram +GLAD_API_CALL PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages; +#define glUseProgramStages glad_glUseProgramStages +GLAD_API_CALL PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram; +#define glValidateProgram glad_glValidateProgram +GLAD_API_CALL PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline; +#define glValidateProgramPipeline glad_glValidateProgramPipeline +GLAD_API_CALL PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f; +#define glVertexAttrib1f glad_glVertexAttrib1f +GLAD_API_CALL PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv; +#define glVertexAttrib1fv glad_glVertexAttrib1fv +GLAD_API_CALL PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f; +#define glVertexAttrib2f glad_glVertexAttrib2f +GLAD_API_CALL PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv; +#define glVertexAttrib2fv glad_glVertexAttrib2fv +GLAD_API_CALL PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f; +#define glVertexAttrib3f glad_glVertexAttrib3f +GLAD_API_CALL PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv; +#define glVertexAttrib3fv glad_glVertexAttrib3fv +GLAD_API_CALL PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f; +#define glVertexAttrib4f glad_glVertexAttrib4f +GLAD_API_CALL PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv; +#define glVertexAttrib4fv glad_glVertexAttrib4fv +GLAD_API_CALL PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding; +#define glVertexAttribBinding glad_glVertexAttribBinding +GLAD_API_CALL PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor; +#define glVertexAttribDivisor glad_glVertexAttribDivisor +GLAD_API_CALL PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat; +#define glVertexAttribFormat glad_glVertexAttribFormat +GLAD_API_CALL PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i; +#define glVertexAttribI4i glad_glVertexAttribI4i +GLAD_API_CALL PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv; +#define glVertexAttribI4iv glad_glVertexAttribI4iv +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui; +#define glVertexAttribI4ui glad_glVertexAttribI4ui +GLAD_API_CALL PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv; +#define glVertexAttribI4uiv glad_glVertexAttribI4uiv +GLAD_API_CALL PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat; +#define glVertexAttribIFormat glad_glVertexAttribIFormat +GLAD_API_CALL PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer; +#define glVertexAttribIPointer glad_glVertexAttribIPointer +GLAD_API_CALL PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer; +#define glVertexAttribPointer glad_glVertexAttribPointer +GLAD_API_CALL PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor; +#define glVertexBindingDivisor glad_glVertexBindingDivisor +GLAD_API_CALL PFNGLVIEWPORTPROC glad_glViewport; +#define glViewport glad_glViewport +GLAD_API_CALL PFNGLWAITSYNCPROC glad_glWaitSync; +#define glWaitSync glad_glWaitSync + + + + + +GLAD_API_CALL int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr); +GLAD_API_CALL int gladLoadGLES2( GLADloadfunc load); + + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/external/glad/src/gles2.c b/external/glad/src/gles2.c new file mode 100644 index 000000000..9251e5ac7 --- /dev/null +++ b/external/glad/src/gles2.c @@ -0,0 +1,955 @@ +/** + * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 + */ +#include +#include +#include +#include + +#ifndef GLAD_IMPL_UTIL_C_ +#define GLAD_IMPL_UTIL_C_ + +#ifdef _MSC_VER +#define GLAD_IMPL_UTIL_SSCANF sscanf_s +#else +#define GLAD_IMPL_UTIL_SSCANF sscanf +#endif + +#endif /* GLAD_IMPL_UTIL_C_ */ + +#ifdef __cplusplus +extern "C" { +#endif + + + +int GLAD_GL_ES_VERSION_2_0 = 0; +int GLAD_GL_ES_VERSION_3_0 = 0; +int GLAD_GL_ES_VERSION_3_1 = 0; +int GLAD_GL_ES_VERSION_3_2 = 0; +int GLAD_GL_EXT_geometry_shader = 0; +int GLAD_GL_EXT_texture_compression_dxt1 = 0; +int GLAD_GL_EXT_texture_filter_anisotropic = 0; +int GLAD_GL_OES_EGL_image = 0; +int GLAD_GL_OES_EGL_image_external = 0; +int GLAD_GL_OES_EGL_image_external_essl3 = 0; +int GLAD_GL_OES_texture_compression_astc = 0; + + + +PFNGLACTIVESHADERPROGRAMPROC glad_glActiveShaderProgram = NULL; +PFNGLACTIVETEXTUREPROC glad_glActiveTexture = NULL; +PFNGLATTACHSHADERPROC glad_glAttachShader = NULL; +PFNGLBEGINQUERYPROC glad_glBeginQuery = NULL; +PFNGLBEGINTRANSFORMFEEDBACKPROC glad_glBeginTransformFeedback = NULL; +PFNGLBINDATTRIBLOCATIONPROC glad_glBindAttribLocation = NULL; +PFNGLBINDBUFFERPROC glad_glBindBuffer = NULL; +PFNGLBINDBUFFERBASEPROC glad_glBindBufferBase = NULL; +PFNGLBINDBUFFERRANGEPROC glad_glBindBufferRange = NULL; +PFNGLBINDFRAMEBUFFERPROC glad_glBindFramebuffer = NULL; +PFNGLBINDIMAGETEXTUREPROC glad_glBindImageTexture = NULL; +PFNGLBINDPROGRAMPIPELINEPROC glad_glBindProgramPipeline = NULL; +PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL; +PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL; +PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL; +PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL; +PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL; +PFNGLBINDVERTEXBUFFERPROC glad_glBindVertexBuffer = NULL; +PFNGLBLENDBARRIERPROC glad_glBlendBarrier = NULL; +PFNGLBLENDCOLORPROC glad_glBlendColor = NULL; +PFNGLBLENDEQUATIONPROC glad_glBlendEquation = NULL; +PFNGLBLENDEQUATIONSEPARATEPROC glad_glBlendEquationSeparate = NULL; +PFNGLBLENDEQUATIONSEPARATEIPROC glad_glBlendEquationSeparatei = NULL; +PFNGLBLENDEQUATIONIPROC glad_glBlendEquationi = NULL; +PFNGLBLENDFUNCPROC glad_glBlendFunc = NULL; +PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL; +PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei = NULL; +PFNGLBLENDFUNCIPROC glad_glBlendFunci = NULL; +PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL; +PFNGLBUFFERDATAPROC glad_glBufferData = NULL; +PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL; +PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL; +PFNGLCLEARPROC glad_glClear = NULL; +PFNGLCLEARBUFFERFIPROC glad_glClearBufferfi = NULL; +PFNGLCLEARBUFFERFVPROC glad_glClearBufferfv = NULL; +PFNGLCLEARBUFFERIVPROC glad_glClearBufferiv = NULL; +PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL; +PFNGLCLEARCOLORPROC glad_glClearColor = NULL; +PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL; +PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL; +PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL; +PFNGLCOLORMASKPROC glad_glColorMask = NULL; +PFNGLCOLORMASKIPROC glad_glColorMaski = NULL; +PFNGLCOMPILESHADERPROC glad_glCompileShader = NULL; +PFNGLCOMPRESSEDTEXIMAGE2DPROC glad_glCompressedTexImage2D = NULL; +PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL; +PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL; +PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL; +PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData = NULL; +PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL; +PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL; +PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL; +PFNGLCREATESHADERPROC glad_glCreateShader = NULL; +PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv = NULL; +PFNGLCULLFACEPROC glad_glCullFace = NULL; +PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL; +PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL; +PFNGLDEBUGMESSAGEINSERTPROC glad_glDebugMessageInsert = NULL; +PFNGLDELETEBUFFERSPROC glad_glDeleteBuffers = NULL; +PFNGLDELETEFRAMEBUFFERSPROC glad_glDeleteFramebuffers = NULL; +PFNGLDELETEPROGRAMPROC glad_glDeleteProgram = NULL; +PFNGLDELETEPROGRAMPIPELINESPROC glad_glDeleteProgramPipelines = NULL; +PFNGLDELETEQUERIESPROC glad_glDeleteQueries = NULL; +PFNGLDELETERENDERBUFFERSPROC glad_glDeleteRenderbuffers = NULL; +PFNGLDELETESAMPLERSPROC glad_glDeleteSamplers = NULL; +PFNGLDELETESHADERPROC glad_glDeleteShader = NULL; +PFNGLDELETESYNCPROC glad_glDeleteSync = NULL; +PFNGLDELETETEXTURESPROC glad_glDeleteTextures = NULL; +PFNGLDELETETRANSFORMFEEDBACKSPROC glad_glDeleteTransformFeedbacks = NULL; +PFNGLDELETEVERTEXARRAYSPROC glad_glDeleteVertexArrays = NULL; +PFNGLDEPTHFUNCPROC glad_glDepthFunc = NULL; +PFNGLDEPTHMASKPROC glad_glDepthMask = NULL; +PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL; +PFNGLDETACHSHADERPROC glad_glDetachShader = NULL; +PFNGLDISABLEPROC glad_glDisable = NULL; +PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL; +PFNGLDISABLEIPROC glad_glDisablei = NULL; +PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute = NULL; +PFNGLDISPATCHCOMPUTEINDIRECTPROC glad_glDispatchComputeIndirect = NULL; +PFNGLDRAWARRAYSPROC glad_glDrawArrays = NULL; +PFNGLDRAWARRAYSINDIRECTPROC glad_glDrawArraysIndirect = NULL; +PFNGLDRAWARRAYSINSTANCEDPROC glad_glDrawArraysInstanced = NULL; +PFNGLDRAWBUFFERSPROC glad_glDrawBuffers = NULL; +PFNGLDRAWELEMENTSPROC glad_glDrawElements = NULL; +PFNGLDRAWELEMENTSBASEVERTEXPROC glad_glDrawElementsBaseVertex = NULL; +PFNGLDRAWELEMENTSINDIRECTPROC glad_glDrawElementsIndirect = NULL; +PFNGLDRAWELEMENTSINSTANCEDPROC glad_glDrawElementsInstanced = NULL; +PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC glad_glDrawElementsInstancedBaseVertex = NULL; +PFNGLDRAWRANGEELEMENTSPROC glad_glDrawRangeElements = NULL; +PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC glad_glDrawRangeElementsBaseVertex = NULL; +PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC glad_glEGLImageTargetRenderbufferStorageOES = NULL; +PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glad_glEGLImageTargetTexture2DOES = NULL; +PFNGLENABLEPROC glad_glEnable = NULL; +PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL; +PFNGLENABLEIPROC glad_glEnablei = NULL; +PFNGLENDQUERYPROC glad_glEndQuery = NULL; +PFNGLENDTRANSFORMFEEDBACKPROC glad_glEndTransformFeedback = NULL; +PFNGLFENCESYNCPROC glad_glFenceSync = NULL; +PFNGLFINISHPROC glad_glFinish = NULL; +PFNGLFLUSHPROC glad_glFlush = NULL; +PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL; +PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri = NULL; +PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL; +PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL; +PFNGLFRAMEBUFFERTEXTURE2DPROC glad_glFramebufferTexture2D = NULL; +PFNGLFRAMEBUFFERTEXTUREEXTPROC glad_glFramebufferTextureEXT = NULL; +PFNGLFRAMEBUFFERTEXTURELAYERPROC glad_glFramebufferTextureLayer = NULL; +PFNGLFRONTFACEPROC glad_glFrontFace = NULL; +PFNGLGENBUFFERSPROC glad_glGenBuffers = NULL; +PFNGLGENFRAMEBUFFERSPROC glad_glGenFramebuffers = NULL; +PFNGLGENPROGRAMPIPELINESPROC glad_glGenProgramPipelines = NULL; +PFNGLGENQUERIESPROC glad_glGenQueries = NULL; +PFNGLGENRENDERBUFFERSPROC glad_glGenRenderbuffers = NULL; +PFNGLGENSAMPLERSPROC glad_glGenSamplers = NULL; +PFNGLGENTEXTURESPROC glad_glGenTextures = NULL; +PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL; +PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL; +PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL; +PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL; +PFNGLGETACTIVEUNIFORMPROC glad_glGetActiveUniform = NULL; +PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC glad_glGetActiveUniformBlockName = NULL; +PFNGLGETACTIVEUNIFORMBLOCKIVPROC glad_glGetActiveUniformBlockiv = NULL; +PFNGLGETACTIVEUNIFORMSIVPROC glad_glGetActiveUniformsiv = NULL; +PFNGLGETATTACHEDSHADERSPROC glad_glGetAttachedShaders = NULL; +PFNGLGETATTRIBLOCATIONPROC glad_glGetAttribLocation = NULL; +PFNGLGETBOOLEANI_VPROC glad_glGetBooleani_v = NULL; +PFNGLGETBOOLEANVPROC glad_glGetBooleanv = NULL; +PFNGLGETBUFFERPARAMETERI64VPROC glad_glGetBufferParameteri64v = NULL; +PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL; +PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL; +PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL; +PFNGLGETERRORPROC glad_glGetError = NULL; +PFNGLGETFLOATVPROC glad_glGetFloatv = NULL; +PFNGLGETFRAGDATALOCATIONPROC glad_glGetFragDataLocation = NULL; +PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetFramebufferAttachmentParameteriv = NULL; +PFNGLGETFRAMEBUFFERPARAMETERIVPROC glad_glGetFramebufferParameteriv = NULL; +PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus = NULL; +PFNGLGETINTEGER64I_VPROC glad_glGetInteger64i_v = NULL; +PFNGLGETINTEGER64VPROC glad_glGetInteger64v = NULL; +PFNGLGETINTEGERI_VPROC glad_glGetIntegeri_v = NULL; +PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL; +PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL; +PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL; +PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL; +PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL; +PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL; +PFNGLGETPROGRAMBINARYPROC glad_glGetProgramBinary = NULL; +PFNGLGETPROGRAMINFOLOGPROC glad_glGetProgramInfoLog = NULL; +PFNGLGETPROGRAMINTERFACEIVPROC glad_glGetProgramInterfaceiv = NULL; +PFNGLGETPROGRAMPIPELINEINFOLOGPROC glad_glGetProgramPipelineInfoLog = NULL; +PFNGLGETPROGRAMPIPELINEIVPROC glad_glGetProgramPipelineiv = NULL; +PFNGLGETPROGRAMRESOURCEINDEXPROC glad_glGetProgramResourceIndex = NULL; +PFNGLGETPROGRAMRESOURCELOCATIONPROC glad_glGetProgramResourceLocation = NULL; +PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName = NULL; +PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv = NULL; +PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL; +PFNGLGETQUERYOBJECTUIVPROC glad_glGetQueryObjectuiv = NULL; +PFNGLGETQUERYIVPROC glad_glGetQueryiv = NULL; +PFNGLGETRENDERBUFFERPARAMETERIVPROC glad_glGetRenderbufferParameteriv = NULL; +PFNGLGETSAMPLERPARAMETERIIVPROC glad_glGetSamplerParameterIiv = NULL; +PFNGLGETSAMPLERPARAMETERIUIVPROC glad_glGetSamplerParameterIuiv = NULL; +PFNGLGETSAMPLERPARAMETERFVPROC glad_glGetSamplerParameterfv = NULL; +PFNGLGETSAMPLERPARAMETERIVPROC glad_glGetSamplerParameteriv = NULL; +PFNGLGETSHADERINFOLOGPROC glad_glGetShaderInfoLog = NULL; +PFNGLGETSHADERPRECISIONFORMATPROC glad_glGetShaderPrecisionFormat = NULL; +PFNGLGETSHADERSOURCEPROC glad_glGetShaderSource = NULL; +PFNGLGETSHADERIVPROC glad_glGetShaderiv = NULL; +PFNGLGETSTRINGPROC glad_glGetString = NULL; +PFNGLGETSTRINGIPROC glad_glGetStringi = NULL; +PFNGLGETSYNCIVPROC glad_glGetSynciv = NULL; +PFNGLGETTEXLEVELPARAMETERFVPROC glad_glGetTexLevelParameterfv = NULL; +PFNGLGETTEXLEVELPARAMETERIVPROC glad_glGetTexLevelParameteriv = NULL; +PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL; +PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL; +PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL; +PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL; +PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL; +PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL; +PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL; +PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL; +PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL; +PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL; +PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL; +PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL; +PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL; +PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL; +PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL; +PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL; +PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv = NULL; +PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv = NULL; +PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv = NULL; +PFNGLHINTPROC glad_glHint = NULL; +PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL; +PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL; +PFNGLISBUFFERPROC glad_glIsBuffer = NULL; +PFNGLISENABLEDPROC glad_glIsEnabled = NULL; +PFNGLISENABLEDIPROC glad_glIsEnabledi = NULL; +PFNGLISFRAMEBUFFERPROC glad_glIsFramebuffer = NULL; +PFNGLISPROGRAMPROC glad_glIsProgram = NULL; +PFNGLISPROGRAMPIPELINEPROC glad_glIsProgramPipeline = NULL; +PFNGLISQUERYPROC glad_glIsQuery = NULL; +PFNGLISRENDERBUFFERPROC glad_glIsRenderbuffer = NULL; +PFNGLISSAMPLERPROC glad_glIsSampler = NULL; +PFNGLISSHADERPROC glad_glIsShader = NULL; +PFNGLISSYNCPROC glad_glIsSync = NULL; +PFNGLISTEXTUREPROC glad_glIsTexture = NULL; +PFNGLISTRANSFORMFEEDBACKPROC glad_glIsTransformFeedback = NULL; +PFNGLISVERTEXARRAYPROC glad_glIsVertexArray = NULL; +PFNGLLINEWIDTHPROC glad_glLineWidth = NULL; +PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL; +PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL; +PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier = NULL; +PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion = NULL; +PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading = NULL; +PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL; +PFNGLOBJECTPTRLABELPROC glad_glObjectPtrLabel = NULL; +PFNGLPATCHPARAMETERIPROC glad_glPatchParameteri = NULL; +PFNGLPAUSETRANSFORMFEEDBACKPROC glad_glPauseTransformFeedback = NULL; +PFNGLPIXELSTOREIPROC glad_glPixelStorei = NULL; +PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL; +PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL; +PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox = NULL; +PFNGLPROGRAMBINARYPROC glad_glProgramBinary = NULL; +PFNGLPROGRAMPARAMETERIPROC glad_glProgramParameteri = NULL; +PFNGLPROGRAMUNIFORM1FPROC glad_glProgramUniform1f = NULL; +PFNGLPROGRAMUNIFORM1FVPROC glad_glProgramUniform1fv = NULL; +PFNGLPROGRAMUNIFORM1IPROC glad_glProgramUniform1i = NULL; +PFNGLPROGRAMUNIFORM1IVPROC glad_glProgramUniform1iv = NULL; +PFNGLPROGRAMUNIFORM1UIPROC glad_glProgramUniform1ui = NULL; +PFNGLPROGRAMUNIFORM1UIVPROC glad_glProgramUniform1uiv = NULL; +PFNGLPROGRAMUNIFORM2FPROC glad_glProgramUniform2f = NULL; +PFNGLPROGRAMUNIFORM2FVPROC glad_glProgramUniform2fv = NULL; +PFNGLPROGRAMUNIFORM2IPROC glad_glProgramUniform2i = NULL; +PFNGLPROGRAMUNIFORM2IVPROC glad_glProgramUniform2iv = NULL; +PFNGLPROGRAMUNIFORM2UIPROC glad_glProgramUniform2ui = NULL; +PFNGLPROGRAMUNIFORM2UIVPROC glad_glProgramUniform2uiv = NULL; +PFNGLPROGRAMUNIFORM3FPROC glad_glProgramUniform3f = NULL; +PFNGLPROGRAMUNIFORM3FVPROC glad_glProgramUniform3fv = NULL; +PFNGLPROGRAMUNIFORM3IPROC glad_glProgramUniform3i = NULL; +PFNGLPROGRAMUNIFORM3IVPROC glad_glProgramUniform3iv = NULL; +PFNGLPROGRAMUNIFORM3UIPROC glad_glProgramUniform3ui = NULL; +PFNGLPROGRAMUNIFORM3UIVPROC glad_glProgramUniform3uiv = NULL; +PFNGLPROGRAMUNIFORM4FPROC glad_glProgramUniform4f = NULL; +PFNGLPROGRAMUNIFORM4FVPROC glad_glProgramUniform4fv = NULL; +PFNGLPROGRAMUNIFORM4IPROC glad_glProgramUniform4i = NULL; +PFNGLPROGRAMUNIFORM4IVPROC glad_glProgramUniform4iv = NULL; +PFNGLPROGRAMUNIFORM4UIPROC glad_glProgramUniform4ui = NULL; +PFNGLPROGRAMUNIFORM4UIVPROC glad_glProgramUniform4uiv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2FVPROC glad_glProgramUniformMatrix2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC glad_glProgramUniformMatrix2x3fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC glad_glProgramUniformMatrix2x4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3FVPROC glad_glProgramUniformMatrix3fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC glad_glProgramUniformMatrix3x2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC glad_glProgramUniformMatrix3x4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4FVPROC glad_glProgramUniformMatrix4fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC glad_glProgramUniformMatrix4x2fv = NULL; +PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC glad_glProgramUniformMatrix4x3fv = NULL; +PFNGLPUSHDEBUGGROUPPROC glad_glPushDebugGroup = NULL; +PFNGLREADBUFFERPROC glad_glReadBuffer = NULL; +PFNGLREADPIXELSPROC glad_glReadPixels = NULL; +PFNGLREADNPIXELSPROC glad_glReadnPixels = NULL; +PFNGLRELEASESHADERCOMPILERPROC glad_glReleaseShaderCompiler = NULL; +PFNGLRENDERBUFFERSTORAGEPROC glad_glRenderbufferStorage = NULL; +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glRenderbufferStorageMultisample = NULL; +PFNGLRESUMETRANSFORMFEEDBACKPROC glad_glResumeTransformFeedback = NULL; +PFNGLSAMPLECOVERAGEPROC glad_glSampleCoverage = NULL; +PFNGLSAMPLEMASKIPROC glad_glSampleMaski = NULL; +PFNGLSAMPLERPARAMETERIIVPROC glad_glSamplerParameterIiv = NULL; +PFNGLSAMPLERPARAMETERIUIVPROC glad_glSamplerParameterIuiv = NULL; +PFNGLSAMPLERPARAMETERFPROC glad_glSamplerParameterf = NULL; +PFNGLSAMPLERPARAMETERFVPROC glad_glSamplerParameterfv = NULL; +PFNGLSAMPLERPARAMETERIPROC glad_glSamplerParameteri = NULL; +PFNGLSAMPLERPARAMETERIVPROC glad_glSamplerParameteriv = NULL; +PFNGLSCISSORPROC glad_glScissor = NULL; +PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL; +PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL; +PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL; +PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL; +PFNGLSTENCILMASKPROC glad_glStencilMask = NULL; +PFNGLSTENCILMASKSEPARATEPROC glad_glStencilMaskSeparate = NULL; +PFNGLSTENCILOPPROC glad_glStencilOp = NULL; +PFNGLSTENCILOPSEPARATEPROC glad_glStencilOpSeparate = NULL; +PFNGLTEXBUFFERPROC glad_glTexBuffer = NULL; +PFNGLTEXBUFFERRANGEPROC glad_glTexBufferRange = NULL; +PFNGLTEXIMAGE2DPROC glad_glTexImage2D = NULL; +PFNGLTEXIMAGE3DPROC glad_glTexImage3D = NULL; +PFNGLTEXPARAMETERIIVPROC glad_glTexParameterIiv = NULL; +PFNGLTEXPARAMETERIUIVPROC glad_glTexParameterIuiv = NULL; +PFNGLTEXPARAMETERFPROC glad_glTexParameterf = NULL; +PFNGLTEXPARAMETERFVPROC glad_glTexParameterfv = NULL; +PFNGLTEXPARAMETERIPROC glad_glTexParameteri = NULL; +PFNGLTEXPARAMETERIVPROC glad_glTexParameteriv = NULL; +PFNGLTEXSTORAGE2DPROC glad_glTexStorage2D = NULL; +PFNGLTEXSTORAGE2DMULTISAMPLEPROC glad_glTexStorage2DMultisample = NULL; +PFNGLTEXSTORAGE3DPROC glad_glTexStorage3D = NULL; +PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample = NULL; +PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL; +PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL; +PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL; +PFNGLUNIFORM1FPROC glad_glUniform1f = NULL; +PFNGLUNIFORM1FVPROC glad_glUniform1fv = NULL; +PFNGLUNIFORM1IPROC glad_glUniform1i = NULL; +PFNGLUNIFORM1IVPROC glad_glUniform1iv = NULL; +PFNGLUNIFORM1UIPROC glad_glUniform1ui = NULL; +PFNGLUNIFORM1UIVPROC glad_glUniform1uiv = NULL; +PFNGLUNIFORM2FPROC glad_glUniform2f = NULL; +PFNGLUNIFORM2FVPROC glad_glUniform2fv = NULL; +PFNGLUNIFORM2IPROC glad_glUniform2i = NULL; +PFNGLUNIFORM2IVPROC glad_glUniform2iv = NULL; +PFNGLUNIFORM2UIPROC glad_glUniform2ui = NULL; +PFNGLUNIFORM2UIVPROC glad_glUniform2uiv = NULL; +PFNGLUNIFORM3FPROC glad_glUniform3f = NULL; +PFNGLUNIFORM3FVPROC glad_glUniform3fv = NULL; +PFNGLUNIFORM3IPROC glad_glUniform3i = NULL; +PFNGLUNIFORM3IVPROC glad_glUniform3iv = NULL; +PFNGLUNIFORM3UIPROC glad_glUniform3ui = NULL; +PFNGLUNIFORM3UIVPROC glad_glUniform3uiv = NULL; +PFNGLUNIFORM4FPROC glad_glUniform4f = NULL; +PFNGLUNIFORM4FVPROC glad_glUniform4fv = NULL; +PFNGLUNIFORM4IPROC glad_glUniform4i = NULL; +PFNGLUNIFORM4IVPROC glad_glUniform4iv = NULL; +PFNGLUNIFORM4UIPROC glad_glUniform4ui = NULL; +PFNGLUNIFORM4UIVPROC glad_glUniform4uiv = NULL; +PFNGLUNIFORMBLOCKBINDINGPROC glad_glUniformBlockBinding = NULL; +PFNGLUNIFORMMATRIX2FVPROC glad_glUniformMatrix2fv = NULL; +PFNGLUNIFORMMATRIX2X3FVPROC glad_glUniformMatrix2x3fv = NULL; +PFNGLUNIFORMMATRIX2X4FVPROC glad_glUniformMatrix2x4fv = NULL; +PFNGLUNIFORMMATRIX3FVPROC glad_glUniformMatrix3fv = NULL; +PFNGLUNIFORMMATRIX3X2FVPROC glad_glUniformMatrix3x2fv = NULL; +PFNGLUNIFORMMATRIX3X4FVPROC glad_glUniformMatrix3x4fv = NULL; +PFNGLUNIFORMMATRIX4FVPROC glad_glUniformMatrix4fv = NULL; +PFNGLUNIFORMMATRIX4X2FVPROC glad_glUniformMatrix4x2fv = NULL; +PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL; +PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL; +PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL; +PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages = NULL; +PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL; +PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline = NULL; +PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL; +PFNGLVERTEXATTRIB1FVPROC glad_glVertexAttrib1fv = NULL; +PFNGLVERTEXATTRIB2FPROC glad_glVertexAttrib2f = NULL; +PFNGLVERTEXATTRIB2FVPROC glad_glVertexAttrib2fv = NULL; +PFNGLVERTEXATTRIB3FPROC glad_glVertexAttrib3f = NULL; +PFNGLVERTEXATTRIB3FVPROC glad_glVertexAttrib3fv = NULL; +PFNGLVERTEXATTRIB4FPROC glad_glVertexAttrib4f = NULL; +PFNGLVERTEXATTRIB4FVPROC glad_glVertexAttrib4fv = NULL; +PFNGLVERTEXATTRIBBINDINGPROC glad_glVertexAttribBinding = NULL; +PFNGLVERTEXATTRIBDIVISORPROC glad_glVertexAttribDivisor = NULL; +PFNGLVERTEXATTRIBFORMATPROC glad_glVertexAttribFormat = NULL; +PFNGLVERTEXATTRIBI4IPROC glad_glVertexAttribI4i = NULL; +PFNGLVERTEXATTRIBI4IVPROC glad_glVertexAttribI4iv = NULL; +PFNGLVERTEXATTRIBI4UIPROC glad_glVertexAttribI4ui = NULL; +PFNGLVERTEXATTRIBI4UIVPROC glad_glVertexAttribI4uiv = NULL; +PFNGLVERTEXATTRIBIFORMATPROC glad_glVertexAttribIFormat = NULL; +PFNGLVERTEXATTRIBIPOINTERPROC glad_glVertexAttribIPointer = NULL; +PFNGLVERTEXATTRIBPOINTERPROC glad_glVertexAttribPointer = NULL; +PFNGLVERTEXBINDINGDIVISORPROC glad_glVertexBindingDivisor = NULL; +PFNGLVIEWPORTPROC glad_glViewport = NULL; +PFNGLWAITSYNCPROC glad_glWaitSync = NULL; + + +static void glad_gl_load_GL_ES_VERSION_2_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ES_VERSION_2_0) return; + glad_glActiveTexture = (PFNGLACTIVETEXTUREPROC) load(userptr, "glActiveTexture"); + glad_glAttachShader = (PFNGLATTACHSHADERPROC) load(userptr, "glAttachShader"); + glad_glBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC) load(userptr, "glBindAttribLocation"); + glad_glBindBuffer = (PFNGLBINDBUFFERPROC) load(userptr, "glBindBuffer"); + glad_glBindFramebuffer = (PFNGLBINDFRAMEBUFFERPROC) load(userptr, "glBindFramebuffer"); + glad_glBindRenderbuffer = (PFNGLBINDRENDERBUFFERPROC) load(userptr, "glBindRenderbuffer"); + glad_glBindTexture = (PFNGLBINDTEXTUREPROC) load(userptr, "glBindTexture"); + glad_glBlendColor = (PFNGLBLENDCOLORPROC) load(userptr, "glBlendColor"); + glad_glBlendEquation = (PFNGLBLENDEQUATIONPROC) load(userptr, "glBlendEquation"); + glad_glBlendEquationSeparate = (PFNGLBLENDEQUATIONSEPARATEPROC) load(userptr, "glBlendEquationSeparate"); + glad_glBlendFunc = (PFNGLBLENDFUNCPROC) load(userptr, "glBlendFunc"); + glad_glBlendFuncSeparate = (PFNGLBLENDFUNCSEPARATEPROC) load(userptr, "glBlendFuncSeparate"); + glad_glBufferData = (PFNGLBUFFERDATAPROC) load(userptr, "glBufferData"); + glad_glBufferSubData = (PFNGLBUFFERSUBDATAPROC) load(userptr, "glBufferSubData"); + glad_glCheckFramebufferStatus = (PFNGLCHECKFRAMEBUFFERSTATUSPROC) load(userptr, "glCheckFramebufferStatus"); + glad_glClear = (PFNGLCLEARPROC) load(userptr, "glClear"); + glad_glClearColor = (PFNGLCLEARCOLORPROC) load(userptr, "glClearColor"); + glad_glClearDepthf = (PFNGLCLEARDEPTHFPROC) load(userptr, "glClearDepthf"); + glad_glClearStencil = (PFNGLCLEARSTENCILPROC) load(userptr, "glClearStencil"); + glad_glColorMask = (PFNGLCOLORMASKPROC) load(userptr, "glColorMask"); + glad_glCompileShader = (PFNGLCOMPILESHADERPROC) load(userptr, "glCompileShader"); + glad_glCompressedTexImage2D = (PFNGLCOMPRESSEDTEXIMAGE2DPROC) load(userptr, "glCompressedTexImage2D"); + glad_glCompressedTexSubImage2D = (PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC) load(userptr, "glCompressedTexSubImage2D"); + glad_glCopyTexImage2D = (PFNGLCOPYTEXIMAGE2DPROC) load(userptr, "glCopyTexImage2D"); + glad_glCopyTexSubImage2D = (PFNGLCOPYTEXSUBIMAGE2DPROC) load(userptr, "glCopyTexSubImage2D"); + glad_glCreateProgram = (PFNGLCREATEPROGRAMPROC) load(userptr, "glCreateProgram"); + glad_glCreateShader = (PFNGLCREATESHADERPROC) load(userptr, "glCreateShader"); + glad_glCullFace = (PFNGLCULLFACEPROC) load(userptr, "glCullFace"); + glad_glDeleteBuffers = (PFNGLDELETEBUFFERSPROC) load(userptr, "glDeleteBuffers"); + glad_glDeleteFramebuffers = (PFNGLDELETEFRAMEBUFFERSPROC) load(userptr, "glDeleteFramebuffers"); + glad_glDeleteProgram = (PFNGLDELETEPROGRAMPROC) load(userptr, "glDeleteProgram"); + glad_glDeleteRenderbuffers = (PFNGLDELETERENDERBUFFERSPROC) load(userptr, "glDeleteRenderbuffers"); + glad_glDeleteShader = (PFNGLDELETESHADERPROC) load(userptr, "glDeleteShader"); + glad_glDeleteTextures = (PFNGLDELETETEXTURESPROC) load(userptr, "glDeleteTextures"); + glad_glDepthFunc = (PFNGLDEPTHFUNCPROC) load(userptr, "glDepthFunc"); + glad_glDepthMask = (PFNGLDEPTHMASKPROC) load(userptr, "glDepthMask"); + glad_glDepthRangef = (PFNGLDEPTHRANGEFPROC) load(userptr, "glDepthRangef"); + glad_glDetachShader = (PFNGLDETACHSHADERPROC) load(userptr, "glDetachShader"); + glad_glDisable = (PFNGLDISABLEPROC) load(userptr, "glDisable"); + glad_glDisableVertexAttribArray = (PFNGLDISABLEVERTEXATTRIBARRAYPROC) load(userptr, "glDisableVertexAttribArray"); + glad_glDrawArrays = (PFNGLDRAWARRAYSPROC) load(userptr, "glDrawArrays"); + glad_glDrawElements = (PFNGLDRAWELEMENTSPROC) load(userptr, "glDrawElements"); + glad_glEnable = (PFNGLENABLEPROC) load(userptr, "glEnable"); + glad_glEnableVertexAttribArray = (PFNGLENABLEVERTEXATTRIBARRAYPROC) load(userptr, "glEnableVertexAttribArray"); + glad_glFinish = (PFNGLFINISHPROC) load(userptr, "glFinish"); + glad_glFlush = (PFNGLFLUSHPROC) load(userptr, "glFlush"); + glad_glFramebufferRenderbuffer = (PFNGLFRAMEBUFFERRENDERBUFFERPROC) load(userptr, "glFramebufferRenderbuffer"); + glad_glFramebufferTexture2D = (PFNGLFRAMEBUFFERTEXTURE2DPROC) load(userptr, "glFramebufferTexture2D"); + glad_glFrontFace = (PFNGLFRONTFACEPROC) load(userptr, "glFrontFace"); + glad_glGenBuffers = (PFNGLGENBUFFERSPROC) load(userptr, "glGenBuffers"); + glad_glGenFramebuffers = (PFNGLGENFRAMEBUFFERSPROC) load(userptr, "glGenFramebuffers"); + glad_glGenRenderbuffers = (PFNGLGENRENDERBUFFERSPROC) load(userptr, "glGenRenderbuffers"); + glad_glGenTextures = (PFNGLGENTEXTURESPROC) load(userptr, "glGenTextures"); + glad_glGenerateMipmap = (PFNGLGENERATEMIPMAPPROC) load(userptr, "glGenerateMipmap"); + glad_glGetActiveAttrib = (PFNGLGETACTIVEATTRIBPROC) load(userptr, "glGetActiveAttrib"); + glad_glGetActiveUniform = (PFNGLGETACTIVEUNIFORMPROC) load(userptr, "glGetActiveUniform"); + glad_glGetAttachedShaders = (PFNGLGETATTACHEDSHADERSPROC) load(userptr, "glGetAttachedShaders"); + glad_glGetAttribLocation = (PFNGLGETATTRIBLOCATIONPROC) load(userptr, "glGetAttribLocation"); + glad_glGetBooleanv = (PFNGLGETBOOLEANVPROC) load(userptr, "glGetBooleanv"); + glad_glGetBufferParameteriv = (PFNGLGETBUFFERPARAMETERIVPROC) load(userptr, "glGetBufferParameteriv"); + glad_glGetError = (PFNGLGETERRORPROC) load(userptr, "glGetError"); + glad_glGetFloatv = (PFNGLGETFLOATVPROC) load(userptr, "glGetFloatv"); + glad_glGetFramebufferAttachmentParameteriv = (PFNGLGETFRAMEBUFFERATTACHMENTPARAMETERIVPROC) load(userptr, "glGetFramebufferAttachmentParameteriv"); + glad_glGetIntegerv = (PFNGLGETINTEGERVPROC) load(userptr, "glGetIntegerv"); + glad_glGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC) load(userptr, "glGetProgramInfoLog"); + glad_glGetProgramiv = (PFNGLGETPROGRAMIVPROC) load(userptr, "glGetProgramiv"); + glad_glGetRenderbufferParameteriv = (PFNGLGETRENDERBUFFERPARAMETERIVPROC) load(userptr, "glGetRenderbufferParameteriv"); + glad_glGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC) load(userptr, "glGetShaderInfoLog"); + glad_glGetShaderPrecisionFormat = (PFNGLGETSHADERPRECISIONFORMATPROC) load(userptr, "glGetShaderPrecisionFormat"); + glad_glGetShaderSource = (PFNGLGETSHADERSOURCEPROC) load(userptr, "glGetShaderSource"); + glad_glGetShaderiv = (PFNGLGETSHADERIVPROC) load(userptr, "glGetShaderiv"); + glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + glad_glGetTexParameterfv = (PFNGLGETTEXPARAMETERFVPROC) load(userptr, "glGetTexParameterfv"); + glad_glGetTexParameteriv = (PFNGLGETTEXPARAMETERIVPROC) load(userptr, "glGetTexParameteriv"); + glad_glGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC) load(userptr, "glGetUniformLocation"); + glad_glGetUniformfv = (PFNGLGETUNIFORMFVPROC) load(userptr, "glGetUniformfv"); + glad_glGetUniformiv = (PFNGLGETUNIFORMIVPROC) load(userptr, "glGetUniformiv"); + glad_glGetVertexAttribPointerv = (PFNGLGETVERTEXATTRIBPOINTERVPROC) load(userptr, "glGetVertexAttribPointerv"); + glad_glGetVertexAttribfv = (PFNGLGETVERTEXATTRIBFVPROC) load(userptr, "glGetVertexAttribfv"); + glad_glGetVertexAttribiv = (PFNGLGETVERTEXATTRIBIVPROC) load(userptr, "glGetVertexAttribiv"); + glad_glHint = (PFNGLHINTPROC) load(userptr, "glHint"); + glad_glIsBuffer = (PFNGLISBUFFERPROC) load(userptr, "glIsBuffer"); + glad_glIsEnabled = (PFNGLISENABLEDPROC) load(userptr, "glIsEnabled"); + glad_glIsFramebuffer = (PFNGLISFRAMEBUFFERPROC) load(userptr, "glIsFramebuffer"); + glad_glIsProgram = (PFNGLISPROGRAMPROC) load(userptr, "glIsProgram"); + glad_glIsRenderbuffer = (PFNGLISRENDERBUFFERPROC) load(userptr, "glIsRenderbuffer"); + glad_glIsShader = (PFNGLISSHADERPROC) load(userptr, "glIsShader"); + glad_glIsTexture = (PFNGLISTEXTUREPROC) load(userptr, "glIsTexture"); + glad_glLineWidth = (PFNGLLINEWIDTHPROC) load(userptr, "glLineWidth"); + glad_glLinkProgram = (PFNGLLINKPROGRAMPROC) load(userptr, "glLinkProgram"); + glad_glPixelStorei = (PFNGLPIXELSTOREIPROC) load(userptr, "glPixelStorei"); + glad_glPolygonOffset = (PFNGLPOLYGONOFFSETPROC) load(userptr, "glPolygonOffset"); + glad_glReadPixels = (PFNGLREADPIXELSPROC) load(userptr, "glReadPixels"); + glad_glReleaseShaderCompiler = (PFNGLRELEASESHADERCOMPILERPROC) load(userptr, "glReleaseShaderCompiler"); + glad_glRenderbufferStorage = (PFNGLRENDERBUFFERSTORAGEPROC) load(userptr, "glRenderbufferStorage"); + glad_glSampleCoverage = (PFNGLSAMPLECOVERAGEPROC) load(userptr, "glSampleCoverage"); + glad_glScissor = (PFNGLSCISSORPROC) load(userptr, "glScissor"); + glad_glShaderBinary = (PFNGLSHADERBINARYPROC) load(userptr, "glShaderBinary"); + glad_glShaderSource = (PFNGLSHADERSOURCEPROC) load(userptr, "glShaderSource"); + glad_glStencilFunc = (PFNGLSTENCILFUNCPROC) load(userptr, "glStencilFunc"); + glad_glStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEPROC) load(userptr, "glStencilFuncSeparate"); + glad_glStencilMask = (PFNGLSTENCILMASKPROC) load(userptr, "glStencilMask"); + glad_glStencilMaskSeparate = (PFNGLSTENCILMASKSEPARATEPROC) load(userptr, "glStencilMaskSeparate"); + glad_glStencilOp = (PFNGLSTENCILOPPROC) load(userptr, "glStencilOp"); + glad_glStencilOpSeparate = (PFNGLSTENCILOPSEPARATEPROC) load(userptr, "glStencilOpSeparate"); + glad_glTexImage2D = (PFNGLTEXIMAGE2DPROC) load(userptr, "glTexImage2D"); + glad_glTexParameterf = (PFNGLTEXPARAMETERFPROC) load(userptr, "glTexParameterf"); + glad_glTexParameterfv = (PFNGLTEXPARAMETERFVPROC) load(userptr, "glTexParameterfv"); + glad_glTexParameteri = (PFNGLTEXPARAMETERIPROC) load(userptr, "glTexParameteri"); + glad_glTexParameteriv = (PFNGLTEXPARAMETERIVPROC) load(userptr, "glTexParameteriv"); + glad_glTexSubImage2D = (PFNGLTEXSUBIMAGE2DPROC) load(userptr, "glTexSubImage2D"); + glad_glUniform1f = (PFNGLUNIFORM1FPROC) load(userptr, "glUniform1f"); + glad_glUniform1fv = (PFNGLUNIFORM1FVPROC) load(userptr, "glUniform1fv"); + glad_glUniform1i = (PFNGLUNIFORM1IPROC) load(userptr, "glUniform1i"); + glad_glUniform1iv = (PFNGLUNIFORM1IVPROC) load(userptr, "glUniform1iv"); + glad_glUniform2f = (PFNGLUNIFORM2FPROC) load(userptr, "glUniform2f"); + glad_glUniform2fv = (PFNGLUNIFORM2FVPROC) load(userptr, "glUniform2fv"); + glad_glUniform2i = (PFNGLUNIFORM2IPROC) load(userptr, "glUniform2i"); + glad_glUniform2iv = (PFNGLUNIFORM2IVPROC) load(userptr, "glUniform2iv"); + glad_glUniform3f = (PFNGLUNIFORM3FPROC) load(userptr, "glUniform3f"); + glad_glUniform3fv = (PFNGLUNIFORM3FVPROC) load(userptr, "glUniform3fv"); + glad_glUniform3i = (PFNGLUNIFORM3IPROC) load(userptr, "glUniform3i"); + glad_glUniform3iv = (PFNGLUNIFORM3IVPROC) load(userptr, "glUniform3iv"); + glad_glUniform4f = (PFNGLUNIFORM4FPROC) load(userptr, "glUniform4f"); + glad_glUniform4fv = (PFNGLUNIFORM4FVPROC) load(userptr, "glUniform4fv"); + glad_glUniform4i = (PFNGLUNIFORM4IPROC) load(userptr, "glUniform4i"); + glad_glUniform4iv = (PFNGLUNIFORM4IVPROC) load(userptr, "glUniform4iv"); + glad_glUniformMatrix2fv = (PFNGLUNIFORMMATRIX2FVPROC) load(userptr, "glUniformMatrix2fv"); + glad_glUniformMatrix3fv = (PFNGLUNIFORMMATRIX3FVPROC) load(userptr, "glUniformMatrix3fv"); + glad_glUniformMatrix4fv = (PFNGLUNIFORMMATRIX4FVPROC) load(userptr, "glUniformMatrix4fv"); + glad_glUseProgram = (PFNGLUSEPROGRAMPROC) load(userptr, "glUseProgram"); + glad_glValidateProgram = (PFNGLVALIDATEPROGRAMPROC) load(userptr, "glValidateProgram"); + glad_glVertexAttrib1f = (PFNGLVERTEXATTRIB1FPROC) load(userptr, "glVertexAttrib1f"); + glad_glVertexAttrib1fv = (PFNGLVERTEXATTRIB1FVPROC) load(userptr, "glVertexAttrib1fv"); + glad_glVertexAttrib2f = (PFNGLVERTEXATTRIB2FPROC) load(userptr, "glVertexAttrib2f"); + glad_glVertexAttrib2fv = (PFNGLVERTEXATTRIB2FVPROC) load(userptr, "glVertexAttrib2fv"); + glad_glVertexAttrib3f = (PFNGLVERTEXATTRIB3FPROC) load(userptr, "glVertexAttrib3f"); + glad_glVertexAttrib3fv = (PFNGLVERTEXATTRIB3FVPROC) load(userptr, "glVertexAttrib3fv"); + glad_glVertexAttrib4f = (PFNGLVERTEXATTRIB4FPROC) load(userptr, "glVertexAttrib4f"); + glad_glVertexAttrib4fv = (PFNGLVERTEXATTRIB4FVPROC) load(userptr, "glVertexAttrib4fv"); + glad_glVertexAttribPointer = (PFNGLVERTEXATTRIBPOINTERPROC) load(userptr, "glVertexAttribPointer"); + glad_glViewport = (PFNGLVIEWPORTPROC) load(userptr, "glViewport"); +} +static void glad_gl_load_GL_ES_VERSION_3_0( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ES_VERSION_3_0) return; + glad_glBeginQuery = (PFNGLBEGINQUERYPROC) load(userptr, "glBeginQuery"); + glad_glBeginTransformFeedback = (PFNGLBEGINTRANSFORMFEEDBACKPROC) load(userptr, "glBeginTransformFeedback"); + glad_glBindBufferBase = (PFNGLBINDBUFFERBASEPROC) load(userptr, "glBindBufferBase"); + glad_glBindBufferRange = (PFNGLBINDBUFFERRANGEPROC) load(userptr, "glBindBufferRange"); + glad_glBindSampler = (PFNGLBINDSAMPLERPROC) load(userptr, "glBindSampler"); + glad_glBindTransformFeedback = (PFNGLBINDTRANSFORMFEEDBACKPROC) load(userptr, "glBindTransformFeedback"); + glad_glBindVertexArray = (PFNGLBINDVERTEXARRAYPROC) load(userptr, "glBindVertexArray"); + glad_glBlitFramebuffer = (PFNGLBLITFRAMEBUFFERPROC) load(userptr, "glBlitFramebuffer"); + glad_glClearBufferfi = (PFNGLCLEARBUFFERFIPROC) load(userptr, "glClearBufferfi"); + glad_glClearBufferfv = (PFNGLCLEARBUFFERFVPROC) load(userptr, "glClearBufferfv"); + glad_glClearBufferiv = (PFNGLCLEARBUFFERIVPROC) load(userptr, "glClearBufferiv"); + glad_glClearBufferuiv = (PFNGLCLEARBUFFERUIVPROC) load(userptr, "glClearBufferuiv"); + glad_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC) load(userptr, "glClientWaitSync"); + glad_glCompressedTexImage3D = (PFNGLCOMPRESSEDTEXIMAGE3DPROC) load(userptr, "glCompressedTexImage3D"); + glad_glCompressedTexSubImage3D = (PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC) load(userptr, "glCompressedTexSubImage3D"); + glad_glCopyBufferSubData = (PFNGLCOPYBUFFERSUBDATAPROC) load(userptr, "glCopyBufferSubData"); + glad_glCopyTexSubImage3D = (PFNGLCOPYTEXSUBIMAGE3DPROC) load(userptr, "glCopyTexSubImage3D"); + glad_glDeleteQueries = (PFNGLDELETEQUERIESPROC) load(userptr, "glDeleteQueries"); + glad_glDeleteSamplers = (PFNGLDELETESAMPLERSPROC) load(userptr, "glDeleteSamplers"); + glad_glDeleteSync = (PFNGLDELETESYNCPROC) load(userptr, "glDeleteSync"); + glad_glDeleteTransformFeedbacks = (PFNGLDELETETRANSFORMFEEDBACKSPROC) load(userptr, "glDeleteTransformFeedbacks"); + glad_glDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC) load(userptr, "glDeleteVertexArrays"); + glad_glDrawArraysInstanced = (PFNGLDRAWARRAYSINSTANCEDPROC) load(userptr, "glDrawArraysInstanced"); + glad_glDrawBuffers = (PFNGLDRAWBUFFERSPROC) load(userptr, "glDrawBuffers"); + glad_glDrawElementsInstanced = (PFNGLDRAWELEMENTSINSTANCEDPROC) load(userptr, "glDrawElementsInstanced"); + glad_glDrawRangeElements = (PFNGLDRAWRANGEELEMENTSPROC) load(userptr, "glDrawRangeElements"); + glad_glEndQuery = (PFNGLENDQUERYPROC) load(userptr, "glEndQuery"); + glad_glEndTransformFeedback = (PFNGLENDTRANSFORMFEEDBACKPROC) load(userptr, "glEndTransformFeedback"); + glad_glFenceSync = (PFNGLFENCESYNCPROC) load(userptr, "glFenceSync"); + glad_glFlushMappedBufferRange = (PFNGLFLUSHMAPPEDBUFFERRANGEPROC) load(userptr, "glFlushMappedBufferRange"); + glad_glFramebufferTextureLayer = (PFNGLFRAMEBUFFERTEXTURELAYERPROC) load(userptr, "glFramebufferTextureLayer"); + glad_glGenQueries = (PFNGLGENQUERIESPROC) load(userptr, "glGenQueries"); + glad_glGenSamplers = (PFNGLGENSAMPLERSPROC) load(userptr, "glGenSamplers"); + glad_glGenTransformFeedbacks = (PFNGLGENTRANSFORMFEEDBACKSPROC) load(userptr, "glGenTransformFeedbacks"); + glad_glGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC) load(userptr, "glGenVertexArrays"); + glad_glGetActiveUniformBlockName = (PFNGLGETACTIVEUNIFORMBLOCKNAMEPROC) load(userptr, "glGetActiveUniformBlockName"); + glad_glGetActiveUniformBlockiv = (PFNGLGETACTIVEUNIFORMBLOCKIVPROC) load(userptr, "glGetActiveUniformBlockiv"); + glad_glGetActiveUniformsiv = (PFNGLGETACTIVEUNIFORMSIVPROC) load(userptr, "glGetActiveUniformsiv"); + glad_glGetBufferParameteri64v = (PFNGLGETBUFFERPARAMETERI64VPROC) load(userptr, "glGetBufferParameteri64v"); + glad_glGetBufferPointerv = (PFNGLGETBUFFERPOINTERVPROC) load(userptr, "glGetBufferPointerv"); + glad_glGetFragDataLocation = (PFNGLGETFRAGDATALOCATIONPROC) load(userptr, "glGetFragDataLocation"); + glad_glGetInteger64i_v = (PFNGLGETINTEGER64I_VPROC) load(userptr, "glGetInteger64i_v"); + glad_glGetInteger64v = (PFNGLGETINTEGER64VPROC) load(userptr, "glGetInteger64v"); + glad_glGetIntegeri_v = (PFNGLGETINTEGERI_VPROC) load(userptr, "glGetIntegeri_v"); + glad_glGetInternalformativ = (PFNGLGETINTERNALFORMATIVPROC) load(userptr, "glGetInternalformativ"); + glad_glGetProgramBinary = (PFNGLGETPROGRAMBINARYPROC) load(userptr, "glGetProgramBinary"); + glad_glGetQueryObjectuiv = (PFNGLGETQUERYOBJECTUIVPROC) load(userptr, "glGetQueryObjectuiv"); + glad_glGetQueryiv = (PFNGLGETQUERYIVPROC) load(userptr, "glGetQueryiv"); + glad_glGetSamplerParameterfv = (PFNGLGETSAMPLERPARAMETERFVPROC) load(userptr, "glGetSamplerParameterfv"); + glad_glGetSamplerParameteriv = (PFNGLGETSAMPLERPARAMETERIVPROC) load(userptr, "glGetSamplerParameteriv"); + glad_glGetStringi = (PFNGLGETSTRINGIPROC) load(userptr, "glGetStringi"); + glad_glGetSynciv = (PFNGLGETSYNCIVPROC) load(userptr, "glGetSynciv"); + glad_glGetTransformFeedbackVarying = (PFNGLGETTRANSFORMFEEDBACKVARYINGPROC) load(userptr, "glGetTransformFeedbackVarying"); + glad_glGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC) load(userptr, "glGetUniformBlockIndex"); + glad_glGetUniformIndices = (PFNGLGETUNIFORMINDICESPROC) load(userptr, "glGetUniformIndices"); + glad_glGetUniformuiv = (PFNGLGETUNIFORMUIVPROC) load(userptr, "glGetUniformuiv"); + glad_glGetVertexAttribIiv = (PFNGLGETVERTEXATTRIBIIVPROC) load(userptr, "glGetVertexAttribIiv"); + glad_glGetVertexAttribIuiv = (PFNGLGETVERTEXATTRIBIUIVPROC) load(userptr, "glGetVertexAttribIuiv"); + glad_glInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC) load(userptr, "glInvalidateFramebuffer"); + glad_glInvalidateSubFramebuffer = (PFNGLINVALIDATESUBFRAMEBUFFERPROC) load(userptr, "glInvalidateSubFramebuffer"); + glad_glIsQuery = (PFNGLISQUERYPROC) load(userptr, "glIsQuery"); + glad_glIsSampler = (PFNGLISSAMPLERPROC) load(userptr, "glIsSampler"); + glad_glIsSync = (PFNGLISSYNCPROC) load(userptr, "glIsSync"); + glad_glIsTransformFeedback = (PFNGLISTRANSFORMFEEDBACKPROC) load(userptr, "glIsTransformFeedback"); + glad_glIsVertexArray = (PFNGLISVERTEXARRAYPROC) load(userptr, "glIsVertexArray"); + glad_glMapBufferRange = (PFNGLMAPBUFFERRANGEPROC) load(userptr, "glMapBufferRange"); + glad_glPauseTransformFeedback = (PFNGLPAUSETRANSFORMFEEDBACKPROC) load(userptr, "glPauseTransformFeedback"); + glad_glProgramBinary = (PFNGLPROGRAMBINARYPROC) load(userptr, "glProgramBinary"); + glad_glProgramParameteri = (PFNGLPROGRAMPARAMETERIPROC) load(userptr, "glProgramParameteri"); + glad_glReadBuffer = (PFNGLREADBUFFERPROC) load(userptr, "glReadBuffer"); + glad_glRenderbufferStorageMultisample = (PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC) load(userptr, "glRenderbufferStorageMultisample"); + glad_glResumeTransformFeedback = (PFNGLRESUMETRANSFORMFEEDBACKPROC) load(userptr, "glResumeTransformFeedback"); + glad_glSamplerParameterf = (PFNGLSAMPLERPARAMETERFPROC) load(userptr, "glSamplerParameterf"); + glad_glSamplerParameterfv = (PFNGLSAMPLERPARAMETERFVPROC) load(userptr, "glSamplerParameterfv"); + glad_glSamplerParameteri = (PFNGLSAMPLERPARAMETERIPROC) load(userptr, "glSamplerParameteri"); + glad_glSamplerParameteriv = (PFNGLSAMPLERPARAMETERIVPROC) load(userptr, "glSamplerParameteriv"); + glad_glTexImage3D = (PFNGLTEXIMAGE3DPROC) load(userptr, "glTexImage3D"); + glad_glTexStorage2D = (PFNGLTEXSTORAGE2DPROC) load(userptr, "glTexStorage2D"); + glad_glTexStorage3D = (PFNGLTEXSTORAGE3DPROC) load(userptr, "glTexStorage3D"); + glad_glTexSubImage3D = (PFNGLTEXSUBIMAGE3DPROC) load(userptr, "glTexSubImage3D"); + glad_glTransformFeedbackVaryings = (PFNGLTRANSFORMFEEDBACKVARYINGSPROC) load(userptr, "glTransformFeedbackVaryings"); + glad_glUniform1ui = (PFNGLUNIFORM1UIPROC) load(userptr, "glUniform1ui"); + glad_glUniform1uiv = (PFNGLUNIFORM1UIVPROC) load(userptr, "glUniform1uiv"); + glad_glUniform2ui = (PFNGLUNIFORM2UIPROC) load(userptr, "glUniform2ui"); + glad_glUniform2uiv = (PFNGLUNIFORM2UIVPROC) load(userptr, "glUniform2uiv"); + glad_glUniform3ui = (PFNGLUNIFORM3UIPROC) load(userptr, "glUniform3ui"); + glad_glUniform3uiv = (PFNGLUNIFORM3UIVPROC) load(userptr, "glUniform3uiv"); + glad_glUniform4ui = (PFNGLUNIFORM4UIPROC) load(userptr, "glUniform4ui"); + glad_glUniform4uiv = (PFNGLUNIFORM4UIVPROC) load(userptr, "glUniform4uiv"); + glad_glUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC) load(userptr, "glUniformBlockBinding"); + glad_glUniformMatrix2x3fv = (PFNGLUNIFORMMATRIX2X3FVPROC) load(userptr, "glUniformMatrix2x3fv"); + glad_glUniformMatrix2x4fv = (PFNGLUNIFORMMATRIX2X4FVPROC) load(userptr, "glUniformMatrix2x4fv"); + glad_glUniformMatrix3x2fv = (PFNGLUNIFORMMATRIX3X2FVPROC) load(userptr, "glUniformMatrix3x2fv"); + glad_glUniformMatrix3x4fv = (PFNGLUNIFORMMATRIX3X4FVPROC) load(userptr, "glUniformMatrix3x4fv"); + glad_glUniformMatrix4x2fv = (PFNGLUNIFORMMATRIX4X2FVPROC) load(userptr, "glUniformMatrix4x2fv"); + glad_glUniformMatrix4x3fv = (PFNGLUNIFORMMATRIX4X3FVPROC) load(userptr, "glUniformMatrix4x3fv"); + glad_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC) load(userptr, "glUnmapBuffer"); + glad_glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC) load(userptr, "glVertexAttribDivisor"); + glad_glVertexAttribI4i = (PFNGLVERTEXATTRIBI4IPROC) load(userptr, "glVertexAttribI4i"); + glad_glVertexAttribI4iv = (PFNGLVERTEXATTRIBI4IVPROC) load(userptr, "glVertexAttribI4iv"); + glad_glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) load(userptr, "glVertexAttribI4ui"); + glad_glVertexAttribI4uiv = (PFNGLVERTEXATTRIBI4UIVPROC) load(userptr, "glVertexAttribI4uiv"); + glad_glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) load(userptr, "glVertexAttribIPointer"); + glad_glWaitSync = (PFNGLWAITSYNCPROC) load(userptr, "glWaitSync"); +} +static void glad_gl_load_GL_ES_VERSION_3_1( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ES_VERSION_3_1) return; + glad_glActiveShaderProgram = (PFNGLACTIVESHADERPROGRAMPROC) load(userptr, "glActiveShaderProgram"); + glad_glBindImageTexture = (PFNGLBINDIMAGETEXTUREPROC) load(userptr, "glBindImageTexture"); + glad_glBindProgramPipeline = (PFNGLBINDPROGRAMPIPELINEPROC) load(userptr, "glBindProgramPipeline"); + glad_glBindVertexBuffer = (PFNGLBINDVERTEXBUFFERPROC) load(userptr, "glBindVertexBuffer"); + glad_glCreateShaderProgramv = (PFNGLCREATESHADERPROGRAMVPROC) load(userptr, "glCreateShaderProgramv"); + glad_glDeleteProgramPipelines = (PFNGLDELETEPROGRAMPIPELINESPROC) load(userptr, "glDeleteProgramPipelines"); + glad_glDispatchCompute = (PFNGLDISPATCHCOMPUTEPROC) load(userptr, "glDispatchCompute"); + glad_glDispatchComputeIndirect = (PFNGLDISPATCHCOMPUTEINDIRECTPROC) load(userptr, "glDispatchComputeIndirect"); + glad_glDrawArraysIndirect = (PFNGLDRAWARRAYSINDIRECTPROC) load(userptr, "glDrawArraysIndirect"); + glad_glDrawElementsIndirect = (PFNGLDRAWELEMENTSINDIRECTPROC) load(userptr, "glDrawElementsIndirect"); + glad_glFramebufferParameteri = (PFNGLFRAMEBUFFERPARAMETERIPROC) load(userptr, "glFramebufferParameteri"); + glad_glGenProgramPipelines = (PFNGLGENPROGRAMPIPELINESPROC) load(userptr, "glGenProgramPipelines"); + glad_glGetBooleani_v = (PFNGLGETBOOLEANI_VPROC) load(userptr, "glGetBooleani_v"); + glad_glGetFramebufferParameteriv = (PFNGLGETFRAMEBUFFERPARAMETERIVPROC) load(userptr, "glGetFramebufferParameteriv"); + glad_glGetMultisamplefv = (PFNGLGETMULTISAMPLEFVPROC) load(userptr, "glGetMultisamplefv"); + glad_glGetProgramInterfaceiv = (PFNGLGETPROGRAMINTERFACEIVPROC) load(userptr, "glGetProgramInterfaceiv"); + glad_glGetProgramPipelineInfoLog = (PFNGLGETPROGRAMPIPELINEINFOLOGPROC) load(userptr, "glGetProgramPipelineInfoLog"); + glad_glGetProgramPipelineiv = (PFNGLGETPROGRAMPIPELINEIVPROC) load(userptr, "glGetProgramPipelineiv"); + glad_glGetProgramResourceIndex = (PFNGLGETPROGRAMRESOURCEINDEXPROC) load(userptr, "glGetProgramResourceIndex"); + glad_glGetProgramResourceLocation = (PFNGLGETPROGRAMRESOURCELOCATIONPROC) load(userptr, "glGetProgramResourceLocation"); + glad_glGetProgramResourceName = (PFNGLGETPROGRAMRESOURCENAMEPROC) load(userptr, "glGetProgramResourceName"); + glad_glGetProgramResourceiv = (PFNGLGETPROGRAMRESOURCEIVPROC) load(userptr, "glGetProgramResourceiv"); + glad_glGetTexLevelParameterfv = (PFNGLGETTEXLEVELPARAMETERFVPROC) load(userptr, "glGetTexLevelParameterfv"); + glad_glGetTexLevelParameteriv = (PFNGLGETTEXLEVELPARAMETERIVPROC) load(userptr, "glGetTexLevelParameteriv"); + glad_glIsProgramPipeline = (PFNGLISPROGRAMPIPELINEPROC) load(userptr, "glIsProgramPipeline"); + glad_glMemoryBarrier = (PFNGLMEMORYBARRIERPROC) load(userptr, "glMemoryBarrier"); + glad_glMemoryBarrierByRegion = (PFNGLMEMORYBARRIERBYREGIONPROC) load(userptr, "glMemoryBarrierByRegion"); + glad_glProgramUniform1f = (PFNGLPROGRAMUNIFORM1FPROC) load(userptr, "glProgramUniform1f"); + glad_glProgramUniform1fv = (PFNGLPROGRAMUNIFORM1FVPROC) load(userptr, "glProgramUniform1fv"); + glad_glProgramUniform1i = (PFNGLPROGRAMUNIFORM1IPROC) load(userptr, "glProgramUniform1i"); + glad_glProgramUniform1iv = (PFNGLPROGRAMUNIFORM1IVPROC) load(userptr, "glProgramUniform1iv"); + glad_glProgramUniform1ui = (PFNGLPROGRAMUNIFORM1UIPROC) load(userptr, "glProgramUniform1ui"); + glad_glProgramUniform1uiv = (PFNGLPROGRAMUNIFORM1UIVPROC) load(userptr, "glProgramUniform1uiv"); + glad_glProgramUniform2f = (PFNGLPROGRAMUNIFORM2FPROC) load(userptr, "glProgramUniform2f"); + glad_glProgramUniform2fv = (PFNGLPROGRAMUNIFORM2FVPROC) load(userptr, "glProgramUniform2fv"); + glad_glProgramUniform2i = (PFNGLPROGRAMUNIFORM2IPROC) load(userptr, "glProgramUniform2i"); + glad_glProgramUniform2iv = (PFNGLPROGRAMUNIFORM2IVPROC) load(userptr, "glProgramUniform2iv"); + glad_glProgramUniform2ui = (PFNGLPROGRAMUNIFORM2UIPROC) load(userptr, "glProgramUniform2ui"); + glad_glProgramUniform2uiv = (PFNGLPROGRAMUNIFORM2UIVPROC) load(userptr, "glProgramUniform2uiv"); + glad_glProgramUniform3f = (PFNGLPROGRAMUNIFORM3FPROC) load(userptr, "glProgramUniform3f"); + glad_glProgramUniform3fv = (PFNGLPROGRAMUNIFORM3FVPROC) load(userptr, "glProgramUniform3fv"); + glad_glProgramUniform3i = (PFNGLPROGRAMUNIFORM3IPROC) load(userptr, "glProgramUniform3i"); + glad_glProgramUniform3iv = (PFNGLPROGRAMUNIFORM3IVPROC) load(userptr, "glProgramUniform3iv"); + glad_glProgramUniform3ui = (PFNGLPROGRAMUNIFORM3UIPROC) load(userptr, "glProgramUniform3ui"); + glad_glProgramUniform3uiv = (PFNGLPROGRAMUNIFORM3UIVPROC) load(userptr, "glProgramUniform3uiv"); + glad_glProgramUniform4f = (PFNGLPROGRAMUNIFORM4FPROC) load(userptr, "glProgramUniform4f"); + glad_glProgramUniform4fv = (PFNGLPROGRAMUNIFORM4FVPROC) load(userptr, "glProgramUniform4fv"); + glad_glProgramUniform4i = (PFNGLPROGRAMUNIFORM4IPROC) load(userptr, "glProgramUniform4i"); + glad_glProgramUniform4iv = (PFNGLPROGRAMUNIFORM4IVPROC) load(userptr, "glProgramUniform4iv"); + glad_glProgramUniform4ui = (PFNGLPROGRAMUNIFORM4UIPROC) load(userptr, "glProgramUniform4ui"); + glad_glProgramUniform4uiv = (PFNGLPROGRAMUNIFORM4UIVPROC) load(userptr, "glProgramUniform4uiv"); + glad_glProgramUniformMatrix2fv = (PFNGLPROGRAMUNIFORMMATRIX2FVPROC) load(userptr, "glProgramUniformMatrix2fv"); + glad_glProgramUniformMatrix2x3fv = (PFNGLPROGRAMUNIFORMMATRIX2X3FVPROC) load(userptr, "glProgramUniformMatrix2x3fv"); + glad_glProgramUniformMatrix2x4fv = (PFNGLPROGRAMUNIFORMMATRIX2X4FVPROC) load(userptr, "glProgramUniformMatrix2x4fv"); + glad_glProgramUniformMatrix3fv = (PFNGLPROGRAMUNIFORMMATRIX3FVPROC) load(userptr, "glProgramUniformMatrix3fv"); + glad_glProgramUniformMatrix3x2fv = (PFNGLPROGRAMUNIFORMMATRIX3X2FVPROC) load(userptr, "glProgramUniformMatrix3x2fv"); + glad_glProgramUniformMatrix3x4fv = (PFNGLPROGRAMUNIFORMMATRIX3X4FVPROC) load(userptr, "glProgramUniformMatrix3x4fv"); + glad_glProgramUniformMatrix4fv = (PFNGLPROGRAMUNIFORMMATRIX4FVPROC) load(userptr, "glProgramUniformMatrix4fv"); + glad_glProgramUniformMatrix4x2fv = (PFNGLPROGRAMUNIFORMMATRIX4X2FVPROC) load(userptr, "glProgramUniformMatrix4x2fv"); + glad_glProgramUniformMatrix4x3fv = (PFNGLPROGRAMUNIFORMMATRIX4X3FVPROC) load(userptr, "glProgramUniformMatrix4x3fv"); + glad_glSampleMaski = (PFNGLSAMPLEMASKIPROC) load(userptr, "glSampleMaski"); + glad_glTexStorage2DMultisample = (PFNGLTEXSTORAGE2DMULTISAMPLEPROC) load(userptr, "glTexStorage2DMultisample"); + glad_glUseProgramStages = (PFNGLUSEPROGRAMSTAGESPROC) load(userptr, "glUseProgramStages"); + glad_glValidateProgramPipeline = (PFNGLVALIDATEPROGRAMPIPELINEPROC) load(userptr, "glValidateProgramPipeline"); + glad_glVertexAttribBinding = (PFNGLVERTEXATTRIBBINDINGPROC) load(userptr, "glVertexAttribBinding"); + glad_glVertexAttribFormat = (PFNGLVERTEXATTRIBFORMATPROC) load(userptr, "glVertexAttribFormat"); + glad_glVertexAttribIFormat = (PFNGLVERTEXATTRIBIFORMATPROC) load(userptr, "glVertexAttribIFormat"); + glad_glVertexBindingDivisor = (PFNGLVERTEXBINDINGDIVISORPROC) load(userptr, "glVertexBindingDivisor"); +} +static void glad_gl_load_GL_ES_VERSION_3_2( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_ES_VERSION_3_2) return; + glad_glBlendBarrier = (PFNGLBLENDBARRIERPROC) load(userptr, "glBlendBarrier"); + glad_glBlendEquationSeparatei = (PFNGLBLENDEQUATIONSEPARATEIPROC) load(userptr, "glBlendEquationSeparatei"); + glad_glBlendEquationi = (PFNGLBLENDEQUATIONIPROC) load(userptr, "glBlendEquationi"); + glad_glBlendFuncSeparatei = (PFNGLBLENDFUNCSEPARATEIPROC) load(userptr, "glBlendFuncSeparatei"); + glad_glBlendFunci = (PFNGLBLENDFUNCIPROC) load(userptr, "glBlendFunci"); + glad_glColorMaski = (PFNGLCOLORMASKIPROC) load(userptr, "glColorMaski"); + glad_glCopyImageSubData = (PFNGLCOPYIMAGESUBDATAPROC) load(userptr, "glCopyImageSubData"); + glad_glDebugMessageCallback = (PFNGLDEBUGMESSAGECALLBACKPROC) load(userptr, "glDebugMessageCallback"); + glad_glDebugMessageControl = (PFNGLDEBUGMESSAGECONTROLPROC) load(userptr, "glDebugMessageControl"); + glad_glDebugMessageInsert = (PFNGLDEBUGMESSAGEINSERTPROC) load(userptr, "glDebugMessageInsert"); + glad_glDisablei = (PFNGLDISABLEIPROC) load(userptr, "glDisablei"); + glad_glDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC) load(userptr, "glDrawElementsBaseVertex"); + glad_glDrawElementsInstancedBaseVertex = (PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXPROC) load(userptr, "glDrawElementsInstancedBaseVertex"); + glad_glDrawRangeElementsBaseVertex = (PFNGLDRAWRANGEELEMENTSBASEVERTEXPROC) load(userptr, "glDrawRangeElementsBaseVertex"); + glad_glEnablei = (PFNGLENABLEIPROC) load(userptr, "glEnablei"); + glad_glFramebufferTexture = (PFNGLFRAMEBUFFERTEXTUREPROC) load(userptr, "glFramebufferTexture"); + glad_glGetDebugMessageLog = (PFNGLGETDEBUGMESSAGELOGPROC) load(userptr, "glGetDebugMessageLog"); + glad_glGetGraphicsResetStatus = (PFNGLGETGRAPHICSRESETSTATUSPROC) load(userptr, "glGetGraphicsResetStatus"); + glad_glGetObjectLabel = (PFNGLGETOBJECTLABELPROC) load(userptr, "glGetObjectLabel"); + glad_glGetObjectPtrLabel = (PFNGLGETOBJECTPTRLABELPROC) load(userptr, "glGetObjectPtrLabel"); + glad_glGetPointerv = (PFNGLGETPOINTERVPROC) load(userptr, "glGetPointerv"); + glad_glGetSamplerParameterIiv = (PFNGLGETSAMPLERPARAMETERIIVPROC) load(userptr, "glGetSamplerParameterIiv"); + glad_glGetSamplerParameterIuiv = (PFNGLGETSAMPLERPARAMETERIUIVPROC) load(userptr, "glGetSamplerParameterIuiv"); + glad_glGetTexParameterIiv = (PFNGLGETTEXPARAMETERIIVPROC) load(userptr, "glGetTexParameterIiv"); + glad_glGetTexParameterIuiv = (PFNGLGETTEXPARAMETERIUIVPROC) load(userptr, "glGetTexParameterIuiv"); + glad_glGetnUniformfv = (PFNGLGETNUNIFORMFVPROC) load(userptr, "glGetnUniformfv"); + glad_glGetnUniformiv = (PFNGLGETNUNIFORMIVPROC) load(userptr, "glGetnUniformiv"); + glad_glGetnUniformuiv = (PFNGLGETNUNIFORMUIVPROC) load(userptr, "glGetnUniformuiv"); + glad_glIsEnabledi = (PFNGLISENABLEDIPROC) load(userptr, "glIsEnabledi"); + glad_glMinSampleShading = (PFNGLMINSAMPLESHADINGPROC) load(userptr, "glMinSampleShading"); + glad_glObjectLabel = (PFNGLOBJECTLABELPROC) load(userptr, "glObjectLabel"); + glad_glObjectPtrLabel = (PFNGLOBJECTPTRLABELPROC) load(userptr, "glObjectPtrLabel"); + glad_glPatchParameteri = (PFNGLPATCHPARAMETERIPROC) load(userptr, "glPatchParameteri"); + glad_glPopDebugGroup = (PFNGLPOPDEBUGGROUPPROC) load(userptr, "glPopDebugGroup"); + glad_glPrimitiveBoundingBox = (PFNGLPRIMITIVEBOUNDINGBOXPROC) load(userptr, "glPrimitiveBoundingBox"); + glad_glPushDebugGroup = (PFNGLPUSHDEBUGGROUPPROC) load(userptr, "glPushDebugGroup"); + glad_glReadnPixels = (PFNGLREADNPIXELSPROC) load(userptr, "glReadnPixels"); + glad_glSamplerParameterIiv = (PFNGLSAMPLERPARAMETERIIVPROC) load(userptr, "glSamplerParameterIiv"); + glad_glSamplerParameterIuiv = (PFNGLSAMPLERPARAMETERIUIVPROC) load(userptr, "glSamplerParameterIuiv"); + glad_glTexBuffer = (PFNGLTEXBUFFERPROC) load(userptr, "glTexBuffer"); + glad_glTexBufferRange = (PFNGLTEXBUFFERRANGEPROC) load(userptr, "glTexBufferRange"); + glad_glTexParameterIiv = (PFNGLTEXPARAMETERIIVPROC) load(userptr, "glTexParameterIiv"); + glad_glTexParameterIuiv = (PFNGLTEXPARAMETERIUIVPROC) load(userptr, "glTexParameterIuiv"); + glad_glTexStorage3DMultisample = (PFNGLTEXSTORAGE3DMULTISAMPLEPROC) load(userptr, "glTexStorage3DMultisample"); +} +static void glad_gl_load_GL_EXT_geometry_shader( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_EXT_geometry_shader) return; + glad_glFramebufferTextureEXT = (PFNGLFRAMEBUFFERTEXTUREEXTPROC) load(userptr, "glFramebufferTextureEXT"); +} +static void glad_gl_load_GL_OES_EGL_image( GLADuserptrloadfunc load, void* userptr) { + if(!GLAD_GL_OES_EGL_image) return; + glad_glEGLImageTargetRenderbufferStorageOES = (PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) load(userptr, "glEGLImageTargetRenderbufferStorageOES"); + glad_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) load(userptr, "glEGLImageTargetTexture2DOES"); +} + + + +static void glad_gl_free_extensions(char **exts_i) { + if (exts_i != NULL) { + unsigned int index; + for(index = 0; exts_i[index]; index++) { + free((void *) (exts_i[index])); + } + free((void *)exts_i); + exts_i = NULL; + } +} +static int glad_gl_get_extensions( const char **out_exts, char ***out_exts_i) { +#if defined(GL_ES_VERSION_3_0) || defined(GL_VERSION_3_0) + if (glad_glGetStringi != NULL && glad_glGetIntegerv != NULL) { + unsigned int index = 0; + unsigned int num_exts_i = 0; + char **exts_i = NULL; + glad_glGetIntegerv(GL_NUM_EXTENSIONS, (int*) &num_exts_i); + exts_i = (char **) malloc((num_exts_i + 1) * (sizeof *exts_i)); + if (exts_i == NULL) { + return 0; + } + for(index = 0; index < num_exts_i; index++) { + const char *gl_str_tmp = (const char*) glad_glGetStringi(GL_EXTENSIONS, index); + size_t len = strlen(gl_str_tmp) + 1; + + char *local_str = (char*) malloc(len * sizeof(char)); + if(local_str == NULL) { + exts_i[index] = NULL; + glad_gl_free_extensions(exts_i); + return 0; + } + + memcpy(local_str, gl_str_tmp, len * sizeof(char)); + exts_i[index] = local_str; + } + exts_i[index] = NULL; + + *out_exts_i = exts_i; + + return 1; + } +#else + GLAD_UNUSED(out_exts_i); +#endif + if (glad_glGetString == NULL) { + return 0; + } + *out_exts = (const char *)glad_glGetString(GL_EXTENSIONS); + return 1; +} +static int glad_gl_has_extension(const char *exts, char **exts_i, const char *ext) { + if(exts_i) { + unsigned int index; + for(index = 0; exts_i[index]; index++) { + const char *e = exts_i[index]; + if(strcmp(e, ext) == 0) { + return 1; + } + } + } else { + const char *extensions; + const char *loc; + const char *terminator; + extensions = exts; + if(extensions == NULL || ext == NULL) { + return 0; + } + while(1) { + loc = strstr(extensions, ext); + if(loc == NULL) { + return 0; + } + terminator = loc + strlen(ext); + if((loc == extensions || *(loc - 1) == ' ') && + (*terminator == ' ' || *terminator == '\0')) { + return 1; + } + extensions = terminator; + } + } + return 0; +} + +static GLADapiproc glad_gl_get_proc_from_userptr(void *userptr, const char* name) { + return (GLAD_GNUC_EXTENSION (GLADapiproc (*)(const char *name)) userptr)(name); +} + +static int glad_gl_find_extensions_gles2(void) { + const char *exts = NULL; + char **exts_i = NULL; + if (!glad_gl_get_extensions(&exts, &exts_i)) return 0; + + GLAD_GL_EXT_geometry_shader = glad_gl_has_extension(exts, exts_i, "GL_EXT_geometry_shader"); + GLAD_GL_EXT_texture_compression_dxt1 = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_compression_dxt1"); + GLAD_GL_EXT_texture_filter_anisotropic = glad_gl_has_extension(exts, exts_i, "GL_EXT_texture_filter_anisotropic"); + GLAD_GL_OES_EGL_image = glad_gl_has_extension(exts, exts_i, "GL_OES_EGL_image"); + GLAD_GL_OES_EGL_image_external = glad_gl_has_extension(exts, exts_i, "GL_OES_EGL_image_external"); + GLAD_GL_OES_EGL_image_external_essl3 = glad_gl_has_extension(exts, exts_i, "GL_OES_EGL_image_external_essl3"); + GLAD_GL_OES_texture_compression_astc = glad_gl_has_extension(exts, exts_i, "GL_OES_texture_compression_astc"); + + glad_gl_free_extensions(exts_i); + + return 1; +} + +static int glad_gl_find_core_gles2(void) { + int i; + const char* version; + const char* prefixes[] = { + "OpenGL ES-CM ", + "OpenGL ES-CL ", + "OpenGL ES ", + "OpenGL SC ", + NULL + }; + int major = 0; + int minor = 0; + version = (const char*) glad_glGetString(GL_VERSION); + if (!version) return 0; + for (i = 0; prefixes[i]; i++) { + const size_t length = strlen(prefixes[i]); + if (strncmp(version, prefixes[i], length) == 0) { + version += length; + break; + } + } + + GLAD_IMPL_UTIL_SSCANF(version, "%d.%d", &major, &minor); + + GLAD_GL_ES_VERSION_2_0 = (major == 2 && minor >= 0) || major > 2; + GLAD_GL_ES_VERSION_3_0 = (major == 3 && minor >= 0) || major > 3; + GLAD_GL_ES_VERSION_3_1 = (major == 3 && minor >= 1) || major > 3; + GLAD_GL_ES_VERSION_3_2 = (major == 3 && minor >= 2) || major > 3; + + return GLAD_MAKE_VERSION(major, minor); +} + +int gladLoadGLES2UserPtr( GLADuserptrloadfunc load, void *userptr) { + int version; + + glad_glGetString = (PFNGLGETSTRINGPROC) load(userptr, "glGetString"); + if(glad_glGetString == NULL) return 0; + version = glad_gl_find_core_gles2(); + + glad_gl_load_GL_ES_VERSION_2_0(load, userptr); + glad_gl_load_GL_ES_VERSION_3_0(load, userptr); + glad_gl_load_GL_ES_VERSION_3_1(load, userptr); + glad_gl_load_GL_ES_VERSION_3_2(load, userptr); + + if (!glad_gl_find_extensions_gles2()) return 0; + glad_gl_load_GL_EXT_geometry_shader(load, userptr); + glad_gl_load_GL_OES_EGL_image(load, userptr); + + + + return version; +} + + +int gladLoadGLES2( GLADloadfunc load) { + return gladLoadGLES2UserPtr( glad_gl_get_proc_from_userptr, GLAD_GNUC_EXTENSION (void*) load); +} + + + + + + +#ifdef __cplusplus +} +#endif diff --git a/external/glslang b/external/glslang index bcf6a2430..ee2f5d09e 160000 --- a/external/glslang +++ b/external/glslang @@ -1 +1 @@ -Subproject commit bcf6a2430e99e8fc24f9f266e99316905e6d5134 +Subproject commit ee2f5d09eaf8f4e8d0d598bd2172fce290d4ca60 diff --git a/external/glslang-os-dep/GenericSingleThreaded/ossource.cpp b/external/glslang-os-dep/GenericSingleThreaded/ossource.cpp deleted file mode 100644 index f1ab3b409..000000000 --- a/external/glslang-os-dep/GenericSingleThreaded/ossource.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (C) 2018 BMW Car IT GmbH -// ------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// ------------------------------------------------------------------------- - -#include "OSDependent/osinclude.h" -#include "assert.h" -#include "stdio.h" - -// arbitrary number of slots. should always be enough for anyone -#define MAX_TLS_SLOTS ((size_t)10) -static bool tls_slots_in_use[MAX_TLS_SLOTS] = {false}; -static void* tls_slots_values[MAX_TLS_SLOTS] = {0}; - -namespace glslang { - -void OS_CleanupThreadData(void) -{ -} - -OS_TLSIndex OS_AllocTLSIndex() -{ - for (size_t idx = 0; idx < MAX_TLS_SLOTS; ++idx) - if (!tls_slots_in_use[idx]) { - tls_slots_in_use[idx] = true; - return (void*)(idx + 1); - } - return OS_INVALID_TLS_INDEX; -} - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - size_t idx = (size_t)nIndex; - if (nIndex == OS_INVALID_TLS_INDEX || - idx >= MAX_TLS_SLOTS || - !tls_slots_in_use[idx-1]) - return false; - tls_slots_values[idx-1] = lpvValue; - return true; -} - -void* OS_GetTLSValue(OS_TLSIndex nIndex) -{ - size_t idx = (size_t)nIndex; - if (nIndex == OS_INVALID_TLS_INDEX || - idx >= MAX_TLS_SLOTS || - !tls_slots_in_use[idx-1]) - return 0; - return tls_slots_values[idx-1]; -} - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - size_t idx = (size_t)nIndex; - if (nIndex == OS_INVALID_TLS_INDEX || - idx >= MAX_TLS_SLOTS || - !tls_slots_in_use[idx-1]) - return 0; - tls_slots_in_use[idx-1] = false; - return true; -} - -void InitGlobalLock() -{ -} - -void GetGlobalLock() -{ -} - -void ReleaseGlobalLock() -{ -} - -void* OS_CreateThread(TThreadEntrypoint /*entry*/) -{ - return 0; -} - -void OS_WaitForAllThreads(void* /*threads*/, int /*numThreads*/) -{ -} - -void OS_Sleep(int /*milliseconds*/) -{ -} - -void OS_DumpMemoryCounters() -{ -} - -} // end namespace glslang - diff --git a/external/khronos/GLES2/gl2.h b/external/khronos/GLES2/gl2.h deleted file mode 100644 index 8c5ae900e..000000000 --- a/external/khronos/GLES2/gl2.h +++ /dev/null @@ -1,525 +0,0 @@ -#ifndef __gl2_h_ -#define __gl2_h_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2013-2014 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -/* -** This header is generated from the Khronos OpenGL / OpenGL ES XML -** API Registry. The current version of the Registry, generator scripts -** used to make the header, and the header can be found at -** http://www.opengl.org/registry/ -** -** Khronos $Revision$ on $Date$ -*/ - -#include - -/* Generated on date 20141204 */ - -/* Generated C header for: - * API: gles2 - * Profile: common - * Versions considered: 2\.[0-9] - * Versions emitted: .* - * Default extensions included: None - * Additional extensions included: _nomatch_^ - * Extensions removed: _nomatch_^ - */ - -#ifndef GL_ES_VERSION_2_0 -#define GL_ES_VERSION_2_0 1 -#include -typedef khronos_int8_t GLbyte; -typedef khronos_float_t GLclampf; -typedef khronos_int32_t GLfixed; -typedef short GLshort; -typedef unsigned short GLushort; -typedef void GLvoid; -typedef struct __GLsync *GLsync; -typedef khronos_int64_t GLint64; -typedef khronos_uint64_t GLuint64; -typedef unsigned int GLenum; -typedef unsigned int GLuint; -typedef char GLchar; -typedef khronos_float_t GLfloat; -typedef khronos_ssize_t GLsizeiptr; -typedef khronos_intptr_t GLintptr; -typedef unsigned int GLbitfield; -typedef int GLint; -typedef unsigned char GLboolean; -typedef int GLsizei; -typedef khronos_uint8_t GLubyte; -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_FALSE 0 -#define GL_TRUE 1 -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 -#define GL_ZERO 0 -#define GL_ONE 1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_FUNC_ADD 0x8006 -#define GL_BLEND_EQUATION 0x8009 -#define GL_BLEND_EQUATION_RGB 0x8009 -#define GL_BLEND_EQUATION_ALPHA 0x883D -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 -#define GL_STREAM_DRAW 0x88E0 -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_CULL_FACE 0x0B44 -#define GL_BLEND 0x0BE2 -#define GL_DITHER 0x0BD0 -#define GL_STENCIL_TEST 0x0B90 -#define GL_DEPTH_TEST 0x0B71 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_COVERAGE 0x80A0 -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_OUT_OF_MEMORY 0x0505 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_LINE_WIDTH 0x0B21 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_STENCIL_CLEAR_VALUE 0x0B91 -#define GL_STENCIL_FUNC 0x0B92 -#define GL_STENCIL_FAIL 0x0B94 -#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 -#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 -#define GL_STENCIL_REF 0x0B97 -#define GL_STENCIL_VALUE_MASK 0x0B93 -#define GL_STENCIL_WRITEMASK 0x0B98 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 -#define GL_VIEWPORT 0x0BA2 -#define GL_SCISSOR_BOX 0x0C10 -#define GL_COLOR_CLEAR_VALUE 0x0C22 -#define GL_COLOR_WRITEMASK 0x0C23 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 -#define GL_GENERATE_MIPMAP_HINT 0x8192 -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB -#define GL_MAX_VARYING_VECTORS 0x8DFC -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD -#define GL_SHADER_TYPE 0x8B4F -#define GL_DELETE_STATUS 0x8B80 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_INVERT 0x150A -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_TEXTURE 0x1702 -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_CUBE 0x8B60 -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F -#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B -#define GL_COMPILE_STATUS 0x8B81 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_SHADER_COMPILER 0x8DFA -#define GL_SHADER_BINARY_FORMATS 0x8DF8 -#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 -#define GL_LOW_FLOAT 0x8DF0 -#define GL_MEDIUM_FLOAT 0x8DF1 -#define GL_HIGH_FLOAT 0x8DF2 -#define GL_LOW_INT 0x8DF3 -#define GL_MEDIUM_INT 0x8DF4 -#define GL_HIGH_INT 0x8DF5 -#define GL_FRAMEBUFFER 0x8D40 -#define GL_RENDERBUFFER 0x8D41 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGB565 0x8D62 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_STENCIL_INDEX8 0x8D48 -#define GL_RENDERBUFFER_WIDTH 0x8D42 -#define GL_RENDERBUFFER_HEIGHT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 -#define GL_RENDERBUFFER_RED_SIZE 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 -#define GL_NONE 0 -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#define GL_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_RENDERBUFFER_BINDING 0x8CA7 -#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 -#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 -GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); -GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); -GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); -GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); -GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); -GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); -GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); -GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); -GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); -GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); -GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); -GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); -GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d); -GL_APICALL void GL_APIENTRY glClearStencil (GLint s); -GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); -GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); -GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); -GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); -GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); -GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); -GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); -GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); -GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); -GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); -GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); -GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); -GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); -GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glDisable (GLenum cap); -GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); -GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); -GL_APICALL void GL_APIENTRY glEnable (GLenum cap); -GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glFinish (void); -GL_APICALL void GL_APIENTRY glFlush (void); -GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); -GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); -GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); -GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); -GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); -GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); -GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); -GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); -GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL GLenum GL_APIENTRY glGetError (void); -GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); -GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); -GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); -GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); -GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name); -GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); -GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); -GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); -GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); -GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); -GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); -GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); -GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); -GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); -GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); -GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); -GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); -GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); -GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); -GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); -GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); -GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); -GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); -GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); -GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); -GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); -GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0); -GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0); -GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); -GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); -GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); -GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); -GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); -GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); -GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); -GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); -#endif /* GL_ES_VERSION_2_0 */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/external/khronos/GLES2/gl2ext.h b/external/khronos/GLES2/gl2ext.h deleted file mode 100644 index 7bf38d66e..000000000 --- a/external/khronos/GLES2/gl2ext.h +++ /dev/null @@ -1,2448 +0,0 @@ -#ifndef __gl2ext_h_ -#define __gl2ext_h_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2013-2014 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -/* -** This header is generated from the Khronos OpenGL / OpenGL ES XML -** API Registry. The current version of the Registry, generator scripts -** used to make the header, and the header can be found at -** http://www.opengl.org/registry/ -** -** Khronos $Revision$ on $Date$ -*/ - -#ifndef GL_APIENTRYP -#define GL_APIENTRYP GL_APIENTRY* -#endif - -/* Generated on date 20141204 */ - -/* Generated C header for: - * API: gles2 - * Profile: common - * Versions considered: 2\.[0-9] - * Versions emitted: _nomatch_^ - * Default extensions included: gles2 - * Additional extensions included: _nomatch_^ - * Extensions removed: _nomatch_^ - */ - -#ifndef GL_KHR_blend_equation_advanced -#define GL_KHR_blend_equation_advanced 1 -#define GL_MULTIPLY_KHR 0x9294 -#define GL_SCREEN_KHR 0x9295 -#define GL_OVERLAY_KHR 0x9296 -#define GL_DARKEN_KHR 0x9297 -#define GL_LIGHTEN_KHR 0x9298 -#define GL_COLORDODGE_KHR 0x9299 -#define GL_COLORBURN_KHR 0x929A -#define GL_HARDLIGHT_KHR 0x929B -#define GL_SOFTLIGHT_KHR 0x929C -#define GL_DIFFERENCE_KHR 0x929E -#define GL_EXCLUSION_KHR 0x92A0 -#define GL_HSL_HUE_KHR 0x92AD -#define GL_HSL_SATURATION_KHR 0x92AE -#define GL_HSL_COLOR_KHR 0x92AF -#define GL_HSL_LUMINOSITY_KHR 0x92B0 -typedef void (GL_APIENTRYP PFNGLBLENDBARRIERKHRPROC) (void); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBlendBarrierKHR (void); -#endif -#endif /* GL_KHR_blend_equation_advanced */ - -#ifndef GL_KHR_blend_equation_advanced_coherent -#define GL_KHR_blend_equation_advanced_coherent 1 -#define GL_BLEND_ADVANCED_COHERENT_KHR 0x9285 -#endif /* GL_KHR_blend_equation_advanced_coherent */ - -#ifndef GL_KHR_context_flush_control -#define GL_KHR_context_flush_control 1 -#define GL_CONTEXT_RELEASE_BEHAVIOR_KHR 0x82FB -#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR 0x82FC -#endif /* GL_KHR_context_flush_control */ - -#ifndef GL_KHR_debug -#define GL_KHR_debug 1 -typedef void (GL_APIENTRY *GLDEBUGPROCKHR)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam); -#define GL_SAMPLER 0x82E6 -#define GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR 0x8242 -#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR 0x8243 -#define GL_DEBUG_CALLBACK_FUNCTION_KHR 0x8244 -#define GL_DEBUG_CALLBACK_USER_PARAM_KHR 0x8245 -#define GL_DEBUG_SOURCE_API_KHR 0x8246 -#define GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR 0x8247 -#define GL_DEBUG_SOURCE_SHADER_COMPILER_KHR 0x8248 -#define GL_DEBUG_SOURCE_THIRD_PARTY_KHR 0x8249 -#define GL_DEBUG_SOURCE_APPLICATION_KHR 0x824A -#define GL_DEBUG_SOURCE_OTHER_KHR 0x824B -#define GL_DEBUG_TYPE_ERROR_KHR 0x824C -#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR 0x824D -#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR 0x824E -#define GL_DEBUG_TYPE_PORTABILITY_KHR 0x824F -#define GL_DEBUG_TYPE_PERFORMANCE_KHR 0x8250 -#define GL_DEBUG_TYPE_OTHER_KHR 0x8251 -#define GL_DEBUG_TYPE_MARKER_KHR 0x8268 -#define GL_DEBUG_TYPE_PUSH_GROUP_KHR 0x8269 -#define GL_DEBUG_TYPE_POP_GROUP_KHR 0x826A -#define GL_DEBUG_SEVERITY_NOTIFICATION_KHR 0x826B -#define GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR 0x826C -#define GL_DEBUG_GROUP_STACK_DEPTH_KHR 0x826D -#define GL_BUFFER_KHR 0x82E0 -#define GL_SHADER_KHR 0x82E1 -#define GL_PROGRAM_KHR 0x82E2 -#define GL_VERTEX_ARRAY_KHR 0x8074 -#define GL_QUERY_KHR 0x82E3 -#define GL_SAMPLER_KHR 0x82E6 -#define GL_MAX_LABEL_LENGTH_KHR 0x82E8 -#define GL_MAX_DEBUG_MESSAGE_LENGTH_KHR 0x9143 -#define GL_MAX_DEBUG_LOGGED_MESSAGES_KHR 0x9144 -#define GL_DEBUG_LOGGED_MESSAGES_KHR 0x9145 -#define GL_DEBUG_SEVERITY_HIGH_KHR 0x9146 -#define GL_DEBUG_SEVERITY_MEDIUM_KHR 0x9147 -#define GL_DEBUG_SEVERITY_LOW_KHR 0x9148 -#define GL_DEBUG_OUTPUT_KHR 0x92E0 -#define GL_CONTEXT_FLAG_DEBUG_BIT_KHR 0x00000002 -#define GL_STACK_OVERFLOW_KHR 0x0503 -#define GL_STACK_UNDERFLOW_KHR 0x0504 -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLKHRPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTKHRPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKKHRPROC) (GLDEBUGPROCKHR callback, const void *userParam); -typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGKHRPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPKHRPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); -typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPKHRPROC) (void); -typedef void (GL_APIENTRYP PFNGLOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELKHRPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); -typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELKHRPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETPOINTERVKHRPROC) (GLenum pname, void **params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDebugMessageControlKHR (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); -GL_APICALL void GL_APIENTRY glDebugMessageInsertKHR (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); -GL_APICALL void GL_APIENTRY glDebugMessageCallbackKHR (GLDEBUGPROCKHR callback, const void *userParam); -GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLogKHR (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); -GL_APICALL void GL_APIENTRY glPushDebugGroupKHR (GLenum source, GLuint id, GLsizei length, const GLchar *message); -GL_APICALL void GL_APIENTRY glPopDebugGroupKHR (void); -GL_APICALL void GL_APIENTRY glObjectLabelKHR (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectLabelKHR (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); -GL_APICALL void GL_APIENTRY glObjectPtrLabelKHR (const void *ptr, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectPtrLabelKHR (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); -GL_APICALL void GL_APIENTRY glGetPointervKHR (GLenum pname, void **params); -#endif -#endif /* GL_KHR_debug */ - -#ifndef GL_KHR_robust_buffer_access_behavior -#define GL_KHR_robust_buffer_access_behavior 1 -#endif /* GL_KHR_robust_buffer_access_behavior */ - -#ifndef GL_KHR_robustness -#define GL_KHR_robustness 1 -#define GL_CONTEXT_ROBUST_ACCESS_KHR 0x90F3 -#define GL_LOSE_CONTEXT_ON_RESET_KHR 0x8252 -#define GL_GUILTY_CONTEXT_RESET_KHR 0x8253 -#define GL_INNOCENT_CONTEXT_RESET_KHR 0x8254 -#define GL_UNKNOWN_CONTEXT_RESET_KHR 0x8255 -#define GL_RESET_NOTIFICATION_STRATEGY_KHR 0x8256 -#define GL_NO_RESET_NOTIFICATION_KHR 0x8261 -#define GL_CONTEXT_LOST_KHR 0x0507 -typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC) (void); -typedef void (GL_APIENTRYP PFNGLREADNPIXELSKHRPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMUIVKHRPROC) (GLuint program, GLint location, GLsizei bufSize, GLuint *params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusKHR (void); -GL_APICALL void GL_APIENTRY glReadnPixelsKHR (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -GL_APICALL void GL_APIENTRY glGetnUniformfvKHR (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetnUniformivKHR (GLuint program, GLint location, GLsizei bufSize, GLint *params); -GL_APICALL void GL_APIENTRY glGetnUniformuivKHR (GLuint program, GLint location, GLsizei bufSize, GLuint *params); -#endif -#endif /* GL_KHR_robustness */ - -#ifndef GL_KHR_texture_compression_astc_hdr -#define GL_KHR_texture_compression_astc_hdr 1 -#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 -#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 -#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 -#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 -#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 -#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 -#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 -#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 -#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 -#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 -#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA -#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB -#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC -#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD -#endif /* GL_KHR_texture_compression_astc_hdr */ - -#ifndef GL_KHR_texture_compression_astc_ldr -#define GL_KHR_texture_compression_astc_ldr 1 -#endif /* GL_KHR_texture_compression_astc_ldr */ - -#ifndef GL_OES_EGL_image -#define GL_OES_EGL_image 1 -typedef void *GLeglImageOES; -typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES image); -typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenum target, GLeglImageOES image); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glEGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image); -GL_APICALL void GL_APIENTRY glEGLImageTargetRenderbufferStorageOES (GLenum target, GLeglImageOES image); -#endif -#endif /* GL_OES_EGL_image */ - -#ifndef GL_OES_EGL_image_external -#define GL_OES_EGL_image_external 1 -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#define GL_TEXTURE_BINDING_EXTERNAL_OES 0x8D67 -#define GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES 0x8D68 -#define GL_SAMPLER_EXTERNAL_OES 0x8D66 -#endif /* GL_OES_EGL_image_external */ - -#ifndef GL_OES_compressed_ETC1_RGB8_sub_texture -#define GL_OES_compressed_ETC1_RGB8_sub_texture 1 -#endif /* GL_OES_compressed_ETC1_RGB8_sub_texture */ - -#ifndef GL_OES_compressed_ETC1_RGB8_texture -#define GL_OES_compressed_ETC1_RGB8_texture 1 -#define GL_ETC1_RGB8_OES 0x8D64 -#endif /* GL_OES_compressed_ETC1_RGB8_texture */ - -#ifndef GL_OES_compressed_paletted_texture -#define GL_OES_compressed_paletted_texture 1 -#define GL_PALETTE4_RGB8_OES 0x8B90 -#define GL_PALETTE4_RGBA8_OES 0x8B91 -#define GL_PALETTE4_R5_G6_B5_OES 0x8B92 -#define GL_PALETTE4_RGBA4_OES 0x8B93 -#define GL_PALETTE4_RGB5_A1_OES 0x8B94 -#define GL_PALETTE8_RGB8_OES 0x8B95 -#define GL_PALETTE8_RGBA8_OES 0x8B96 -#define GL_PALETTE8_R5_G6_B5_OES 0x8B97 -#define GL_PALETTE8_RGBA4_OES 0x8B98 -#define GL_PALETTE8_RGB5_A1_OES 0x8B99 -#endif /* GL_OES_compressed_paletted_texture */ - -#ifndef GL_OES_depth24 -#define GL_OES_depth24 1 -#define GL_DEPTH_COMPONENT24_OES 0x81A6 -#endif /* GL_OES_depth24 */ - -#ifndef GL_OES_depth32 -#define GL_OES_depth32 1 -#define GL_DEPTH_COMPONENT32_OES 0x81A7 -#endif /* GL_OES_depth32 */ - -#ifndef GL_OES_depth_texture -#define GL_OES_depth_texture 1 -#endif /* GL_OES_depth_texture */ - -#ifndef GL_OES_element_index_uint -#define GL_OES_element_index_uint 1 -#endif /* GL_OES_element_index_uint */ - -#ifndef GL_OES_fbo_render_mipmap -#define GL_OES_fbo_render_mipmap 1 -#endif /* GL_OES_fbo_render_mipmap */ - -#ifndef GL_OES_fragment_precision_high -#define GL_OES_fragment_precision_high 1 -#endif /* GL_OES_fragment_precision_high */ - -#ifndef GL_OES_get_program_binary -#define GL_OES_get_program_binary 1 -#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE -#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF -typedef void (GL_APIENTRYP PFNGLGETPROGRAMBINARYOESPROC) (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); -typedef void (GL_APIENTRYP PFNGLPROGRAMBINARYOESPROC) (GLuint program, GLenum binaryFormat, const void *binary, GLint length); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetProgramBinaryOES (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); -GL_APICALL void GL_APIENTRY glProgramBinaryOES (GLuint program, GLenum binaryFormat, const void *binary, GLint length); -#endif -#endif /* GL_OES_get_program_binary */ - -#ifndef GL_OES_mapbuffer -#define GL_OES_mapbuffer 1 -#define GL_WRITE_ONLY_OES 0x88B9 -#define GL_BUFFER_ACCESS_OES 0x88BB -#define GL_BUFFER_MAPPED_OES 0x88BC -#define GL_BUFFER_MAP_POINTER_OES 0x88BD -typedef void *(GL_APIENTRYP PFNGLMAPBUFFEROESPROC) (GLenum target, GLenum access); -typedef GLboolean (GL_APIENTRYP PFNGLUNMAPBUFFEROESPROC) (GLenum target); -typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum pname, void **params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void *GL_APIENTRY glMapBufferOES (GLenum target, GLenum access); -GL_APICALL GLboolean GL_APIENTRY glUnmapBufferOES (GLenum target); -GL_APICALL void GL_APIENTRY glGetBufferPointervOES (GLenum target, GLenum pname, void **params); -#endif -#endif /* GL_OES_mapbuffer */ - -#ifndef GL_OES_packed_depth_stencil -#define GL_OES_packed_depth_stencil 1 -#define GL_DEPTH_STENCIL_OES 0x84F9 -#define GL_UNSIGNED_INT_24_8_OES 0x84FA -#define GL_DEPTH24_STENCIL8_OES 0x88F0 -#endif /* GL_OES_packed_depth_stencil */ - -#ifndef GL_OES_required_internalformat -#define GL_OES_required_internalformat 1 -#define GL_ALPHA8_OES 0x803C -#define GL_DEPTH_COMPONENT16_OES 0x81A5 -#define GL_LUMINANCE4_ALPHA4_OES 0x8043 -#define GL_LUMINANCE8_ALPHA8_OES 0x8045 -#define GL_LUMINANCE8_OES 0x8040 -#define GL_RGBA4_OES 0x8056 -#define GL_RGB5_A1_OES 0x8057 -#define GL_RGB565_OES 0x8D62 -#define GL_RGB8_OES 0x8051 -#define GL_RGBA8_OES 0x8058 -#define GL_RGB10_EXT 0x8052 -#define GL_RGB10_A2_EXT 0x8059 -#endif /* GL_OES_required_internalformat */ - -#ifndef GL_OES_rgb8_rgba8 -#define GL_OES_rgb8_rgba8 1 -#endif /* GL_OES_rgb8_rgba8 */ - -#ifndef GL_OES_sample_shading -#define GL_OES_sample_shading 1 -#define GL_SAMPLE_SHADING_OES 0x8C36 -#define GL_MIN_SAMPLE_SHADING_VALUE_OES 0x8C37 -typedef void (GL_APIENTRYP PFNGLMINSAMPLESHADINGOESPROC) (GLfloat value); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glMinSampleShadingOES (GLfloat value); -#endif -#endif /* GL_OES_sample_shading */ - -#ifndef GL_OES_sample_variables -#define GL_OES_sample_variables 1 -#endif /* GL_OES_sample_variables */ - -#ifndef GL_OES_shader_image_atomic -#define GL_OES_shader_image_atomic 1 -#endif /* GL_OES_shader_image_atomic */ - -#ifndef GL_OES_shader_multisample_interpolation -#define GL_OES_shader_multisample_interpolation 1 -#define GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5B -#define GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES 0x8E5C -#define GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES 0x8E5D -#endif /* GL_OES_shader_multisample_interpolation */ - -#ifndef GL_OES_standard_derivatives -#define GL_OES_standard_derivatives 1 -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES 0x8B8B -#endif /* GL_OES_standard_derivatives */ - -#ifndef GL_OES_stencil1 -#define GL_OES_stencil1 1 -#define GL_STENCIL_INDEX1_OES 0x8D46 -#endif /* GL_OES_stencil1 */ - -#ifndef GL_OES_stencil4 -#define GL_OES_stencil4 1 -#define GL_STENCIL_INDEX4_OES 0x8D47 -#endif /* GL_OES_stencil4 */ - -#ifndef GL_OES_surfaceless_context -#define GL_OES_surfaceless_context 1 -#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219 -#endif /* GL_OES_surfaceless_context */ - -#ifndef GL_OES_texture_3D -#define GL_OES_texture_3D 1 -#define GL_TEXTURE_WRAP_R_OES 0x8072 -#define GL_TEXTURE_3D_OES 0x806F -#define GL_TEXTURE_BINDING_3D_OES 0x806A -#define GL_MAX_3D_TEXTURE_SIZE_OES 0x8073 -#define GL_SAMPLER_3D_OES 0x8B5F -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4 -typedef void (GL_APIENTRYP PFNGLTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); -typedef void (GL_APIENTRYP PFNGLTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); -typedef void (GL_APIENTRYP PFNGLCOPYTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXIMAGE3DOESPROC) (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); -typedef void (GL_APIENTRYP PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE3DOESPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glCopyTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glCompressedTexImage3DOES (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage3DOES (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glFramebufferTexture3DOES (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLint zoffset); -#endif -#endif /* GL_OES_texture_3D */ - -#ifndef GL_OES_texture_compression_astc -#define GL_OES_texture_compression_astc 1 -#define GL_COMPRESSED_RGBA_ASTC_3x3x3_OES 0x93C0 -#define GL_COMPRESSED_RGBA_ASTC_4x3x3_OES 0x93C1 -#define GL_COMPRESSED_RGBA_ASTC_4x4x3_OES 0x93C2 -#define GL_COMPRESSED_RGBA_ASTC_4x4x4_OES 0x93C3 -#define GL_COMPRESSED_RGBA_ASTC_5x4x4_OES 0x93C4 -#define GL_COMPRESSED_RGBA_ASTC_5x5x4_OES 0x93C5 -#define GL_COMPRESSED_RGBA_ASTC_5x5x5_OES 0x93C6 -#define GL_COMPRESSED_RGBA_ASTC_6x5x5_OES 0x93C7 -#define GL_COMPRESSED_RGBA_ASTC_6x6x5_OES 0x93C8 -#define GL_COMPRESSED_RGBA_ASTC_6x6x6_OES 0x93C9 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES 0x93E0 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES 0x93E1 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES 0x93E2 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES 0x93E3 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES 0x93E4 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES 0x93E5 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES 0x93E6 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES 0x93E7 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES 0x93E8 -#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES 0x93E9 -#endif /* GL_OES_texture_compression_astc */ - -#ifndef GL_OES_texture_float -#define GL_OES_texture_float 1 -#endif /* GL_OES_texture_float */ - -#ifndef GL_OES_texture_float_linear -#define GL_OES_texture_float_linear 1 -#endif /* GL_OES_texture_float_linear */ - -#ifndef GL_OES_texture_half_float -#define GL_OES_texture_half_float 1 -#define GL_HALF_FLOAT_OES 0x8D61 -#endif /* GL_OES_texture_half_float */ - -#ifndef GL_OES_texture_half_float_linear -#define GL_OES_texture_half_float_linear 1 -#endif /* GL_OES_texture_half_float_linear */ - -#ifndef GL_OES_texture_npot -#define GL_OES_texture_npot 1 -#endif /* GL_OES_texture_npot */ - -#ifndef GL_OES_texture_stencil8 -#define GL_OES_texture_stencil8 1 -#define GL_STENCIL_INDEX_OES 0x1901 -#define GL_STENCIL_INDEX8_OES 0x8D48 -#endif /* GL_OES_texture_stencil8 */ - -#ifndef GL_OES_texture_storage_multisample_2d_array -#define GL_OES_texture_storage_multisample_2d_array 1 -#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES 0x9102 -#define GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES 0x9105 -#define GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910B -#define GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910C -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES 0x910D -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DMULTISAMPLEOESPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexStorage3DMultisampleOES (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations); -#endif -#endif /* GL_OES_texture_storage_multisample_2d_array */ - -#ifndef GL_OES_vertex_array_object -#define GL_OES_vertex_array_object 1 -#define GL_VERTEX_ARRAY_BINDING_OES 0x85B5 -typedef void (GL_APIENTRYP PFNGLBINDVERTEXARRAYOESPROC) (GLuint array); -typedef void (GL_APIENTRYP PFNGLDELETEVERTEXARRAYSOESPROC) (GLsizei n, const GLuint *arrays); -typedef void (GL_APIENTRYP PFNGLGENVERTEXARRAYSOESPROC) (GLsizei n, GLuint *arrays); -typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBindVertexArrayOES (GLuint array); -GL_APICALL void GL_APIENTRY glDeleteVertexArraysOES (GLsizei n, const GLuint *arrays); -GL_APICALL void GL_APIENTRY glGenVertexArraysOES (GLsizei n, GLuint *arrays); -GL_APICALL GLboolean GL_APIENTRY glIsVertexArrayOES (GLuint array); -#endif -#endif /* GL_OES_vertex_array_object */ - -#ifndef GL_OES_vertex_half_float -#define GL_OES_vertex_half_float 1 -#endif /* GL_OES_vertex_half_float */ - -#ifndef GL_OES_vertex_type_10_10_10_2 -#define GL_OES_vertex_type_10_10_10_2 1 -#define GL_UNSIGNED_INT_10_10_10_2_OES 0x8DF6 -#define GL_INT_10_10_10_2_OES 0x8DF7 -#endif /* GL_OES_vertex_type_10_10_10_2 */ - -#ifndef GL_AMD_compressed_3DC_texture -#define GL_AMD_compressed_3DC_texture 1 -#define GL_3DC_X_AMD 0x87F9 -#define GL_3DC_XY_AMD 0x87FA -#endif /* GL_AMD_compressed_3DC_texture */ - -#ifndef GL_AMD_compressed_ATC_texture -#define GL_AMD_compressed_ATC_texture 1 -#define GL_ATC_RGB_AMD 0x8C92 -#define GL_ATC_RGBA_EXPLICIT_ALPHA_AMD 0x8C93 -#define GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD 0x87EE -#endif /* GL_AMD_compressed_ATC_texture */ - -#ifndef GL_AMD_performance_monitor -#define GL_AMD_performance_monitor 1 -#define GL_COUNTER_TYPE_AMD 0x8BC0 -#define GL_COUNTER_RANGE_AMD 0x8BC1 -#define GL_UNSIGNED_INT64_AMD 0x8BC2 -#define GL_PERCENTAGE_AMD 0x8BC3 -#define GL_PERFMON_RESULT_AVAILABLE_AMD 0x8BC4 -#define GL_PERFMON_RESULT_SIZE_AMD 0x8BC5 -#define GL_PERFMON_RESULT_AMD 0x8BC6 -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSAMDPROC) (GLint *numGroups, GLsizei groupsSize, GLuint *groups); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSAMDPROC) (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORGROUPSTRINGAMDPROC) (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERSTRINGAMDPROC) (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERINFOAMDPROC) (GLuint group, GLuint counter, GLenum pname, void *data); -typedef void (GL_APIENTRYP PFNGLGENPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (GL_APIENTRYP PFNGLDELETEPERFMONITORSAMDPROC) (GLsizei n, GLuint *monitors); -typedef void (GL_APIENTRYP PFNGLSELECTPERFMONITORCOUNTERSAMDPROC) (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); -typedef void (GL_APIENTRYP PFNGLBEGINPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GL_APIENTRYP PFNGLENDPERFMONITORAMDPROC) (GLuint monitor); -typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupsAMD (GLint *numGroups, GLsizei groupsSize, GLuint *groups); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCountersAMD (GLuint group, GLint *numCounters, GLint *maxActiveCounters, GLsizei counterSize, GLuint *counters); -GL_APICALL void GL_APIENTRY glGetPerfMonitorGroupStringAMD (GLuint group, GLsizei bufSize, GLsizei *length, GLchar *groupString); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterStringAMD (GLuint group, GLuint counter, GLsizei bufSize, GLsizei *length, GLchar *counterString); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterInfoAMD (GLuint group, GLuint counter, GLenum pname, void *data); -GL_APICALL void GL_APIENTRY glGenPerfMonitorsAMD (GLsizei n, GLuint *monitors); -GL_APICALL void GL_APIENTRY glDeletePerfMonitorsAMD (GLsizei n, GLuint *monitors); -GL_APICALL void GL_APIENTRY glSelectPerfMonitorCountersAMD (GLuint monitor, GLboolean enable, GLuint group, GLint numCounters, GLuint *counterList); -GL_APICALL void GL_APIENTRY glBeginPerfMonitorAMD (GLuint monitor); -GL_APICALL void GL_APIENTRY glEndPerfMonitorAMD (GLuint monitor); -GL_APICALL void GL_APIENTRY glGetPerfMonitorCounterDataAMD (GLuint monitor, GLenum pname, GLsizei dataSize, GLuint *data, GLint *bytesWritten); -#endif -#endif /* GL_AMD_performance_monitor */ - -#ifndef GL_AMD_program_binary_Z400 -#define GL_AMD_program_binary_Z400 1 -#define GL_Z400_BINARY_AMD 0x8740 -#endif /* GL_AMD_program_binary_Z400 */ - -#ifndef GL_ANDROID_extension_pack_es31a -#define GL_ANDROID_extension_pack_es31a 1 -#endif /* GL_ANDROID_extension_pack_es31a */ - -#ifndef GL_ANGLE_depth_texture -#define GL_ANGLE_depth_texture 1 -#endif /* GL_ANGLE_depth_texture */ - -#ifndef GL_ANGLE_framebuffer_blit -#define GL_ANGLE_framebuffer_blit 1 -#define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_ANGLE 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_ANGLE 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_ANGLE 0x8CAA -typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERANGLEPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBlitFramebufferANGLE (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif -#endif /* GL_ANGLE_framebuffer_blit */ - -#ifndef GL_ANGLE_framebuffer_multisample -#define GL_ANGLE_framebuffer_multisample 1 -#define GL_RENDERBUFFER_SAMPLES_ANGLE 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56 -#define GL_MAX_SAMPLES_ANGLE 0x8D57 -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif -#endif /* GL_ANGLE_framebuffer_multisample */ - -#ifndef GL_ANGLE_instanced_arrays -#define GL_ANGLE_instanced_arrays 1 -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE -typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); -#endif -#endif /* GL_ANGLE_instanced_arrays */ - -#ifndef GL_ANGLE_pack_reverse_row_order -#define GL_ANGLE_pack_reverse_row_order 1 -#define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 -#endif /* GL_ANGLE_pack_reverse_row_order */ - -#ifndef GL_ANGLE_program_binary -#define GL_ANGLE_program_binary 1 -#define GL_PROGRAM_BINARY_ANGLE 0x93A6 -#endif /* GL_ANGLE_program_binary */ - -#ifndef GL_ANGLE_texture_compression_dxt3 -#define GL_ANGLE_texture_compression_dxt3 1 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 -#endif /* GL_ANGLE_texture_compression_dxt3 */ - -#ifndef GL_ANGLE_texture_compression_dxt5 -#define GL_ANGLE_texture_compression_dxt5 1 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 -#endif /* GL_ANGLE_texture_compression_dxt5 */ - -#ifndef GL_ANGLE_texture_usage -#define GL_ANGLE_texture_usage 1 -#define GL_TEXTURE_USAGE_ANGLE 0x93A2 -#define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 -#endif /* GL_ANGLE_texture_usage */ - -#ifndef GL_ANGLE_translated_shader_source -#define GL_ANGLE_translated_shader_source 1 -#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 -typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); -#endif -#endif /* GL_ANGLE_translated_shader_source */ - -#ifndef GL_APPLE_clip_distance -#define GL_APPLE_clip_distance 1 -#define GL_MAX_CLIP_DISTANCES_APPLE 0x0D32 -#define GL_CLIP_DISTANCE0_APPLE 0x3000 -#define GL_CLIP_DISTANCE1_APPLE 0x3001 -#define GL_CLIP_DISTANCE2_APPLE 0x3002 -#define GL_CLIP_DISTANCE3_APPLE 0x3003 -#define GL_CLIP_DISTANCE4_APPLE 0x3004 -#define GL_CLIP_DISTANCE5_APPLE 0x3005 -#define GL_CLIP_DISTANCE6_APPLE 0x3006 -#define GL_CLIP_DISTANCE7_APPLE 0x3007 -#endif /* GL_APPLE_clip_distance */ - -#ifndef GL_APPLE_color_buffer_packed_float -#define GL_APPLE_color_buffer_packed_float 1 -#endif /* GL_APPLE_color_buffer_packed_float */ - -#ifndef GL_APPLE_copy_texture_levels -#define GL_APPLE_copy_texture_levels 1 -typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); -#endif -#endif /* GL_APPLE_copy_texture_levels */ - -#ifndef GL_APPLE_framebuffer_multisample -#define GL_APPLE_framebuffer_multisample 1 -#define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56 -#define GL_MAX_SAMPLES_APPLE 0x8D57 -#define GL_READ_FRAMEBUFFER_APPLE 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_APPLE 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_APPLE 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleAPPLE (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glResolveMultisampleFramebufferAPPLE (void); -#endif -#endif /* GL_APPLE_framebuffer_multisample */ - -#ifndef GL_APPLE_rgb_422 -#define GL_APPLE_rgb_422 1 -#define GL_RGB_422_APPLE 0x8A1F -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB -#define GL_RGB_RAW_422_APPLE 0x8A51 -#endif /* GL_APPLE_rgb_422 */ - -#ifndef GL_APPLE_sync -#define GL_APPLE_sync 1 -#define GL_SYNC_OBJECT_APPLE 0x8A53 -#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111 -#define GL_OBJECT_TYPE_APPLE 0x9112 -#define GL_SYNC_CONDITION_APPLE 0x9113 -#define GL_SYNC_STATUS_APPLE 0x9114 -#define GL_SYNC_FLAGS_APPLE 0x9115 -#define GL_SYNC_FENCE_APPLE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117 -#define GL_UNSIGNALED_APPLE 0x9118 -#define GL_SIGNALED_APPLE 0x9119 -#define GL_ALREADY_SIGNALED_APPLE 0x911A -#define GL_TIMEOUT_EXPIRED_APPLE 0x911B -#define GL_CONDITION_SATISFIED_APPLE 0x911C -#define GL_WAIT_FAILED_APPLE 0x911D -#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001 -#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull -typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags); -typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync); -typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync); -typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); -typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params); -typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags); -GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync); -GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync); -GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params); -GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -#endif -#endif /* GL_APPLE_sync */ - -#ifndef GL_APPLE_texture_format_BGRA8888 -#define GL_APPLE_texture_format_BGRA8888 1 -#define GL_BGRA_EXT 0x80E1 -#define GL_BGRA8_EXT 0x93A1 -#endif /* GL_APPLE_texture_format_BGRA8888 */ - -#ifndef GL_APPLE_texture_max_level -#define GL_APPLE_texture_max_level 1 -#define GL_TEXTURE_MAX_LEVEL_APPLE 0x813D -#endif /* GL_APPLE_texture_max_level */ - -#ifndef GL_APPLE_texture_packed_float -#define GL_APPLE_texture_packed_float 1 -#define GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE 0x8C3B -#define GL_UNSIGNED_INT_5_9_9_9_REV_APPLE 0x8C3E -#define GL_R11F_G11F_B10F_APPLE 0x8C3A -#define GL_RGB9_E5_APPLE 0x8C3D -#endif /* GL_APPLE_texture_packed_float */ - -#ifndef GL_ARM_mali_program_binary -#define GL_ARM_mali_program_binary 1 -#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61 -#endif /* GL_ARM_mali_program_binary */ - -#ifndef GL_ARM_mali_shader_binary -#define GL_ARM_mali_shader_binary 1 -#define GL_MALI_SHADER_BINARY_ARM 0x8F60 -#endif /* GL_ARM_mali_shader_binary */ - -#ifndef GL_ARM_rgba8 -#define GL_ARM_rgba8 1 -#endif /* GL_ARM_rgba8 */ - -#ifndef GL_ARM_shader_framebuffer_fetch -#define GL_ARM_shader_framebuffer_fetch 1 -#define GL_FETCH_PER_SAMPLE_ARM 0x8F65 -#define GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM 0x8F66 -#endif /* GL_ARM_shader_framebuffer_fetch */ - -#ifndef GL_ARM_shader_framebuffer_fetch_depth_stencil -#define GL_ARM_shader_framebuffer_fetch_depth_stencil 1 -#endif /* GL_ARM_shader_framebuffer_fetch_depth_stencil */ - -#ifndef GL_DMP_program_binary -#define GL_DMP_program_binary 1 -#define GL_SMAPHS30_PROGRAM_BINARY_DMP 0x9251 -#define GL_SMAPHS_PROGRAM_BINARY_DMP 0x9252 -#define GL_DMP_PROGRAM_BINARY_DMP 0x9253 -#endif /* GL_DMP_program_binary */ - -#ifndef GL_DMP_shader_binary -#define GL_DMP_shader_binary 1 -#define GL_SHADER_BINARY_DMP 0x9250 -#endif /* GL_DMP_shader_binary */ - -#ifndef GL_EXT_base_instance -#define GL_EXT_base_instance 1 -typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCEEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawArraysInstancedBaseInstanceEXT (GLenum mode, GLint first, GLsizei count, GLsizei instancecount, GLuint baseinstance); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLuint baseinstance); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexBaseInstanceEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex, GLuint baseinstance); -#endif -#endif /* GL_EXT_base_instance */ - -#ifndef GL_EXT_blend_minmax -#define GL_EXT_blend_minmax 1 -#define GL_MIN_EXT 0x8007 -#define GL_MAX_EXT 0x8008 -#endif /* GL_EXT_blend_minmax */ - -#ifndef GL_EXT_color_buffer_half_float -#define GL_EXT_color_buffer_half_float 1 -#define GL_RGBA16F_EXT 0x881A -#define GL_RGB16F_EXT 0x881B -#define GL_RG16F_EXT 0x822F -#define GL_R16F_EXT 0x822D -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT 0x8211 -#define GL_UNSIGNED_NORMALIZED_EXT 0x8C17 -#endif /* GL_EXT_color_buffer_half_float */ - -#ifndef GL_EXT_copy_image -#define GL_EXT_copy_image 1 -typedef void (GL_APIENTRYP PFNGLCOPYIMAGESUBDATAEXTPROC) (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glCopyImageSubDataEXT (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth); -#endif -#endif /* GL_EXT_copy_image */ - -#ifndef GL_EXT_debug_label -#define GL_EXT_debug_label 1 -#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F -#define GL_PROGRAM_OBJECT_EXT 0x8B40 -#define GL_SHADER_OBJECT_EXT 0x8B48 -#define GL_BUFFER_OBJECT_EXT 0x9151 -#define GL_QUERY_OBJECT_EXT 0x9153 -#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154 -#define GL_TRANSFORM_FEEDBACK 0x8E22 -typedef void (GL_APIENTRYP PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label); -typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glLabelObjectEXT (GLenum type, GLuint object, GLsizei length, const GLchar *label); -GL_APICALL void GL_APIENTRY glGetObjectLabelEXT (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label); -#endif -#endif /* GL_EXT_debug_label */ - -#ifndef GL_EXT_debug_marker -#define GL_EXT_debug_marker 1 -typedef void (GL_APIENTRYP PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker); -typedef void (GL_APIENTRYP PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker); -typedef void (GL_APIENTRYP PFNGLPOPGROUPMARKEREXTPROC) (void); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glInsertEventMarkerEXT (GLsizei length, const GLchar *marker); -GL_APICALL void GL_APIENTRY glPushGroupMarkerEXT (GLsizei length, const GLchar *marker); -GL_APICALL void GL_APIENTRY glPopGroupMarkerEXT (void); -#endif -#endif /* GL_EXT_debug_marker */ - -#ifndef GL_EXT_discard_framebuffer -#define GL_EXT_discard_framebuffer 1 -#define GL_COLOR_EXT 0x1800 -#define GL_DEPTH_EXT 0x1801 -#define GL_STENCIL_EXT 0x1802 -typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numAttachments, const GLenum *attachments); -#endif -#endif /* GL_EXT_discard_framebuffer */ - -#ifndef GL_EXT_disjoint_timer_query -#define GL_EXT_disjoint_timer_query 1 -#define GL_QUERY_COUNTER_BITS_EXT 0x8864 -#define GL_CURRENT_QUERY_EXT 0x8865 -#define GL_QUERY_RESULT_EXT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE_EXT 0x8867 -#define GL_TIME_ELAPSED_EXT 0x88BF -#define GL_TIMESTAMP_EXT 0x8E28 -#define GL_GPU_DISJOINT_EXT 0x8FBB -typedef void (GL_APIENTRYP PFNGLGENQUERIESEXTPROC) (GLsizei n, GLuint *ids); -typedef void (GL_APIENTRYP PFNGLDELETEQUERIESEXTPROC) (GLsizei n, const GLuint *ids); -typedef GLboolean (GL_APIENTRYP PFNGLISQUERYEXTPROC) (GLuint id); -typedef void (GL_APIENTRYP PFNGLBEGINQUERYEXTPROC) (GLenum target, GLuint id); -typedef void (GL_APIENTRYP PFNGLENDQUERYEXTPROC) (GLenum target); -typedef void (GL_APIENTRYP PFNGLQUERYCOUNTEREXTPROC) (GLuint id, GLenum target); -typedef void (GL_APIENTRYP PFNGLGETQUERYIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTIVEXTPROC) (GLuint id, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUIVEXTPROC) (GLuint id, GLenum pname, GLuint *params); -typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTI64VEXTPROC) (GLuint id, GLenum pname, GLint64 *params); -typedef void (GL_APIENTRYP PFNGLGETQUERYOBJECTUI64VEXTPROC) (GLuint id, GLenum pname, GLuint64 *params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGenQueriesEXT (GLsizei n, GLuint *ids); -GL_APICALL void GL_APIENTRY glDeleteQueriesEXT (GLsizei n, const GLuint *ids); -GL_APICALL GLboolean GL_APIENTRY glIsQueryEXT (GLuint id); -GL_APICALL void GL_APIENTRY glBeginQueryEXT (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glEndQueryEXT (GLenum target); -GL_APICALL void GL_APIENTRY glQueryCounterEXT (GLuint id, GLenum target); -GL_APICALL void GL_APIENTRY glGetQueryivEXT (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetQueryObjectivEXT (GLuint id, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetQueryObjectuivEXT (GLuint id, GLenum pname, GLuint *params); -GL_APICALL void GL_APIENTRY glGetQueryObjecti64vEXT (GLuint id, GLenum pname, GLint64 *params); -GL_APICALL void GL_APIENTRY glGetQueryObjectui64vEXT (GLuint id, GLenum pname, GLuint64 *params); -#endif -#endif /* GL_EXT_disjoint_timer_query */ - -#ifndef GL_EXT_draw_buffers -#define GL_EXT_draw_buffers 1 -#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF -#define GL_MAX_DRAW_BUFFERS_EXT 0x8824 -#define GL_DRAW_BUFFER0_EXT 0x8825 -#define GL_DRAW_BUFFER1_EXT 0x8826 -#define GL_DRAW_BUFFER2_EXT 0x8827 -#define GL_DRAW_BUFFER3_EXT 0x8828 -#define GL_DRAW_BUFFER4_EXT 0x8829 -#define GL_DRAW_BUFFER5_EXT 0x882A -#define GL_DRAW_BUFFER6_EXT 0x882B -#define GL_DRAW_BUFFER7_EXT 0x882C -#define GL_DRAW_BUFFER8_EXT 0x882D -#define GL_DRAW_BUFFER9_EXT 0x882E -#define GL_DRAW_BUFFER10_EXT 0x882F -#define GL_DRAW_BUFFER11_EXT 0x8830 -#define GL_DRAW_BUFFER12_EXT 0x8831 -#define GL_DRAW_BUFFER13_EXT 0x8832 -#define GL_DRAW_BUFFER14_EXT 0x8833 -#define GL_DRAW_BUFFER15_EXT 0x8834 -#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 -#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 -#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 -#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 -#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 -#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 -#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 -#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 -#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 -#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 -#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA -#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB -#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC -#define GL_COLOR_ATTACHMENT13_EXT 0x8CED -#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE -#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs); -#endif -#endif /* GL_EXT_draw_buffers */ - -#ifndef GL_EXT_draw_buffers_indexed -#define GL_EXT_draw_buffers_indexed 1 -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -typedef void (GL_APIENTRYP PFNGLENABLEIEXTPROC) (GLenum target, GLuint index); -typedef void (GL_APIENTRYP PFNGLDISABLEIEXTPROC) (GLenum target, GLuint index); -typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONIEXTPROC) (GLuint buf, GLenum mode); -typedef void (GL_APIENTRYP PFNGLBLENDEQUATIONSEPARATEIEXTPROC) (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -typedef void (GL_APIENTRYP PFNGLBLENDFUNCIEXTPROC) (GLuint buf, GLenum src, GLenum dst); -typedef void (GL_APIENTRYP PFNGLBLENDFUNCSEPARATEIEXTPROC) (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -typedef void (GL_APIENTRYP PFNGLCOLORMASKIEXTPROC) (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDIEXTPROC) (GLenum target, GLuint index); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glEnableiEXT (GLenum target, GLuint index); -GL_APICALL void GL_APIENTRY glDisableiEXT (GLenum target, GLuint index); -GL_APICALL void GL_APIENTRY glBlendEquationiEXT (GLuint buf, GLenum mode); -GL_APICALL void GL_APIENTRY glBlendEquationSeparateiEXT (GLuint buf, GLenum modeRGB, GLenum modeAlpha); -GL_APICALL void GL_APIENTRY glBlendFunciEXT (GLuint buf, GLenum src, GLenum dst); -GL_APICALL void GL_APIENTRY glBlendFuncSeparateiEXT (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); -GL_APICALL void GL_APIENTRY glColorMaskiEXT (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a); -GL_APICALL GLboolean GL_APIENTRY glIsEnablediEXT (GLenum target, GLuint index); -#endif -#endif /* GL_EXT_draw_buffers_indexed */ - -#ifndef GL_EXT_draw_elements_base_vertex -#define GL_EXT_draw_elements_base_vertex 1 -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); -typedef void (GL_APIENTRYP PFNGLDRAWRANGEELEMENTSBASEVERTEXEXTPROC) (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDBASEVERTEXEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); -typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawElementsBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex); -GL_APICALL void GL_APIENTRY glDrawRangeElementsBaseVertexEXT (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedBaseVertexEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex); -GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex); -#endif -#endif /* GL_EXT_draw_elements_base_vertex */ - -#ifndef GL_EXT_draw_instanced -#define GL_EXT_draw_instanced 1 -typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDEXTPROC) (GLenum mode, GLint start, GLsizei count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDEXTPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawArraysInstancedEXT (GLenum mode, GLint start, GLsizei count, GLsizei primcount); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedEXT (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -#endif -#endif /* GL_EXT_draw_instanced */ - -#ifndef GL_EXT_geometry_point_size -#define GL_EXT_geometry_point_size 1 -#endif /* GL_EXT_geometry_point_size */ - -#ifndef GL_EXT_geometry_shader -#define GL_EXT_geometry_shader 1 -#define GL_GEOMETRY_SHADER_EXT 0x8DD9 -#define GL_GEOMETRY_SHADER_BIT_EXT 0x00000004 -#define GL_GEOMETRY_LINKED_VERTICES_OUT_EXT 0x8916 -#define GL_GEOMETRY_LINKED_INPUT_TYPE_EXT 0x8917 -#define GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT 0x8918 -#define GL_GEOMETRY_SHADER_INVOCATIONS_EXT 0x887F -#define GL_LAYER_PROVOKING_VERTEX_EXT 0x825E -#define GL_LINES_ADJACENCY_EXT 0x000A -#define GL_LINE_STRIP_ADJACENCY_EXT 0x000B -#define GL_TRIANGLES_ADJACENCY_EXT 0x000C -#define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0x000D -#define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF -#define GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT 0x8A2C -#define GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8A32 -#define GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT 0x9123 -#define GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT 0x9124 -#define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0 -#define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1 -#define GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT 0x8E5A -#define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 -#define GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT 0x92CF -#define GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT 0x92D5 -#define GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT 0x90CD -#define GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT 0x90D7 -#define GL_FIRST_VERTEX_CONVENTION_EXT 0x8E4D -#define GL_LAST_VERTEX_CONVENTION_EXT 0x8E4E -#define GL_UNDEFINED_VERTEX_EXT 0x8260 -#define GL_PRIMITIVES_GENERATED_EXT 0x8C87 -#define GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT 0x9312 -#define GL_MAX_FRAMEBUFFER_LAYERS_EXT 0x9317 -#define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 -#define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 -#define GL_REFERENCED_BY_GEOMETRY_SHADER_EXT 0x9309 -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTUREEXTPROC) (GLenum target, GLenum attachment, GLuint texture, GLint level); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glFramebufferTextureEXT (GLenum target, GLenum attachment, GLuint texture, GLint level); -#endif -#endif /* GL_EXT_geometry_shader */ - -#ifndef GL_EXT_gpu_shader5 -#define GL_EXT_gpu_shader5 1 -#endif /* GL_EXT_gpu_shader5 */ - -#ifndef GL_EXT_instanced_arrays -#define GL_EXT_instanced_arrays 1 -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_EXT 0x88FE -typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISOREXTPROC) (GLuint index, GLuint divisor); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glVertexAttribDivisorEXT (GLuint index, GLuint divisor); -#endif -#endif /* GL_EXT_instanced_arrays */ - -#ifndef GL_EXT_map_buffer_range -#define GL_EXT_map_buffer_range 1 -#define GL_MAP_READ_BIT_EXT 0x0001 -#define GL_MAP_WRITE_BIT_EXT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020 -typedef void *(GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void *GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length); -#endif -#endif /* GL_EXT_map_buffer_range */ - -#ifndef GL_EXT_multi_draw_arrays -#define GL_EXT_multi_draw_arrays 1 -typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSEXTPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum mode, const GLint *first, const GLsizei *count, GLsizei primcount); -GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount); -#endif -#endif /* GL_EXT_multi_draw_arrays */ - -#ifndef GL_EXT_multi_draw_indirect -#define GL_EXT_multi_draw_indirect 1 -typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTEXTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); -typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTEXTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glMultiDrawArraysIndirectEXT (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); -GL_APICALL void GL_APIENTRY glMultiDrawElementsIndirectEXT (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride); -#endif -#endif /* GL_EXT_multi_draw_indirect */ - -#ifndef GL_EXT_multisampled_render_to_texture -#define GL_EXT_multisampled_render_to_texture 1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C -#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 -#define GL_MAX_SAMPLES_EXT 0x8D57 -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleEXT (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleEXT (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); -#endif -#endif /* GL_EXT_multisampled_render_to_texture */ - -#ifndef GL_EXT_multiview_draw_buffers -#define GL_EXT_multiview_draw_buffers 1 -#define GL_COLOR_ATTACHMENT_EXT 0x90F0 -#define GL_MULTIVIEW_EXT 0x90F1 -#define GL_DRAW_BUFFER_EXT 0x0C01 -#define GL_READ_BUFFER_EXT 0x0C02 -#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2 -typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); -typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index); -GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices); -GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data); -#endif -#endif /* GL_EXT_multiview_draw_buffers */ - -#ifndef GL_EXT_occlusion_query_boolean -#define GL_EXT_occlusion_query_boolean 1 -#define GL_ANY_SAMPLES_PASSED_EXT 0x8C2F -#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT 0x8D6A -#endif /* GL_EXT_occlusion_query_boolean */ - -#ifndef GL_EXT_primitive_bounding_box -#define GL_EXT_primitive_bounding_box 1 -#define GL_PRIMITIVE_BOUNDING_BOX_EXT 0x92BE -typedef void (GL_APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXEXTPROC) (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glPrimitiveBoundingBoxEXT (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW); -#endif -#endif /* GL_EXT_primitive_bounding_box */ - -#ifndef GL_EXT_pvrtc_sRGB -#define GL_EXT_pvrtc_sRGB 1 -#define GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT 0x8A54 -#define GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT 0x8A55 -#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT 0x8A56 -#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT 0x8A57 -#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG 0x93F0 -#define GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG 0x93F1 -#endif /* GL_EXT_pvrtc_sRGB */ - -#ifndef GL_EXT_read_format_bgra -#define GL_EXT_read_format_bgra 1 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT 0x8365 -#define GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT 0x8366 -#endif /* GL_EXT_read_format_bgra */ - -#ifndef GL_EXT_render_snorm -#define GL_EXT_render_snorm 1 -#define GL_R8_SNORM 0x8F94 -#define GL_RG8_SNORM 0x8F95 -#define GL_RGBA8_SNORM 0x8F97 -#define GL_R16_SNORM_EXT 0x8F98 -#define GL_RG16_SNORM_EXT 0x8F99 -#define GL_RGBA16_SNORM_EXT 0x8F9B -#endif /* GL_EXT_render_snorm */ - -#ifndef GL_EXT_robustness -#define GL_EXT_robustness 1 -#define GL_GUILTY_CONTEXT_RESET_EXT 0x8253 -#define GL_INNOCENT_CONTEXT_RESET_EXT 0x8254 -#define GL_UNKNOWN_CONTEXT_RESET_EXT 0x8255 -#define GL_CONTEXT_ROBUST_ACCESS_EXT 0x90F3 -#define GL_RESET_NOTIFICATION_STRATEGY_EXT 0x8256 -#define GL_LOSE_CONTEXT_ON_RESET_EXT 0x8252 -#define GL_NO_RESET_NOTIFICATION_EXT 0x8261 -typedef GLenum (GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSEXTPROC) (void); -typedef void (GL_APIENTRYP PFNGLREADNPIXELSEXTPROC) (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMFVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); -typedef void (GL_APIENTRYP PFNGLGETNUNIFORMIVEXTPROC) (GLuint program, GLint location, GLsizei bufSize, GLint *params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLenum GL_APIENTRY glGetGraphicsResetStatusEXT (void); -GL_APICALL void GL_APIENTRY glReadnPixelsEXT (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data); -GL_APICALL void GL_APIENTRY glGetnUniformfvEXT (GLuint program, GLint location, GLsizei bufSize, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetnUniformivEXT (GLuint program, GLint location, GLsizei bufSize, GLint *params); -#endif -#endif /* GL_EXT_robustness */ - -#ifndef GL_EXT_sRGB -#define GL_EXT_sRGB 1 -#define GL_SRGB_EXT 0x8C40 -#define GL_SRGB_ALPHA_EXT 0x8C42 -#define GL_SRGB8_ALPHA8_EXT 0x8C43 -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT 0x8210 -#endif /* GL_EXT_sRGB */ - -#ifndef GL_EXT_sRGB_write_control -#define GL_EXT_sRGB_write_control 1 -#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 -#endif /* GL_EXT_sRGB_write_control */ - -#ifndef GL_EXT_separate_shader_objects -#define GL_EXT_separate_shader_objects 1 -#define GL_ACTIVE_PROGRAM_EXT 0x8259 -#define GL_VERTEX_SHADER_BIT_EXT 0x00000001 -#define GL_FRAGMENT_SHADER_BIT_EXT 0x00000002 -#define GL_ALL_SHADER_BITS_EXT 0xFFFFFFFF -#define GL_PROGRAM_SEPARABLE_EXT 0x8258 -#define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A -typedef void (GL_APIENTRYP PFNGLACTIVESHADERPROGRAMEXTPROC) (GLuint pipeline, GLuint program); -typedef void (GL_APIENTRYP PFNGLBINDPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef GLuint (GL_APIENTRYP PFNGLCREATESHADERPROGRAMVEXTPROC) (GLenum type, GLsizei count, const GLchar **strings); -typedef void (GL_APIENTRYP PFNGLDELETEPROGRAMPIPELINESEXTPROC) (GLsizei n, const GLuint *pipelines); -typedef void (GL_APIENTRYP PFNGLGENPROGRAMPIPELINESEXTPROC) (GLsizei n, GLuint *pipelines); -typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEIVEXTPROC) (GLuint pipeline, GLenum pname, GLint *params); -typedef GLboolean (GL_APIENTRYP PFNGLISPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef void (GL_APIENTRYP PFNGLPROGRAMPARAMETERIEXTPROC) (GLuint program, GLenum pname, GLint value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FEXTPROC) (GLuint program, GLint location, GLfloat v0); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IEXTPROC) (GLuint program, GLint location, GLint v0); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FEXTPROC) (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4FVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IEXTPROC) (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4IVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLUSEPROGRAMSTAGESEXTPROC) (GLuint pipeline, GLbitfield stages, GLuint program); -typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIEXTPROC) (GLuint program, GLint location, GLuint v0); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIEXTPROC) (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM1UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM2UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM3UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORM4UIVEXTPROC) (GLuint program, GLint location, GLsizei count, const GLuint *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX2X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X2FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX3X4FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMMATRIX4X3FVEXTPROC) (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glActiveShaderProgramEXT (GLuint pipeline, GLuint program); -GL_APICALL void GL_APIENTRY glBindProgramPipelineEXT (GLuint pipeline); -GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramvEXT (GLenum type, GLsizei count, const GLchar **strings); -GL_APICALL void GL_APIENTRY glDeleteProgramPipelinesEXT (GLsizei n, const GLuint *pipelines); -GL_APICALL void GL_APIENTRY glGenProgramPipelinesEXT (GLsizei n, GLuint *pipelines); -GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLogEXT (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glGetProgramPipelineivEXT (GLuint pipeline, GLenum pname, GLint *params); -GL_APICALL GLboolean GL_APIENTRY glIsProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glProgramParameteriEXT (GLuint program, GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glProgramUniform1fEXT (GLuint program, GLint location, GLfloat v0); -GL_APICALL void GL_APIENTRY glProgramUniform1fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform1iEXT (GLuint program, GLint location, GLint v0); -GL_APICALL void GL_APIENTRY glProgramUniform1ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform2fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1); -GL_APICALL void GL_APIENTRY glProgramUniform2fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform2iEXT (GLuint program, GLint location, GLint v0, GLint v1); -GL_APICALL void GL_APIENTRY glProgramUniform2ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform3fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GL_APICALL void GL_APIENTRY glProgramUniform3fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform3iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -GL_APICALL void GL_APIENTRY glProgramUniform3ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform4fEXT (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GL_APICALL void GL_APIENTRY glProgramUniform4fvEXT (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform4iEXT (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GL_APICALL void GL_APIENTRY glProgramUniform4ivEXT (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUseProgramStagesEXT (GLuint pipeline, GLbitfield stages, GLuint program); -GL_APICALL void GL_APIENTRY glValidateProgramPipelineEXT (GLuint pipeline); -GL_APICALL void GL_APIENTRY glProgramUniform1uiEXT (GLuint program, GLint location, GLuint v0); -GL_APICALL void GL_APIENTRY glProgramUniform2uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1); -GL_APICALL void GL_APIENTRY glProgramUniform3uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -GL_APICALL void GL_APIENTRY glProgramUniform4uiEXT (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GL_APICALL void GL_APIENTRY glProgramUniform1uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniform2uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniform3uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniform4uivEXT (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fvEXT (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -#endif -#endif /* GL_EXT_separate_shader_objects */ - -#ifndef GL_EXT_shader_framebuffer_fetch -#define GL_EXT_shader_framebuffer_fetch 1 -#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 -#endif /* GL_EXT_shader_framebuffer_fetch */ - -#ifndef GL_EXT_shader_implicit_conversions -#define GL_EXT_shader_implicit_conversions 1 -#endif /* GL_EXT_shader_implicit_conversions */ - -#ifndef GL_EXT_shader_integer_mix -#define GL_EXT_shader_integer_mix 1 -#endif /* GL_EXT_shader_integer_mix */ - -#ifndef GL_EXT_shader_io_blocks -#define GL_EXT_shader_io_blocks 1 -#endif /* GL_EXT_shader_io_blocks */ - -#ifndef GL_EXT_shader_pixel_local_storage -#define GL_EXT_shader_pixel_local_storage 1 -#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63 -#define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT 0x8F67 -#define GL_SHADER_PIXEL_LOCAL_STORAGE_EXT 0x8F64 -#endif /* GL_EXT_shader_pixel_local_storage */ - -#ifndef GL_EXT_shader_texture_lod -#define GL_EXT_shader_texture_lod 1 -#endif /* GL_EXT_shader_texture_lod */ - -#ifndef GL_EXT_shadow_samplers -#define GL_EXT_shadow_samplers 1 -#define GL_TEXTURE_COMPARE_MODE_EXT 0x884C -#define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D -#define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E -#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 -#endif /* GL_EXT_shadow_samplers */ - -#ifndef GL_EXT_tessellation_point_size -#define GL_EXT_tessellation_point_size 1 -#endif /* GL_EXT_tessellation_point_size */ - -#ifndef GL_EXT_tessellation_shader -#define GL_EXT_tessellation_shader 1 -#define GL_PATCHES_EXT 0x000E -#define GL_PATCH_VERTICES_EXT 0x8E72 -#define GL_TESS_CONTROL_OUTPUT_VERTICES_EXT 0x8E75 -#define GL_TESS_GEN_MODE_EXT 0x8E76 -#define GL_TESS_GEN_SPACING_EXT 0x8E77 -#define GL_TESS_GEN_VERTEX_ORDER_EXT 0x8E78 -#define GL_TESS_GEN_POINT_MODE_EXT 0x8E79 -#define GL_ISOLINES_EXT 0x8E7A -#define GL_QUADS_EXT 0x0007 -#define GL_FRACTIONAL_ODD_EXT 0x8E7B -#define GL_FRACTIONAL_EVEN_EXT 0x8E7C -#define GL_MAX_PATCH_VERTICES_EXT 0x8E7D -#define GL_MAX_TESS_GEN_LEVEL_EXT 0x8E7E -#define GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E7F -#define GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E80 -#define GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT 0x8E81 -#define GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT 0x8E82 -#define GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT 0x8E83 -#define GL_MAX_TESS_PATCH_COMPONENTS_EXT 0x8E84 -#define GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT 0x8E85 -#define GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT 0x8E86 -#define GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT 0x8E89 -#define GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT 0x8E8A -#define GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT 0x886C -#define GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT 0x886D -#define GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT 0x8E1E -#define GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT 0x8E1F -#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT 0x92CD -#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT 0x92CE -#define GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT 0x92D3 -#define GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT 0x92D4 -#define GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT 0x90CB -#define GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT 0x90CC -#define GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT 0x90D8 -#define GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT 0x90D9 -#define GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED 0x8221 -#define GL_IS_PER_PATCH_EXT 0x92E7 -#define GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT 0x9307 -#define GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT 0x9308 -#define GL_TESS_CONTROL_SHADER_EXT 0x8E88 -#define GL_TESS_EVALUATION_SHADER_EXT 0x8E87 -#define GL_TESS_CONTROL_SHADER_BIT_EXT 0x00000008 -#define GL_TESS_EVALUATION_SHADER_BIT_EXT 0x00000010 -typedef void (GL_APIENTRYP PFNGLPATCHPARAMETERIEXTPROC) (GLenum pname, GLint value); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glPatchParameteriEXT (GLenum pname, GLint value); -#endif -#endif /* GL_EXT_tessellation_shader */ - -#ifndef GL_EXT_texture_border_clamp -#define GL_EXT_texture_border_clamp 1 -#define GL_TEXTURE_BORDER_COLOR_EXT 0x1004 -#define GL_CLAMP_TO_BORDER_EXT 0x812D -typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, const GLint *params); -typedef void (GL_APIENTRYP PFNGLTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, const GLuint *params); -typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIIVEXTPROC) (GLenum target, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETTEXPARAMETERIUIVEXTPROC) (GLenum target, GLenum pname, GLuint *params); -typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, const GLint *param); -typedef void (GL_APIENTRYP PFNGLSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, const GLuint *param); -typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIIVEXTPROC) (GLuint sampler, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLGETSAMPLERPARAMETERIUIVEXTPROC) (GLuint sampler, GLenum pname, GLuint *params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexParameterIivEXT (GLenum target, GLenum pname, const GLint *params); -GL_APICALL void GL_APIENTRY glTexParameterIuivEXT (GLenum target, GLenum pname, const GLuint *params); -GL_APICALL void GL_APIENTRY glGetTexParameterIivEXT (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetTexParameterIuivEXT (GLenum target, GLenum pname, GLuint *params); -GL_APICALL void GL_APIENTRY glSamplerParameterIivEXT (GLuint sampler, GLenum pname, const GLint *param); -GL_APICALL void GL_APIENTRY glSamplerParameterIuivEXT (GLuint sampler, GLenum pname, const GLuint *param); -GL_APICALL void GL_APIENTRY glGetSamplerParameterIivEXT (GLuint sampler, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetSamplerParameterIuivEXT (GLuint sampler, GLenum pname, GLuint *params); -#endif -#endif /* GL_EXT_texture_border_clamp */ - -#ifndef GL_EXT_texture_buffer -#define GL_EXT_texture_buffer 1 -#define GL_TEXTURE_BUFFER_EXT 0x8C2A -#define GL_TEXTURE_BUFFER_BINDING_EXT 0x8C2A -#define GL_MAX_TEXTURE_BUFFER_SIZE_EXT 0x8C2B -#define GL_TEXTURE_BINDING_BUFFER_EXT 0x8C2C -#define GL_TEXTURE_BUFFER_DATA_STORE_BINDING_EXT 0x8C2D -#define GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_EXT 0x919F -#define GL_SAMPLER_BUFFER_EXT 0x8DC2 -#define GL_INT_SAMPLER_BUFFER_EXT 0x8DD0 -#define GL_UNSIGNED_INT_SAMPLER_BUFFER_EXT 0x8DD8 -#define GL_IMAGE_BUFFER_EXT 0x9051 -#define GL_INT_IMAGE_BUFFER_EXT 0x905C -#define GL_UNSIGNED_INT_IMAGE_BUFFER_EXT 0x9067 -#define GL_TEXTURE_BUFFER_OFFSET_EXT 0x919D -#define GL_TEXTURE_BUFFER_SIZE_EXT 0x919E -typedef void (GL_APIENTRYP PFNGLTEXBUFFEREXTPROC) (GLenum target, GLenum internalformat, GLuint buffer); -typedef void (GL_APIENTRYP PFNGLTEXBUFFERRANGEEXTPROC) (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexBufferEXT (GLenum target, GLenum internalformat, GLuint buffer); -GL_APICALL void GL_APIENTRY glTexBufferRangeEXT (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size); -#endif -#endif /* GL_EXT_texture_buffer */ - -#ifndef GL_EXT_texture_compression_dxt1 -#define GL_EXT_texture_compression_dxt1 1 -#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0 -#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1 -#endif /* GL_EXT_texture_compression_dxt1 */ - -#ifndef GL_EXT_texture_compression_s3tc -#define GL_EXT_texture_compression_s3tc 1 -#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2 -#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3 -#endif /* GL_EXT_texture_compression_s3tc */ - -#ifndef GL_EXT_texture_cube_map_array -#define GL_EXT_texture_cube_map_array 1 -#define GL_TEXTURE_CUBE_MAP_ARRAY_EXT 0x9009 -#define GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_EXT 0x900A -#define GL_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900C -#define GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_EXT 0x900D -#define GL_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900E -#define GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_EXT 0x900F -#define GL_IMAGE_CUBE_MAP_ARRAY_EXT 0x9054 -#define GL_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x905F -#define GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_EXT 0x906A -#endif /* GL_EXT_texture_cube_map_array */ - -#ifndef GL_EXT_texture_filter_anisotropic -#define GL_EXT_texture_filter_anisotropic 1 -#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE -#define GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT 0x84FF -#endif /* GL_EXT_texture_filter_anisotropic */ - -#ifndef GL_EXT_texture_format_BGRA8888 -#define GL_EXT_texture_format_BGRA8888 1 -#endif /* GL_EXT_texture_format_BGRA8888 */ - -#ifndef GL_EXT_texture_norm16 -#define GL_EXT_texture_norm16 1 -#define GL_R16_EXT 0x822A -#define GL_RG16_EXT 0x822C -#define GL_RGBA16_EXT 0x805B -#define GL_RGB16_EXT 0x8054 -#define GL_RGB16_SNORM_EXT 0x8F9A -#endif /* GL_EXT_texture_norm16 */ - -#ifndef GL_EXT_texture_rg -#define GL_EXT_texture_rg 1 -#define GL_RED_EXT 0x1903 -#define GL_RG_EXT 0x8227 -#define GL_R8_EXT 0x8229 -#define GL_RG8_EXT 0x822B -#endif /* GL_EXT_texture_rg */ - -#ifndef GL_EXT_texture_sRGB_decode -#define GL_EXT_texture_sRGB_decode 1 -#define GL_TEXTURE_SRGB_DECODE_EXT 0x8A48 -#define GL_DECODE_EXT 0x8A49 -#define GL_SKIP_DECODE_EXT 0x8A4A -#endif /* GL_EXT_texture_sRGB_decode */ - -#ifndef GL_EXT_texture_storage -#define GL_EXT_texture_storage 1 -#define GL_TEXTURE_IMMUTABLE_FORMAT_EXT 0x912F -#define GL_ALPHA8_EXT 0x803C -#define GL_LUMINANCE8_EXT 0x8040 -#define GL_LUMINANCE8_ALPHA8_EXT 0x8045 -#define GL_RGBA32F_EXT 0x8814 -#define GL_RGB32F_EXT 0x8815 -#define GL_ALPHA32F_EXT 0x8816 -#define GL_LUMINANCE32F_EXT 0x8818 -#define GL_LUMINANCE_ALPHA32F_EXT 0x8819 -#define GL_ALPHA16F_EXT 0x881C -#define GL_LUMINANCE16F_EXT 0x881E -#define GL_LUMINANCE_ALPHA16F_EXT 0x881F -#define GL_R32F_EXT 0x822E -#define GL_RG32F_EXT 0x8230 -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE1DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE2DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLTEXSTORAGE3DEXTPROC) (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE1DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE2DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTexStorage1DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -GL_APICALL void GL_APIENTRY glTexStorage2DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage3DEXT (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -GL_APICALL void GL_APIENTRY glTextureStorage1DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width); -GL_APICALL void GL_APIENTRY glTextureStorage2DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTextureStorage3DEXT (GLuint texture, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -#endif -#endif /* GL_EXT_texture_storage */ - -#ifndef GL_EXT_texture_type_2_10_10_10_REV -#define GL_EXT_texture_type_2_10_10_10_REV 1 -#define GL_UNSIGNED_INT_2_10_10_10_REV_EXT 0x8368 -#endif /* GL_EXT_texture_type_2_10_10_10_REV */ - -#ifndef GL_EXT_texture_view -#define GL_EXT_texture_view 1 -#define GL_TEXTURE_VIEW_MIN_LEVEL_EXT 0x82DB -#define GL_TEXTURE_VIEW_NUM_LEVELS_EXT 0x82DC -#define GL_TEXTURE_VIEW_MIN_LAYER_EXT 0x82DD -#define GL_TEXTURE_VIEW_NUM_LAYERS_EXT 0x82DE -#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF -typedef void (GL_APIENTRYP PFNGLTEXTUREVIEWEXTPROC) (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glTextureViewEXT (GLuint texture, GLenum target, GLuint origtexture, GLenum internalformat, GLuint minlevel, GLuint numlevels, GLuint minlayer, GLuint numlayers); -#endif -#endif /* GL_EXT_texture_view */ - -#ifndef GL_EXT_unpack_subimage -#define GL_EXT_unpack_subimage 1 -#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2 -#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4 -#endif /* GL_EXT_unpack_subimage */ - -#ifndef GL_FJ_shader_binary_GCCSO -#define GL_FJ_shader_binary_GCCSO 1 -#define GL_GCCSO_SHADER_BINARY_FJ 0x9260 -#endif /* GL_FJ_shader_binary_GCCSO */ - -#ifndef GL_IMG_multisampled_render_to_texture -#define GL_IMG_multisampled_render_to_texture 1 -#define GL_RENDERBUFFER_SAMPLES_IMG 0x9133 -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG 0x9134 -#define GL_MAX_SAMPLES_IMG 0x9135 -#define GL_TEXTURE_SAMPLES_IMG 0x9136 -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); -#endif -#endif /* GL_IMG_multisampled_render_to_texture */ - -#ifndef GL_IMG_program_binary -#define GL_IMG_program_binary 1 -#define GL_SGX_PROGRAM_BINARY_IMG 0x9130 -#endif /* GL_IMG_program_binary */ - -#ifndef GL_IMG_read_format -#define GL_IMG_read_format 1 -#define GL_BGRA_IMG 0x80E1 -#define GL_UNSIGNED_SHORT_4_4_4_4_REV_IMG 0x8365 -#endif /* GL_IMG_read_format */ - -#ifndef GL_IMG_shader_binary -#define GL_IMG_shader_binary 1 -#define GL_SGX_BINARY_IMG 0x8C0A -#endif /* GL_IMG_shader_binary */ - -#ifndef GL_IMG_texture_compression_pvrtc -#define GL_IMG_texture_compression_pvrtc 1 -#define GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG 0x8C00 -#define GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG 0x8C01 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG 0x8C02 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 -#endif /* GL_IMG_texture_compression_pvrtc */ - -#ifndef GL_IMG_texture_compression_pvrtc2 -#define GL_IMG_texture_compression_pvrtc2 1 -#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 -#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 -#endif /* GL_IMG_texture_compression_pvrtc2 */ - -#ifndef GL_INTEL_performance_query -#define GL_INTEL_performance_query 1 -#define GL_PERFQUERY_SINGLE_CONTEXT_INTEL 0x00000000 -#define GL_PERFQUERY_GLOBAL_CONTEXT_INTEL 0x00000001 -#define GL_PERFQUERY_WAIT_INTEL 0x83FB -#define GL_PERFQUERY_FLUSH_INTEL 0x83FA -#define GL_PERFQUERY_DONOT_FLUSH_INTEL 0x83F9 -#define GL_PERFQUERY_COUNTER_EVENT_INTEL 0x94F0 -#define GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL 0x94F1 -#define GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL 0x94F2 -#define GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL 0x94F3 -#define GL_PERFQUERY_COUNTER_RAW_INTEL 0x94F4 -#define GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL 0x94F5 -#define GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL 0x94F8 -#define GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL 0x94F9 -#define GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL 0x94FA -#define GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL 0x94FB -#define GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL 0x94FC -#define GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL 0x94FD -#define GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL 0x94FE -#define GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL 0x94FF -#define GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL 0x9500 -typedef void (GL_APIENTRYP PFNGLBEGINPERFQUERYINTELPROC) (GLuint queryHandle); -typedef void (GL_APIENTRYP PFNGLCREATEPERFQUERYINTELPROC) (GLuint queryId, GLuint *queryHandle); -typedef void (GL_APIENTRYP PFNGLDELETEPERFQUERYINTELPROC) (GLuint queryHandle); -typedef void (GL_APIENTRYP PFNGLENDPERFQUERYINTELPROC) (GLuint queryHandle); -typedef void (GL_APIENTRYP PFNGLGETFIRSTPERFQUERYIDINTELPROC) (GLuint *queryId); -typedef void (GL_APIENTRYP PFNGLGETNEXTPERFQUERYIDINTELPROC) (GLuint queryId, GLuint *nextQueryId); -typedef void (GL_APIENTRYP PFNGLGETPERFCOUNTERINFOINTELPROC) (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); -typedef void (GL_APIENTRYP PFNGLGETPERFQUERYDATAINTELPROC) (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); -typedef void (GL_APIENTRYP PFNGLGETPERFQUERYIDBYNAMEINTELPROC) (GLchar *queryName, GLuint *queryId); -typedef void (GL_APIENTRYP PFNGLGETPERFQUERYINFOINTELPROC) (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBeginPerfQueryINTEL (GLuint queryHandle); -GL_APICALL void GL_APIENTRY glCreatePerfQueryINTEL (GLuint queryId, GLuint *queryHandle); -GL_APICALL void GL_APIENTRY glDeletePerfQueryINTEL (GLuint queryHandle); -GL_APICALL void GL_APIENTRY glEndPerfQueryINTEL (GLuint queryHandle); -GL_APICALL void GL_APIENTRY glGetFirstPerfQueryIdINTEL (GLuint *queryId); -GL_APICALL void GL_APIENTRY glGetNextPerfQueryIdINTEL (GLuint queryId, GLuint *nextQueryId); -GL_APICALL void GL_APIENTRY glGetPerfCounterInfoINTEL (GLuint queryId, GLuint counterId, GLuint counterNameLength, GLchar *counterName, GLuint counterDescLength, GLchar *counterDesc, GLuint *counterOffset, GLuint *counterDataSize, GLuint *counterTypeEnum, GLuint *counterDataTypeEnum, GLuint64 *rawCounterMaxValue); -GL_APICALL void GL_APIENTRY glGetPerfQueryDataINTEL (GLuint queryHandle, GLuint flags, GLsizei dataSize, GLvoid *data, GLuint *bytesWritten); -GL_APICALL void GL_APIENTRY glGetPerfQueryIdByNameINTEL (GLchar *queryName, GLuint *queryId); -GL_APICALL void GL_APIENTRY glGetPerfQueryInfoINTEL (GLuint queryId, GLuint queryNameLength, GLchar *queryName, GLuint *dataSize, GLuint *noCounters, GLuint *noInstances, GLuint *capsMask); -#endif -#endif /* GL_INTEL_performance_query */ - -#ifndef GL_NV_bindless_texture -#define GL_NV_bindless_texture 1 -typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTUREHANDLENVPROC) (GLuint texture); -typedef GLuint64 (GL_APIENTRYP PFNGLGETTEXTURESAMPLERHANDLENVPROC) (GLuint texture, GLuint sampler); -typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); -typedef void (GL_APIENTRYP PFNGLMAKETEXTUREHANDLENONRESIDENTNVPROC) (GLuint64 handle); -typedef GLuint64 (GL_APIENTRYP PFNGLGETIMAGEHANDLENVPROC) (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); -typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle, GLenum access); -typedef void (GL_APIENTRYP PFNGLMAKEIMAGEHANDLENONRESIDENTNVPROC) (GLuint64 handle); -typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64NVPROC) (GLint location, GLuint64 value); -typedef void (GL_APIENTRYP PFNGLUNIFORMHANDLEUI64VNVPROC) (GLint location, GLsizei count, const GLuint64 *value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64NVPROC) (GLuint program, GLint location, GLuint64 value); -typedef void (GL_APIENTRYP PFNGLPROGRAMUNIFORMHANDLEUI64VNVPROC) (GLuint program, GLint location, GLsizei count, const GLuint64 *values); -typedef GLboolean (GL_APIENTRYP PFNGLISTEXTUREHANDLERESIDENTNVPROC) (GLuint64 handle); -typedef GLboolean (GL_APIENTRYP PFNGLISIMAGEHANDLERESIDENTNVPROC) (GLuint64 handle); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLuint64 GL_APIENTRY glGetTextureHandleNV (GLuint texture); -GL_APICALL GLuint64 GL_APIENTRY glGetTextureSamplerHandleNV (GLuint texture, GLuint sampler); -GL_APICALL void GL_APIENTRY glMakeTextureHandleResidentNV (GLuint64 handle); -GL_APICALL void GL_APIENTRY glMakeTextureHandleNonResidentNV (GLuint64 handle); -GL_APICALL GLuint64 GL_APIENTRY glGetImageHandleNV (GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum format); -GL_APICALL void GL_APIENTRY glMakeImageHandleResidentNV (GLuint64 handle, GLenum access); -GL_APICALL void GL_APIENTRY glMakeImageHandleNonResidentNV (GLuint64 handle); -GL_APICALL void GL_APIENTRY glUniformHandleui64NV (GLint location, GLuint64 value); -GL_APICALL void GL_APIENTRY glUniformHandleui64vNV (GLint location, GLsizei count, const GLuint64 *value); -GL_APICALL void GL_APIENTRY glProgramUniformHandleui64NV (GLuint program, GLint location, GLuint64 value); -GL_APICALL void GL_APIENTRY glProgramUniformHandleui64vNV (GLuint program, GLint location, GLsizei count, const GLuint64 *values); -GL_APICALL GLboolean GL_APIENTRY glIsTextureHandleResidentNV (GLuint64 handle); -GL_APICALL GLboolean GL_APIENTRY glIsImageHandleResidentNV (GLuint64 handle); -#endif -#endif /* GL_NV_bindless_texture */ - -#ifndef GL_NV_blend_equation_advanced -#define GL_NV_blend_equation_advanced 1 -#define GL_BLEND_OVERLAP_NV 0x9281 -#define GL_BLEND_PREMULTIPLIED_SRC_NV 0x9280 -#define GL_BLUE_NV 0x1905 -#define GL_COLORBURN_NV 0x929A -#define GL_COLORDODGE_NV 0x9299 -#define GL_CONJOINT_NV 0x9284 -#define GL_CONTRAST_NV 0x92A1 -#define GL_DARKEN_NV 0x9297 -#define GL_DIFFERENCE_NV 0x929E -#define GL_DISJOINT_NV 0x9283 -#define GL_DST_ATOP_NV 0x928F -#define GL_DST_IN_NV 0x928B -#define GL_DST_NV 0x9287 -#define GL_DST_OUT_NV 0x928D -#define GL_DST_OVER_NV 0x9289 -#define GL_EXCLUSION_NV 0x92A0 -#define GL_GREEN_NV 0x1904 -#define GL_HARDLIGHT_NV 0x929B -#define GL_HARDMIX_NV 0x92A9 -#define GL_HSL_COLOR_NV 0x92AF -#define GL_HSL_HUE_NV 0x92AD -#define GL_HSL_LUMINOSITY_NV 0x92B0 -#define GL_HSL_SATURATION_NV 0x92AE -#define GL_INVERT_OVG_NV 0x92B4 -#define GL_INVERT_RGB_NV 0x92A3 -#define GL_LIGHTEN_NV 0x9298 -#define GL_LINEARBURN_NV 0x92A5 -#define GL_LINEARDODGE_NV 0x92A4 -#define GL_LINEARLIGHT_NV 0x92A7 -#define GL_MINUS_CLAMPED_NV 0x92B3 -#define GL_MINUS_NV 0x929F -#define GL_MULTIPLY_NV 0x9294 -#define GL_OVERLAY_NV 0x9296 -#define GL_PINLIGHT_NV 0x92A8 -#define GL_PLUS_CLAMPED_ALPHA_NV 0x92B2 -#define GL_PLUS_CLAMPED_NV 0x92B1 -#define GL_PLUS_DARKER_NV 0x9292 -#define GL_PLUS_NV 0x9291 -#define GL_RED_NV 0x1903 -#define GL_SCREEN_NV 0x9295 -#define GL_SOFTLIGHT_NV 0x929C -#define GL_SRC_ATOP_NV 0x928E -#define GL_SRC_IN_NV 0x928A -#define GL_SRC_NV 0x9286 -#define GL_SRC_OUT_NV 0x928C -#define GL_SRC_OVER_NV 0x9288 -#define GL_UNCORRELATED_NV 0x9282 -#define GL_VIVIDLIGHT_NV 0x92A6 -#define GL_XOR_NV 0x1506 -typedef void (GL_APIENTRYP PFNGLBLENDPARAMETERINVPROC) (GLenum pname, GLint value); -typedef void (GL_APIENTRYP PFNGLBLENDBARRIERNVPROC) (void); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBlendParameteriNV (GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glBlendBarrierNV (void); -#endif -#endif /* GL_NV_blend_equation_advanced */ - -#ifndef GL_NV_blend_equation_advanced_coherent -#define GL_NV_blend_equation_advanced_coherent 1 -#define GL_BLEND_ADVANCED_COHERENT_NV 0x9285 -#endif /* GL_NV_blend_equation_advanced_coherent */ - -#ifndef GL_NV_conditional_render -#define GL_NV_conditional_render 1 -#define GL_QUERY_WAIT_NV 0x8E13 -#define GL_QUERY_NO_WAIT_NV 0x8E14 -#define GL_QUERY_BY_REGION_WAIT_NV 0x8E15 -#define GL_QUERY_BY_REGION_NO_WAIT_NV 0x8E16 -typedef void (GL_APIENTRYP PFNGLBEGINCONDITIONALRENDERNVPROC) (GLuint id, GLenum mode); -typedef void (GL_APIENTRYP PFNGLENDCONDITIONALRENDERNVPROC) (void); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBeginConditionalRenderNV (GLuint id, GLenum mode); -GL_APICALL void GL_APIENTRY glEndConditionalRenderNV (void); -#endif -#endif /* GL_NV_conditional_render */ - -#ifndef GL_NV_copy_buffer -#define GL_NV_copy_buffer 1 -#define GL_COPY_READ_BUFFER_NV 0x8F36 -#define GL_COPY_WRITE_BUFFER_NV 0x8F37 -typedef void (GL_APIENTRYP PFNGLCOPYBUFFERSUBDATANVPROC) (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glCopyBufferSubDataNV (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -#endif -#endif /* GL_NV_copy_buffer */ - -#ifndef GL_NV_coverage_sample -#define GL_NV_coverage_sample 1 -#define GL_COVERAGE_COMPONENT_NV 0x8ED0 -#define GL_COVERAGE_COMPONENT4_NV 0x8ED1 -#define GL_COVERAGE_ATTACHMENT_NV 0x8ED2 -#define GL_COVERAGE_BUFFERS_NV 0x8ED3 -#define GL_COVERAGE_SAMPLES_NV 0x8ED4 -#define GL_COVERAGE_ALL_FRAGMENTS_NV 0x8ED5 -#define GL_COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6 -#define GL_COVERAGE_AUTOMATIC_NV 0x8ED7 -#define GL_COVERAGE_BUFFER_BIT_NV 0x00008000 -typedef void (GL_APIENTRYP PFNGLCOVERAGEMASKNVPROC) (GLboolean mask); -typedef void (GL_APIENTRYP PFNGLCOVERAGEOPERATIONNVPROC) (GLenum operation); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glCoverageMaskNV (GLboolean mask); -GL_APICALL void GL_APIENTRY glCoverageOperationNV (GLenum operation); -#endif -#endif /* GL_NV_coverage_sample */ - -#ifndef GL_NV_depth_nonlinear -#define GL_NV_depth_nonlinear 1 -#define GL_DEPTH_COMPONENT16_NONLINEAR_NV 0x8E2C -#endif /* GL_NV_depth_nonlinear */ - -#ifndef GL_NV_draw_buffers -#define GL_NV_draw_buffers 1 -#define GL_MAX_DRAW_BUFFERS_NV 0x8824 -#define GL_DRAW_BUFFER0_NV 0x8825 -#define GL_DRAW_BUFFER1_NV 0x8826 -#define GL_DRAW_BUFFER2_NV 0x8827 -#define GL_DRAW_BUFFER3_NV 0x8828 -#define GL_DRAW_BUFFER4_NV 0x8829 -#define GL_DRAW_BUFFER5_NV 0x882A -#define GL_DRAW_BUFFER6_NV 0x882B -#define GL_DRAW_BUFFER7_NV 0x882C -#define GL_DRAW_BUFFER8_NV 0x882D -#define GL_DRAW_BUFFER9_NV 0x882E -#define GL_DRAW_BUFFER10_NV 0x882F -#define GL_DRAW_BUFFER11_NV 0x8830 -#define GL_DRAW_BUFFER12_NV 0x8831 -#define GL_DRAW_BUFFER13_NV 0x8832 -#define GL_DRAW_BUFFER14_NV 0x8833 -#define GL_DRAW_BUFFER15_NV 0x8834 -#define GL_COLOR_ATTACHMENT0_NV 0x8CE0 -#define GL_COLOR_ATTACHMENT1_NV 0x8CE1 -#define GL_COLOR_ATTACHMENT2_NV 0x8CE2 -#define GL_COLOR_ATTACHMENT3_NV 0x8CE3 -#define GL_COLOR_ATTACHMENT4_NV 0x8CE4 -#define GL_COLOR_ATTACHMENT5_NV 0x8CE5 -#define GL_COLOR_ATTACHMENT6_NV 0x8CE6 -#define GL_COLOR_ATTACHMENT7_NV 0x8CE7 -#define GL_COLOR_ATTACHMENT8_NV 0x8CE8 -#define GL_COLOR_ATTACHMENT9_NV 0x8CE9 -#define GL_COLOR_ATTACHMENT10_NV 0x8CEA -#define GL_COLOR_ATTACHMENT11_NV 0x8CEB -#define GL_COLOR_ATTACHMENT12_NV 0x8CEC -#define GL_COLOR_ATTACHMENT13_NV 0x8CED -#define GL_COLOR_ATTACHMENT14_NV 0x8CEE -#define GL_COLOR_ATTACHMENT15_NV 0x8CEF -typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); -#endif -#endif /* GL_NV_draw_buffers */ - -#ifndef GL_NV_draw_instanced -#define GL_NV_draw_instanced 1 -typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); -#endif -#endif /* GL_NV_draw_instanced */ - -#ifndef GL_NV_explicit_attrib_location -#define GL_NV_explicit_attrib_location 1 -#endif /* GL_NV_explicit_attrib_location */ - -#ifndef GL_NV_fbo_color_attachments -#define GL_NV_fbo_color_attachments 1 -#define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF -#endif /* GL_NV_fbo_color_attachments */ - -#ifndef GL_NV_fence -#define GL_NV_fence 1 -#define GL_ALL_COMPLETED_NV 0x84F2 -#define GL_FENCE_STATUS_NV 0x84F3 -#define GL_FENCE_CONDITION_NV 0x84F4 -typedef void (GL_APIENTRYP PFNGLDELETEFENCESNVPROC) (GLsizei n, const GLuint *fences); -typedef void (GL_APIENTRYP PFNGLGENFENCESNVPROC) (GLsizei n, GLuint *fences); -typedef GLboolean (GL_APIENTRYP PFNGLISFENCENVPROC) (GLuint fence); -typedef GLboolean (GL_APIENTRYP PFNGLTESTFENCENVPROC) (GLuint fence); -typedef void (GL_APIENTRYP PFNGLGETFENCEIVNVPROC) (GLuint fence, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); -typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glDeleteFencesNV (GLsizei n, const GLuint *fences); -GL_APICALL void GL_APIENTRY glGenFencesNV (GLsizei n, GLuint *fences); -GL_APICALL GLboolean GL_APIENTRY glIsFenceNV (GLuint fence); -GL_APICALL GLboolean GL_APIENTRY glTestFenceNV (GLuint fence); -GL_APICALL void GL_APIENTRY glGetFenceivNV (GLuint fence, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glFinishFenceNV (GLuint fence); -GL_APICALL void GL_APIENTRY glSetFenceNV (GLuint fence, GLenum condition); -#endif -#endif /* GL_NV_fence */ - -#ifndef GL_NV_framebuffer_blit -#define GL_NV_framebuffer_blit 1 -#define GL_READ_FRAMEBUFFER_NV 0x8CA8 -#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9 -#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6 -#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA -typedef void (GL_APIENTRYP PFNGLBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glBlitFramebufferNV (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -#endif -#endif /* GL_NV_framebuffer_blit */ - -#ifndef GL_NV_framebuffer_multisample -#define GL_NV_framebuffer_multisample 1 -#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56 -#define GL_MAX_SAMPLES_NV 0x8D57 -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLENVPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -#endif -#endif /* GL_NV_framebuffer_multisample */ - -#ifndef GL_NV_generate_mipmap_sRGB -#define GL_NV_generate_mipmap_sRGB 1 -#endif /* GL_NV_generate_mipmap_sRGB */ - -#ifndef GL_NV_image_formats -#define GL_NV_image_formats 1 -#endif /* GL_NV_image_formats */ - -#ifndef GL_NV_instanced_arrays -#define GL_NV_instanced_arrays 1 -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE -typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor); -#endif -#endif /* GL_NV_instanced_arrays */ - -#ifndef GL_NV_internalformat_sample_query -#define GL_NV_internalformat_sample_query 1 -#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 -#define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102 -#define GL_MULTISAMPLES_NV 0x9371 -#define GL_SUPERSAMPLE_SCALE_X_NV 0x9372 -#define GL_SUPERSAMPLE_SCALE_Y_NV 0x9373 -#define GL_CONFORMANT_NV 0x9374 -typedef void (GL_APIENTRYP PFNGLGETINTERNALFORMATSAMPLEIVNVPROC) (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetInternalformatSampleivNV (GLenum target, GLenum internalformat, GLsizei samples, GLenum pname, GLsizei bufSize, GLint *params); -#endif -#endif /* GL_NV_internalformat_sample_query */ - -#ifndef GL_NV_non_square_matrices -#define GL_NV_non_square_matrices 1 -#define GL_FLOAT_MAT2x3_NV 0x8B65 -#define GL_FLOAT_MAT2x4_NV 0x8B66 -#define GL_FLOAT_MAT3x2_NV 0x8B67 -#define GL_FLOAT_MAT3x4_NV 0x8B68 -#define GL_FLOAT_MAT4x2_NV 0x8B69 -#define GL_FLOAT_MAT4x3_NV 0x8B6A -typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX2X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X2FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX3X4FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLUNIFORMMATRIX4X3FVNVPROC) (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glUniformMatrix2x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix2x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x2fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x4fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x3fvNV (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -#endif -#endif /* GL_NV_non_square_matrices */ - -#ifndef GL_NV_path_rendering -#define GL_NV_path_rendering 1 -#define GL_PATH_FORMAT_SVG_NV 0x9070 -#define GL_PATH_FORMAT_PS_NV 0x9071 -#define GL_STANDARD_FONT_NAME_NV 0x9072 -#define GL_SYSTEM_FONT_NAME_NV 0x9073 -#define GL_FILE_NAME_NV 0x9074 -#define GL_PATH_STROKE_WIDTH_NV 0x9075 -#define GL_PATH_END_CAPS_NV 0x9076 -#define GL_PATH_INITIAL_END_CAP_NV 0x9077 -#define GL_PATH_TERMINAL_END_CAP_NV 0x9078 -#define GL_PATH_JOIN_STYLE_NV 0x9079 -#define GL_PATH_MITER_LIMIT_NV 0x907A -#define GL_PATH_DASH_CAPS_NV 0x907B -#define GL_PATH_INITIAL_DASH_CAP_NV 0x907C -#define GL_PATH_TERMINAL_DASH_CAP_NV 0x907D -#define GL_PATH_DASH_OFFSET_NV 0x907E -#define GL_PATH_CLIENT_LENGTH_NV 0x907F -#define GL_PATH_FILL_MODE_NV 0x9080 -#define GL_PATH_FILL_MASK_NV 0x9081 -#define GL_PATH_FILL_COVER_MODE_NV 0x9082 -#define GL_PATH_STROKE_COVER_MODE_NV 0x9083 -#define GL_PATH_STROKE_MASK_NV 0x9084 -#define GL_COUNT_UP_NV 0x9088 -#define GL_COUNT_DOWN_NV 0x9089 -#define GL_PATH_OBJECT_BOUNDING_BOX_NV 0x908A -#define GL_CONVEX_HULL_NV 0x908B -#define GL_BOUNDING_BOX_NV 0x908D -#define GL_TRANSLATE_X_NV 0x908E -#define GL_TRANSLATE_Y_NV 0x908F -#define GL_TRANSLATE_2D_NV 0x9090 -#define GL_TRANSLATE_3D_NV 0x9091 -#define GL_AFFINE_2D_NV 0x9092 -#define GL_AFFINE_3D_NV 0x9094 -#define GL_TRANSPOSE_AFFINE_2D_NV 0x9096 -#define GL_TRANSPOSE_AFFINE_3D_NV 0x9098 -#define GL_UTF8_NV 0x909A -#define GL_UTF16_NV 0x909B -#define GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV 0x909C -#define GL_PATH_COMMAND_COUNT_NV 0x909D -#define GL_PATH_COORD_COUNT_NV 0x909E -#define GL_PATH_DASH_ARRAY_COUNT_NV 0x909F -#define GL_PATH_COMPUTED_LENGTH_NV 0x90A0 -#define GL_PATH_FILL_BOUNDING_BOX_NV 0x90A1 -#define GL_PATH_STROKE_BOUNDING_BOX_NV 0x90A2 -#define GL_SQUARE_NV 0x90A3 -#define GL_ROUND_NV 0x90A4 -#define GL_TRIANGULAR_NV 0x90A5 -#define GL_BEVEL_NV 0x90A6 -#define GL_MITER_REVERT_NV 0x90A7 -#define GL_MITER_TRUNCATE_NV 0x90A8 -#define GL_SKIP_MISSING_GLYPH_NV 0x90A9 -#define GL_USE_MISSING_GLYPH_NV 0x90AA -#define GL_PATH_ERROR_POSITION_NV 0x90AB -#define GL_ACCUM_ADJACENT_PAIRS_NV 0x90AD -#define GL_ADJACENT_PAIRS_NV 0x90AE -#define GL_FIRST_TO_REST_NV 0x90AF -#define GL_PATH_GEN_MODE_NV 0x90B0 -#define GL_PATH_GEN_COEFF_NV 0x90B1 -#define GL_PATH_GEN_COMPONENTS_NV 0x90B3 -#define GL_PATH_STENCIL_FUNC_NV 0x90B7 -#define GL_PATH_STENCIL_REF_NV 0x90B8 -#define GL_PATH_STENCIL_VALUE_MASK_NV 0x90B9 -#define GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV 0x90BD -#define GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV 0x90BE -#define GL_PATH_COVER_DEPTH_FUNC_NV 0x90BF -#define GL_PATH_DASH_OFFSET_RESET_NV 0x90B4 -#define GL_MOVE_TO_RESETS_NV 0x90B5 -#define GL_MOVE_TO_CONTINUES_NV 0x90B6 -#define GL_CLOSE_PATH_NV 0x00 -#define GL_MOVE_TO_NV 0x02 -#define GL_RELATIVE_MOVE_TO_NV 0x03 -#define GL_LINE_TO_NV 0x04 -#define GL_RELATIVE_LINE_TO_NV 0x05 -#define GL_HORIZONTAL_LINE_TO_NV 0x06 -#define GL_RELATIVE_HORIZONTAL_LINE_TO_NV 0x07 -#define GL_VERTICAL_LINE_TO_NV 0x08 -#define GL_RELATIVE_VERTICAL_LINE_TO_NV 0x09 -#define GL_QUADRATIC_CURVE_TO_NV 0x0A -#define GL_RELATIVE_QUADRATIC_CURVE_TO_NV 0x0B -#define GL_CUBIC_CURVE_TO_NV 0x0C -#define GL_RELATIVE_CUBIC_CURVE_TO_NV 0x0D -#define GL_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0E -#define GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV 0x0F -#define GL_SMOOTH_CUBIC_CURVE_TO_NV 0x10 -#define GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV 0x11 -#define GL_SMALL_CCW_ARC_TO_NV 0x12 -#define GL_RELATIVE_SMALL_CCW_ARC_TO_NV 0x13 -#define GL_SMALL_CW_ARC_TO_NV 0x14 -#define GL_RELATIVE_SMALL_CW_ARC_TO_NV 0x15 -#define GL_LARGE_CCW_ARC_TO_NV 0x16 -#define GL_RELATIVE_LARGE_CCW_ARC_TO_NV 0x17 -#define GL_LARGE_CW_ARC_TO_NV 0x18 -#define GL_RELATIVE_LARGE_CW_ARC_TO_NV 0x19 -#define GL_RESTART_PATH_NV 0xF0 -#define GL_DUP_FIRST_CUBIC_CURVE_TO_NV 0xF2 -#define GL_DUP_LAST_CUBIC_CURVE_TO_NV 0xF4 -#define GL_RECT_NV 0xF6 -#define GL_CIRCULAR_CCW_ARC_TO_NV 0xF8 -#define GL_CIRCULAR_CW_ARC_TO_NV 0xFA -#define GL_CIRCULAR_TANGENT_ARC_TO_NV 0xFC -#define GL_ARC_TO_NV 0xFE -#define GL_RELATIVE_ARC_TO_NV 0xFF -#define GL_BOLD_BIT_NV 0x01 -#define GL_ITALIC_BIT_NV 0x02 -#define GL_GLYPH_WIDTH_BIT_NV 0x01 -#define GL_GLYPH_HEIGHT_BIT_NV 0x02 -#define GL_GLYPH_HORIZONTAL_BEARING_X_BIT_NV 0x04 -#define GL_GLYPH_HORIZONTAL_BEARING_Y_BIT_NV 0x08 -#define GL_GLYPH_HORIZONTAL_BEARING_ADVANCE_BIT_NV 0x10 -#define GL_GLYPH_VERTICAL_BEARING_X_BIT_NV 0x20 -#define GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV 0x40 -#define GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV 0x80 -#define GL_GLYPH_HAS_KERNING_BIT_NV 0x100 -#define GL_FONT_X_MIN_BOUNDS_BIT_NV 0x00010000 -#define GL_FONT_Y_MIN_BOUNDS_BIT_NV 0x00020000 -#define GL_FONT_X_MAX_BOUNDS_BIT_NV 0x00040000 -#define GL_FONT_Y_MAX_BOUNDS_BIT_NV 0x00080000 -#define GL_FONT_UNITS_PER_EM_BIT_NV 0x00100000 -#define GL_FONT_ASCENDER_BIT_NV 0x00200000 -#define GL_FONT_DESCENDER_BIT_NV 0x00400000 -#define GL_FONT_HEIGHT_BIT_NV 0x00800000 -#define GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV 0x01000000 -#define GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV 0x02000000 -#define GL_FONT_UNDERLINE_POSITION_BIT_NV 0x04000000 -#define GL_FONT_UNDERLINE_THICKNESS_BIT_NV 0x08000000 -#define GL_FONT_HAS_KERNING_BIT_NV 0x10000000 -#define GL_ROUNDED_RECT_NV 0xE8 -#define GL_RELATIVE_ROUNDED_RECT_NV 0xE9 -#define GL_ROUNDED_RECT2_NV 0xEA -#define GL_RELATIVE_ROUNDED_RECT2_NV 0xEB -#define GL_ROUNDED_RECT4_NV 0xEC -#define GL_RELATIVE_ROUNDED_RECT4_NV 0xED -#define GL_ROUNDED_RECT8_NV 0xEE -#define GL_RELATIVE_ROUNDED_RECT8_NV 0xEF -#define GL_RELATIVE_RECT_NV 0xF7 -#define GL_FONT_GLYPHS_AVAILABLE_NV 0x9368 -#define GL_FONT_TARGET_UNAVAILABLE_NV 0x9369 -#define GL_FONT_UNAVAILABLE_NV 0x936A -#define GL_FONT_UNINTELLIGIBLE_NV 0x936B -#define GL_CONIC_CURVE_TO_NV 0x1A -#define GL_RELATIVE_CONIC_CURVE_TO_NV 0x1B -#define GL_FONT_NUM_GLYPH_INDICES_BIT_NV 0x20000000 -#define GL_STANDARD_FONT_FORMAT_NV 0x936C -#define GL_PATH_PROJECTION_NV 0x1701 -#define GL_PATH_MODELVIEW_NV 0x1700 -#define GL_PATH_MODELVIEW_STACK_DEPTH_NV 0x0BA3 -#define GL_PATH_MODELVIEW_MATRIX_NV 0x0BA6 -#define GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV 0x0D36 -#define GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV 0x84E3 -#define GL_PATH_PROJECTION_STACK_DEPTH_NV 0x0BA4 -#define GL_PATH_PROJECTION_MATRIX_NV 0x0BA7 -#define GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV 0x0D38 -#define GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV 0x84E4 -#define GL_FRAGMENT_INPUT_NV 0x936D -typedef GLuint (GL_APIENTRYP PFNGLGENPATHSNVPROC) (GLsizei range); -typedef void (GL_APIENTRYP PFNGLDELETEPATHSNVPROC) (GLuint path, GLsizei range); -typedef GLboolean (GL_APIENTRYP PFNGLISPATHNVPROC) (GLuint path); -typedef void (GL_APIENTRYP PFNGLPATHCOMMANDSNVPROC) (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); -typedef void (GL_APIENTRYP PFNGLPATHCOORDSNVPROC) (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); -typedef void (GL_APIENTRYP PFNGLPATHSUBCOMMANDSNVPROC) (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); -typedef void (GL_APIENTRYP PFNGLPATHSUBCOORDSNVPROC) (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); -typedef void (GL_APIENTRYP PFNGLPATHSTRINGNVPROC) (GLuint path, GLenum format, GLsizei length, const void *pathString); -typedef void (GL_APIENTRYP PFNGLPATHGLYPHSNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -typedef void (GL_APIENTRYP PFNGLPATHGLYPHRANGENVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -typedef void (GL_APIENTRYP PFNGLWEIGHTPATHSNVPROC) (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); -typedef void (GL_APIENTRYP PFNGLCOPYPATHNVPROC) (GLuint resultPath, GLuint srcPath); -typedef void (GL_APIENTRYP PFNGLINTERPOLATEPATHSNVPROC) (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); -typedef void (GL_APIENTRYP PFNGLTRANSFORMPATHNVPROC) (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); -typedef void (GL_APIENTRYP PFNGLPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, const GLint *value); -typedef void (GL_APIENTRYP PFNGLPATHPARAMETERINVPROC) (GLuint path, GLenum pname, GLint value); -typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, const GLfloat *value); -typedef void (GL_APIENTRYP PFNGLPATHPARAMETERFNVPROC) (GLuint path, GLenum pname, GLfloat value); -typedef void (GL_APIENTRYP PFNGLPATHDASHARRAYNVPROC) (GLuint path, GLsizei dashCount, const GLfloat *dashArray); -typedef void (GL_APIENTRYP PFNGLPATHSTENCILFUNCNVPROC) (GLenum func, GLint ref, GLuint mask); -typedef void (GL_APIENTRYP PFNGLPATHSTENCILDEPTHOFFSETNVPROC) (GLfloat factor, GLfloat units); -typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask); -typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask); -typedef void (GL_APIENTRYP PFNGLSTENCILFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); -typedef void (GL_APIENTRYP PFNGLSTENCILSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); -typedef void (GL_APIENTRYP PFNGLPATHCOVERDEPTHFUNCNVPROC) (GLenum func); -typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHNVPROC) (GLuint path, GLenum coverMode); -typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHNVPROC) (GLuint path, GLenum coverMode); -typedef void (GL_APIENTRYP PFNGLCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -typedef void (GL_APIENTRYP PFNGLCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERIVNVPROC) (GLuint path, GLenum pname, GLint *value); -typedef void (GL_APIENTRYP PFNGLGETPATHPARAMETERFVNVPROC) (GLuint path, GLenum pname, GLfloat *value); -typedef void (GL_APIENTRYP PFNGLGETPATHCOMMANDSNVPROC) (GLuint path, GLubyte *commands); -typedef void (GL_APIENTRYP PFNGLGETPATHCOORDSNVPROC) (GLuint path, GLfloat *coords); -typedef void (GL_APIENTRYP PFNGLGETPATHDASHARRAYNVPROC) (GLuint path, GLfloat *dashArray); -typedef void (GL_APIENTRYP PFNGLGETPATHMETRICSNVPROC) (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); -typedef void (GL_APIENTRYP PFNGLGETPATHMETRICRANGENVPROC) (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); -typedef void (GL_APIENTRYP PFNGLGETPATHSPACINGNVPROC) (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); -typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINFILLPATHNVPROC) (GLuint path, GLuint mask, GLfloat x, GLfloat y); -typedef GLboolean (GL_APIENTRYP PFNGLISPOINTINSTROKEPATHNVPROC) (GLuint path, GLfloat x, GLfloat y); -typedef GLfloat (GL_APIENTRYP PFNGLGETPATHLENGTHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments); -typedef GLboolean (GL_APIENTRYP PFNGLPOINTALONGPATHNVPROC) (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); -typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X2FNVPROC) (GLenum matrixMode, const GLfloat *m); -typedef void (GL_APIENTRYP PFNGLMATRIXLOAD3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); -typedef void (GL_APIENTRYP PFNGLMATRIXLOADTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); -typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X2FNVPROC) (GLenum matrixMode, const GLfloat *m); -typedef void (GL_APIENTRYP PFNGLMATRIXMULT3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); -typedef void (GL_APIENTRYP PFNGLMATRIXMULTTRANSPOSE3X3FNVPROC) (GLenum matrixMode, const GLfloat *m); -typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHNVPROC) (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode); -typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHNVPROC) (GLuint path, GLint reference, GLuint mask, GLenum coverMode); -typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERFILLPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -typedef void (GL_APIENTRYP PFNGLSTENCILTHENCOVERSTROKEPATHINSTANCEDNVPROC) (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXRANGENVPROC) (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); -typedef GLenum (GL_APIENTRYP PFNGLPATHGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -typedef GLenum (GL_APIENTRYP PFNGLPATHMEMORYGLYPHINDEXARRAYNVPROC) (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -typedef void (GL_APIENTRYP PFNGLPROGRAMPATHFRAGMENTINPUTGENNVPROC) (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); -typedef void (GL_APIENTRYP PFNGLGETPROGRAMRESOURCEFVNVPROC) (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL GLuint GL_APIENTRY glGenPathsNV (GLsizei range); -GL_APICALL void GL_APIENTRY glDeletePathsNV (GLuint path, GLsizei range); -GL_APICALL GLboolean GL_APIENTRY glIsPathNV (GLuint path); -GL_APICALL void GL_APIENTRY glPathCommandsNV (GLuint path, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); -GL_APICALL void GL_APIENTRY glPathCoordsNV (GLuint path, GLsizei numCoords, GLenum coordType, const void *coords); -GL_APICALL void GL_APIENTRY glPathSubCommandsNV (GLuint path, GLsizei commandStart, GLsizei commandsToDelete, GLsizei numCommands, const GLubyte *commands, GLsizei numCoords, GLenum coordType, const void *coords); -GL_APICALL void GL_APIENTRY glPathSubCoordsNV (GLuint path, GLsizei coordStart, GLsizei numCoords, GLenum coordType, const void *coords); -GL_APICALL void GL_APIENTRY glPathStringNV (GLuint path, GLenum format, GLsizei length, const void *pathString); -GL_APICALL void GL_APIENTRY glPathGlyphsNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLsizei numGlyphs, GLenum type, const void *charcodes, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -GL_APICALL void GL_APIENTRY glPathGlyphRangeNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyph, GLsizei numGlyphs, GLenum handleMissingGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -GL_APICALL void GL_APIENTRY glWeightPathsNV (GLuint resultPath, GLsizei numPaths, const GLuint *paths, const GLfloat *weights); -GL_APICALL void GL_APIENTRY glCopyPathNV (GLuint resultPath, GLuint srcPath); -GL_APICALL void GL_APIENTRY glInterpolatePathsNV (GLuint resultPath, GLuint pathA, GLuint pathB, GLfloat weight); -GL_APICALL void GL_APIENTRY glTransformPathNV (GLuint resultPath, GLuint srcPath, GLenum transformType, const GLfloat *transformValues); -GL_APICALL void GL_APIENTRY glPathParameterivNV (GLuint path, GLenum pname, const GLint *value); -GL_APICALL void GL_APIENTRY glPathParameteriNV (GLuint path, GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glPathParameterfvNV (GLuint path, GLenum pname, const GLfloat *value); -GL_APICALL void GL_APIENTRY glPathParameterfNV (GLuint path, GLenum pname, GLfloat value); -GL_APICALL void GL_APIENTRY glPathDashArrayNV (GLuint path, GLsizei dashCount, const GLfloat *dashArray); -GL_APICALL void GL_APIENTRY glPathStencilFuncNV (GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glPathStencilDepthOffsetNV (GLfloat factor, GLfloat units); -GL_APICALL void GL_APIENTRY glStencilFillPathNV (GLuint path, GLenum fillMode, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilStrokePathNV (GLuint path, GLint reference, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum transformType, const GLfloat *transformValues); -GL_APICALL void GL_APIENTRY glStencilStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum transformType, const GLfloat *transformValues); -GL_APICALL void GL_APIENTRY glPathCoverDepthFuncNV (GLenum func); -GL_APICALL void GL_APIENTRY glCoverFillPathNV (GLuint path, GLenum coverMode); -GL_APICALL void GL_APIENTRY glCoverStrokePathNV (GLuint path, GLenum coverMode); -GL_APICALL void GL_APIENTRY glCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -GL_APICALL void GL_APIENTRY glCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -GL_APICALL void GL_APIENTRY glGetPathParameterivNV (GLuint path, GLenum pname, GLint *value); -GL_APICALL void GL_APIENTRY glGetPathParameterfvNV (GLuint path, GLenum pname, GLfloat *value); -GL_APICALL void GL_APIENTRY glGetPathCommandsNV (GLuint path, GLubyte *commands); -GL_APICALL void GL_APIENTRY glGetPathCoordsNV (GLuint path, GLfloat *coords); -GL_APICALL void GL_APIENTRY glGetPathDashArrayNV (GLuint path, GLfloat *dashArray); -GL_APICALL void GL_APIENTRY glGetPathMetricsNV (GLbitfield metricQueryMask, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLsizei stride, GLfloat *metrics); -GL_APICALL void GL_APIENTRY glGetPathMetricRangeNV (GLbitfield metricQueryMask, GLuint firstPathName, GLsizei numPaths, GLsizei stride, GLfloat *metrics); -GL_APICALL void GL_APIENTRY glGetPathSpacingNV (GLenum pathListMode, GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLfloat advanceScale, GLfloat kerningScale, GLenum transformType, GLfloat *returnedSpacing); -GL_APICALL GLboolean GL_APIENTRY glIsPointInFillPathNV (GLuint path, GLuint mask, GLfloat x, GLfloat y); -GL_APICALL GLboolean GL_APIENTRY glIsPointInStrokePathNV (GLuint path, GLfloat x, GLfloat y); -GL_APICALL GLfloat GL_APIENTRY glGetPathLengthNV (GLuint path, GLsizei startSegment, GLsizei numSegments); -GL_APICALL GLboolean GL_APIENTRY glPointAlongPathNV (GLuint path, GLsizei startSegment, GLsizei numSegments, GLfloat distance, GLfloat *x, GLfloat *y, GLfloat *tangentX, GLfloat *tangentY); -GL_APICALL void GL_APIENTRY glMatrixLoad3x2fNV (GLenum matrixMode, const GLfloat *m); -GL_APICALL void GL_APIENTRY glMatrixLoad3x3fNV (GLenum matrixMode, const GLfloat *m); -GL_APICALL void GL_APIENTRY glMatrixLoadTranspose3x3fNV (GLenum matrixMode, const GLfloat *m); -GL_APICALL void GL_APIENTRY glMatrixMult3x2fNV (GLenum matrixMode, const GLfloat *m); -GL_APICALL void GL_APIENTRY glMatrixMult3x3fNV (GLenum matrixMode, const GLfloat *m); -GL_APICALL void GL_APIENTRY glMatrixMultTranspose3x3fNV (GLenum matrixMode, const GLfloat *m); -GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathNV (GLuint path, GLenum fillMode, GLuint mask, GLenum coverMode); -GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathNV (GLuint path, GLint reference, GLuint mask, GLenum coverMode); -GL_APICALL void GL_APIENTRY glStencilThenCoverFillPathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLenum fillMode, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -GL_APICALL void GL_APIENTRY glStencilThenCoverStrokePathInstancedNV (GLsizei numPaths, GLenum pathNameType, const void *paths, GLuint pathBase, GLint reference, GLuint mask, GLenum coverMode, GLenum transformType, const GLfloat *transformValues); -GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexRangeNV (GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint pathParameterTemplate, GLfloat emScale, GLuint baseAndCount[2]); -GL_APICALL GLenum GL_APIENTRY glPathGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, const void *fontName, GLbitfield fontStyle, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -GL_APICALL GLenum GL_APIENTRY glPathMemoryGlyphIndexArrayNV (GLuint firstPathName, GLenum fontTarget, GLsizeiptr fontSize, const void *fontData, GLsizei faceIndex, GLuint firstGlyphIndex, GLsizei numGlyphs, GLuint pathParameterTemplate, GLfloat emScale); -GL_APICALL void GL_APIENTRY glProgramPathFragmentInputGenNV (GLuint program, GLint location, GLenum genMode, GLint components, const GLfloat *coeffs); -GL_APICALL void GL_APIENTRY glGetProgramResourcefvNV (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLfloat *params); -#endif -#endif /* GL_NV_path_rendering */ - -#ifndef GL_NV_read_buffer -#define GL_NV_read_buffer 1 -#define GL_READ_BUFFER_NV 0x0C02 -typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glReadBufferNV (GLenum mode); -#endif -#endif /* GL_NV_read_buffer */ - -#ifndef GL_NV_read_buffer_front -#define GL_NV_read_buffer_front 1 -#endif /* GL_NV_read_buffer_front */ - -#ifndef GL_NV_read_depth -#define GL_NV_read_depth 1 -#endif /* GL_NV_read_depth */ - -#ifndef GL_NV_read_depth_stencil -#define GL_NV_read_depth_stencil 1 -#endif /* GL_NV_read_depth_stencil */ - -#ifndef GL_NV_read_stencil -#define GL_NV_read_stencil 1 -#endif /* GL_NV_read_stencil */ - -#ifndef GL_NV_sRGB_formats -#define GL_NV_sRGB_formats 1 -#define GL_SLUMINANCE_NV 0x8C46 -#define GL_SLUMINANCE_ALPHA_NV 0x8C44 -#define GL_SRGB8_NV 0x8C41 -#define GL_SLUMINANCE8_NV 0x8C47 -#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45 -#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E -#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F -#define GL_ETC1_SRGB8_NV 0x88EE -#endif /* GL_NV_sRGB_formats */ - -#ifndef GL_NV_shader_noperspective_interpolation -#define GL_NV_shader_noperspective_interpolation 1 -#endif /* GL_NV_shader_noperspective_interpolation */ - -#ifndef GL_NV_shadow_samplers_array -#define GL_NV_shadow_samplers_array 1 -#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4 -#endif /* GL_NV_shadow_samplers_array */ - -#ifndef GL_NV_shadow_samplers_cube -#define GL_NV_shadow_samplers_cube 1 -#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5 -#endif /* GL_NV_shadow_samplers_cube */ - -#ifndef GL_NV_texture_border_clamp -#define GL_NV_texture_border_clamp 1 -#define GL_TEXTURE_BORDER_COLOR_NV 0x1004 -#define GL_CLAMP_TO_BORDER_NV 0x812D -#endif /* GL_NV_texture_border_clamp */ - -#ifndef GL_NV_texture_compression_s3tc_update -#define GL_NV_texture_compression_s3tc_update 1 -#endif /* GL_NV_texture_compression_s3tc_update */ - -#ifndef GL_NV_texture_npot_2D_mipmap -#define GL_NV_texture_npot_2D_mipmap 1 -#endif /* GL_NV_texture_npot_2D_mipmap */ - -#ifndef GL_NV_viewport_array -#define GL_NV_viewport_array 1 -#define GL_MAX_VIEWPORTS_NV 0x825B -#define GL_VIEWPORT_SUBPIXEL_BITS_NV 0x825C -#define GL_VIEWPORT_BOUNDS_RANGE_NV 0x825D -#define GL_VIEWPORT_INDEX_PROVOKING_VERTEX_NV 0x825F -typedef void (GL_APIENTRYP PFNGLVIEWPORTARRAYVNVPROC) (GLuint first, GLsizei count, const GLfloat *v); -typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFNVPROC) (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); -typedef void (GL_APIENTRYP PFNGLVIEWPORTINDEXEDFVNVPROC) (GLuint index, const GLfloat *v); -typedef void (GL_APIENTRYP PFNGLSCISSORARRAYVNVPROC) (GLuint first, GLsizei count, const GLint *v); -typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDNVPROC) (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLSCISSORINDEXEDVNVPROC) (GLuint index, const GLint *v); -typedef void (GL_APIENTRYP PFNGLDEPTHRANGEARRAYFVNVPROC) (GLuint first, GLsizei count, const GLfloat *v); -typedef void (GL_APIENTRYP PFNGLDEPTHRANGEINDEXEDFNVPROC) (GLuint index, GLfloat n, GLfloat f); -typedef void (GL_APIENTRYP PFNGLGETFLOATI_VNVPROC) (GLenum target, GLuint index, GLfloat *data); -typedef void (GL_APIENTRYP PFNGLENABLEINVPROC) (GLenum target, GLuint index); -typedef void (GL_APIENTRYP PFNGLDISABLEINVPROC) (GLenum target, GLuint index); -typedef GLboolean (GL_APIENTRYP PFNGLISENABLEDINVPROC) (GLenum target, GLuint index); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glViewportArrayvNV (GLuint first, GLsizei count, const GLfloat *v); -GL_APICALL void GL_APIENTRY glViewportIndexedfNV (GLuint index, GLfloat x, GLfloat y, GLfloat w, GLfloat h); -GL_APICALL void GL_APIENTRY glViewportIndexedfvNV (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glScissorArrayvNV (GLuint first, GLsizei count, const GLint *v); -GL_APICALL void GL_APIENTRY glScissorIndexedNV (GLuint index, GLint left, GLint bottom, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glScissorIndexedvNV (GLuint index, const GLint *v); -GL_APICALL void GL_APIENTRY glDepthRangeArrayfvNV (GLuint first, GLsizei count, const GLfloat *v); -GL_APICALL void GL_APIENTRY glDepthRangeIndexedfNV (GLuint index, GLfloat n, GLfloat f); -GL_APICALL void GL_APIENTRY glGetFloati_vNV (GLenum target, GLuint index, GLfloat *data); -GL_APICALL void GL_APIENTRY glEnableiNV (GLenum target, GLuint index); -GL_APICALL void GL_APIENTRY glDisableiNV (GLenum target, GLuint index); -GL_APICALL GLboolean GL_APIENTRY glIsEnablediNV (GLenum target, GLuint index); -#endif -#endif /* GL_NV_viewport_array */ - -#ifndef GL_QCOM_alpha_test -#define GL_QCOM_alpha_test 1 -#define GL_ALPHA_TEST_QCOM 0x0BC0 -#define GL_ALPHA_TEST_FUNC_QCOM 0x0BC1 -#define GL_ALPHA_TEST_REF_QCOM 0x0BC2 -typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); -#endif -#endif /* GL_QCOM_alpha_test */ - -#ifndef GL_QCOM_binning_control -#define GL_QCOM_binning_control 1 -#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 -#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 -#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 -#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 -#endif /* GL_QCOM_binning_control */ - -#ifndef GL_QCOM_driver_control -#define GL_QCOM_driver_control 1 -typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSQCOMPROC) (GLint *num, GLsizei size, GLuint *driverControls); -typedef void (GL_APIENTRYP PFNGLGETDRIVERCONTROLSTRINGQCOMPROC) (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); -typedef void (GL_APIENTRYP PFNGLENABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); -typedef void (GL_APIENTRYP PFNGLDISABLEDRIVERCONTROLQCOMPROC) (GLuint driverControl); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetDriverControlsQCOM (GLint *num, GLsizei size, GLuint *driverControls); -GL_APICALL void GL_APIENTRY glGetDriverControlStringQCOM (GLuint driverControl, GLsizei bufSize, GLsizei *length, GLchar *driverControlString); -GL_APICALL void GL_APIENTRY glEnableDriverControlQCOM (GLuint driverControl); -GL_APICALL void GL_APIENTRY glDisableDriverControlQCOM (GLuint driverControl); -#endif -#endif /* GL_QCOM_driver_control */ - -#ifndef GL_QCOM_extended_get -#define GL_QCOM_extended_get 1 -#define GL_TEXTURE_WIDTH_QCOM 0x8BD2 -#define GL_TEXTURE_HEIGHT_QCOM 0x8BD3 -#define GL_TEXTURE_DEPTH_QCOM 0x8BD4 -#define GL_TEXTURE_INTERNAL_FORMAT_QCOM 0x8BD5 -#define GL_TEXTURE_FORMAT_QCOM 0x8BD6 -#define GL_TEXTURE_TYPE_QCOM 0x8BD7 -#define GL_TEXTURE_IMAGE_VALID_QCOM 0x8BD8 -#define GL_TEXTURE_NUM_LEVELS_QCOM 0x8BD9 -#define GL_TEXTURE_TARGET_QCOM 0x8BDA -#define GL_TEXTURE_OBJECT_VALID_QCOM 0x8BDB -#define GL_STATE_RESTORE 0x8BDC -typedef void (GL_APIENTRYP PFNGLEXTGETTEXTURESQCOMPROC) (GLuint *textures, GLint maxTextures, GLint *numTextures); -typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERSQCOMPROC) (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETRENDERBUFFERSQCOMPROC) (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETFRAMEBUFFERSQCOMPROC) (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); -typedef void (GL_APIENTRYP PFNGLEXTGETTEXLEVELPARAMETERIVQCOMPROC) (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); -typedef void (GL_APIENTRYP PFNGLEXTTEXOBJECTSTATEOVERRIDEIQCOMPROC) (GLenum target, GLenum pname, GLint param); -typedef void (GL_APIENTRYP PFNGLEXTGETTEXSUBIMAGEQCOMPROC) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels); -typedef void (GL_APIENTRYP PFNGLEXTGETBUFFERPOINTERVQCOMPROC) (GLenum target, void **params); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glExtGetTexturesQCOM (GLuint *textures, GLint maxTextures, GLint *numTextures); -GL_APICALL void GL_APIENTRY glExtGetBuffersQCOM (GLuint *buffers, GLint maxBuffers, GLint *numBuffers); -GL_APICALL void GL_APIENTRY glExtGetRenderbuffersQCOM (GLuint *renderbuffers, GLint maxRenderbuffers, GLint *numRenderbuffers); -GL_APICALL void GL_APIENTRY glExtGetFramebuffersQCOM (GLuint *framebuffers, GLint maxFramebuffers, GLint *numFramebuffers); -GL_APICALL void GL_APIENTRY glExtGetTexLevelParameterivQCOM (GLuint texture, GLenum face, GLint level, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glExtTexObjectStateOverrideiQCOM (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glExtGetTexSubImageQCOM (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, void *texels); -GL_APICALL void GL_APIENTRY glExtGetBufferPointervQCOM (GLenum target, void **params); -#endif -#endif /* GL_QCOM_extended_get */ - -#ifndef GL_QCOM_extended_get2 -#define GL_QCOM_extended_get2 1 -typedef void (GL_APIENTRYP PFNGLEXTGETSHADERSQCOMPROC) (GLuint *shaders, GLint maxShaders, GLint *numShaders); -typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMSQCOMPROC) (GLuint *programs, GLint maxPrograms, GLint *numPrograms); -typedef GLboolean (GL_APIENTRYP PFNGLEXTISPROGRAMBINARYQCOMPROC) (GLuint program); -typedef void (GL_APIENTRYP PFNGLEXTGETPROGRAMBINARYSOURCEQCOMPROC) (GLuint program, GLenum shadertype, GLchar *source, GLint *length); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glExtGetShadersQCOM (GLuint *shaders, GLint maxShaders, GLint *numShaders); -GL_APICALL void GL_APIENTRY glExtGetProgramsQCOM (GLuint *programs, GLint maxPrograms, GLint *numPrograms); -GL_APICALL GLboolean GL_APIENTRY glExtIsProgramBinaryQCOM (GLuint program); -GL_APICALL void GL_APIENTRY glExtGetProgramBinarySourceQCOM (GLuint program, GLenum shadertype, GLchar *source, GLint *length); -#endif -#endif /* GL_QCOM_extended_get2 */ - -#ifndef GL_QCOM_perfmon_global_mode -#define GL_QCOM_perfmon_global_mode 1 -#define GL_PERFMON_GLOBAL_MODE_QCOM 0x8FA0 -#endif /* GL_QCOM_perfmon_global_mode */ - -#ifndef GL_QCOM_tiled_rendering -#define GL_QCOM_tiled_rendering 1 -#define GL_COLOR_BUFFER_BIT0_QCOM 0x00000001 -#define GL_COLOR_BUFFER_BIT1_QCOM 0x00000002 -#define GL_COLOR_BUFFER_BIT2_QCOM 0x00000004 -#define GL_COLOR_BUFFER_BIT3_QCOM 0x00000008 -#define GL_COLOR_BUFFER_BIT4_QCOM 0x00000010 -#define GL_COLOR_BUFFER_BIT5_QCOM 0x00000020 -#define GL_COLOR_BUFFER_BIT6_QCOM 0x00000040 -#define GL_COLOR_BUFFER_BIT7_QCOM 0x00000080 -#define GL_DEPTH_BUFFER_BIT0_QCOM 0x00000100 -#define GL_DEPTH_BUFFER_BIT1_QCOM 0x00000200 -#define GL_DEPTH_BUFFER_BIT2_QCOM 0x00000400 -#define GL_DEPTH_BUFFER_BIT3_QCOM 0x00000800 -#define GL_DEPTH_BUFFER_BIT4_QCOM 0x00001000 -#define GL_DEPTH_BUFFER_BIT5_QCOM 0x00002000 -#define GL_DEPTH_BUFFER_BIT6_QCOM 0x00004000 -#define GL_DEPTH_BUFFER_BIT7_QCOM 0x00008000 -#define GL_STENCIL_BUFFER_BIT0_QCOM 0x00010000 -#define GL_STENCIL_BUFFER_BIT1_QCOM 0x00020000 -#define GL_STENCIL_BUFFER_BIT2_QCOM 0x00040000 -#define GL_STENCIL_BUFFER_BIT3_QCOM 0x00080000 -#define GL_STENCIL_BUFFER_BIT4_QCOM 0x00100000 -#define GL_STENCIL_BUFFER_BIT5_QCOM 0x00200000 -#define GL_STENCIL_BUFFER_BIT6_QCOM 0x00400000 -#define GL_STENCIL_BUFFER_BIT7_QCOM 0x00800000 -#define GL_MULTISAMPLE_BUFFER_BIT0_QCOM 0x01000000 -#define GL_MULTISAMPLE_BUFFER_BIT1_QCOM 0x02000000 -#define GL_MULTISAMPLE_BUFFER_BIT2_QCOM 0x04000000 -#define GL_MULTISAMPLE_BUFFER_BIT3_QCOM 0x08000000 -#define GL_MULTISAMPLE_BUFFER_BIT4_QCOM 0x10000000 -#define GL_MULTISAMPLE_BUFFER_BIT5_QCOM 0x20000000 -#define GL_MULTISAMPLE_BUFFER_BIT6_QCOM 0x40000000 -#define GL_MULTISAMPLE_BUFFER_BIT7_QCOM 0x80000000 -typedef void (GL_APIENTRYP PFNGLSTARTTILINGQCOMPROC) (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); -typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glStartTilingQCOM (GLuint x, GLuint y, GLuint width, GLuint height, GLbitfield preserveMask); -GL_APICALL void GL_APIENTRY glEndTilingQCOM (GLbitfield preserveMask); -#endif -#endif /* GL_QCOM_tiled_rendering */ - -#ifndef GL_QCOM_writeonly_rendering -#define GL_QCOM_writeonly_rendering 1 -#define GL_WRITEONLY_RENDERING_QCOM 0x8823 -#endif /* GL_QCOM_writeonly_rendering */ - -#ifndef GL_VIV_shader_binary -#define GL_VIV_shader_binary 1 -#define GL_SHADER_BINARY_VIV 0x8FC4 -#endif /* GL_VIV_shader_binary */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/external/khronos/GLES3/gl3.h b/external/khronos/GLES3/gl3.h deleted file mode 100644 index cc80e1067..000000000 --- a/external/khronos/GLES3/gl3.h +++ /dev/null @@ -1,939 +0,0 @@ -#ifndef __gl3_h_ -#define __gl3_h_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2013-2014 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -/* -** This header is generated from the Khronos OpenGL / OpenGL ES XML -** API Registry. The current version of the Registry, generator scripts -** used to make the header, and the header can be found at -** http://www.opengl.org/registry/ -** -** Khronos $Revision$ on $Date$ -*/ - -#include - -/* Generated on date 20141204 */ - -/* Generated C header for: - * API: gles2 - * Profile: common - * Versions considered: 2\.[0-9]|3.0 - * Versions emitted: .* - * Default extensions included: None - * Additional extensions included: _nomatch_^ - * Extensions removed: _nomatch_^ - */ - -#ifndef GL_ES_VERSION_2_0 -#define GL_ES_VERSION_2_0 1 -#include -typedef khronos_int8_t GLbyte; -typedef khronos_float_t GLclampf; -typedef khronos_int32_t GLfixed; -typedef short GLshort; -typedef unsigned short GLushort; -typedef void GLvoid; -typedef struct __GLsync *GLsync; -typedef khronos_int64_t GLint64; -typedef khronos_uint64_t GLuint64; -typedef unsigned int GLenum; -typedef unsigned int GLuint; -typedef char GLchar; -typedef khronos_float_t GLfloat; -typedef khronos_ssize_t GLsizeiptr; -typedef khronos_intptr_t GLintptr; -typedef unsigned int GLbitfield; -typedef int GLint; -typedef unsigned char GLboolean; -typedef int GLsizei; -typedef khronos_uint8_t GLubyte; -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_FALSE 0 -#define GL_TRUE 1 -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 -#define GL_ZERO 0 -#define GL_ONE 1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_FUNC_ADD 0x8006 -#define GL_BLEND_EQUATION 0x8009 -#define GL_BLEND_EQUATION_RGB 0x8009 -#define GL_BLEND_EQUATION_ALPHA 0x883D -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 -#define GL_STREAM_DRAW 0x88E0 -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_CULL_FACE 0x0B44 -#define GL_BLEND 0x0BE2 -#define GL_DITHER 0x0BD0 -#define GL_STENCIL_TEST 0x0B90 -#define GL_DEPTH_TEST 0x0B71 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_COVERAGE 0x80A0 -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_OUT_OF_MEMORY 0x0505 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_LINE_WIDTH 0x0B21 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_STENCIL_CLEAR_VALUE 0x0B91 -#define GL_STENCIL_FUNC 0x0B92 -#define GL_STENCIL_FAIL 0x0B94 -#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 -#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 -#define GL_STENCIL_REF 0x0B97 -#define GL_STENCIL_VALUE_MASK 0x0B93 -#define GL_STENCIL_WRITEMASK 0x0B98 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 -#define GL_VIEWPORT 0x0BA2 -#define GL_SCISSOR_BOX 0x0C10 -#define GL_COLOR_CLEAR_VALUE 0x0C22 -#define GL_COLOR_WRITEMASK 0x0C23 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 -#define GL_GENERATE_MIPMAP_HINT 0x8192 -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB -#define GL_MAX_VARYING_VECTORS 0x8DFC -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD -#define GL_SHADER_TYPE 0x8B4F -#define GL_DELETE_STATUS 0x8B80 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_INVERT 0x150A -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_TEXTURE 0x1702 -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_CUBE 0x8B60 -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F -#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B -#define GL_COMPILE_STATUS 0x8B81 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_SHADER_COMPILER 0x8DFA -#define GL_SHADER_BINARY_FORMATS 0x8DF8 -#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 -#define GL_LOW_FLOAT 0x8DF0 -#define GL_MEDIUM_FLOAT 0x8DF1 -#define GL_HIGH_FLOAT 0x8DF2 -#define GL_LOW_INT 0x8DF3 -#define GL_MEDIUM_INT 0x8DF4 -#define GL_HIGH_INT 0x8DF5 -#define GL_FRAMEBUFFER 0x8D40 -#define GL_RENDERBUFFER 0x8D41 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGB565 0x8D62 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_STENCIL_INDEX8 0x8D48 -#define GL_RENDERBUFFER_WIDTH 0x8D42 -#define GL_RENDERBUFFER_HEIGHT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 -#define GL_RENDERBUFFER_RED_SIZE 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 -#define GL_NONE 0 -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#define GL_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_RENDERBUFFER_BINDING 0x8CA7 -#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 -#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 -GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); -GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); -GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); -GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); -GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); -GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); -GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); -GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); -GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); -GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); -GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); -GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); -GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d); -GL_APICALL void GL_APIENTRY glClearStencil (GLint s); -GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); -GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); -GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); -GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); -GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); -GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); -GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); -GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); -GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); -GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); -GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); -GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); -GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); -GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glDisable (GLenum cap); -GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); -GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); -GL_APICALL void GL_APIENTRY glEnable (GLenum cap); -GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glFinish (void); -GL_APICALL void GL_APIENTRY glFlush (void); -GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); -GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); -GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); -GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); -GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); -GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); -GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); -GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); -GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL GLenum GL_APIENTRY glGetError (void); -GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); -GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); -GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); -GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); -GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name); -GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); -GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); -GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); -GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); -GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); -GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); -GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); -GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); -GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); -GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); -GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); -GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); -GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); -GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); -GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); -GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); -GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); -GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); -GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); -GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); -GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); -GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0); -GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0); -GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); -GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); -GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); -GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); -GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); -GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); -GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); -GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); -#endif /* GL_ES_VERSION_2_0 */ - -#ifndef GL_ES_VERSION_3_0 -#define GL_ES_VERSION_3_0 1 -typedef unsigned short GLhalf; -#define GL_READ_BUFFER 0x0C02 -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#define GL_UNPACK_SKIP_ROWS 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS 0x0CF4 -#define GL_PACK_ROW_LENGTH 0x0D02 -#define GL_PACK_SKIP_ROWS 0x0D03 -#define GL_PACK_SKIP_PIXELS 0x0D04 -#define GL_COLOR 0x1800 -#define GL_DEPTH 0x1801 -#define GL_STENCIL 0x1802 -#define GL_RED 0x1903 -#define GL_RGB8 0x8051 -#define GL_RGBA8 0x8058 -#define GL_RGB10_A2 0x8059 -#define GL_TEXTURE_BINDING_3D 0x806A -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_DEPTH_COMPONENT24 0x81A6 -#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD -#define GL_TEXTURE_COMPARE_MODE 0x884C -#define GL_TEXTURE_COMPARE_FUNC 0x884D -#define GL_CURRENT_QUERY 0x8865 -#define GL_QUERY_RESULT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE 0x8867 -#define GL_BUFFER_MAPPED 0x88BC -#define GL_BUFFER_MAP_POINTER 0x88BD -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_MAX_DRAW_BUFFERS 0x8824 -#define GL_DRAW_BUFFER0 0x8825 -#define GL_DRAW_BUFFER1 0x8826 -#define GL_DRAW_BUFFER2 0x8827 -#define GL_DRAW_BUFFER3 0x8828 -#define GL_DRAW_BUFFER4 0x8829 -#define GL_DRAW_BUFFER5 0x882A -#define GL_DRAW_BUFFER6 0x882B -#define GL_DRAW_BUFFER7 0x882C -#define GL_DRAW_BUFFER8 0x882D -#define GL_DRAW_BUFFER9 0x882E -#define GL_DRAW_BUFFER10 0x882F -#define GL_DRAW_BUFFER11 0x8830 -#define GL_DRAW_BUFFER12 0x8831 -#define GL_DRAW_BUFFER13 0x8832 -#define GL_DRAW_BUFFER14 0x8833 -#define GL_DRAW_BUFFER15 0x8834 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A -#define GL_SAMPLER_3D 0x8B5F -#define GL_SAMPLER_2D_SHADOW 0x8B62 -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B -#define GL_PIXEL_PACK_BUFFER 0x88EB -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF -#define GL_FLOAT_MAT2x3 0x8B65 -#define GL_FLOAT_MAT2x4 0x8B66 -#define GL_FLOAT_MAT3x2 0x8B67 -#define GL_FLOAT_MAT3x4 0x8B68 -#define GL_FLOAT_MAT4x2 0x8B69 -#define GL_FLOAT_MAT4x3 0x8B6A -#define GL_SRGB 0x8C40 -#define GL_SRGB8 0x8C41 -#define GL_SRGB8_ALPHA8 0x8C43 -#define GL_COMPARE_REF_TO_TEXTURE 0x884E -#define GL_MAJOR_VERSION 0x821B -#define GL_MINOR_VERSION 0x821C -#define GL_NUM_EXTENSIONS 0x821D -#define GL_RGBA32F 0x8814 -#define GL_RGB32F 0x8815 -#define GL_RGBA16F 0x881A -#define GL_RGB16F 0x881B -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD -#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF -#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 -#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 -#define GL_MAX_VARYING_COMPONENTS 0x8B4B -#define GL_TEXTURE_2D_ARRAY 0x8C1A -#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D -#define GL_R11F_G11F_B10F 0x8C3A -#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B -#define GL_RGB9_E5 0x8C3D -#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E -#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 -#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 -#define GL_RASTERIZER_DISCARD 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B -#define GL_INTERLEAVED_ATTRIBS 0x8C8C -#define GL_SEPARATE_ATTRIBS 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F -#define GL_RGBA32UI 0x8D70 -#define GL_RGB32UI 0x8D71 -#define GL_RGBA16UI 0x8D76 -#define GL_RGB16UI 0x8D77 -#define GL_RGBA8UI 0x8D7C -#define GL_RGB8UI 0x8D7D -#define GL_RGBA32I 0x8D82 -#define GL_RGB32I 0x8D83 -#define GL_RGBA16I 0x8D88 -#define GL_RGB16I 0x8D89 -#define GL_RGBA8I 0x8D8E -#define GL_RGB8I 0x8D8F -#define GL_RED_INTEGER 0x8D94 -#define GL_RGB_INTEGER 0x8D98 -#define GL_RGBA_INTEGER 0x8D99 -#define GL_SAMPLER_2D_ARRAY 0x8DC1 -#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 -#define GL_UNSIGNED_INT_VEC2 0x8DC6 -#define GL_UNSIGNED_INT_VEC3 0x8DC7 -#define GL_UNSIGNED_INT_VEC4 0x8DC8 -#define GL_INT_SAMPLER_2D 0x8DCA -#define GL_INT_SAMPLER_3D 0x8DCB -#define GL_INT_SAMPLER_CUBE 0x8DCC -#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF -#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 -#define GL_BUFFER_ACCESS_FLAGS 0x911F -#define GL_BUFFER_MAP_LENGTH 0x9120 -#define GL_BUFFER_MAP_OFFSET 0x9121 -#define GL_DEPTH_COMPONENT32F 0x8CAC -#define GL_DEPTH32F_STENCIL8 0x8CAD -#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 -#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 -#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 -#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 -#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 -#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 -#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 -#define GL_FRAMEBUFFER_DEFAULT 0x8218 -#define GL_FRAMEBUFFER_UNDEFINED 0x8219 -#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A -#define GL_DEPTH_STENCIL 0x84F9 -#define GL_UNSIGNED_INT_24_8 0x84FA -#define GL_DEPTH24_STENCIL8 0x88F0 -#define GL_UNSIGNED_NORMALIZED 0x8C17 -#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA -#define GL_RENDERBUFFER_SAMPLES 0x8CAB -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 -#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF -#define GL_COLOR_ATTACHMENT1 0x8CE1 -#define GL_COLOR_ATTACHMENT2 0x8CE2 -#define GL_COLOR_ATTACHMENT3 0x8CE3 -#define GL_COLOR_ATTACHMENT4 0x8CE4 -#define GL_COLOR_ATTACHMENT5 0x8CE5 -#define GL_COLOR_ATTACHMENT6 0x8CE6 -#define GL_COLOR_ATTACHMENT7 0x8CE7 -#define GL_COLOR_ATTACHMENT8 0x8CE8 -#define GL_COLOR_ATTACHMENT9 0x8CE9 -#define GL_COLOR_ATTACHMENT10 0x8CEA -#define GL_COLOR_ATTACHMENT11 0x8CEB -#define GL_COLOR_ATTACHMENT12 0x8CEC -#define GL_COLOR_ATTACHMENT13 0x8CED -#define GL_COLOR_ATTACHMENT14 0x8CEE -#define GL_COLOR_ATTACHMENT15 0x8CEF -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#define GL_MAX_SAMPLES 0x8D57 -#define GL_HALF_FLOAT 0x140B -#define GL_MAP_READ_BIT 0x0001 -#define GL_MAP_WRITE_BIT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 -#define GL_RG 0x8227 -#define GL_RG_INTEGER 0x8228 -#define GL_R8 0x8229 -#define GL_RG8 0x822B -#define GL_R16F 0x822D -#define GL_R32F 0x822E -#define GL_RG16F 0x822F -#define GL_RG32F 0x8230 -#define GL_R8I 0x8231 -#define GL_R8UI 0x8232 -#define GL_R16I 0x8233 -#define GL_R16UI 0x8234 -#define GL_R32I 0x8235 -#define GL_R32UI 0x8236 -#define GL_RG8I 0x8237 -#define GL_RG8UI 0x8238 -#define GL_RG16I 0x8239 -#define GL_RG16UI 0x823A -#define GL_RG32I 0x823B -#define GL_RG32UI 0x823C -#define GL_VERTEX_ARRAY_BINDING 0x85B5 -#define GL_R8_SNORM 0x8F94 -#define GL_RG8_SNORM 0x8F95 -#define GL_RGB8_SNORM 0x8F96 -#define GL_RGBA8_SNORM 0x8F97 -#define GL_SIGNED_NORMALIZED 0x8F9C -#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 -#define GL_COPY_READ_BUFFER 0x8F36 -#define GL_COPY_WRITE_BUFFER 0x8F37 -#define GL_COPY_READ_BUFFER_BINDING 0x8F36 -#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 -#define GL_UNIFORM_BUFFER 0x8A11 -#define GL_UNIFORM_BUFFER_BINDING 0x8A28 -#define GL_UNIFORM_BUFFER_START 0x8A29 -#define GL_UNIFORM_BUFFER_SIZE 0x8A2A -#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B -#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D -#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E -#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F -#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 -#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 -#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 -#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 -#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 -#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 -#define GL_UNIFORM_TYPE 0x8A37 -#define GL_UNIFORM_SIZE 0x8A38 -#define GL_UNIFORM_NAME_LENGTH 0x8A39 -#define GL_UNIFORM_BLOCK_INDEX 0x8A3A -#define GL_UNIFORM_OFFSET 0x8A3B -#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C -#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D -#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E -#define GL_UNIFORM_BLOCK_BINDING 0x8A3F -#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 -#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 -#define GL_INVALID_INDEX 0xFFFFFFFFu -#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 -#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 -#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 -#define GL_OBJECT_TYPE 0x9112 -#define GL_SYNC_CONDITION 0x9113 -#define GL_SYNC_STATUS 0x9114 -#define GL_SYNC_FLAGS 0x9115 -#define GL_SYNC_FENCE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 -#define GL_UNSIGNALED 0x9118 -#define GL_SIGNALED 0x9119 -#define GL_ALREADY_SIGNALED 0x911A -#define GL_TIMEOUT_EXPIRED 0x911B -#define GL_CONDITION_SATISFIED 0x911C -#define GL_WAIT_FAILED 0x911D -#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 -#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE -#define GL_ANY_SAMPLES_PASSED 0x8C2F -#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A -#define GL_SAMPLER_BINDING 0x8919 -#define GL_RGB10_A2UI 0x906F -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_INT_2_10_10_10_REV 0x8D9F -#define GL_TRANSFORM_FEEDBACK 0x8E22 -#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 -#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 -#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 -#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 -#define GL_PROGRAM_BINARY_LENGTH 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE -#define GL_PROGRAM_BINARY_FORMATS 0x87FF -#define GL_COMPRESSED_R11_EAC 0x9270 -#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 -#define GL_COMPRESSED_RG11_EAC 0x9272 -#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 -#define GL_COMPRESSED_RGB8_ETC2 0x9274 -#define GL_COMPRESSED_SRGB8_ETC2 0x9275 -#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 -#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 -#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 -#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 -#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F -#define GL_MAX_ELEMENT_INDEX 0x8D6B -#define GL_NUM_SAMPLE_COUNTS 0x9380 -#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF -GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src); -GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); -GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids); -GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); -GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id); -GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glEndQuery (GLenum target); -GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); -GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target); -GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params); -GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); -GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); -GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array); -GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); -GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); -GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array); -GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); -GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode); -GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); -GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); -GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); -GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); -GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); -GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); -GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); -GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); -GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0); -GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); -GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); -GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); -GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); -GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); -GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); -GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index); -GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); -GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); -GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); -GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); -GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); -GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); -GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); -GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags); -GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync); -GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync); -GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); -GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); -GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); -GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); -GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); -GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); -GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); -GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); -GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); -GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); -GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); -GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); -GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id); -GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); -GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); -GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); -GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); -GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments); -GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); -#endif /* GL_ES_VERSION_3_0 */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/external/khronos/GLES3/gl31.h b/external/khronos/GLES3/gl31.h deleted file mode 100644 index 72c6498e7..000000000 --- a/external/khronos/GLES3/gl31.h +++ /dev/null @@ -1,1184 +0,0 @@ -#ifndef __gl31_h_ -#define __gl31_h_ 1 - -#ifdef __cplusplus -extern "C" { -#endif - -/* -** Copyright (c) 2013-2014 The Khronos Group Inc. -** -** Permission is hereby granted, free of charge, to any person obtaining a -** copy of this software and/or associated documentation files (the -** "Materials"), to deal in the Materials without restriction, including -** without limitation the rights to use, copy, modify, merge, publish, -** distribute, sublicense, and/or sell copies of the Materials, and to -** permit persons to whom the Materials are furnished to do so, subject to -** the following conditions: -** -** The above copyright notice and this permission notice shall be included -** in all copies or substantial portions of the Materials. -** -** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. -*/ -/* -** This header is generated from the Khronos OpenGL / OpenGL ES XML -** API Registry. The current version of the Registry, generator scripts -** used to make the header, and the header can be found at -** http://www.opengl.org/registry/ -** -** Khronos $Revision$ on $Date$ -*/ - -#include - -/* Generated on date 20141204 */ - -/* Generated C header for: - * API: gles2 - * Profile: common - * Versions considered: 2.[0-9]|3.[01] - * Versions emitted: .* - * Default extensions included: None - * Additional extensions included: _nomatch_^ - * Extensions removed: _nomatch_^ - */ - -#ifndef GL_ES_VERSION_2_0 -#define GL_ES_VERSION_2_0 1 -#include -typedef khronos_int8_t GLbyte; -typedef khronos_float_t GLclampf; -typedef khronos_int32_t GLfixed; -typedef short GLshort; -typedef unsigned short GLushort; -typedef void GLvoid; -typedef struct __GLsync *GLsync; -typedef khronos_int64_t GLint64; -typedef khronos_uint64_t GLuint64; -typedef unsigned int GLenum; -typedef unsigned int GLuint; -typedef char GLchar; -typedef khronos_float_t GLfloat; -typedef khronos_ssize_t GLsizeiptr; -typedef khronos_intptr_t GLintptr; -typedef unsigned int GLbitfield; -typedef int GLint; -typedef unsigned char GLboolean; -typedef int GLsizei; -typedef khronos_uint8_t GLubyte; -#define GL_DEPTH_BUFFER_BIT 0x00000100 -#define GL_STENCIL_BUFFER_BIT 0x00000400 -#define GL_COLOR_BUFFER_BIT 0x00004000 -#define GL_FALSE 0 -#define GL_TRUE 1 -#define GL_POINTS 0x0000 -#define GL_LINES 0x0001 -#define GL_LINE_LOOP 0x0002 -#define GL_LINE_STRIP 0x0003 -#define GL_TRIANGLES 0x0004 -#define GL_TRIANGLE_STRIP 0x0005 -#define GL_TRIANGLE_FAN 0x0006 -#define GL_ZERO 0 -#define GL_ONE 1 -#define GL_SRC_COLOR 0x0300 -#define GL_ONE_MINUS_SRC_COLOR 0x0301 -#define GL_SRC_ALPHA 0x0302 -#define GL_ONE_MINUS_SRC_ALPHA 0x0303 -#define GL_DST_ALPHA 0x0304 -#define GL_ONE_MINUS_DST_ALPHA 0x0305 -#define GL_DST_COLOR 0x0306 -#define GL_ONE_MINUS_DST_COLOR 0x0307 -#define GL_SRC_ALPHA_SATURATE 0x0308 -#define GL_FUNC_ADD 0x8006 -#define GL_BLEND_EQUATION 0x8009 -#define GL_BLEND_EQUATION_RGB 0x8009 -#define GL_BLEND_EQUATION_ALPHA 0x883D -#define GL_FUNC_SUBTRACT 0x800A -#define GL_FUNC_REVERSE_SUBTRACT 0x800B -#define GL_BLEND_DST_RGB 0x80C8 -#define GL_BLEND_SRC_RGB 0x80C9 -#define GL_BLEND_DST_ALPHA 0x80CA -#define GL_BLEND_SRC_ALPHA 0x80CB -#define GL_CONSTANT_COLOR 0x8001 -#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 -#define GL_CONSTANT_ALPHA 0x8003 -#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 -#define GL_BLEND_COLOR 0x8005 -#define GL_ARRAY_BUFFER 0x8892 -#define GL_ELEMENT_ARRAY_BUFFER 0x8893 -#define GL_ARRAY_BUFFER_BINDING 0x8894 -#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 -#define GL_STREAM_DRAW 0x88E0 -#define GL_STATIC_DRAW 0x88E4 -#define GL_DYNAMIC_DRAW 0x88E8 -#define GL_BUFFER_SIZE 0x8764 -#define GL_BUFFER_USAGE 0x8765 -#define GL_CURRENT_VERTEX_ATTRIB 0x8626 -#define GL_FRONT 0x0404 -#define GL_BACK 0x0405 -#define GL_FRONT_AND_BACK 0x0408 -#define GL_TEXTURE_2D 0x0DE1 -#define GL_CULL_FACE 0x0B44 -#define GL_BLEND 0x0BE2 -#define GL_DITHER 0x0BD0 -#define GL_STENCIL_TEST 0x0B90 -#define GL_DEPTH_TEST 0x0B71 -#define GL_SCISSOR_TEST 0x0C11 -#define GL_POLYGON_OFFSET_FILL 0x8037 -#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E -#define GL_SAMPLE_COVERAGE 0x80A0 -#define GL_NO_ERROR 0 -#define GL_INVALID_ENUM 0x0500 -#define GL_INVALID_VALUE 0x0501 -#define GL_INVALID_OPERATION 0x0502 -#define GL_OUT_OF_MEMORY 0x0505 -#define GL_CW 0x0900 -#define GL_CCW 0x0901 -#define GL_LINE_WIDTH 0x0B21 -#define GL_ALIASED_POINT_SIZE_RANGE 0x846D -#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E -#define GL_CULL_FACE_MODE 0x0B45 -#define GL_FRONT_FACE 0x0B46 -#define GL_DEPTH_RANGE 0x0B70 -#define GL_DEPTH_WRITEMASK 0x0B72 -#define GL_DEPTH_CLEAR_VALUE 0x0B73 -#define GL_DEPTH_FUNC 0x0B74 -#define GL_STENCIL_CLEAR_VALUE 0x0B91 -#define GL_STENCIL_FUNC 0x0B92 -#define GL_STENCIL_FAIL 0x0B94 -#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 -#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 -#define GL_STENCIL_REF 0x0B97 -#define GL_STENCIL_VALUE_MASK 0x0B93 -#define GL_STENCIL_WRITEMASK 0x0B98 -#define GL_STENCIL_BACK_FUNC 0x8800 -#define GL_STENCIL_BACK_FAIL 0x8801 -#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 -#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 -#define GL_STENCIL_BACK_REF 0x8CA3 -#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 -#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 -#define GL_VIEWPORT 0x0BA2 -#define GL_SCISSOR_BOX 0x0C10 -#define GL_COLOR_CLEAR_VALUE 0x0C22 -#define GL_COLOR_WRITEMASK 0x0C23 -#define GL_UNPACK_ALIGNMENT 0x0CF5 -#define GL_PACK_ALIGNMENT 0x0D05 -#define GL_MAX_TEXTURE_SIZE 0x0D33 -#define GL_MAX_VIEWPORT_DIMS 0x0D3A -#define GL_SUBPIXEL_BITS 0x0D50 -#define GL_RED_BITS 0x0D52 -#define GL_GREEN_BITS 0x0D53 -#define GL_BLUE_BITS 0x0D54 -#define GL_ALPHA_BITS 0x0D55 -#define GL_DEPTH_BITS 0x0D56 -#define GL_STENCIL_BITS 0x0D57 -#define GL_POLYGON_OFFSET_UNITS 0x2A00 -#define GL_POLYGON_OFFSET_FACTOR 0x8038 -#define GL_TEXTURE_BINDING_2D 0x8069 -#define GL_SAMPLE_BUFFERS 0x80A8 -#define GL_SAMPLES 0x80A9 -#define GL_SAMPLE_COVERAGE_VALUE 0x80AA -#define GL_SAMPLE_COVERAGE_INVERT 0x80AB -#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 -#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 -#define GL_DONT_CARE 0x1100 -#define GL_FASTEST 0x1101 -#define GL_NICEST 0x1102 -#define GL_GENERATE_MIPMAP_HINT 0x8192 -#define GL_BYTE 0x1400 -#define GL_UNSIGNED_BYTE 0x1401 -#define GL_SHORT 0x1402 -#define GL_UNSIGNED_SHORT 0x1403 -#define GL_INT 0x1404 -#define GL_UNSIGNED_INT 0x1405 -#define GL_FLOAT 0x1406 -#define GL_FIXED 0x140C -#define GL_DEPTH_COMPONENT 0x1902 -#define GL_ALPHA 0x1906 -#define GL_RGB 0x1907 -#define GL_RGBA 0x1908 -#define GL_LUMINANCE 0x1909 -#define GL_LUMINANCE_ALPHA 0x190A -#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 -#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 -#define GL_UNSIGNED_SHORT_5_6_5 0x8363 -#define GL_FRAGMENT_SHADER 0x8B30 -#define GL_VERTEX_SHADER 0x8B31 -#define GL_MAX_VERTEX_ATTRIBS 0x8869 -#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB -#define GL_MAX_VARYING_VECTORS 0x8DFC -#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D -#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C -#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 -#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD -#define GL_SHADER_TYPE 0x8B4F -#define GL_DELETE_STATUS 0x8B80 -#define GL_LINK_STATUS 0x8B82 -#define GL_VALIDATE_STATUS 0x8B83 -#define GL_ATTACHED_SHADERS 0x8B85 -#define GL_ACTIVE_UNIFORMS 0x8B86 -#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 -#define GL_ACTIVE_ATTRIBUTES 0x8B89 -#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A -#define GL_SHADING_LANGUAGE_VERSION 0x8B8C -#define GL_CURRENT_PROGRAM 0x8B8D -#define GL_NEVER 0x0200 -#define GL_LESS 0x0201 -#define GL_EQUAL 0x0202 -#define GL_LEQUAL 0x0203 -#define GL_GREATER 0x0204 -#define GL_NOTEQUAL 0x0205 -#define GL_GEQUAL 0x0206 -#define GL_ALWAYS 0x0207 -#define GL_KEEP 0x1E00 -#define GL_REPLACE 0x1E01 -#define GL_INCR 0x1E02 -#define GL_DECR 0x1E03 -#define GL_INVERT 0x150A -#define GL_INCR_WRAP 0x8507 -#define GL_DECR_WRAP 0x8508 -#define GL_VENDOR 0x1F00 -#define GL_RENDERER 0x1F01 -#define GL_VERSION 0x1F02 -#define GL_EXTENSIONS 0x1F03 -#define GL_NEAREST 0x2600 -#define GL_LINEAR 0x2601 -#define GL_NEAREST_MIPMAP_NEAREST 0x2700 -#define GL_LINEAR_MIPMAP_NEAREST 0x2701 -#define GL_NEAREST_MIPMAP_LINEAR 0x2702 -#define GL_LINEAR_MIPMAP_LINEAR 0x2703 -#define GL_TEXTURE_MAG_FILTER 0x2800 -#define GL_TEXTURE_MIN_FILTER 0x2801 -#define GL_TEXTURE_WRAP_S 0x2802 -#define GL_TEXTURE_WRAP_T 0x2803 -#define GL_TEXTURE 0x1702 -#define GL_TEXTURE_CUBE_MAP 0x8513 -#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 -#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 -#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A -#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C -#define GL_TEXTURE0 0x84C0 -#define GL_TEXTURE1 0x84C1 -#define GL_TEXTURE2 0x84C2 -#define GL_TEXTURE3 0x84C3 -#define GL_TEXTURE4 0x84C4 -#define GL_TEXTURE5 0x84C5 -#define GL_TEXTURE6 0x84C6 -#define GL_TEXTURE7 0x84C7 -#define GL_TEXTURE8 0x84C8 -#define GL_TEXTURE9 0x84C9 -#define GL_TEXTURE10 0x84CA -#define GL_TEXTURE11 0x84CB -#define GL_TEXTURE12 0x84CC -#define GL_TEXTURE13 0x84CD -#define GL_TEXTURE14 0x84CE -#define GL_TEXTURE15 0x84CF -#define GL_TEXTURE16 0x84D0 -#define GL_TEXTURE17 0x84D1 -#define GL_TEXTURE18 0x84D2 -#define GL_TEXTURE19 0x84D3 -#define GL_TEXTURE20 0x84D4 -#define GL_TEXTURE21 0x84D5 -#define GL_TEXTURE22 0x84D6 -#define GL_TEXTURE23 0x84D7 -#define GL_TEXTURE24 0x84D8 -#define GL_TEXTURE25 0x84D9 -#define GL_TEXTURE26 0x84DA -#define GL_TEXTURE27 0x84DB -#define GL_TEXTURE28 0x84DC -#define GL_TEXTURE29 0x84DD -#define GL_TEXTURE30 0x84DE -#define GL_TEXTURE31 0x84DF -#define GL_ACTIVE_TEXTURE 0x84E0 -#define GL_REPEAT 0x2901 -#define GL_CLAMP_TO_EDGE 0x812F -#define GL_MIRRORED_REPEAT 0x8370 -#define GL_FLOAT_VEC2 0x8B50 -#define GL_FLOAT_VEC3 0x8B51 -#define GL_FLOAT_VEC4 0x8B52 -#define GL_INT_VEC2 0x8B53 -#define GL_INT_VEC3 0x8B54 -#define GL_INT_VEC4 0x8B55 -#define GL_BOOL 0x8B56 -#define GL_BOOL_VEC2 0x8B57 -#define GL_BOOL_VEC3 0x8B58 -#define GL_BOOL_VEC4 0x8B59 -#define GL_FLOAT_MAT2 0x8B5A -#define GL_FLOAT_MAT3 0x8B5B -#define GL_FLOAT_MAT4 0x8B5C -#define GL_SAMPLER_2D 0x8B5E -#define GL_SAMPLER_CUBE 0x8B60 -#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 -#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 -#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 -#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 -#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A -#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 -#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F -#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A -#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B -#define GL_COMPILE_STATUS 0x8B81 -#define GL_INFO_LOG_LENGTH 0x8B84 -#define GL_SHADER_SOURCE_LENGTH 0x8B88 -#define GL_SHADER_COMPILER 0x8DFA -#define GL_SHADER_BINARY_FORMATS 0x8DF8 -#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 -#define GL_LOW_FLOAT 0x8DF0 -#define GL_MEDIUM_FLOAT 0x8DF1 -#define GL_HIGH_FLOAT 0x8DF2 -#define GL_LOW_INT 0x8DF3 -#define GL_MEDIUM_INT 0x8DF4 -#define GL_HIGH_INT 0x8DF5 -#define GL_FRAMEBUFFER 0x8D40 -#define GL_RENDERBUFFER 0x8D41 -#define GL_RGBA4 0x8056 -#define GL_RGB5_A1 0x8057 -#define GL_RGB565 0x8D62 -#define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_STENCIL_INDEX8 0x8D48 -#define GL_RENDERBUFFER_WIDTH 0x8D42 -#define GL_RENDERBUFFER_HEIGHT 0x8D43 -#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 -#define GL_RENDERBUFFER_RED_SIZE 0x8D50 -#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 -#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 -#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 -#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 -#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 -#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 -#define GL_COLOR_ATTACHMENT0 0x8CE0 -#define GL_DEPTH_ATTACHMENT 0x8D00 -#define GL_STENCIL_ATTACHMENT 0x8D20 -#define GL_NONE 0 -#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 -#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 -#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 -#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 -#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD -#define GL_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_RENDERBUFFER_BINDING 0x8CA7 -#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 -#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 -GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); -GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar *name); -GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); -GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); -GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); -GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); -GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); -GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); -GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha); -GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const void *data, GLenum usage); -GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const void *data); -GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); -GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); -GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); -GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat d); -GL_APICALL void GL_APIENTRY glClearStencil (GLint s); -GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); -GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); -GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); -GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); -GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); -GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); -GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint *buffers); -GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint *framebuffers); -GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); -GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint *renderbuffers); -GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); -GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint *textures); -GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); -GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); -GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); -GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); -GL_APICALL void GL_APIENTRY glDisable (GLenum cap); -GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); -GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const void *indices); -GL_APICALL void GL_APIENTRY glEnable (GLenum cap); -GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); -GL_APICALL void GL_APIENTRY glFinish (void); -GL_APICALL void GL_APIENTRY glFlush (void); -GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); -GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); -GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint *buffers); -GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); -GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint *framebuffers); -GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint *renderbuffers); -GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint *textures); -GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxCount, GLsizei *count, GLuint *shaders); -GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean *data); -GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL GLenum GL_APIENTRY glGetError (void); -GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat *data); -GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint *data); -GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint *range, GLint *precision); -GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *source); -GL_APICALL const GLubyte *GL_APIENTRY glGetString (GLenum name); -GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint *params); -GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, void **pointer); -GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); -GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); -GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); -GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); -GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); -GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); -GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); -GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); -GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); -GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); -GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); -GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels); -GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); -GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); -GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei count, const GLuint *shaders, GLenum binaryformat, const void *binary, GLsizei length); -GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length); -GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); -GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); -GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); -GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass); -GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat *params); -GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint *params); -GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat v0); -GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint v0); -GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat v0, GLfloat v1); -GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint v0, GLint v1); -GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint v0, GLint v1, GLint v2); -GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); -GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); -GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint index, GLfloat x); -GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint index, GLfloat x, GLfloat y); -GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint index, GLfloat x, GLfloat y, GLfloat z); -GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w); -GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint index, const GLfloat *v); -GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); -GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); -#endif /* GL_ES_VERSION_2_0 */ - -#ifndef GL_ES_VERSION_3_0 -#define GL_ES_VERSION_3_0 1 -typedef unsigned short GLhalf; -#define GL_READ_BUFFER 0x0C02 -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#define GL_UNPACK_SKIP_ROWS 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS 0x0CF4 -#define GL_PACK_ROW_LENGTH 0x0D02 -#define GL_PACK_SKIP_ROWS 0x0D03 -#define GL_PACK_SKIP_PIXELS 0x0D04 -#define GL_COLOR 0x1800 -#define GL_DEPTH 0x1801 -#define GL_STENCIL 0x1802 -#define GL_RED 0x1903 -#define GL_RGB8 0x8051 -#define GL_RGBA8 0x8058 -#define GL_RGB10_A2 0x8059 -#define GL_TEXTURE_BINDING_3D 0x806A -#define GL_UNPACK_SKIP_IMAGES 0x806D -#define GL_UNPACK_IMAGE_HEIGHT 0x806E -#define GL_TEXTURE_3D 0x806F -#define GL_TEXTURE_WRAP_R 0x8072 -#define GL_MAX_3D_TEXTURE_SIZE 0x8073 -#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 -#define GL_MAX_ELEMENTS_VERTICES 0x80E8 -#define GL_MAX_ELEMENTS_INDICES 0x80E9 -#define GL_TEXTURE_MIN_LOD 0x813A -#define GL_TEXTURE_MAX_LOD 0x813B -#define GL_TEXTURE_BASE_LEVEL 0x813C -#define GL_TEXTURE_MAX_LEVEL 0x813D -#define GL_MIN 0x8007 -#define GL_MAX 0x8008 -#define GL_DEPTH_COMPONENT24 0x81A6 -#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD -#define GL_TEXTURE_COMPARE_MODE 0x884C -#define GL_TEXTURE_COMPARE_FUNC 0x884D -#define GL_CURRENT_QUERY 0x8865 -#define GL_QUERY_RESULT 0x8866 -#define GL_QUERY_RESULT_AVAILABLE 0x8867 -#define GL_BUFFER_MAPPED 0x88BC -#define GL_BUFFER_MAP_POINTER 0x88BD -#define GL_STREAM_READ 0x88E1 -#define GL_STREAM_COPY 0x88E2 -#define GL_STATIC_READ 0x88E5 -#define GL_STATIC_COPY 0x88E6 -#define GL_DYNAMIC_READ 0x88E9 -#define GL_DYNAMIC_COPY 0x88EA -#define GL_MAX_DRAW_BUFFERS 0x8824 -#define GL_DRAW_BUFFER0 0x8825 -#define GL_DRAW_BUFFER1 0x8826 -#define GL_DRAW_BUFFER2 0x8827 -#define GL_DRAW_BUFFER3 0x8828 -#define GL_DRAW_BUFFER4 0x8829 -#define GL_DRAW_BUFFER5 0x882A -#define GL_DRAW_BUFFER6 0x882B -#define GL_DRAW_BUFFER7 0x882C -#define GL_DRAW_BUFFER8 0x882D -#define GL_DRAW_BUFFER9 0x882E -#define GL_DRAW_BUFFER10 0x882F -#define GL_DRAW_BUFFER11 0x8830 -#define GL_DRAW_BUFFER12 0x8831 -#define GL_DRAW_BUFFER13 0x8832 -#define GL_DRAW_BUFFER14 0x8833 -#define GL_DRAW_BUFFER15 0x8834 -#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 -#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A -#define GL_SAMPLER_3D 0x8B5F -#define GL_SAMPLER_2D_SHADOW 0x8B62 -#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B -#define GL_PIXEL_PACK_BUFFER 0x88EB -#define GL_PIXEL_UNPACK_BUFFER 0x88EC -#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED -#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF -#define GL_FLOAT_MAT2x3 0x8B65 -#define GL_FLOAT_MAT2x4 0x8B66 -#define GL_FLOAT_MAT3x2 0x8B67 -#define GL_FLOAT_MAT3x4 0x8B68 -#define GL_FLOAT_MAT4x2 0x8B69 -#define GL_FLOAT_MAT4x3 0x8B6A -#define GL_SRGB 0x8C40 -#define GL_SRGB8 0x8C41 -#define GL_SRGB8_ALPHA8 0x8C43 -#define GL_COMPARE_REF_TO_TEXTURE 0x884E -#define GL_MAJOR_VERSION 0x821B -#define GL_MINOR_VERSION 0x821C -#define GL_NUM_EXTENSIONS 0x821D -#define GL_RGBA32F 0x8814 -#define GL_RGB32F 0x8815 -#define GL_RGBA16F 0x881A -#define GL_RGB16F 0x881B -#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD -#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF -#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 -#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 -#define GL_MAX_VARYING_COMPONENTS 0x8B4B -#define GL_TEXTURE_2D_ARRAY 0x8C1A -#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D -#define GL_R11F_G11F_B10F 0x8C3A -#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B -#define GL_RGB9_E5 0x8C3D -#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E -#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 -#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 -#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 -#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 -#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 -#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 -#define GL_RASTERIZER_DISCARD 0x8C89 -#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A -#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B -#define GL_INTERLEAVED_ATTRIBS 0x8C8C -#define GL_SEPARATE_ATTRIBS 0x8C8D -#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E -#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F -#define GL_RGBA32UI 0x8D70 -#define GL_RGB32UI 0x8D71 -#define GL_RGBA16UI 0x8D76 -#define GL_RGB16UI 0x8D77 -#define GL_RGBA8UI 0x8D7C -#define GL_RGB8UI 0x8D7D -#define GL_RGBA32I 0x8D82 -#define GL_RGB32I 0x8D83 -#define GL_RGBA16I 0x8D88 -#define GL_RGB16I 0x8D89 -#define GL_RGBA8I 0x8D8E -#define GL_RGB8I 0x8D8F -#define GL_RED_INTEGER 0x8D94 -#define GL_RGB_INTEGER 0x8D98 -#define GL_RGBA_INTEGER 0x8D99 -#define GL_SAMPLER_2D_ARRAY 0x8DC1 -#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 -#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 -#define GL_UNSIGNED_INT_VEC2 0x8DC6 -#define GL_UNSIGNED_INT_VEC3 0x8DC7 -#define GL_UNSIGNED_INT_VEC4 0x8DC8 -#define GL_INT_SAMPLER_2D 0x8DCA -#define GL_INT_SAMPLER_3D 0x8DCB -#define GL_INT_SAMPLER_CUBE 0x8DCC -#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF -#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 -#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 -#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 -#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 -#define GL_BUFFER_ACCESS_FLAGS 0x911F -#define GL_BUFFER_MAP_LENGTH 0x9120 -#define GL_BUFFER_MAP_OFFSET 0x9121 -#define GL_DEPTH_COMPONENT32F 0x8CAC -#define GL_DEPTH32F_STENCIL8 0x8CAD -#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD -#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 -#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 -#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 -#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 -#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 -#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 -#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 -#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 -#define GL_FRAMEBUFFER_DEFAULT 0x8218 -#define GL_FRAMEBUFFER_UNDEFINED 0x8219 -#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A -#define GL_DEPTH_STENCIL 0x84F9 -#define GL_UNSIGNED_INT_24_8 0x84FA -#define GL_DEPTH24_STENCIL8 0x88F0 -#define GL_UNSIGNED_NORMALIZED 0x8C17 -#define GL_DRAW_FRAMEBUFFER_BINDING 0x8CA6 -#define GL_READ_FRAMEBUFFER 0x8CA8 -#define GL_DRAW_FRAMEBUFFER 0x8CA9 -#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA -#define GL_RENDERBUFFER_SAMPLES 0x8CAB -#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 -#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF -#define GL_COLOR_ATTACHMENT1 0x8CE1 -#define GL_COLOR_ATTACHMENT2 0x8CE2 -#define GL_COLOR_ATTACHMENT3 0x8CE3 -#define GL_COLOR_ATTACHMENT4 0x8CE4 -#define GL_COLOR_ATTACHMENT5 0x8CE5 -#define GL_COLOR_ATTACHMENT6 0x8CE6 -#define GL_COLOR_ATTACHMENT7 0x8CE7 -#define GL_COLOR_ATTACHMENT8 0x8CE8 -#define GL_COLOR_ATTACHMENT9 0x8CE9 -#define GL_COLOR_ATTACHMENT10 0x8CEA -#define GL_COLOR_ATTACHMENT11 0x8CEB -#define GL_COLOR_ATTACHMENT12 0x8CEC -#define GL_COLOR_ATTACHMENT13 0x8CED -#define GL_COLOR_ATTACHMENT14 0x8CEE -#define GL_COLOR_ATTACHMENT15 0x8CEF -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 -#define GL_MAX_SAMPLES 0x8D57 -#define GL_HALF_FLOAT 0x140B -#define GL_MAP_READ_BIT 0x0001 -#define GL_MAP_WRITE_BIT 0x0002 -#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 -#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 -#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 -#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 -#define GL_RG 0x8227 -#define GL_RG_INTEGER 0x8228 -#define GL_R8 0x8229 -#define GL_RG8 0x822B -#define GL_R16F 0x822D -#define GL_R32F 0x822E -#define GL_RG16F 0x822F -#define GL_RG32F 0x8230 -#define GL_R8I 0x8231 -#define GL_R8UI 0x8232 -#define GL_R16I 0x8233 -#define GL_R16UI 0x8234 -#define GL_R32I 0x8235 -#define GL_R32UI 0x8236 -#define GL_RG8I 0x8237 -#define GL_RG8UI 0x8238 -#define GL_RG16I 0x8239 -#define GL_RG16UI 0x823A -#define GL_RG32I 0x823B -#define GL_RG32UI 0x823C -#define GL_VERTEX_ARRAY_BINDING 0x85B5 -#define GL_R8_SNORM 0x8F94 -#define GL_RG8_SNORM 0x8F95 -#define GL_RGB8_SNORM 0x8F96 -#define GL_RGBA8_SNORM 0x8F97 -#define GL_SIGNED_NORMALIZED 0x8F9C -#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 -#define GL_COPY_READ_BUFFER 0x8F36 -#define GL_COPY_WRITE_BUFFER 0x8F37 -#define GL_COPY_READ_BUFFER_BINDING 0x8F36 -#define GL_COPY_WRITE_BUFFER_BINDING 0x8F37 -#define GL_UNIFORM_BUFFER 0x8A11 -#define GL_UNIFORM_BUFFER_BINDING 0x8A28 -#define GL_UNIFORM_BUFFER_START 0x8A29 -#define GL_UNIFORM_BUFFER_SIZE 0x8A2A -#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B -#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D -#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E -#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F -#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 -#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 -#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 -#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 -#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 -#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 -#define GL_UNIFORM_TYPE 0x8A37 -#define GL_UNIFORM_SIZE 0x8A38 -#define GL_UNIFORM_NAME_LENGTH 0x8A39 -#define GL_UNIFORM_BLOCK_INDEX 0x8A3A -#define GL_UNIFORM_OFFSET 0x8A3B -#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C -#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D -#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E -#define GL_UNIFORM_BLOCK_BINDING 0x8A3F -#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 -#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 -#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 -#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 -#define GL_INVALID_INDEX 0xFFFFFFFFu -#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 -#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 -#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 -#define GL_OBJECT_TYPE 0x9112 -#define GL_SYNC_CONDITION 0x9113 -#define GL_SYNC_STATUS 0x9114 -#define GL_SYNC_FLAGS 0x9115 -#define GL_SYNC_FENCE 0x9116 -#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 -#define GL_UNSIGNALED 0x9118 -#define GL_SIGNALED 0x9119 -#define GL_ALREADY_SIGNALED 0x911A -#define GL_TIMEOUT_EXPIRED 0x911B -#define GL_CONDITION_SATISFIED 0x911C -#define GL_WAIT_FAILED 0x911D -#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 -#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE -#define GL_ANY_SAMPLES_PASSED 0x8C2F -#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A -#define GL_SAMPLER_BINDING 0x8919 -#define GL_RGB10_A2UI 0x906F -#define GL_TEXTURE_SWIZZLE_R 0x8E42 -#define GL_TEXTURE_SWIZZLE_G 0x8E43 -#define GL_TEXTURE_SWIZZLE_B 0x8E44 -#define GL_TEXTURE_SWIZZLE_A 0x8E45 -#define GL_GREEN 0x1904 -#define GL_BLUE 0x1905 -#define GL_INT_2_10_10_10_REV 0x8D9F -#define GL_TRANSFORM_FEEDBACK 0x8E22 -#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 -#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 -#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 -#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 -#define GL_PROGRAM_BINARY_LENGTH 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE -#define GL_PROGRAM_BINARY_FORMATS 0x87FF -#define GL_COMPRESSED_R11_EAC 0x9270 -#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 -#define GL_COMPRESSED_RG11_EAC 0x9272 -#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 -#define GL_COMPRESSED_RGB8_ETC2 0x9274 -#define GL_COMPRESSED_SRGB8_ETC2 0x9275 -#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 -#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 -#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 -#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 -#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F -#define GL_MAX_ELEMENT_INDEX 0x8D6B -#define GL_NUM_SAMPLE_COUNTS 0x9380 -#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF -GL_APICALL void GL_APIENTRY glReadBuffer (GLenum src); -GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); -GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *pixels); -GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *data); -GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint *ids); -GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint *ids); -GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id); -GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glEndQuery (GLenum target); -GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint *params); -GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target); -GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, void **params); -GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum *bufs); -GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); -GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -GL_APICALL void *GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); -GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); -GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array); -GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint *arrays); -GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint *arrays); -GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array); -GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint *data); -GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode); -GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); -GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); -GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); -GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar *const*varyings, GLenum bufferMode); -GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name); -GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const void *pointer); -GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint *params); -GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); -GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); -GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint *v); -GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint *v); -GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint *params); -GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); -GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0); -GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); -GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); -GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint *value); -GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint *value); -GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat *value); -GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); -GL_APICALL const GLubyte *GL_APIENTRY glGetStringi (GLenum name, GLuint index); -GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); -GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar *const*uniformNames, GLuint *uniformIndices); -GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint *uniformIndices, GLenum pname, GLint *params); -GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar *uniformBlockName); -GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName); -GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); -GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instancecount); -GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount); -GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags); -GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync); -GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync); -GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); -GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64 *data); -GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); -GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64 *data); -GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64 *params); -GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint *samplers); -GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint *samplers); -GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); -GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); -GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint *param); -GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); -GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat *param); -GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); -GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id); -GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint *ids); -GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint *ids); -GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id); -GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); -GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); -GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary); -GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const void *binary, GLsizei length); -GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); -GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments); -GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint *params); -#endif /* GL_ES_VERSION_3_0 */ - -#ifndef GL_ES_VERSION_3_1 -#define GL_ES_VERSION_3_1 1 -#define GL_COMPUTE_SHADER 0x91B9 -#define GL_MAX_COMPUTE_UNIFORM_BLOCKS 0x91BB -#define GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS 0x91BC -#define GL_MAX_COMPUTE_IMAGE_UNIFORMS 0x91BD -#define GL_MAX_COMPUTE_SHARED_MEMORY_SIZE 0x8262 -#define GL_MAX_COMPUTE_UNIFORM_COMPONENTS 0x8263 -#define GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS 0x8264 -#define GL_MAX_COMPUTE_ATOMIC_COUNTERS 0x8265 -#define GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS 0x8266 -#define GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS 0x90EB -#define GL_MAX_COMPUTE_WORK_GROUP_COUNT 0x91BE -#define GL_MAX_COMPUTE_WORK_GROUP_SIZE 0x91BF -#define GL_COMPUTE_WORK_GROUP_SIZE 0x8267 -#define GL_DISPATCH_INDIRECT_BUFFER 0x90EE -#define GL_DISPATCH_INDIRECT_BUFFER_BINDING 0x90EF -#define GL_COMPUTE_SHADER_BIT 0x00000020 -#define GL_DRAW_INDIRECT_BUFFER 0x8F3F -#define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 -#define GL_MAX_UNIFORM_LOCATIONS 0x826E -#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310 -#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311 -#define GL_FRAMEBUFFER_DEFAULT_SAMPLES 0x9313 -#define GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS 0x9314 -#define GL_MAX_FRAMEBUFFER_WIDTH 0x9315 -#define GL_MAX_FRAMEBUFFER_HEIGHT 0x9316 -#define GL_MAX_FRAMEBUFFER_SAMPLES 0x9318 -#define GL_UNIFORM 0x92E1 -#define GL_UNIFORM_BLOCK 0x92E2 -#define GL_PROGRAM_INPUT 0x92E3 -#define GL_PROGRAM_OUTPUT 0x92E4 -#define GL_BUFFER_VARIABLE 0x92E5 -#define GL_SHADER_STORAGE_BLOCK 0x92E6 -#define GL_ATOMIC_COUNTER_BUFFER 0x92C0 -#define GL_TRANSFORM_FEEDBACK_VARYING 0x92F4 -#define GL_ACTIVE_RESOURCES 0x92F5 -#define GL_MAX_NAME_LENGTH 0x92F6 -#define GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7 -#define GL_NAME_LENGTH 0x92F9 -#define GL_TYPE 0x92FA -#define GL_ARRAY_SIZE 0x92FB -#define GL_OFFSET 0x92FC -#define GL_BLOCK_INDEX 0x92FD -#define GL_ARRAY_STRIDE 0x92FE -#define GL_MATRIX_STRIDE 0x92FF -#define GL_IS_ROW_MAJOR 0x9300 -#define GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301 -#define GL_BUFFER_BINDING 0x9302 -#define GL_BUFFER_DATA_SIZE 0x9303 -#define GL_NUM_ACTIVE_VARIABLES 0x9304 -#define GL_ACTIVE_VARIABLES 0x9305 -#define GL_REFERENCED_BY_VERTEX_SHADER 0x9306 -#define GL_REFERENCED_BY_FRAGMENT_SHADER 0x930A -#define GL_REFERENCED_BY_COMPUTE_SHADER 0x930B -#define GL_TOP_LEVEL_ARRAY_SIZE 0x930C -#define GL_TOP_LEVEL_ARRAY_STRIDE 0x930D -#define GL_LOCATION 0x930E -#define GL_VERTEX_SHADER_BIT 0x00000001 -#define GL_FRAGMENT_SHADER_BIT 0x00000002 -#define GL_ALL_SHADER_BITS 0xFFFFFFFF -#define GL_PROGRAM_SEPARABLE 0x8258 -#define GL_ACTIVE_PROGRAM 0x8259 -#define GL_PROGRAM_PIPELINE_BINDING 0x825A -#define GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 -#define GL_ATOMIC_COUNTER_BUFFER_START 0x92C2 -#define GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 -#define GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC -#define GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 -#define GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 -#define GL_MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 -#define GL_MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 -#define GL_MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 -#define GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 -#define GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC -#define GL_ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 -#define GL_UNSIGNED_INT_ATOMIC_COUNTER 0x92DB -#define GL_MAX_IMAGE_UNITS 0x8F38 -#define GL_MAX_VERTEX_IMAGE_UNIFORMS 0x90CA -#define GL_MAX_FRAGMENT_IMAGE_UNIFORMS 0x90CE -#define GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF -#define GL_IMAGE_BINDING_NAME 0x8F3A -#define GL_IMAGE_BINDING_LEVEL 0x8F3B -#define GL_IMAGE_BINDING_LAYERED 0x8F3C -#define GL_IMAGE_BINDING_LAYER 0x8F3D -#define GL_IMAGE_BINDING_ACCESS 0x8F3E -#define GL_IMAGE_BINDING_FORMAT 0x906E -#define GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT 0x00000001 -#define GL_ELEMENT_ARRAY_BARRIER_BIT 0x00000002 -#define GL_UNIFORM_BARRIER_BIT 0x00000004 -#define GL_TEXTURE_FETCH_BARRIER_BIT 0x00000008 -#define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 -#define GL_COMMAND_BARRIER_BIT 0x00000040 -#define GL_PIXEL_BUFFER_BARRIER_BIT 0x00000080 -#define GL_TEXTURE_UPDATE_BARRIER_BIT 0x00000100 -#define GL_BUFFER_UPDATE_BARRIER_BIT 0x00000200 -#define GL_FRAMEBUFFER_BARRIER_BIT 0x00000400 -#define GL_TRANSFORM_FEEDBACK_BARRIER_BIT 0x00000800 -#define GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000 -#define GL_ALL_BARRIER_BITS 0xFFFFFFFF -#define GL_IMAGE_2D 0x904D -#define GL_IMAGE_3D 0x904E -#define GL_IMAGE_CUBE 0x9050 -#define GL_IMAGE_2D_ARRAY 0x9053 -#define GL_INT_IMAGE_2D 0x9058 -#define GL_INT_IMAGE_3D 0x9059 -#define GL_INT_IMAGE_CUBE 0x905B -#define GL_INT_IMAGE_2D_ARRAY 0x905E -#define GL_UNSIGNED_INT_IMAGE_2D 0x9063 -#define GL_UNSIGNED_INT_IMAGE_3D 0x9064 -#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066 -#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069 -#define GL_IMAGE_FORMAT_COMPATIBILITY_TYPE 0x90C7 -#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE 0x90C8 -#define GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS 0x90C9 -#define GL_READ_ONLY 0x88B8 -#define GL_WRITE_ONLY 0x88B9 -#define GL_READ_WRITE 0x88BA -#define GL_SHADER_STORAGE_BUFFER 0x90D2 -#define GL_SHADER_STORAGE_BUFFER_BINDING 0x90D3 -#define GL_SHADER_STORAGE_BUFFER_START 0x90D4 -#define GL_SHADER_STORAGE_BUFFER_SIZE 0x90D5 -#define GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS 0x90D6 -#define GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS 0x90DA -#define GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS 0x90DB -#define GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC -#define GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS 0x90DD -#define GL_MAX_SHADER_STORAGE_BLOCK_SIZE 0x90DE -#define GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT 0x90DF -#define GL_SHADER_STORAGE_BARRIER_BIT 0x00002000 -#define GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39 -#define GL_DEPTH_STENCIL_TEXTURE_MODE 0x90EA -#define GL_STENCIL_INDEX 0x1901 -#define GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5E -#define GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET 0x8E5F -#define GL_SAMPLE_POSITION 0x8E50 -#define GL_SAMPLE_MASK 0x8E51 -#define GL_SAMPLE_MASK_VALUE 0x8E52 -#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 -#define GL_MAX_SAMPLE_MASK_WORDS 0x8E59 -#define GL_MAX_COLOR_TEXTURE_SAMPLES 0x910E -#define GL_MAX_DEPTH_TEXTURE_SAMPLES 0x910F -#define GL_MAX_INTEGER_SAMPLES 0x9110 -#define GL_TEXTURE_BINDING_2D_MULTISAMPLE 0x9104 -#define GL_TEXTURE_SAMPLES 0x9106 -#define GL_TEXTURE_FIXED_SAMPLE_LOCATIONS 0x9107 -#define GL_TEXTURE_WIDTH 0x1000 -#define GL_TEXTURE_HEIGHT 0x1001 -#define GL_TEXTURE_DEPTH 0x8071 -#define GL_TEXTURE_INTERNAL_FORMAT 0x1003 -#define GL_TEXTURE_RED_SIZE 0x805C -#define GL_TEXTURE_GREEN_SIZE 0x805D -#define GL_TEXTURE_BLUE_SIZE 0x805E -#define GL_TEXTURE_ALPHA_SIZE 0x805F -#define GL_TEXTURE_DEPTH_SIZE 0x884A -#define GL_TEXTURE_STENCIL_SIZE 0x88F1 -#define GL_TEXTURE_SHARED_SIZE 0x8C3F -#define GL_TEXTURE_RED_TYPE 0x8C10 -#define GL_TEXTURE_GREEN_TYPE 0x8C11 -#define GL_TEXTURE_BLUE_TYPE 0x8C12 -#define GL_TEXTURE_ALPHA_TYPE 0x8C13 -#define GL_TEXTURE_DEPTH_TYPE 0x8C16 -#define GL_TEXTURE_COMPRESSED 0x86A1 -#define GL_SAMPLER_2D_MULTISAMPLE 0x9108 -#define GL_INT_SAMPLER_2D_MULTISAMPLE 0x9109 -#define GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE 0x910A -#define GL_VERTEX_ATTRIB_BINDING 0x82D4 -#define GL_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D5 -#define GL_VERTEX_BINDING_DIVISOR 0x82D6 -#define GL_VERTEX_BINDING_OFFSET 0x82D7 -#define GL_VERTEX_BINDING_STRIDE 0x82D8 -#define GL_VERTEX_BINDING_BUFFER 0x8F4F -#define GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET 0x82D9 -#define GL_MAX_VERTEX_ATTRIB_BINDINGS 0x82DA -#define GL_MAX_VERTEX_ATTRIB_STRIDE 0x82E5 -GL_APICALL void GL_APIENTRY glDispatchCompute (GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); -GL_APICALL void GL_APIENTRY glDispatchComputeIndirect (GLintptr indirect); -GL_APICALL void GL_APIENTRY glDrawArraysIndirect (GLenum mode, const void *indirect); -GL_APICALL void GL_APIENTRY glDrawElementsIndirect (GLenum mode, GLenum type, const void *indirect); -GL_APICALL void GL_APIENTRY glFramebufferParameteri (GLenum target, GLenum pname, GLint param); -GL_APICALL void GL_APIENTRY glGetFramebufferParameteriv (GLenum target, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetProgramInterfaceiv (GLuint program, GLenum programInterface, GLenum pname, GLint *params); -GL_APICALL GLuint GL_APIENTRY glGetProgramResourceIndex (GLuint program, GLenum programInterface, const GLchar *name); -GL_APICALL void GL_APIENTRY glGetProgramResourceName (GLuint program, GLenum programInterface, GLuint index, GLsizei bufSize, GLsizei *length, GLchar *name); -GL_APICALL void GL_APIENTRY glGetProgramResourceiv (GLuint program, GLenum programInterface, GLuint index, GLsizei propCount, const GLenum *props, GLsizei bufSize, GLsizei *length, GLint *params); -GL_APICALL GLint GL_APIENTRY glGetProgramResourceLocation (GLuint program, GLenum programInterface, const GLchar *name); -GL_APICALL void GL_APIENTRY glUseProgramStages (GLuint pipeline, GLbitfield stages, GLuint program); -GL_APICALL void GL_APIENTRY glActiveShaderProgram (GLuint pipeline, GLuint program); -GL_APICALL GLuint GL_APIENTRY glCreateShaderProgramv (GLenum type, GLsizei count, const GLchar *const*strings); -GL_APICALL void GL_APIENTRY glBindProgramPipeline (GLuint pipeline); -GL_APICALL void GL_APIENTRY glDeleteProgramPipelines (GLsizei n, const GLuint *pipelines); -GL_APICALL void GL_APIENTRY glGenProgramPipelines (GLsizei n, GLuint *pipelines); -GL_APICALL GLboolean GL_APIENTRY glIsProgramPipeline (GLuint pipeline); -GL_APICALL void GL_APIENTRY glGetProgramPipelineiv (GLuint pipeline, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glProgramUniform1i (GLuint program, GLint location, GLint v0); -GL_APICALL void GL_APIENTRY glProgramUniform2i (GLuint program, GLint location, GLint v0, GLint v1); -GL_APICALL void GL_APIENTRY glProgramUniform3i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2); -GL_APICALL void GL_APIENTRY glProgramUniform4i (GLuint program, GLint location, GLint v0, GLint v1, GLint v2, GLint v3); -GL_APICALL void GL_APIENTRY glProgramUniform1ui (GLuint program, GLint location, GLuint v0); -GL_APICALL void GL_APIENTRY glProgramUniform2ui (GLuint program, GLint location, GLuint v0, GLuint v1); -GL_APICALL void GL_APIENTRY glProgramUniform3ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2); -GL_APICALL void GL_APIENTRY glProgramUniform4ui (GLuint program, GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); -GL_APICALL void GL_APIENTRY glProgramUniform1f (GLuint program, GLint location, GLfloat v0); -GL_APICALL void GL_APIENTRY glProgramUniform2f (GLuint program, GLint location, GLfloat v0, GLfloat v1); -GL_APICALL void GL_APIENTRY glProgramUniform3f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2); -GL_APICALL void GL_APIENTRY glProgramUniform4f (GLuint program, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3); -GL_APICALL void GL_APIENTRY glProgramUniform1iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform2iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform3iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform4iv (GLuint program, GLint location, GLsizei count, const GLint *value); -GL_APICALL void GL_APIENTRY glProgramUniform1uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniform2uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniform3uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniform4uiv (GLuint program, GLint location, GLsizei count, const GLuint *value); -GL_APICALL void GL_APIENTRY glProgramUniform1fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform2fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform3fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniform4fv (GLuint program, GLint location, GLsizei count, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix2x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x2fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix3x4fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glProgramUniformMatrix4x3fv (GLuint program, GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); -GL_APICALL void GL_APIENTRY glValidateProgramPipeline (GLuint pipeline); -GL_APICALL void GL_APIENTRY glGetProgramPipelineInfoLog (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); -GL_APICALL void GL_APIENTRY glBindImageTexture (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format); -GL_APICALL void GL_APIENTRY glGetBooleani_v (GLenum target, GLuint index, GLboolean *data); -GL_APICALL void GL_APIENTRY glMemoryBarrier (GLbitfield barriers); -GL_APICALL void GL_APIENTRY glMemoryBarrierByRegion (GLbitfield barriers); -GL_APICALL void GL_APIENTRY glTexStorage2DMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); -GL_APICALL void GL_APIENTRY glGetMultisamplefv (GLenum pname, GLuint index, GLfloat *val); -GL_APICALL void GL_APIENTRY glSampleMaski (GLuint maskNumber, GLbitfield mask); -GL_APICALL void GL_APIENTRY glGetTexLevelParameteriv (GLenum target, GLint level, GLenum pname, GLint *params); -GL_APICALL void GL_APIENTRY glGetTexLevelParameterfv (GLenum target, GLint level, GLenum pname, GLfloat *params); -GL_APICALL void GL_APIENTRY glBindVertexBuffer (GLuint bindingindex, GLuint buffer, GLintptr offset, GLsizei stride); -GL_APICALL void GL_APIENTRY glVertexAttribFormat (GLuint attribindex, GLint size, GLenum type, GLboolean normalized, GLuint relativeoffset); -GL_APICALL void GL_APIENTRY glVertexAttribIFormat (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset); -GL_APICALL void GL_APIENTRY glVertexAttribBinding (GLuint attribindex, GLuint bindingindex); -GL_APICALL void GL_APIENTRY glVertexBindingDivisor (GLuint bindingindex, GLuint divisor); -#endif /* GL_ES_VERSION_3_1 */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/external/khronos/GLES3/gl3ext.h b/external/khronos/GLES3/gl3ext.h deleted file mode 100644 index 8fb0924db..000000000 --- a/external/khronos/GLES3/gl3ext.h +++ /dev/null @@ -1 +0,0 @@ -// this file is intentionally left blank \ No newline at end of file diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 88f85e506..bf07ca7a8 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -32,11 +32,9 @@ if(ramses-sdk_TEXT_SUPPORT) target_compile_definitions(ramses-api INTERFACE RAMSES_TEXT_ENABLED) endif() -if(ramses-sdk_ENABLE_LOGIC) - file(GLOB - RAMSES_CLIENT_LOGIC_API_FILES_HEADER - ramses/client/logic/*.h) -endif() +file(GLOB + RAMSES_CLIENT_LOGIC_API_FILES_HEADER + ramses/client/logic/*.h) # renderer if(ANY_WINDOW_TYPE_ENABLED) @@ -66,9 +64,7 @@ if(ramses-sdk_ENABLE_INSTALL) if(ramses-sdk_TEXT_SUPPORT) install(FILES ${RAMSES_CLIENT_TEXT_API_FILES_HEADER} DESTINATION "${RAMSES_INSTALL_HEADERS_PATH}/ramses/client/text" COMPONENT ramses-sdk-devel) endif() - if(ramses-sdk_ENABLE_LOGIC) - install(FILES ${RAMSES_CLIENT_LOGIC_API_FILES_HEADER} DESTINATION "${RAMSES_INSTALL_HEADERS_PATH}/ramses/client/logic" COMPONENT ramses-sdk-devel) - endif() + install(FILES ${RAMSES_CLIENT_LOGIC_API_FILES_HEADER} DESTINATION "${RAMSES_INSTALL_HEADERS_PATH}/ramses/client/logic" COMPONENT ramses-sdk-devel) if(ANY_WINDOW_TYPE_ENABLED) install(FILES ${RAMSES_RENDERER_API_FILES_HEADER} DESTINATION "${RAMSES_INSTALL_HEADERS_PATH}/ramses/renderer" COMPONENT ramses-sdk-devel) diff --git a/include/ramses/client/Effect.h b/include/ramses/client/Effect.h index 357e164e8..888aadfd6 100644 --- a/include/ramses/client/Effect.h +++ b/include/ramses/client/Effect.h @@ -95,6 +95,14 @@ namespace ramses */ [[nodiscard]] std::optional findAttributeInput(EEffectAttributeSemantic attributeSemantic) const; + /** + * @brief Finds uniform input for a uniform buffer using binding. + * + * @param[in] uniformBufferBinding Binding specified in the layout of the uniform buffer in the shader + * @return #ramses::UniformInput if successful, otherwise, std::nullopt + */ + [[nodiscard]] std::optional findUniformInputAtBinding(uint32_t uniformBufferBinding) const; + /** * @brief Checks if the \p effect has a geometry shader attached to it. * diff --git a/include/ramses/client/EffectDescription.h b/include/ramses/client/EffectDescription.h index 7b94b31d1..42b3d39b1 100644 --- a/include/ramses/client/EffectDescription.h +++ b/include/ramses/client/EffectDescription.h @@ -82,7 +82,7 @@ namespace ramses bool addCompilerDefine(std::string_view define); /** - * @brief Sets an uniform semantic. + * @brief Sets a uniform semantic. * Used for uniforms which are not locally available * on the client, such as projection matrix, framebuffer resolution etc. * Value of an uniform corresponding to the given semantic name @@ -93,6 +93,18 @@ namespace ramses */ bool setUniformSemantic(std::string_view inputName, EEffectUniformSemantic semanticType); + /** + * @brief Sets a uniform semantic on a uniform buffer using layout binding. + * Used for uniform buffers that represent values that are not locally available + * on the client, such as model block, camera block...etc. + * Values of a uniform buffer corresponding to the given semantic + * will be automatically set based on its semantic type. + * @param[in] uniformBufferBinding Binding specified in the shader source code in the definition of a uniform buffer's layout. + * @param[in] semanticType Semantic type to be used for given input. + * @return true on success, false if an error occurred (error is logged) + */ + bool setUniformSemantic(uint32_t uniformBufferBinding, EEffectUniformSemantic semanticType); + /** * @brief Sets an attribute semantic. * Used to mark attributes as special inputs (eg. text specific inputs). diff --git a/include/ramses/client/EffectInputSemantic.h b/include/ramses/client/EffectInputSemantic.h index 4b1c54e3d..f38d87291 100644 --- a/include/ramses/client/EffectInputSemantic.h +++ b/include/ramses/client/EffectInputSemantic.h @@ -16,23 +16,65 @@ namespace ramses */ enum class EEffectUniformSemantic { - Invalid = 0, ///< Invalid semantic - ProjectionMatrix, ///< Projection matrix 4x4 - ModelMatrix, ///< Mesh model matrix 4x4 - CameraWorldPosition, ///< Camera position vector 3 - ///< ^ Position, from where the renderer eye looks at the scene in world coordinates - ViewMatrix, ///< View matrix 4x4 - ModelViewMatrix, ///< Model-view matrix 4x4 - ModelViewMatrix33, ///< Model-view matrix 3x3 - ModelViewProjectionMatrix, ///< Model-view-projection matrix 4x4 - NormalMatrix, ///< Transposed and inversed MVP matrix for vertex normals - DisplayBufferResolution, ///< Resolution of currently set destination display buffer (either display framebuffer or offscreen buffer, does not give RenderTarget resolution) - - TextTexture, ///< Text specific + Invalid = 0, ///< Invalid semantic + ProjectionMatrix, ///< Projection matrix 4x4 + ModelMatrix, ///< Mesh model matrix 4x4 + CameraWorldPosition, ///< Camera position vector 3 (camera world position of the camera used in current render pass) + ViewMatrix, ///< View matrix 4x4 + ModelViewMatrix, ///< Model-view matrix 4x4 + ModelViewMatrix33, ///< Model-view matrix 3x3 + ModelViewProjectionMatrix, ///< Model-view-projection matrix 4x4 + NormalMatrix, ///< Transposed and inversed MVP matrix for vertex normals + DisplayBufferResolution, ///< Resolution of currently set destination display buffer (either display framebuffer or offscreen buffer, does not give RenderTarget resolution) + TextTexture, ///< Text specific TimeMs, ///< synchronized clock in milliseconds, resets to 0 every ~24 days, i.e. value range is: 0 .. std::numeric_limits::max(). ///< In order to avoid handling the wrap in the shader code or potential overflow issues the value should be reset using #ramses::Scene::resetUniformTimeMs(). ///< The value is not reset automatically at startup, but contains the time elapsed since clock epoch. + + ModelBlock, ///< Uniform buffer containing: ModelMatrix (mat44) + ///< - exists per MeshNode and is updated whenever MeshNode transformation changes + ///< Declaration example in shader: + ///< layout(std140, binding = 1) uniform uniformBlock_t + ///< { + ///< mat4 modelMat; + ///< } myModelUBO; + + CameraBlock, ///< Uniform buffer containing (in this order): ProjectionMatrix(mat44), ViewMatrix(mat44), CameraWorldPosition(vec3) + ///< - exists per Camera and is updated whenever Camera transformation or view/projection parameters change + ///< Declaration example in shader: + ///< layout(std140, binding = 1) uniform uniformBlock_t + ///< { + ///< mat4 projMat; + ///< mat4 viewMat; + ///< vec3 camPos; + ///< } myCameraUBO; + + ModelCameraBlock, ///< Uniform buffer containing (in this order): ModelViewProjectionMatrix(mat44), ModelViewMatrix(mat44), NormalMatrix(mat44) + ///< - exists per every Camera/MeshNode combination in render passes and is updated whenever Camera or MeshNode transformation changes or Camera view/projection parameters change + ///< Declaration example in shader: + ///< layout(std140, binding = 1) uniform uniformBlock_t + ///< { + ///< mat4 mvpMat; + ///< mat4 mvMat; + ///< mat4 normalMat; + ///< } myModelCameraUBO; + + FramebufferBlock, ///< Uniform buffer containing: FramebufferResolution(vec2) + ///< - exists per RenderTarget and is never updated + ///< Declaration example in shader: + ///< layout(std140, binding = 1) uniform uniformBlock_t + ///< { + ///< vec2 resolution; + ///< } myFramebufferInfoUBO; + + SceneBlock, ///< Uniform buffer containing: TimeMs(int) + ///< - exists per Scene and is updated once per frame + ///< Declaration example in shader: + ///< layout(std140, binding = 1) uniform uniformBlock_t + ///< { + ///< int time; + ///< } mySceneInfoUBO; }; /** diff --git a/include/ramses/client/RamsesClient.h b/include/ramses/client/RamsesClient.h index a6ebe7f7c..8c156007b 100644 --- a/include/ramses/client/RamsesClient.h +++ b/include/ramses/client/RamsesClient.h @@ -134,6 +134,59 @@ namespace ramses */ bool loadSceneFromFileAsync(std::string_view fileName, const SceneConfig& config = {}); + /** + * @brief Loads scene contents and resources from a file and merges them into an existing scene. + * + * Same rules apply as for loading a scene from file - Ramses SDK major version and #ramses::EFeatureLevel must match. + * + * @param[in] scene Scene that all new content from file is going to be merged into. + * @param[in] fileName File name to load the scene from. + * @return True if loading and merging was successful. + */ + bool mergeSceneFromFile(Scene& scene, std::string_view fileName); + + /** + * @brief Loads scene contents and resources from a memory buffer and merges them into an existing scene. + * + * Same rules apply as for loading a scene from file - Ramses SDK major version and #ramses::EFeatureLevel must match. + * + * Ramses takes ownership of the memory buffer passed in via data and will delete it via the provided deleter from + * unique_ptr when not used anymore. The caller may not modify the referenced memory anymore after this call. + * The behavior is undefined if data does not contain a complete serialized ramses scene or if size does not + * match the size of the scene data in bytes. + * + * The deleter on data allows safe memory ownership passing on windows when ramses is used as dll. For more + * details and a convenience wrapper see #ramses::RamsesUtils::LoadSceneFromMemory. + * + * @param[in] scene Scene that all new content from file is going to be merged into. + * @param[in] data Memory buffer to load the scene from. + * @param[in] size The size in bytes of the data memory. + * @return True if loading and merging was successful. + */ + // NOLINTNEXTLINE(modernize-avoid-c-arrays) + bool mergeSceneFromMemory(Scene& scene, std::unique_ptr data, size_t size); + + /** + * @brief Loads scene contents and resources from an open file descriptor and merges them info an existing scene. + * + * Same rules apply as for loading a scene from file - Ramses SDK major version and #ramses::EFeatureLevel must match. + * + * The ramses scene must be in the already opened filedescriptor at absolute position offset within + * the file. The filedescriptor must be opened for read access and may not be modified anymore after + * this call. The filedescriptor must support seeking. + * Ramses takes ownership of the filedescriptor and will close it when not needed anymore. + * + * The behavior is undefined if the filedescriptor does not contain a complete serialized ramses scene + * at offset. + * + * @param[in] scene Scene that all new content from file is going to merged into. + * @param[in] fd Open and readable filedescriptor. + * @param[in] offset Absolute starting position of ramses scene within fd. + * @param[in] length Size of the scene data within fd. + * @return True if loading and merging was successful. + */ + bool mergeSceneFromFileDescriptor(Scene& scene, int fd, size_t offset, size_t length); + /** * Attempts to parse feature level from a Ramses scene file. * diff --git a/include/ramses/client/Scene.h b/include/ramses/client/Scene.h index a732747f8..45c0feceb 100644 --- a/include/ramses/client/Scene.h +++ b/include/ramses/client/Scene.h @@ -214,6 +214,7 @@ namespace ramses bool destroy(SceneObject& object); /** + * \deprecated { This feature will not be available in next major release, contact developer team immediately if you plan on using it } * @brief Expiration timestamp is a point in time till which the scene is considered to be up-to-date. * @details Logic on renderer side will check the time every frame and in case it detects the scene * to be rendered after its expiration timestamp it will generate an event (#ramses::IRendererSceneControlEventHandler::sceneExpired). @@ -234,7 +235,7 @@ namespace ramses * * @return true for success, false otherwise (check log or #ramses::RamsesFramework::getLastError for details). */ - bool setExpirationTimestamp(uint64_t ptpExpirationTimestampInMilliseconds); + [[deprecated]] bool setExpirationTimestamp(uint64_t ptpExpirationTimestampInMilliseconds); /** * @brief Commits all changes done to the scene since the last flush or since scene creation. @@ -776,6 +777,7 @@ namespace ramses bool createTextureConsumer(const TextureSamplerExternal& sampler, dataConsumerId_t dataId); /** + * \deprecated { This feature will not be available in next major release, contact developer team immediately if you plan on using it } * @brief Creates a new SceneReference object. * @details The SceneReference object references a scene, which might be unknown * to this RamsesClient, but is or expected to be known to the RamsesRenderer subscribed to this scene. @@ -793,7 +795,7 @@ namespace ramses * @param[in] name The optional name of the created SceneReference. * @return A pointer to the created SceneReference. */ - SceneReference* createSceneReference(sceneId_t referencedScene, std::string_view name = {}); + [[deprecated]] SceneReference* createSceneReference(sceneId_t referencedScene, std::string_view name = {}); /** * @brief Tell the RamsesRenderer to link a data provider to a data consumer across two scenes. diff --git a/include/ramses/client/SceneConfig.h b/include/ramses/client/SceneConfig.h index 972eeef9b..0f282f337 100644 --- a/include/ramses/client/SceneConfig.h +++ b/include/ramses/client/SceneConfig.h @@ -11,6 +11,7 @@ #include "ramses/framework/APIExport.h" #include "ramses/framework/RamsesFrameworkTypes.h" #include "ramses/framework/EScenePublicationMode.h" +#include "ramses/framework/ERenderBackendCompatibility.h" #include @@ -40,8 +41,9 @@ namespace ramses * @param sceneId Each scene requires a sceneId for global identification (sceneId is used for scene mapping on renderer side). * If no sceneId is provided Ramses will use the sceneId stored in the serialized file or raise an error if the scene is created at runtime. * @param publicationMode see #ramses::SceneConfig::setPublicationMode for details + * @param renderBackendCompatibility see #ramses::SceneConfig::setRenderBackendCompatibility for details */ - explicit SceneConfig(sceneId_t sceneId, EScenePublicationMode publicationMode = EScenePublicationMode::LocalOnly); + explicit SceneConfig(sceneId_t sceneId, EScenePublicationMode publicationMode = EScenePublicationMode::LocalOnly, ERenderBackendCompatibility renderBackendCompatibility = ERenderBackendCompatibility::OpenGL); /** * @brief Destructor of SceneConfig @@ -74,6 +76,15 @@ namespace ramses */ void setMemoryVerificationEnabled(bool enabled); + /** + * Set compatibility of scene and its resources to render backend devices available on the renderer. + * If a scene object or a resource is created in the scene and it is not compatible + * with the selected render backend device on the renderer side, the scene will be rejected and cannot be rendered. + * + * @param renderBackendCompatibility Render backend compatibility of scene and its resources. + */ + void setRenderBackendCompatibility(ERenderBackendCompatibility renderBackendCompatibility); + /** * @brief Copy constructor * @param other source to copy from diff --git a/include/ramses/client/UniformInput.h b/include/ramses/client/UniformInput.h index 263f02b03..f92155ba4 100644 --- a/include/ramses/client/UniformInput.h +++ b/include/ramses/client/UniformInput.h @@ -38,6 +38,15 @@ namespace ramses */ [[nodiscard]] size_t getElementCount() const; + /** + * @brief Returns the binding specified in the layout for uniform buffer declaration in the shader. + * @details If the uniform object input reports to either a uniform buffer or a uniform buffer field/item, + * then the binding specified for the uniform buffer in layout is returned. Same value is returned + * for inputs representing a uniform buffer and all its fields. + * @return the uniform buffer binding or nullopt if the input is neither a uniform buffer nor a field within a uniform buffer + */ + [[nodiscard]] std::optional getUniformBufferBinding() const; + /** * @brief Destructor of UniformInput. */ diff --git a/include/ramses/framework/DataTypes.h b/include/ramses/framework/DataTypes.h index d23508408..95896efdd 100644 --- a/include/ramses/framework/DataTypes.h +++ b/include/ramses/framework/DataTypes.h @@ -96,6 +96,7 @@ namespace ramses case EDataType::TextureSampler3D: case EDataType::TextureSamplerCube: case EDataType::TextureSamplerExternal: + case EDataType::UniformBuffer: return false; } @@ -133,6 +134,7 @@ namespace ramses case EDataType::TextureSampler3D: case EDataType::TextureSamplerCube: case EDataType::TextureSamplerExternal: + case EDataType::UniformBuffer: return false; } diff --git a/include/ramses/framework/EDataType.h b/include/ramses/framework/EDataType.h index e26cd3f27..8d8eff839 100644 --- a/include/ramses/framework/EDataType.h +++ b/include/ramses/framework/EDataType.h @@ -41,6 +41,8 @@ namespace ramses TextureSampler3D, ///< 3D Texture sampler data type TextureSamplerCube, ///< Cube Texture sampler data type TextureSamplerExternal, ///< External Texture sampler data type + + UniformBuffer, ///< Uniform buffer object data type }; /** @@ -80,6 +82,7 @@ namespace ramses case EDataType::TextureSampler3D: case EDataType::TextureSamplerCube: case EDataType::TextureSamplerExternal: + case EDataType::UniformBuffer: return 0u; } @@ -126,6 +129,7 @@ namespace ramses case EDataType::TextureSampler3D: case EDataType::TextureSamplerCube: case EDataType::TextureSamplerExternal: + case EDataType::UniformBuffer: return 0u; } diff --git a/include/ramses/framework/EFeatureLevel.h b/include/ramses/framework/EFeatureLevel.h index 5be34d1b5..d55e4152f 100644 --- a/include/ramses/framework/EFeatureLevel.h +++ b/include/ramses/framework/EFeatureLevel.h @@ -49,7 +49,12 @@ namespace ramses /// Base level of features released with version 28.0 EFeatureLevel_01 = 1, + /// Added features: Uniform buffer objects + EFeatureLevel_02 = 2, + /// Equals to the latest feature level - EFeatureLevel_Latest = EFeatureLevel_01 + /// Avoid using this enum in application code because it will change also in minor releases when new feature level is added! + /// Use concrete feature level when instantiating Ramses framework, level which matches desired use case or supports certain asset. + EFeatureLevel_Latest = EFeatureLevel_02 }; } diff --git a/include/ramses/framework/ERenderBackendCompatibility.h b/include/ramses/framework/ERenderBackendCompatibility.h new file mode 100644 index 000000000..5534e62a3 --- /dev/null +++ b/include/ramses/framework/ERenderBackendCompatibility.h @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include + +namespace ramses +{ + /** + * @ingroup CoreAPI + * Specifies compatibility of scene and its resources with the different renderer devices. + */ + enum class ERenderBackendCompatibility : uint8_t + { + OpenGL, + VulkanAndOpenGL + }; +} diff --git a/include/ramses/renderer/DisplayConfig.h b/include/ramses/renderer/DisplayConfig.h index cd71aea40..d229fc4f2 100644 --- a/include/ramses/renderer/DisplayConfig.h +++ b/include/ramses/renderer/DisplayConfig.h @@ -75,6 +75,14 @@ namespace ramses */ [[nodiscard]] EWindowType getWindowType() const; + /** + * @brief Sets the window title + * + * @param[in] windowTitle window title. + * @return true on success, false if an error occurred (error is logged) + */ + bool setWindowTitle(std::string_view windowTitle); + /** * @brief Sets the window size and position in display pixel space. * This is ignored if window is set fullscreen. diff --git a/include/ramses/renderer/RamsesRenderer.h b/include/ramses/renderer/RamsesRenderer.h index 8af8e96a8..a8556c666 100644 --- a/include/ramses/renderer/RamsesRenderer.h +++ b/include/ramses/renderer/RamsesRenderer.h @@ -521,7 +521,7 @@ namespace ramses * @param visibility visibility to set * @return true for success, false otherwise (check log or #ramses::RamsesFramework::getLastError for details). **/ - bool setSurfaceVisibility(uint32_t surfaceId, bool visibility); + [[deprecated]] bool setSurfaceVisibility(uint32_t surfaceId, bool visibility); /** * @brief Set opacity of given surface at the system compositor @@ -529,7 +529,7 @@ namespace ramses * @param opacity Opacity in the range 0.0 (fully transparent) to 1.0 (fully opaque) * @return true for success, false otherwise (check log or #ramses::RamsesFramework::getLastError for details). **/ - bool setSurfaceOpacity(uint32_t surfaceId, float opacity); + [[deprecated]] bool setSurfaceOpacity(uint32_t surfaceId, float opacity); /** * @brief Set output rectangle of given surface at the system compositor @@ -540,7 +540,7 @@ namespace ramses * @param height Output height of surface * @return true for success, false otherwise (check log or #ramses::RamsesFramework::getLastError for details). */ - bool setSurfaceRectangle(uint32_t surfaceId, int32_t x, int32_t y, int32_t width, int32_t height); + [[deprecated]] bool setSurfaceRectangle(uint32_t surfaceId, int32_t x, int32_t y, int32_t width, int32_t height); /** * @brief Set visibility of given layer at the system compositor @@ -548,7 +548,7 @@ namespace ramses * @param visibility If \c true the layer's visibility will be enabled, otherwise disabled * @return true for success, false otherwise (check log or #ramses::RamsesFramework::getLastError for details). **/ - bool setLayerVisibility(uint32_t layerId, bool visibility); + [[deprecated]] bool setLayerVisibility(uint32_t layerId, bool visibility); /** * @brief Trigger the System Compositor to take a screenshot and store it in a file. @@ -557,7 +557,7 @@ namespace ramses * on a single existing screen (fails asynchronously if more than one screen exists) * @return true for success, false otherwise (check log or #ramses::RamsesFramework::getLastError for details). */ - bool takeSystemCompositorScreenshot(std::string_view fileName, int32_t screenIviId); + [[deprecated]] bool takeSystemCompositorScreenshot(std::string_view fileName, int32_t screenIviId); ///////////////////////////////////////////////// // End of System Compositor API diff --git a/include/ramses/renderer/RendererConfig.h b/include/ramses/renderer/RendererConfig.h index e5cb143fb..c37118252 100644 --- a/include/ramses/renderer/RendererConfig.h +++ b/include/ramses/renderer/RendererConfig.h @@ -53,7 +53,7 @@ namespace ramses * * @return true on success, false if an error occurred (error is logged) */ - bool enableSystemCompositorControl(); + [[deprecated]] bool enableSystemCompositorControl(); /** * @brief Set the maximum time to wait for the system compositor frame callback @@ -76,14 +76,14 @@ namespace ramses * @param[in] waylandDisplay Wayland display name to use for connection * @return true on success, false if an error occurred (error is logged) */ - bool setSystemCompositorWaylandDisplay(std::string_view waylandDisplay); + [[deprecated]] bool setSystemCompositorWaylandDisplay(std::string_view waylandDisplay); /** * @brief Get the current setting of Wayland display name * * @return Wayland display name to use for connection, empty means default */ - [[nodiscard]] std::string_view getSystemCompositorWaylandDisplay() const; + [[deprecated]] [[nodiscard]] std::string_view getSystemCompositorWaylandDisplay() const; /** * @brief Set the desired reporting period for first display loop timings. diff --git a/include/ramses/renderer/Types.h b/include/ramses/renderer/Types.h index 87921b6d0..9c917161d 100644 --- a/include/ramses/renderer/Types.h +++ b/include/ramses/renderer/Types.h @@ -293,7 +293,8 @@ namespace ramses { GLES_3_0, GL_4_2, - GL_4_5 + GL_4_5, + Vulkan }; /** diff --git a/scripts/ci/build/build.py b/scripts/ci/build/build.py index 71346631f..b1b5689c8 100644 --- a/scripts/ci/build/build.py +++ b/scripts/ci/build/build.py @@ -31,8 +31,8 @@ def __init__(self, compiler, config, build_dir): super(BuildConfig, self).__init__(compiler, config, build_dir) def cmake_configure(self, - disable_default_window_type, enable_x11, enable_android, enable_wayland_ivi, enable_wayland_wl_shell, - flatbuf_gen, android_abi, disable_logic, use_imagemagick, + disable_default_window_type, enable_x11, enable_android, enable_wayland_ivi, enable_wayland_wl_shell, enable_vulkan, + flatbuf_gen, android_abi, use_imagemagick, no_full_shared_lib, no_examples, no_demos, no_tests, no_tools, generator, enable_dlt, enable_lto, test_coverage, enable_coverage, sanitizer_name, @@ -73,9 +73,6 @@ def cmake_configure(self, if no_full_shared_lib: optional_args.append('-Dramses-sdk_BUILD_FULL_SHARED_LIB=0') - if disable_logic: - optional_args.append('-Dramses-sdk_ENABLE_LOGIC=OFF') - if disable_default_window_type: optional_args.append('-Dramses-sdk_ENABLE_DEFAULT_WINDOW_TYPE=0') @@ -109,6 +106,7 @@ def cmake_configure(self, f'-Dramses-sdk_ENABLE_WINDOW_TYPE_ANDROID={to_cmake(enable_android)}', f'-Dramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_IVI={to_cmake(enable_wayland_ivi)}', f'-Dramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL={to_cmake(enable_wayland_wl_shell)}', + f'-Dramses-sdk_ENABLE_DEVICE_TYPE_VULKAN={to_cmake(enable_vulkan)}', f'-Dramses-sdk_ENABLE_DLT={to_cmake(enable_dlt)}', f'-Dramses-sdk_ENABLE_FLATBUFFERS_GENERATION={to_cmake(flatbuf_gen)}', f'-Dramses-sdk_BUILD_WITH_LTO={to_cmake(enable_lto)}', @@ -153,6 +151,7 @@ def copy_package(self, package_target): @click.option('--enable-android', is_flag=True, default=False, help='Enable building for creating android window') @click.option('--enable-wayland-ivi', is_flag=True, default=False, help='Enable building for creating wayland windows that use ivi_shell') @click.option('--enable-wayland-wl-shell', is_flag=True, default=False, help='Enable building for creating wayland windows that use wl_shell') +@click.option('--enable-vulkan', is_flag=True, default=False, help='Enable building for creating vulkan device') @click.option('--build-target', default='install', help='What CMake target to build') @click.option('--flatbuf-gen', is_flag=True, default=False, help='Generate flatbuffer file headers') @click.option('--android-abi', help='Set ABI when building on Android') @@ -172,7 +171,6 @@ def copy_package(self, package_target): @click.option('--package-name', default="", help='Use a different package name for CPack than the default') @click.option('--package-destination', type=click.Path(exists=True, file_okay=False), help='Specify a folder where the package shall be copied') @click.option('--cpp-std', type=click.Choice(CPP_STANDARDS), default=CPP_STANDARDS[0]) -@click.option('--disable-logic', is_flag=True, default=False, help='Disable building ramses logic') @click.option('--use-imagemagick', is_flag=True, default=False, help='Build tests that use imagemagick') @click.option('--cmake-modules', help='Sets cmake module path') def build(compiler, config, build_dir, configure_only, build_target, package_destination, **kwargs): diff --git a/scripts/ci/build/common.py b/scripts/ci/build/common.py index 970ec3c0d..1065ea6a4 100755 --- a/scripts/ci/build/common.py +++ b/scripts/ci/build/common.py @@ -17,6 +17,7 @@ 'gcc', 'llvm', 'clang-tidy', + 'clang15' ] # Default is the first entry @@ -48,5 +49,7 @@ def get_toolchain(self): return self.src_dir / 'cmake/toolchain/Linux_X86_64.toolchain' elif self.compiler in ['llvm', 'clang-tidy']: return self.src_dir / 'cmake/toolchain/Linux_X86_64_llvm.toolchain' + elif self.compiler in ['clang15']: + return self.src_dir / 'cmake/toolchain/Linux_X86_64_clang15.toolchain' else: return None diff --git a/scripts/ci/build/test-cmake-configurations.py b/scripts/ci/build/test-cmake-configurations.py index c16211aad..798b07c41 100755 --- a/scripts/ci/build/test-cmake-configurations.py +++ b/scripts/ci/build/test-cmake-configurations.py @@ -56,10 +56,10 @@ def check_expectations(condition, *expectations): x11 = "enable_x11" in cmake_options wayland_ivi = "enable_wayland_ivi" in cmake_options wayland_shell = "enable_wayland_wl_shell" in cmake_options + vulkan = "enable_vulkan" in cmake_options tests = "no_tests" not in cmake_options examples = "no_examples" not in cmake_options tools = "no_tools" not in cmake_options - logic = "disable_logic" not in cmake_options use_imagemagick = "use_imagemagick" in cmake_options luajit = "enable_luajit" in cmake_options @@ -72,7 +72,7 @@ def check_expectations(condition, *expectations): check_expectations(True, "ramses-client") # expect internal lua target unless luajit is configured - check_expectations(logic and not luajit, "lua (internal)") + check_expectations(not luajit, "lua (internal)") if luajit: assert "Found LuaJIT" in process_output @@ -81,34 +81,35 @@ def check_expectations(condition, *expectations): check_expectations(full_shared_lib, "ramses-shared-lib") # renderer - check_expectations(x11, "X11") - check_expectations(wayland_ivi, "Wayland ivi") - check_expectations(wayland_shell, "Wayland wl_shell") + check_expectations(x11, "Window Type: X11") + check_expectations(wayland_ivi, "Window Type: Wayland ivi") + check_expectations(wayland_shell, "Window Type: Wayland wl_shell") + check_expectations(vulkan, "Vulkan") check_expectations(renderer, "ramses-renderer-internal", "ramses-renderer") # tools check_expectations(tools, "ivi-gears", "ivi-simple-dmabuf-egl", "ramses-daemon") check_expectations(tools and renderer, "ramses-renderer-standalone", "ramses-stream-viewer", "ramses-imgui") - check_expectations(tools and logic, "ramses-viewer-headless", "test-asset-producer") - check_expectations(tools and logic and renderer, "ramses-viewer") + check_expectations(tools, "ramses-viewer-headless", "test-asset-producer") + check_expectations(tools and renderer, "ramses-viewer") # tests check_expectations(tests, "ramses-framework-test", "ramses-client-test") check_expectations(tests and renderer, "ramses-renderer-internal-test", "ramses-renderer-test", "rendering-tests", "ramses-test-client") - check_expectations(tests and logic, "ramses-logic-benchmarks") + check_expectations(tests, "ramses-logic-benchmarks") check_expectations(x11 and tests, "window-x11-test") check_expectations(wayland_ivi and tests, "window-wayland-ivi-test") check_expectations(wayland_shell and tests, "window-wayland-wl-shell-test") # tool tests - check_expectations(tests and tools and logic, "ramses-viewer-test") - check_expectations(tests and tools and logic and renderer and use_imagemagick, "ramses-viewer-gui-test") + check_expectations(tests and tools, "ramses-viewer-test") + check_expectations(tests and tools and renderer and use_imagemagick, "ramses-viewer-gui-test") # examples check_expectations(examples, "ramses-example-basic-geometry") check_expectations(examples and full_shared_lib, "ramses-example-local-client") - check_expectations(examples and logic, "00_minimal") - check_expectations(examples and full_shared_lib and logic, "13_render_order") + check_expectations(examples, "00_minimal") + check_expectations(examples and full_shared_lib, "13_render_order") if tests: ctestProcessResult = subprocess.run(["ctest", "--show-only"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, cwd=test_dir) @@ -132,7 +133,7 @@ def check_expectations(condition, *expectations): if full_shared_lib: expected_tests += ['ramses-shared-lib-tests_RNDSANDWICHTEST_SWRAST'] - if examples and logic: + if examples: expected_tests += [ '00_minimal_UNITTEST', '01a_primitive_properties_UNITTEST', @@ -190,12 +191,15 @@ def check_expectations(condition, *expectations): 'rendering-tests_wayland-wl-shell-gles30_RNDSANDWICHTEST', 'render-backend-tests_wayland-wl-shell-gles30_RNDSANDWICHTEST', 'resource-stress-tests_wayland-wl-shell-gles30_RNDSANDWICHTEST'] + if vulkan: + expected_tests += [ + 'render-backend-tests_x11-vulkan_RNDSANDWICHTEST_SWRAST'] - if logic and tools: + if tools: expected_tests += [ 'ramses-viewer-test_UNITTEST'] - if logic and tools and renderer and use_imagemagick: + if tools and renderer and use_imagemagick: expected_tests += [ 'ramses-viewer-gui-test_RNDSANDWICHTEST_SWRAST'] @@ -243,6 +247,9 @@ def main(cli_context, build_dir): test_cmake_configuration(cli_context, build_dir, True, enable_wayland_ivi=True) test_cmake_configuration(cli_context, build_dir, True, enable_wayland_wl_shell=True) + # can configure with vulkan + test_cmake_configuration(cli_context, build_dir, True, enable_x11=True, enable_vulkan=True) + # can configure with any of examples, demos, tests or tool disabled test_cmake_configuration(cli_context, build_dir, True, enable_x11=True, no_examples=True) test_cmake_configuration(cli_context, build_dir, True, enable_x11=True, no_demos=True) @@ -257,10 +264,6 @@ def main(cli_context, build_dir): test_cmake_configuration(cli_context, build_dir, True, no_full_shared_lib=True, use_imagemagick=True) test_cmake_configuration(cli_context, build_dir, True, enable_x11=True, no_full_shared_lib=True, use_imagemagick=True) - # can configure with ramses logic disabled - test_cmake_configuration(cli_context, build_dir, True, disable_logic=True, no_full_shared_lib=True) - test_cmake_configuration(cli_context, build_dir, True, disable_logic=True, no_full_shared_lib=True, use_imagemagick=True) - elapsed_time = time.time() - start_time print(f"Tests finished SUCCESSFULLY...Elapsed time to run cmake configuration tests : {elapsed_time:.2f} seconds") diff --git a/scripts/ci/collect-coverage.py b/scripts/ci/collect-coverage.py index ae9d29f74..6b2893871 100755 --- a/scripts/ci/collect-coverage.py +++ b/scripts/ci/collect-coverage.py @@ -43,7 +43,10 @@ def main(): if not profdir.is_dir(): raise Exception(f'profdir does not exist {profdir}') - prof_files = [e.name for e in profdir.glob(f'{allowed_selections[args.select]}.profraw')] + # filter out embedded compositing rendering tests since they break coverage collection + execlude_files = [e.name for e in profdir.glob('embedded-compositing-rendering-tests_RNDSANDWICHTEST_SWRAST*.profraw')] + prof_files = [e.name for e in profdir.glob(f'{allowed_selections[args.select]}.profraw') if e.name not in execlude_files] + if not prof_files: raise Exception('No profraw files match filter') @@ -55,15 +58,10 @@ def main(): merged_data = f'coverage-merged-{args.select}.profdata' print(f'Generate {merged_data}') - for attempt in range(3): - try: - subprocess.check_call(['llvm-profdata', 'merge', '-o', merged_data] + prof_files, shell=False, cwd=profdir) - except subprocess.CalledProcessError as e: - print(f'Attempt {attempt} failed: {e}') - else: - break - else: - raise Exception(f'Generate {merged_data} failed') + try: + subprocess.check_call(['llvm-profdata', 'merge', '-o', merged_data] + prof_files, shell=False, cwd=profdir) + except subprocess.CalledProcessError as e: + raise Exception(f'Generate {merged_data} failed with exception {e}') merged_executable = f'merge-executable-{args.select}' print(f'Generate {merged_executable}') diff --git a/scripts/ci/common/compilationdb.py b/scripts/ci/common/compilationdb.py index ca0aa664b..9f53025ca 100644 --- a/scripts/ci/common/compilationdb.py +++ b/scripts/ci/common/compilationdb.py @@ -41,7 +41,10 @@ def file(self): def relative_file(self): if not self._project_root: raise RuntimeError('project_root not set') - return str(Path(self.file).relative_to(self._project_root)) + try: + return str(Path(self.file).relative_to(self._project_root)) + except Exception: + return self.file @property def includes(self): diff --git a/scripts/ci/config/clang-tidy-wrapper.yaml b/scripts/ci/config/clang-tidy-wrapper.yaml index 1a3c1f77e..5d653b551 100644 --- a/scripts/ci/config/clang-tidy-wrapper.yaml +++ b/scripts/ci/config/clang-tidy-wrapper.yaml @@ -13,6 +13,8 @@ include: exclude: # exclude all external - ^external/ + # exclude generated file by glslang + - .*/external/glslang/.*\.hxx\.cxx # exclude generated flatbuffers files - ^src/client/internal/logic/flatbuffers/ @@ -44,6 +46,11 @@ check-filter: exclude: - ^examples/ramses-example-local-dma-offscreenbuffer/src/main.cpp$ - ^tests/integration/renderer-tests/dma-offscreen-buffer-rendering-tests/DmaOffscreenBufferTests.cpp$ + - ^src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.cpp$ + - check: modernize-avoid-bind + exclude: + - ^src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.cpp$ + - check: modernize-avoid-c-arrays exclude: - ^tests/.* diff --git a/scripts/ci/config/sanitizer/tsan_blacklist.txt b/scripts/ci/config/sanitizer/tsan_blacklist.txt index 557e10583..103027b5d 100644 --- a/scripts/ci/config/sanitizer/tsan_blacklist.txt +++ b/scripts/ci/config/sanitizer/tsan_blacklist.txt @@ -4,3 +4,10 @@ mutex:dlt_free # EGL de/init in mesa swrast EGL implementation causes both leak (lsan, valgrind) and data race (tsan), # it might be worth to check if still happening on future driver versions race:~Context_EGL() +race:Context_EGL::init() +# XauFileName in Xlib seems not thread safe, race when initialzing window from multiple ramses instances in parallel +race:XauFileName +# Data race of static string storage in swrast, reading via glGetString during device init (should be harmless). +# Given the tsan suppression format and race callstack sadly it cannot be narrowed down to more concrete filter +# than filtering the whole swrast lib +race:swrast_dri.so diff --git a/scripts/ci/config/sanitizer/ubsan_blacklist.txt b/scripts/ci/config/sanitizer/ubsan_blacklist.txt index 1b9cbc445..b896016cc 100644 --- a/scripts/ci/config/sanitizer/ubsan_blacklist.txt +++ b/scripts/ci/config/sanitizer/ubsan_blacklist.txt @@ -1,2 +1,3 @@ -#glslang uses EShLanguageMask enum as bitfield +# glslang uses EShLanguageMask enum as bitfield fun:_ZN7glslang14TParseVersions12requireStageERKNS_10TSourceLocE15EShLanguageMaskPKc +src:*/glslang/SPIRV/spirv.hpp diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index cdc1c26cb..07f56c663 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -9,22 +9,19 @@ add_subdirectory(internal) if(ramses-sdk_TEXT_SUPPORT) - list(APPEND CLIENT_IMPL_SOURCES impl/text/*.h + list(APPEND TEXT_IMPL_SOURCES impl/text/*.h impl/text/*.cpp) endif() -if(ramses-sdk_ENABLE_LOGIC) - list(APPEND CLIENT_IMPL_SOURCES impl/logic/*.h - impl/logic/*.cpp) -endif() - createModule( NAME ramses-client TYPE STATIC_LIBRARY ENABLE_INSTALL OFF SRC_FILES impl/*.h impl/*.cpp - ${CLIENT_IMPL_SOURCES} + impl/logic/*.h + impl/logic/*.cpp + ${TEXT_IMPL_SOURCES} DEPENDENCIES ramses-client-internal ramses-framework ) diff --git a/src/client/impl/AppearanceImpl.cpp b/src/client/impl/AppearanceImpl.cpp index 778e718d8..f42fb76b1 100644 --- a/src/client/impl/AppearanceImpl.cpp +++ b/src/client/impl/AppearanceImpl.cpp @@ -30,6 +30,7 @@ #include "internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.h" #include "internal/SceneGraph/SceneUtils/ISceneDataArrayAccessor.h" #include "internal/SceneGraph/SceneUtils/DataInstanceHelper.h" +#include "internal/SceneGraph/SceneUtils/UniformBufferUtils.h" #include "internal/SceneGraph/SceneAPI/EDataType.h" #include @@ -254,9 +255,9 @@ namespace ramses::internal DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_effectImpl); - inStream >> m_renderStateHandle; - inStream >> m_uniformLayout; - inStream >> m_uniformInstance; + serializationContext.deserializeAndMap(inStream, m_renderStateHandle); + serializationContext.deserializeAndMap(inStream, m_uniformLayout); + serializationContext.deserializeAndMap(inStream, m_uniformInstance); uint32_t bindableInputCount = 0u; inStream >> bindableInputCount; @@ -270,7 +271,7 @@ namespace ramses::internal BindableInput bindableInput; DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, bindableInput.externallyBoundDataObject); - inStream >> bindableInput.dataReference; + serializationContext.deserializeAndMap(inStream, bindableInput.dataReference); m_bindableInputs.put(inputIndex, bindableInput); } @@ -385,6 +386,17 @@ namespace ramses::internal void AppearanceImpl::deinitializeFrameworkData() { + const auto& dataFields = getIScene().getDataLayout(m_uniformLayout).getDataFields(); + for (DataFieldHandle datFieldHandle{ 0u }; datFieldHandle < dataFields.size(); ++datFieldHandle) + { + const auto& field = dataFields[datFieldHandle.asMemoryHandle()]; + if (field.dataType == EDataType::UniformBuffer && field.semantics == EFixedSemantics::Invalid) + { + const auto ubHandle = getIScene().getDataUniformBuffer(m_uniformInstance, datFieldHandle); + getIScene().releaseUniformBuffer(ubHandle); + } + } + getIScene().releaseDataInstance(m_uniformInstance); m_uniformInstance = DataInstanceHandle::Invalid(); @@ -426,22 +438,37 @@ namespace ramses::internal void AppearanceImpl::createUniformDataInstance(const EffectImpl& effect) { - InputIndexVector referencedInputs; const EffectInputInformationVector& uniformsInputInfo = effect.getUniformInputInformation(); - m_uniformLayout = DataLayoutCreationHelper::CreateUniformDataLayoutMatchingEffectInputs(getIScene(), uniformsInputInfo, referencedInputs, effect.getLowlevelResourceHash()); + InputIndexVector referencedInputs; + std::tie(m_uniformLayout, referencedInputs) = DataLayoutCreationHelper::CreateUniformDataLayoutMatchingEffectInputs(getIScene(), uniformsInputInfo, effect.getLowlevelResourceHash()); m_uniformInstance = getIScene().allocateDataInstance(m_uniformLayout, {}); m_bindableInputs.reserve(m_bindableInputs.size() + referencedInputs.size()); for (const auto& refInput : referencedInputs) { - const DataFieldHandle dataField(refInput); + const DataFieldHandle dataField(uniformsInputInfo[refInput].dataFieldHandle); BindableInput bindableInput; bindableInput.externallyBoundDataObject = nullptr; bindableInput.dataReference = DataLayoutCreationHelper::CreateAndBindDataReference(getIScene(), m_uniformInstance, dataField, uniformsInputInfo[refInput].dataType); m_bindableInputs.put(refInput, bindableInput); } + + createUniformBuffers(uniformsInputInfo); + } + + void AppearanceImpl::createUniformBuffers(const EffectInputInformationVector& uniformsInputs) + { + for (const auto& uniformInput : uniformsInputs) + { + if (uniformInput.dataType == EDataType::UniformBuffer && uniformInput.semantics == EFixedSemantics::Invalid) + { + assert(uniformInput.uniformBufferElementSize.isValid()); + const auto ubHandle = getIScene().allocateUniformBuffer(uniformInput.uniformBufferElementSize.getValue(), {}); + getIScene().setDataUniformBuffer(m_uniformInstance, uniformInput.dataFieldHandle, ubHandle); + } + } } bool AppearanceImpl::checkEffectInputValidityAndValueCompatibility(const EffectInputImpl& input, size_t valueElementCount, std::initializer_list valueDataType) const @@ -508,7 +535,7 @@ namespace ramses::internal return false; } - const DataFieldHandle dataField(inputIndex); + const DataFieldHandle dataField = input.getDataFieldHandle(); if (isBindable) { const DataInstanceHandle dataReference = getDataReference(dataField, input.getInternalDataType()); @@ -518,6 +545,10 @@ namespace ramses::internal ISceneDataArrayAccessor::SetDataArray(&getIScene(), dataReference, DataFieldHandle(0u), 1u, values); } } + else if (input.getUniformBufferFieldOffset().isValid()) + { + setUniformBufferField(elementCount, values, input); + } else { static_assert( std::is_same_v == true ); @@ -532,6 +563,39 @@ namespace ramses::internal return true; } + template + void AppearanceImpl::setUniformBufferField(size_t elementCount, const T* values, const EffectInputImpl& input) + { + const DataFieldHandle dataField = input.getDataFieldHandle(); + const auto fieldOffset = input.getUniformBufferFieldOffset().getValue(); + const auto ubHandle = getIScene().getDataUniformBuffer(m_uniformInstance, dataField); + const std::byte* currentValueRaw = getIScene().getUniformBuffer(ubHandle).data.data() + fieldOffset; + + if (UniformBufferUtils::IsDataTightlyPacked(elementCount)) + { + // optimally only types which fall into this category should be used, i.e., mat4, vec4, mat34, mat24 + // or scalars that could be tightly packed according to their situation in std140 + const auto size = uint32_t(elementCount * sizeof(T)); + if (PlatformMemory::Compare(currentValueRaw, values, size) != 0) + { + getIScene().updateUniformBuffer(ubHandle, fieldOffset, size, reinterpret_cast(values)); + } + } + else + { + const auto elementSize = input.getUniformBufferElementSize().getValue(); + for (uint32_t i = 0u; i < elementCount; ++i) + { + const auto elementArrayOffset = i * elementSize; + const auto newValuePadded{ UniformBufferUtils::Pad(values[i]) }; + if (PlatformMemory::Compare(currentValueRaw + elementArrayOffset, &newValuePadded, elementSize) != 0) + { + getIScene().updateUniformBuffer(ubHandle, fieldOffset + elementArrayOffset, elementSize, reinterpret_cast(&newValuePadded)); + } + } + } + } + template bool AppearanceImpl::getDataArrayChecked(size_t elementCount, T* values, const EffectInputImpl& input) const { @@ -551,12 +615,16 @@ namespace ramses::internal return false; } - const DataFieldHandle dataField(static_cast(input.getInputIndex())); + const DataFieldHandle dataField = input.getDataFieldHandle(); if (isBindable) { const DataInstanceHandle dataReference = getDataReference(dataField, input.getInternalDataType()); PlatformMemory::Copy(values, ISceneDataArrayAccessor::GetDataArray(&getIScene(), dataReference, DataFieldHandle(0u)), EnumToSize(input.getInternalDataType())); } + else if (input.getUniformBufferFieldOffset().isValid()) + { + getUniformBufferField(elementCount, values, input); + } else { PlatformMemory::Copy(values, ISceneDataArrayAccessor::GetDataArray(&getIScene(), m_uniformInstance, dataField), elementCount * EnumToSize(input.getInternalDataType())); @@ -565,6 +633,29 @@ namespace ramses::internal return true; } + template + void AppearanceImpl::getUniformBufferField(size_t elementCount, T* values, const EffectInputImpl& input) const + { + const DataFieldHandle dataField = input.getDataFieldHandle(); + const auto fieldOffset = input.getUniformBufferFieldOffset().getValue(); + const auto ubHandle = getIScene().getDataUniformBuffer(m_uniformInstance, dataField); + const std::byte* fieldDataRaw = getIScene().getUniformBuffer(ubHandle).data.data() + fieldOffset; + if (UniformBufferUtils::IsDataTightlyPacked(elementCount)) + { + PlatformMemory::Copy(values, fieldDataRaw, elementCount * sizeof(T)); + } + else + { + for (uint32_t i = 0u; i < elementCount; ++i) + { + const auto elementArrayOffset = i * input.getUniformBufferElementSize().getValue(); + using PaddingT = typename UniformBufferUtils::std140_padding_info::padding_type_t; + const auto& valueWithPaddingRef = *reinterpret_cast(fieldDataRaw + elementArrayOffset); + UniformBufferUtils::RemovePadding(valueWithPaddingRef, values[i]); + } + } + } + bool AppearanceImpl::setInputTexture(const EffectInputImpl& input, const TextureSamplerImpl& textureSampler) { if (!isFromTheSameSceneAs(textureSampler)) @@ -583,7 +674,7 @@ namespace ramses::internal {ramses::internal::EDataType::TextureSampler2D, ramses::internal::EDataType::TextureSampler3D, ramses::internal::EDataType::TextureSamplerCube})) return false; - const DataFieldHandle dataField(static_cast(input.getInputIndex())); + const DataFieldHandle dataField = input.getDataFieldHandle(); const auto samplerHandle = getIScene().getDataTextureSamplerHandle(m_uniformInstance, dataField); if (samplerHandle.isValid()) { @@ -607,7 +698,7 @@ namespace ramses::internal {ramses::internal::EDataType::TextureSampler2DMS})) return false; - const DataFieldHandle dataField(static_cast(input.getInputIndex())); + const DataFieldHandle dataField = input.getDataFieldHandle(); const auto samplerHandle = getIScene().getDataTextureSamplerHandle(m_uniformInstance, dataField); if (samplerHandle.isValid()) { @@ -631,7 +722,7 @@ namespace ramses::internal {ramses::internal::EDataType::TextureSamplerExternal})) return false; - const DataFieldHandle dataField(static_cast(input.getInputIndex())); + const DataFieldHandle dataField = input.getDataFieldHandle(); const auto samplerHandle = getIScene().getDataTextureSamplerHandle(m_uniformInstance, dataField); if (samplerHandle.isValid()) { @@ -659,6 +750,12 @@ namespace ramses::internal if (!checkEffectInputValidityAndValueCompatibility(input, 1u, {DataTypeUtils::ConvertDataTypeToInternal(dataObject.getDataType())})) return false; + if (input.getUniformBufferFieldOffset().isValid()) + { + getErrorReporting().set("Appearance::bindInput failed, input is part of a uniform buffer"); + return false; + } + const auto inputIndex = static_cast(input.getInputIndex()); BindableInput* bindableInput = m_bindableInputs.get(inputIndex); if (bindableInput == nullptr) @@ -695,7 +792,7 @@ namespace ramses::internal if (!checkEffectInputValidityAndValueCompatibility(input, 1u, {textureSampler.getTextureDataType()})) return false; - const DataFieldHandle dataField(static_cast(input.getInputIndex())); + const DataFieldHandle dataField = input.getDataFieldHandle(); const TextureSamplerHandle samplerHandle = textureSampler.getTextureSamplerHandle(); getIScene().setDataTextureSamplerHandle(m_uniformInstance, dataField, samplerHandle); return true; @@ -704,7 +801,7 @@ namespace ramses::internal bool AppearanceImpl::bindInputInternal(const EffectInputImpl& input, const DataObjectImpl& dataObject) { const auto inputIndex = static_cast(input.getInputIndex()); - const DataFieldHandle dataField(inputIndex); + const DataFieldHandle dataField = input.getDataFieldHandle(); getIScene().setDataReference(m_uniformInstance, dataField, dataObject.getDataReference()); BindableInput* bindableInput = m_bindableInputs.get(inputIndex); diff --git a/src/client/impl/AppearanceImpl.h b/src/client/impl/AppearanceImpl.h index b7bb0547f..f7052286e 100644 --- a/src/client/impl/AppearanceImpl.h +++ b/src/client/impl/AppearanceImpl.h @@ -19,6 +19,7 @@ #include "internal/SceneGraph/SceneAPI/Handles.h" #include "internal/SceneGraph/SceneAPI/EDataType.h" #include "internal/PlatformAbstraction/Collections/HashMap.h" +#include "internal/SceneGraph/Resource/EffectInputInformation.h" #include #include @@ -93,6 +94,7 @@ namespace ramses::internal private: void createUniformDataInstance(const EffectImpl& effect); + void createUniformBuffers(const EffectInputInformationVector& uniformsInputs); [[nodiscard]] bool checkEffectInputValidityAndValueCompatibility(const EffectInputImpl& input, size_t valueElementCount, std::initializer_list valueDataType) const; [[nodiscard]] DataInstanceHandle getDataReference(DataFieldHandle dataField, ramses::internal::EDataType expectedDataType) const; @@ -102,6 +104,11 @@ namespace ramses::internal template bool getDataArrayChecked(size_t elementCount, T* values, const EffectInputImpl& input) const; + template + void setUniformBufferField(size_t elementCount, const T* values, const EffectInputImpl& input); + template + void getUniformBufferField(size_t elementCount, T* values, const EffectInputImpl& input) const; + bool setInputTextureInternal(const EffectInputImpl& input, const TextureSamplerImpl& textureSampler); bool bindInputInternal(const EffectInputImpl& input, const DataObjectImpl& dataObject); bool unbindInputInternal(const EffectInputImpl& input); diff --git a/src/client/impl/ArrayBufferImpl.cpp b/src/client/impl/ArrayBufferImpl.cpp index 8aa1afe7c..7993eaab1 100644 --- a/src/client/impl/ArrayBufferImpl.cpp +++ b/src/client/impl/ArrayBufferImpl.cpp @@ -86,7 +86,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_dataBufferHandle; + serializationContext.deserializeAndMap(inStream, m_dataBufferHandle); return true; } diff --git a/src/client/impl/BlitPassImpl.cpp b/src/client/impl/BlitPassImpl.cpp index c05862ba6..228cf4cd3 100644 --- a/src/client/impl/BlitPassImpl.cpp +++ b/src/client/impl/BlitPassImpl.cpp @@ -119,7 +119,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_blitPassHandle; + serializationContext.deserializeAndMap(inStream, m_blitPassHandle); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_sourceRenderBufferImpl); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_destinationRenderBufferImpl); diff --git a/src/client/impl/CameraNodeImpl.cpp b/src/client/impl/CameraNodeImpl.cpp index ff344c163..8a5b1c8b2 100644 --- a/src/client/impl/CameraNodeImpl.cpp +++ b/src/client/impl/CameraNodeImpl.cpp @@ -11,6 +11,8 @@ #include "impl/DataObjectImpl.h" #include "impl/SerializationContext.h" #include "impl/ErrorReporting.h" +#include "impl/RamsesClientImpl.h" +#include "impl/RamsesFrameworkImpl.h" #include "internal/SceneGraph/Scene/ClientScene.h" #include "internal/SceneGraph/SceneUtils/DataInstanceHelper.h" #include "internal/Core/Math3d/CameraMatrixHelper.h" @@ -51,16 +53,16 @@ namespace ramses::internal if (!NodeImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_cameraHandle; - inStream >> m_dataLayout; - inStream >> m_dataInstance; - inStream >> m_viewportDataReferenceLayout; - inStream >> m_viewportOffsetDataReference; - inStream >> m_viewportSizeDataReference; - inStream >> m_frustumPlanesDataReferenceLayout; - inStream >> m_frustumPlanesDataReference; - inStream >> m_frustumNearFarDataReferenceLayout; - inStream >> m_frustumNearFarDataReference; + serializationContext.deserializeAndMap(inStream, m_cameraHandle); + serializationContext.deserializeAndMap(inStream, m_dataLayout); + serializationContext.deserializeAndMap(inStream, m_dataInstance); + serializationContext.deserializeAndMap(inStream, m_viewportDataReferenceLayout); + serializationContext.deserializeAndMap(inStream, m_viewportOffsetDataReference); + serializationContext.deserializeAndMap(inStream, m_viewportSizeDataReference); + serializationContext.deserializeAndMap(inStream, m_frustumPlanesDataReferenceLayout); + serializationContext.deserializeAndMap(inStream, m_frustumPlanesDataReference); + serializationContext.deserializeAndMap(inStream, m_frustumNearFarDataReferenceLayout); + serializationContext.deserializeAndMap(inStream, m_frustumNearFarDataReference); inStream >> m_frustumInitialized; inStream >> m_viewportInitialized; diff --git a/src/client/impl/ClientFactory.cpp b/src/client/impl/ClientFactory.cpp index 723eb5807..6586d82dd 100644 --- a/src/client/impl/ClientFactory.cpp +++ b/src/client/impl/ClientFactory.cpp @@ -15,8 +15,14 @@ namespace ramses::internal ClientUniquePtr ClientFactory::createClient(RamsesFrameworkImpl& framework, std::string_view applicationName) const { auto impl = std::make_unique(framework, applicationName); - return ClientUniquePtr{ new RamsesClient{ std::move(impl) }, - [](RamsesClient* client_) { delete client_; } }; + return ClientUniquePtr{ new RamsesClient{ std::move(impl) }, ClientFactory::DeleteClient }; + } + + void ClientFactory::DeleteClient(RamsesClient* client) + { + assert(client); + client->impl().deinitializeFrameworkData(); + delete client; } bool ClientFactory::RegisterClientFactory() diff --git a/src/client/impl/ClientFactory.h b/src/client/impl/ClientFactory.h index 097ce8f6a..3f115fe98 100644 --- a/src/client/impl/ClientFactory.h +++ b/src/client/impl/ClientFactory.h @@ -21,6 +21,9 @@ namespace ramses::internal static bool RegisterClientFactory(); ClientUniquePtr createClient(RamsesFrameworkImpl& framework, std::string_view applicationName) const override; + + private: + static void DeleteClient(RamsesClient* client); }; } diff --git a/src/client/impl/DataObjectImpl.cpp b/src/client/impl/DataObjectImpl.cpp index e54961df9..084400e5e 100644 --- a/src/client/impl/DataObjectImpl.cpp +++ b/src/client/impl/DataObjectImpl.cpp @@ -13,6 +13,7 @@ #include "internal/SceneGraph/Scene/ClientScene.h" #include "internal/SceneGraph/SceneUtils/ISceneDataArrayAccessor.h" #include "internal/SceneGraph/SceneAPI/ResourceContentHash.h" +#include "impl/SerializationContext.h" namespace ramses::internal { @@ -66,8 +67,8 @@ namespace ramses::internal uint32_t enumType = 0u; inStream >> enumType; m_dataType = static_cast(enumType); - inStream >> m_layoutHandle; - inStream >> m_dataReference; + serializationContext.deserializeAndMap(inStream, m_layoutHandle); + serializationContext.deserializeAndMap(inStream, m_dataReference); return true; } diff --git a/src/client/impl/Effect.cpp b/src/client/impl/Effect.cpp index 5709b976f..f48e34270 100644 --- a/src/client/impl/Effect.cpp +++ b/src/client/impl/Effect.cpp @@ -42,6 +42,11 @@ namespace ramses return m_impl.findUniformInput(uniformSemantic); } + std::optional Effect::findUniformInputAtBinding(uint32_t uniformBufferBinding) const + { + return m_impl.findUniformInputAtBinding(uniformBufferBinding); + } + std::optional Effect::getAttributeInput(size_t index) const { return m_impl.getAttributeInput(index); diff --git a/src/client/impl/EffectDescription.cpp b/src/client/impl/EffectDescription.cpp index d8bd249bf..8f8e6cc14 100644 --- a/src/client/impl/EffectDescription.cpp +++ b/src/client/impl/EffectDescription.cpp @@ -93,6 +93,13 @@ namespace ramses return status; } + bool EffectDescription::setUniformSemantic(uint32_t uniformBufferBinding, EEffectUniformSemantic semanticType) + { + const auto status = m_impl->setUniformSemantic(uniformBufferBinding, semanticType); + LOG_HL_CLIENT_API2(status, uniformBufferBinding, semanticType); + return status; + } + bool EffectDescription::setAttributeSemantic(std::string_view inputName, EEffectAttributeSemantic semanticType) { const auto status = m_impl->setAttributeSemantic(inputName, semanticType); diff --git a/src/client/impl/EffectDescriptionImpl.cpp b/src/client/impl/EffectDescriptionImpl.cpp index 128f61c5d..864441a34 100644 --- a/src/client/impl/EffectDescriptionImpl.cpp +++ b/src/client/impl/EffectDescriptionImpl.cpp @@ -92,7 +92,13 @@ namespace ramses::internal return false; } - m_inputSemantics.put(std::string{semanticName}, semanticType); + m_inputSemantics[std::string{semanticName}] = semanticType; + return true; + } + + bool EffectDescriptionImpl::setSemantic(uint32_t uniformBufferBinding, EFixedSemantics semanticType) + { + m_inputSemantics[UniformBufferBinding{ uniformBufferBinding }] = semanticType; return true; } @@ -102,6 +108,12 @@ namespace ramses::internal return setSemantic(semanticName, semanticTypeInternal); } + bool EffectDescriptionImpl::setUniformSemantic(uint32_t uniformBufferBinding, EEffectUniformSemantic semanticType) + { + const EFixedSemantics semanticTypeInternal = EffectInputSemanticUtils::GetEffectInputSemanticInternal(semanticType); + return setSemantic(uniformBufferBinding, semanticTypeInternal); + } + bool EffectDescriptionImpl::setAttributeSemantic(std::string_view semanticName, EEffectAttributeSemantic semanticType) { const EFixedSemantics semanticTypeInternal = EffectInputSemanticUtils::GetEffectInputSemanticInternal(semanticType); @@ -143,7 +155,7 @@ namespace ramses::internal return nullptr; } - const EffectDescriptionImpl::SemanticsMap& EffectDescriptionImpl::getSemanticsMap() const + const SemanticsMap& EffectDescriptionImpl::getSemanticsMap() const { return m_inputSemantics; } diff --git a/src/client/impl/EffectDescriptionImpl.h b/src/client/impl/EffectDescriptionImpl.h index 0bd986861..2ac63c850 100644 --- a/src/client/impl/EffectDescriptionImpl.h +++ b/src/client/impl/EffectDescriptionImpl.h @@ -13,7 +13,6 @@ #include "ramses/client/EffectInputSemantic.h" // ramses framework -#include "internal/PlatformAbstraction/Collections/HashMap.h" #include "internal/SceneGraph/SceneAPI/EFixedSemantics.h" #include @@ -25,8 +24,6 @@ namespace ramses::internal class EffectDescriptionImpl { public: - using SemanticsMap = HashMap; - EffectDescriptionImpl(); ~EffectDescriptionImpl(); @@ -38,6 +35,7 @@ namespace ramses::internal [[nodiscard]] bool setGeometryShaderFromFile(std::string_view shaderSourceFileName); [[nodiscard]] bool addCompilerDefine(std::string_view define); [[nodiscard]] bool setUniformSemantic(std::string_view semanticName, EEffectUniformSemantic semanticType); + [[nodiscard]] bool setUniformSemantic(uint32_t uniformBufferBinding, EEffectUniformSemantic semanticType); [[nodiscard]] bool setAttributeSemantic(std::string_view semanticName, EEffectAttributeSemantic semanticType); [[nodiscard]] const char* getVertexShader() const; @@ -52,6 +50,7 @@ namespace ramses::internal private: [[nodiscard]] bool setSemantic(std::string_view semanticName, EFixedSemantics semanticType); + [[nodiscard]] bool setSemantic(uint32_t uniformBufferBinding, EFixedSemantics semanticType); std::string m_vertexShaderSource; std::string m_fragmentShaderSource; diff --git a/src/client/impl/EffectImpl.cpp b/src/client/impl/EffectImpl.cpp index adb317f00..751619bb3 100644 --- a/src/client/impl/EffectImpl.cpp +++ b/src/client/impl/EffectImpl.cpp @@ -10,6 +10,7 @@ #include "impl/EffectInputImpl.h" #include "impl/SerializationContext.h" #include "impl/RamsesClientImpl.h" +#include "impl/RamsesFrameworkImpl.h" #include "impl/EffectInputSemanticUtils.h" #include "impl/ErrorReporting.h" @@ -17,7 +18,6 @@ #include "internal/SceneGraph/Resource/IResource.h" #include "internal/Components/ResourceHashUsage.h" #include "internal/SceneGraph/Resource/EffectResource.h" -#include "internal/PlatformAbstraction/Collections/StringOutputStream.h" #include "fmt/format.h" @@ -52,6 +52,8 @@ namespace ramses::internal if (!ResourceImpl::serialize(outStream, serializationContext)) return false; + const bool serializeUBO = (getClientImpl().getFramework().getFeatureLevel() >= EFeatureLevel_02); + outStream << static_cast(m_effectUniformInputs.size()); for(const auto& input : m_effectUniformInputs) { @@ -59,6 +61,13 @@ namespace ramses::internal outStream << static_cast(input.dataType); outStream << static_cast(input.elementCount); outStream << static_cast(input.semantics); + + if (serializeUBO) + { + outStream << input.uniformBufferBinding.getValue(); + outStream << input.uniformBufferFieldOffset.getValue(); + outStream << input.uniformBufferFieldOffset.getValue(); + } } outStream << static_cast(m_effectAttributeInputs.size()); @@ -80,6 +89,8 @@ namespace ramses::internal if (!ResourceImpl::deserialize(inStream, serializationContext)) return false; + const bool deserializeUBO = (getClientImpl().getFramework().getFeatureLevel() >= EFeatureLevel_02); + uint32_t count = 0u; inStream >> count; m_effectUniformInputs.resize(count); @@ -97,6 +108,19 @@ namespace ramses::internal m_effectUniformInputs[i].dataType = static_cast(dataTypeAsUInt); m_effectUniformInputs[i].elementCount = elementCount; m_effectUniformInputs[i].semantics = static_cast(semanticAsUInt); + + if (deserializeUBO) + { + uint32_t uniformBufferBindingAsUInt = 0; + inStream >> uniformBufferBindingAsUInt; + uint32_t uniformBufferElementSizeAsUInt = 0; + inStream >> uniformBufferElementSizeAsUInt; + uint32_t uniformBufferFieldOffsetAsUInt = 0; + inStream >> uniformBufferFieldOffsetAsUInt; + m_effectUniformInputs[i].uniformBufferBinding.getReference() = uniformBufferBindingAsUInt; + m_effectUniformInputs[i].uniformBufferElementSize.getReference() = uniformBufferElementSizeAsUInt; + m_effectUniformInputs[i].uniformBufferFieldOffset.getReference() = uniformBufferFieldOffsetAsUInt; + } } inStream >> count; @@ -122,6 +146,9 @@ namespace ramses::internal m_shaderWarnings.reset(); + DataLayoutCreationHelper::SetDataFieldMappingForUniformInputs(m_effectUniformInputs); + DataLayoutCreationHelper::SetDataFieldMappingForAttributeInputs(m_effectAttributeInputs); + return true; } @@ -268,6 +295,21 @@ namespace ramses::internal return input; } + std::optional EffectImpl::findUniformInputAtBinding(uint32_t uniformBufferBinding) const + { + const size_t index = GetUniformBufferInputIndex(m_effectUniformInputs, UniformBufferBinding{ uniformBufferBinding }); + if (index == InvalidInputIndex) + { + LOG_ERROR(CONTEXT_CLIENT, "Effect: findUniformInputAtBinding failed, uniform buffer with specified binding is not defined in effect!"); + return std::nullopt; + } + + UniformInput input; + initializeEffectInputData(*input.m_impl, m_effectUniformInputs[index], index); + + return input; + } + const EffectInputInformationVector& EffectImpl::getUniformInputInformation() const { return m_effectUniformInputs; @@ -293,6 +335,22 @@ namespace ramses::internal return InvalidInputIndex; } + size_t EffectImpl::GetUniformBufferInputIndex(const EffectInputInformationVector& effectInputVector, UniformBufferBinding uniformBufferBinding) + { + const size_t numInputs = effectInputVector.size(); + for (size_t i = 0u; i < numInputs; ++i) + { + const EffectInputInformation& effectInputInfo = effectInputVector[i]; + if (effectInputInfo.dataType == EDataType::UniformBuffer && + effectInputInfo.uniformBufferBinding == uniformBufferBinding) + { + return i; + } + } + + return InvalidInputIndex; + } + size_t EffectImpl::FindEffectInputIndex(const EffectInputInformationVector& effectInputVector, EFixedSemantics inputSemantics) { if (EFixedSemantics::Invalid == inputSemantics) @@ -313,14 +371,7 @@ namespace ramses::internal void EffectImpl::initializeEffectInputData(EffectInputImpl& effectInputImpl, const EffectInputInformation& effectInputInfo, size_t index) const { - effectInputImpl.initialize( - getLowlevelResourceHash(), - effectInputInfo.inputName, - effectInputInfo.dataType, - effectInputInfo.semantics, - effectInputInfo.elementCount, - index - ); + effectInputImpl.initialize(getLowlevelResourceHash(), effectInputInfo, index); } bool EffectImpl::hasGeometryShader() const @@ -332,7 +383,7 @@ namespace ramses::internal { if (!hasGeometryShader()) { - getErrorReporting().set((StringOutputStream() << "Effect::getGeometryShaderInputType: failed, effect '" << getName() << "' has no geometry shader attached to it!").c_str(), *this); + getErrorReporting().set(fmt::format("Effect::getGeometryShaderInputType: failed, effect '{}' has no geometry shader attached to it!", getName()), *this); return false; } diff --git a/src/client/impl/EffectImpl.h b/src/client/impl/EffectImpl.h index bd74c9593..07e62a6db 100644 --- a/src/client/impl/EffectImpl.h +++ b/src/client/impl/EffectImpl.h @@ -55,6 +55,7 @@ namespace ramses::internal std::optional findAttributeInput(std::string_view inputName) const; std::optional findUniformInput(EEffectUniformSemantic uniformSemantic) const; std::optional findAttributeInput(EEffectAttributeSemantic attributeSemantic) const; + std::optional findUniformInputAtBinding(uint32_t uniformBufferBinding) const; const EffectInputInformationVector& getUniformInputInformation() const; const EffectInputInformationVector& getAttributeInputInformation() const; @@ -64,6 +65,7 @@ namespace ramses::internal static size_t GetEffectInputIndex(const EffectInputInformationVector& effectInputVector, std::string_view inputName); static size_t FindEffectInputIndex(const EffectInputInformationVector& effectInputVector, EFixedSemantics inputSemantics); + static size_t GetUniformBufferInputIndex(const EffectInputInformationVector& effectInputVector, UniformBufferBinding uniformBufferBinding); void initializeEffectInputData(EffectInputImpl& effectInputImpl, const EffectInputInformation& effectInputInfo, size_t index) const; EffectInputInformationVector m_effectUniformInputs; diff --git a/src/client/impl/EffectInputImpl.cpp b/src/client/impl/EffectInputImpl.cpp index 9a175a64d..749820287 100644 --- a/src/client/impl/EffectInputImpl.cpp +++ b/src/client/impl/EffectInputImpl.cpp @@ -13,19 +13,10 @@ namespace ramses::internal { - void EffectInputImpl::initialize( - const ResourceContentHash& effectHash, - std::string_view name, - ramses::internal::EDataType dataType, - EFixedSemantics semantics, - size_t elementCount, - size_t index) + void EffectInputImpl::initialize(const ResourceContentHash& effectHash, const EffectInputInformation& inputInfo, size_t index) { m_effectHash = effectHash; - m_name = name; - m_dataType = dataType; - m_semantics = semantics; - m_elementCount = elementCount; + m_inputInfo = inputInfo; m_inputIndex = index; } @@ -36,27 +27,27 @@ namespace ramses::internal const std::string& EffectInputImpl::getName() const { - return m_name; + return m_inputInfo.inputName; } ramses::EDataType EffectInputImpl::getDataType() const { - return DataTypeUtils::ConvertDataTypeFromInternal(m_dataType); + return DataTypeUtils::ConvertDataTypeFromInternal(m_inputInfo.dataType); } ramses::internal::EDataType EffectInputImpl::getInternalDataType() const { - return m_dataType; + return m_inputInfo.dataType; } EFixedSemantics EffectInputImpl::getSemantics() const { - return m_semantics; + return m_inputInfo.semantics; } size_t EffectInputImpl::getElementCount() const { - return m_elementCount; + return m_inputInfo.elementCount; } size_t EffectInputImpl::getInputIndex() const @@ -66,11 +57,26 @@ namespace ramses::internal EEffectUniformSemantic EffectInputImpl::getUniformSemantics() const { - return EffectInputSemanticUtils::GetEffectUniformSemanticFromInternal(m_semantics); + return EffectInputSemanticUtils::GetEffectUniformSemanticFromInternal(m_inputInfo.semantics); } EEffectAttributeSemantic EffectInputImpl::getAttributeSemantics() const { - return EffectInputSemanticUtils::GetEffectAttributeSemanticFromInternal(m_semantics); + return EffectInputSemanticUtils::GetEffectAttributeSemanticFromInternal(m_inputInfo.semantics); + } + + UniformBufferBinding EffectInputImpl::getUniformBufferBinding() const + { + return m_inputInfo.uniformBufferBinding; + } + + UniformBufferElementSize EffectInputImpl::getUniformBufferElementSize() const + { + return m_inputInfo.uniformBufferElementSize; + } + + UniformBufferFieldOffset EffectInputImpl::getUniformBufferFieldOffset() const + { + return m_inputInfo.uniformBufferFieldOffset; } } diff --git a/src/client/impl/EffectInputImpl.h b/src/client/impl/EffectInputImpl.h index a898e4614..c7447bb6b 100644 --- a/src/client/impl/EffectInputImpl.h +++ b/src/client/impl/EffectInputImpl.h @@ -15,8 +15,8 @@ // framework #include "internal/SceneGraph/SceneAPI/ResourceContentHash.h" -#include "internal/SceneGraph/SceneAPI/EDataType.h" -#include "internal/SceneGraph/SceneAPI/EFixedSemantics.h" +#include "internal/SceneGraph/Resource/EffectInputInformation.h" +#include "internal/SceneGraph/SceneAPI/SceneTypes.h" #include #include @@ -28,13 +28,7 @@ namespace ramses::internal public: EffectInputImpl() = default; - void initialize( - const ResourceContentHash& effectHash, - std::string_view name, - ramses::internal::EDataType dataType, - EFixedSemantics semantics, - size_t elementCount, - size_t index); + void initialize(const ResourceContentHash& effectHash, const EffectInputInformation& inputInfo, size_t index); [[nodiscard]] ResourceContentHash getEffectHash() const; [[nodiscard]] const std::string& getName() const; @@ -42,17 +36,19 @@ namespace ramses::internal [[nodiscard]] EFixedSemantics getSemantics() const; [[nodiscard]] size_t getElementCount() const; [[nodiscard]] size_t getInputIndex() const; + [[nodiscard]] UniformBufferBinding getUniformBufferBinding() const; + [[nodiscard]] UniformBufferFieldOffset getUniformBufferFieldOffset() const; + [[nodiscard]] UniformBufferElementSize getUniformBufferElementSize() const; [[nodiscard]] ramses::EDataType getDataType() const; [[nodiscard]] EEffectUniformSemantic getUniformSemantics() const; [[nodiscard]] EEffectAttributeSemantic getAttributeSemantics() const; + [[nodiscard]] DataFieldHandle getDataFieldHandle() const { return m_inputInfo.dataFieldHandle; } + private: ResourceContentHash m_effectHash{}; - std::string m_name; - ramses::internal::EDataType m_dataType{ramses::internal::EDataType::Invalid}; - EFixedSemantics m_semantics{EFixedSemantics::Invalid}; - size_t m_elementCount{0u}; - size_t m_inputIndex{std::numeric_limits::max()}; + EffectInputInformation m_inputInfo; + size_t m_inputIndex{ std::numeric_limits::max() }; }; } diff --git a/src/client/impl/EffectInputSemanticUtils.h b/src/client/impl/EffectInputSemanticUtils.h index 7fb1f7045..60e57bd6e 100644 --- a/src/client/impl/EffectInputSemanticUtils.h +++ b/src/client/impl/EffectInputSemanticUtils.h @@ -21,6 +21,16 @@ namespace ramses { switch (semanticType) { + case EEffectUniformSemantic::ModelBlock: + return ramses::internal::EFixedSemantics::ModelBlock; + case EEffectUniformSemantic::CameraBlock: + return ramses::internal::EFixedSemantics::CameraBlock; + case EEffectUniformSemantic::ModelCameraBlock: + return ramses::internal::EFixedSemantics::ModelCameraBlock; + case EEffectUniformSemantic::FramebufferBlock: + return ramses::internal::EFixedSemantics::FramebufferBlock; + case EEffectUniformSemantic::SceneBlock: + return ramses::internal::EFixedSemantics::SceneBlock; case EEffectUniformSemantic::ProjectionMatrix: return ramses::internal::EFixedSemantics::ProjectionMatrix; case EEffectUniformSemantic::ModelMatrix: @@ -55,6 +65,16 @@ namespace ramses { switch (semanticType) { + case ramses::internal::EFixedSemantics::ModelBlock: + return EEffectUniformSemantic::ModelBlock; + case ramses::internal::EFixedSemantics::CameraBlock: + return EEffectUniformSemantic::CameraBlock; + case ramses::internal::EFixedSemantics::ModelCameraBlock: + return EEffectUniformSemantic::ModelCameraBlock; + case ramses::internal::EFixedSemantics::FramebufferBlock: + return EEffectUniformSemantic::FramebufferBlock; + case ramses::internal::EFixedSemantics::SceneBlock: + return EEffectUniformSemantic::SceneBlock; case ramses::internal::EFixedSemantics::ProjectionMatrix: return EEffectUniformSemantic::ProjectionMatrix; case ramses::internal::EFixedSemantics::ModelMatrix: diff --git a/src/client/impl/GeometryImpl.cpp b/src/client/impl/GeometryImpl.cpp index 5148307a8..c56388e9b 100644 --- a/src/client/impl/GeometryImpl.cpp +++ b/src/client/impl/GeometryImpl.cpp @@ -80,8 +80,8 @@ namespace ramses::internal DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_effectImpl); - inStream >> m_attributeLayout; - inStream >> m_attributeInstance; + serializationContext.deserializeAndMap(inStream, m_attributeLayout); + serializationContext.deserializeAndMap(inStream, m_attributeInstance); inStream >> m_indicesCount; serializationContext.addForDependencyResolve(this); @@ -328,8 +328,7 @@ namespace ramses::internal return false; } - // data field index on low level scene is indexed starting after reserved slot for indices - const ramses::internal::DataFieldHandle dataField(static_cast(input.getInputIndex()) + IndicesDataFieldIndex + 1u); + const auto dataField(input.getDataFieldHandle()); getIScene().setDataResource(m_attributeInstance, dataField, bufferResource.getLowlevelResourceHash(), ramses::internal::DataBufferHandle::Invalid(), instancingDivisor, offset, stride); return true; @@ -370,8 +369,7 @@ namespace ramses::internal return false; } - // data field index on low level scene is indexed starting after reserved slot for indices - const ramses::internal::DataFieldHandle dataField(static_cast(input.getInputIndex()) + IndicesDataFieldIndex + 1u); + const auto dataField(input.getDataFieldHandle()); getIScene().setDataResource(m_attributeInstance, dataField, ramses::internal::ResourceContentHash::Invalid(), dataBufferHandle, instancingDivisor, offset, stride); return true; diff --git a/src/client/impl/MeshNodeImpl.cpp b/src/client/impl/MeshNodeImpl.cpp index 5c7aa47a7..d79381993 100644 --- a/src/client/impl/MeshNodeImpl.cpp +++ b/src/client/impl/MeshNodeImpl.cpp @@ -8,6 +8,8 @@ // internal #include "impl/MeshNodeImpl.h" +#include "impl/RamsesClientImpl.h" +#include "impl/RamsesFrameworkImpl.h" // API #include "ramses/client/Geometry.h" @@ -43,22 +45,8 @@ namespace ramses::internal return false; outStream << m_renderableHandle; - if (m_appearanceImpl != nullptr) - { - outStream << serializationContext.getIDForObject(m_appearanceImpl); - } - else - { - outStream << SerializationContext::GetObjectIDNull(); - } - if (m_geometryImpl != nullptr) - { - outStream << serializationContext.getIDForObject(m_geometryImpl); - } - else - { - outStream << SerializationContext::GetObjectIDNull(); - } + outStream << (m_appearanceImpl ? serializationContext.getIDForObject(m_appearanceImpl) : SerializationContext::GetObjectIDNull()); + outStream << (m_geometryImpl ? serializationContext.getIDForObject(m_geometryImpl) : SerializationContext::GetObjectIDNull()); return true; } @@ -68,7 +56,7 @@ namespace ramses::internal if (!NodeImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_renderableHandle; + serializationContext.deserializeAndMap(inStream, m_renderableHandle); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_appearanceImpl); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_geometryImpl); @@ -127,6 +115,7 @@ namespace ramses::internal void MeshNodeImpl::deinitializeFrameworkData() { assert(m_renderableHandle.isValid()); + getIScene().releaseRenderable(m_renderableHandle); NodeImpl::deinitializeFrameworkData(); @@ -194,12 +183,11 @@ namespace ramses::internal bool MeshNodeImpl::removeAppearanceAndGeometry() { m_appearanceImpl = nullptr; - getIScene().setRenderableUniformsDataInstanceAndState(m_renderableHandle, ramses::internal::DataInstanceHandle::Invalid(), ramses::internal::RenderStateHandle::Invalid()); m_geometryImpl = nullptr; - getIScene().setRenderableDataInstance(m_renderableHandle, ramses::internal::ERenderableDataSlotType_Geometry, ramses::internal::DataInstanceHandle::Invalid()); + return setIndexCount(0u); } diff --git a/src/client/impl/MeshNodeImpl.h b/src/client/impl/MeshNodeImpl.h index 4265df05e..2fc405a07 100644 --- a/src/client/impl/MeshNodeImpl.h +++ b/src/client/impl/MeshNodeImpl.h @@ -69,9 +69,9 @@ namespace ramses::internal private: static bool AreGeometryAndAppearanceCompatible(const GeometryImpl& geometry, const AppearanceImpl& appearance); - ramses::internal::RenderableHandle m_renderableHandle; + RenderableHandle m_renderableHandle; - const AppearanceImpl* m_appearanceImpl; - const GeometryImpl* m_geometryImpl; + const AppearanceImpl* m_appearanceImpl; + const GeometryImpl* m_geometryImpl; }; } diff --git a/src/client/impl/NodeImpl.cpp b/src/client/impl/NodeImpl.cpp index 20999fe67..d3637f6f5 100644 --- a/src/client/impl/NodeImpl.cpp +++ b/src/client/impl/NodeImpl.cpp @@ -44,9 +44,9 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_nodeHandle; + serializationContext.deserializeAndMap(inStream, m_nodeHandle); inStream >> m_visibilityMode; - inStream >> m_transformHandle; + serializationContext.deserializeAndMap(inStream, m_transformHandle); serializationContext.addForDependencyResolve(this); serializationContext.addNodeHandleToNodeImplMapping(m_nodeHandle, this); diff --git a/src/client/impl/PickableObjectImpl.cpp b/src/client/impl/PickableObjectImpl.cpp index 02f11b4d6..7c7c779d8 100644 --- a/src/client/impl/PickableObjectImpl.cpp +++ b/src/client/impl/PickableObjectImpl.cpp @@ -71,7 +71,7 @@ namespace ramses::internal if (!NodeImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_pickableObjectHandle; + serializationContext.deserializeAndMap(inStream, m_pickableObjectHandle); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_geometryBufferImpl); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_cameraImpl); diff --git a/src/client/impl/RamsesClient.cpp b/src/client/impl/RamsesClient.cpp index ff1b2fd95..289125c48 100644 --- a/src/client/impl/RamsesClient.cpp +++ b/src/client/impl/RamsesClient.cpp @@ -74,6 +74,28 @@ namespace ramses return status; } + bool RamsesClient::mergeSceneFromFile(Scene & scene, std::string_view fileName) + { + auto status = m_impl.mergeSceneFromFile(scene, fileName); + LOG_HL_CLIENT_API1(status, fileName); + return status; + } + + // NOLINTNEXTLINE(modernize-avoid-c-arrays) + bool RamsesClient::mergeSceneFromMemory(Scene& scene, std::unique_ptr data, size_t size) + { + auto status = m_impl.mergeSceneFromMemory(scene, std::move(data), size); + LOG_HL_CLIENT_API1(status, size); + return status; + } + + bool RamsesClient::mergeSceneFromFileDescriptor(Scene& scene, int fd, size_t offset, size_t length) + { + auto status = m_impl.mergeSceneFromFileDescriptor(scene, fd, offset, length); + LOG_HL_CLIENT_API3(status, fd, offset, length); + return status; + } + bool RamsesClient::GetFeatureLevelFromFile(std::string_view fileName, EFeatureLevel& detectedFeatureLevel) { const bool ret = internal::RamsesClientImpl::GetFeatureLevelFromFile(fileName, detectedFeatureLevel); diff --git a/src/client/impl/RamsesClientImpl.cpp b/src/client/impl/RamsesClientImpl.cpp index fee9e5c97..d172ae0a5 100644 --- a/src/client/impl/RamsesClientImpl.cpp +++ b/src/client/impl/RamsesClientImpl.cpp @@ -37,6 +37,7 @@ #include "internal/SceneGraph/Resource/IResource.h" #include "internal/ClientCommands/PrintSceneList.h" #include "internal/ClientCommands/FlushSceneVersion.h" +#include "internal/ClientCommands/SetProperty.h" #include "impl/SerializationContext.h" #include "internal/Core/Utils/BinaryFileOutputStream.h" #include "internal/Core/Utils/BinaryFileInputStream.h" @@ -57,6 +58,8 @@ #include "internal/glslEffectBlock/GlslEffect.h" #include "impl/EffectDescriptionImpl.h" #include "impl/TextureUtils.h" +#include "internal/SceneGraph/Scene/SceneActionApplier.h" +#include "ramses/framework/EFeatureLevel.h" #include #include @@ -76,11 +79,15 @@ namespace ramses::internal m_appLogic.init(framework.getResourceComponent(), framework.getScenegraphComponent()); m_cmdPrintSceneList = std::make_shared(*this); + m_cmdSetProperty = std::make_shared(*this); + m_cmdSetPropertyAll = std::make_shared(*this); m_cmdPrintValidation = std::make_shared(*this); m_cmdFlushSceneVersion = std::make_shared(*this); m_cmdDumpSceneToFile = std::make_shared(*this); m_cmdLogResourceMemoryUsage = std::make_shared(*this); framework.getRamsh().add(m_cmdPrintSceneList); + framework.getRamsh().add(m_cmdSetProperty); + framework.getRamsh().add(m_cmdSetPropertyAll); framework.getRamsh().add(m_cmdPrintValidation); framework.getRamsh().add(m_cmdFlushSceneVersion); framework.getRamsh().add(m_cmdDumpSceneToFile); @@ -91,8 +98,6 @@ namespace ramses::internal RamsesClientImpl::~RamsesClientImpl() { LOG_INFO(CONTEXT_CLIENT, "RamsesClientImpl::~RamsesClientImpl"); - m_deleteSceneQueue.disableAcceptingTasksAfterExecutingCurrentQueue(); - m_loadFromFileTaskQueue.disableAcceptingTasksAfterExecutingCurrentQueue(); // delete async loaded scenes that were never collected via calling dispatchEvents ramses::internal::PlatformGuard g(m_clientLock); @@ -110,9 +115,11 @@ namespace ramses::internal m_hlClient = hlClient; } - void RamsesClientImpl::deinitializeFrameworkData() { + LOG_INFO(CONTEXT_CLIENT, "RamsesClientImpl::deinitializeFrameworkData waiting for task queue to finish"); + m_deleteSceneQueue.disableAcceptingTasksAfterExecutingCurrentQueue(); + m_loadFromFileTaskQueue.disableAcceptingTasksAfterExecutingCurrentQueue(); } const ramses::internal::ClientApplicationLogic& RamsesClientImpl::getClientApplication() const @@ -133,12 +140,24 @@ namespace ramses::internal return nullptr; } + const auto featureLevel = getFramework().getFeatureLevel(); + const bool vulkanCompatible = sceneConfig.getRenderBackendCompatibility() == ERenderBackendCompatibility::VulkanAndOpenGL; + + if (vulkanCompatible && featureLevel < EFeatureLevel_02) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::createScene: ERenderBackendCompatibility::VulkanAndOpenGL supported only with feature level 02 or higher"); + return nullptr; + } + ramses::internal::PlatformGuard g(m_clientLock); ramses::internal::SceneInfo sceneInfo; sceneInfo.friendlyName = name; sceneInfo.sceneID = ramses::internal::SceneId(sceneConfig.getSceneId().getValue()); + sceneInfo.renderBackendCompatibility = sceneConfig.getRenderBackendCompatibility(); + sceneInfo.vulkanAPIVersion = (vulkanCompatible ? TargetVulkanApiVersion : EVulkanAPIVersion::Invalid); + sceneInfo.spirvVersion = (vulkanCompatible ? TargetSPIRVVersion : ESPIRVVersion::Invalid); - ramses::internal::ClientScene* internalScene = m_sceneFactory.createScene(sceneInfo); + ramses::internal::ClientScene* internalScene = m_sceneFactory.createScene(sceneInfo, featureLevel); if (nullptr == internalScene) { return nullptr; @@ -177,7 +196,7 @@ namespace ramses::internal getClientApplication().removeScene(sceneID); - scene.impl().closeSceneFile(); + scene.impl().closeSceneFiles(); auto task = new DeleteSceneRunnable(std::move(sceneOwnPtr), std::move(llscene)); m_deleteSceneQueue.enqueue(*task); task->release(); @@ -232,22 +251,21 @@ namespace ramses::internal LOG_TRACE(CONTEXT_CLIENT, "RamsesClient::prepareSceneFromInputStream: start loading scene from input stream"); ramses::internal::SceneCreationInformation createInfo; - ramses::internal::ScenePersistation::ReadSceneMetadataFromStream(inputStream, createInfo); + ramses::internal::ScenePersistation::ReadSceneMetadataFromStream(inputStream, createInfo, getFramework().getFeatureLevel()); if (config.getSceneId().isValid()) { const auto newSceneId = ramses::internal::SceneId(config.getSceneId().getValue()); - LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Override stored scene id: {} with user provided scene id: {}", caller, createInfo.m_id, newSceneId); - createInfo.m_id = newSceneId; + LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Override stored scene id: {} with user provided scene id: {}", caller, createInfo.m_sceneInfo.sceneID, newSceneId); + createInfo.m_sceneInfo.sceneID = newSceneId; } const ramses::internal::SceneSizeInformation& sizeInformation = createInfo.m_sizeInfo; - const ramses::internal::SceneInfo sceneInfo(createInfo.m_id, createInfo.m_name); LOG_DEBUG(CONTEXT_CLIENT, "RamsesClient::prepareSceneFromInputStream: scene to be loaded has {}", sizeInformation); ramses::internal::ClientScene* internalScene = nullptr; { ramses::internal::PlatformGuard g(m_clientLock); - internalScene = m_sceneFactory.createScene(sceneInfo); + internalScene = m_sceneFactory.createScene(createInfo.m_sceneInfo, getFramework().getFeatureLevel()); } if (nullptr == internalScene) { @@ -258,18 +276,18 @@ namespace ramses::internal // need first to create the pimpl, so that internal framework components know the new scene if (config.getPublicationMode() == EScenePublicationMode::LocalOnly) { - LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Mark file loaded from {} with sceneId {} as local only", caller, filename, createInfo.m_id); + LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Mark file loaded from {} with sceneId {} as local only", caller, filename, createInfo.m_sceneInfo.sceneID); } else { - LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Mark file loaded from {} with sceneId {} as local and remote", caller, filename, createInfo.m_id); + LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Mark file loaded from {} with sceneId {} as local and remote", caller, filename, createInfo.m_sceneInfo.sceneID); } auto impl = std::make_unique(*internalScene, config, *m_hlClient); // now the scene is registered, so it's possible to load the low level content into the scene LOG_TRACE(CONTEXT_CLIENT, " Reading low level scene from stream"); - ramses::internal::ScenePersistation::ReadSceneFromStream(inputStream, *internalScene); + ramses::internal::ScenePersistation::ReadSceneFromStream(inputStream, *internalScene, getFramework().getFeatureLevel(), nullptr); LOG_TRACE(CONTEXT_CLIENT, " Deserializing high level scene objects from stream"); DeserializationContext deserializationContext(config); @@ -286,23 +304,106 @@ namespace ramses::internal return SceneOwningPtr{ new ramses::Scene{ std::move(impl) }, [](ramses::Scene* s) { delete s; } }; } + + bool RamsesClientImpl::mergeSceneObjectFromStream(::ramses::Scene & scene, + const std::string& caller, + std::string const& filename, + ramses::internal::IInputStream& inputStream, + const SceneConfigImpl& config) + { + LOG_TRACE(CONTEXT_CLIENT, "RamsesClient::prepareSceneFromInputStream: start merging scene from input stream"); + + if (getFramework().getFeatureLevel() < EFeatureLevel::EFeatureLevel_02) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::mergeSceneObjectFromStream: Min feature level {} required for merging.", EFeatureLevel::EFeatureLevel_02); + return false; + } + + ramses::internal::SceneCreationInformation createInfo; + ramses::internal::ScenePersistation::ReadSceneMetadataFromStream(inputStream, createInfo, getFramework().getFeatureLevel()); + const ramses::internal::SceneSizeInformation& sizeInformation = createInfo.m_sizeInfo; + + LOG_DEBUG(CONTEXT_CLIENT, "RamsesClient::prepareSceneFromInputStream: scene to be merged has {}", sizeInformation); + + ramses::internal::ClientScene& internalScene = scene.m_impl.getIScene(); + if (internalScene.getRenderBackendCompatibility() != createInfo.m_sceneInfo.renderBackendCompatibility + || internalScene.getVulkanAPIVersion() != createInfo.m_sceneInfo.vulkanAPIVersion + || internalScene.getSPIRVVersion() != createInfo.m_sceneInfo.spirvVersion) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::mergeSceneObjectFromStream: Trying to merge scenes with incompatible render backends"); + return false; + } + + SceneMergeHandleMapping mapping; + + LOG_TRACE(CONTEXT_CLIENT, " Reading low level scene from stream caller={} file={}", caller, filename); + ramses::internal::ScenePersistation::ReadSceneFromStream(inputStream, internalScene, getFramework().getFeatureLevel(), &mapping); + + LOG_TRACE(CONTEXT_CLIENT, " Deserializing high level scene objects from stream"); + DeserializationContext deserializationContext(config, &mapping); + SerializationHelper::DeserializeObjectID(inputStream); + if (!scene.m_impl.deserialize(inputStream, deserializationContext)) + { + LOG_ERROR(CONTEXT_CLIENT, " Failed to deserialize high level scene:"); + LOG_ERROR(CONTEXT_CLIENT, m_framework.getErrorReporting().getError().value_or(Issue{}).message); + return false; + } + + LOG_TRACE(CONTEXT_CLIENT, " Done with preparing scene from input stream."); + + return true; + } + SceneOwningPtr RamsesClientImpl::loadSceneFromCreationConfig(const SceneCreationConfig& cconfig) + { + SaveFileConfigImpl::ExporterVersion exporter; + std::vector sceneData; + + if (!readInitialSceneInformation(cconfig, exporter, sceneData)) + { + return {}; + } + + ramses::internal::IInputStream& inputStream = cconfig.streamContainer->getStream(); + + SceneOwningPtr scene; + if (cconfig.prefetchData) + { + ramses::internal::BinaryInputStream sceneDataStream(sceneData.data()); + scene = loadSceneObjectFromStream(cconfig.caller, cconfig.dataSource, sceneDataStream, cconfig.config); + } + else + { + // this path will be used in the future when creating scene from user provided stream + scene = loadSceneObjectFromStream(cconfig.caller, cconfig.dataSource, inputStream, cconfig.config); + } + if (!scene) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::{}: scene creation for '{}' failed", cconfig.caller, cconfig.dataSource); + return nullptr; + } + + readAndRegisterResourceFile(inputStream, *scene, cconfig); + + return scene; + } + + bool RamsesClientImpl::readInitialSceneInformation(const SceneCreationConfig& cconfig, SaveFileConfigImpl::ExporterVersion& exporter, std::vector& sceneData) { // this stream contains scene data AND resource data and will be handed over to and held open by resource component as resource stream ramses::internal::IInputStream& inputStream = cconfig.streamContainer->getStream(); if (inputStream.getState() != ramses::internal::EStatus::Ok) { LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::{}: failed to open scene source {}", cconfig.caller, cconfig.dataSource); - return nullptr; + return false; } if (!ReadRamsesVersionAndPrintWarningOnMismatch(inputStream, "scene file", getFramework().getFeatureLevel())) { LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::{}: failed to read from scene source {}", cconfig.caller, cconfig.dataSource); - return nullptr; + return false; } - SaveFileConfigImpl::ExporterVersion exporter; std::string metadataString; inputStream >> exporter; inputStream >> metadataString; @@ -315,42 +416,65 @@ namespace ramses::internal inputStream >> sceneObjectStart; inputStream >> llResourceStart; - SceneOwningPtr scene; if (cconfig.prefetchData) { - std::vector sceneData(static_cast(llResourceStart - sceneObjectStart)); + sceneData.resize(static_cast(llResourceStart - sceneObjectStart)); inputStream.read(sceneData.data(), sceneData.size()); + } - if (inputStream.getState() != ramses::internal::EStatus::Ok) - { - LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::{}: Failed reading scene from file: {} ", cconfig.caller, inputStream.getState()); - return nullptr; - } + if (inputStream.getState() != ramses::internal::EStatus::Ok) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::{}: Failed reading scene from file: {} ", cconfig.caller, inputStream.getState()); + return false; + } + + return true; + } + + void RamsesClientImpl::readAndRegisterResourceFile(IInputStream& inputStream, ramses::Scene& scene, const SceneCreationConfig& cconfig) + { + // calls on m_appLogic are thread safe + // register stream for on-demand resource loading (LL-Resources) + ramses::internal::ResourceTableOfContents loadedTOC; + loadedTOC.readTOCPosAndTOCFromStream(inputStream); + const ramses::internal::SceneFileHandle fileHandle = m_appLogic.addResourceFile(cconfig.streamContainer, loadedTOC); + scene.m_impl.addSceneFileHandle(fileHandle); + + LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Source '{}' has handle {}", cconfig.caller, cconfig.dataSource, fileHandle); + } + + bool RamsesClientImpl::mergeSceneFromCreationConfig(::ramses::Scene& scene, const SceneCreationConfig& cconfig) + { + SaveFileConfigImpl::ExporterVersion exporter; + std::vector sceneData; + if (!readInitialSceneInformation(cconfig, exporter, sceneData)) + { + return false; + } + + ramses::internal::IInputStream& inputStream = cconfig.streamContainer->getStream(); + + bool success = true; + if (cconfig.prefetchData) + { ramses::internal::BinaryInputStream sceneDataStream(sceneData.data()); - scene = loadSceneObjectFromStream(cconfig.caller, cconfig.dataSource, sceneDataStream, cconfig.config); + success = mergeSceneObjectFromStream(scene, cconfig.caller, cconfig.dataSource, sceneDataStream, cconfig.config); } else { // this path will be used in the future when creating scene from user provided stream - scene = loadSceneObjectFromStream(cconfig.caller, cconfig.dataSource, inputStream, cconfig.config); + success = mergeSceneObjectFromStream(scene, cconfig.caller, cconfig.dataSource, inputStream, cconfig.config); } - if (!scene) + if (!success) { LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::{}: scene creation for '{}' failed", cconfig.caller, cconfig.dataSource); - return nullptr; + return false; } - // calls on m_appLogic are thread safe - // register stream for on-demand resource loading (LL-Resources) - ramses::internal::ResourceTableOfContents loadedTOC; - loadedTOC.readTOCPosAndTOCFromStream(inputStream); - const ramses::internal::SceneFileHandle fileHandle = m_appLogic.addResourceFile(cconfig.streamContainer, loadedTOC); - scene->m_impl.setSceneFileHandle(fileHandle); + readAndRegisterResourceFile(inputStream, scene, cconfig); - LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{}: Source '{}' has handle {}", cconfig.caller, cconfig.dataSource, fileHandle); - - return scene; + return true; } ramses::Scene* RamsesClientImpl::loadSceneFromFile(std::string_view fileName, const SceneConfigImpl& config) @@ -361,7 +485,7 @@ namespace ramses::internal return nullptr; } - return loadSceneSynchonousCommon({ + return loadSceneSynchronousCommon({ "loadSceneFromFile", std::string{fileName}, std::make_shared(fileName), true, config @@ -382,7 +506,7 @@ namespace ramses::internal return nullptr; } - return loadSceneSynchonousCommon({ + return loadSceneSynchronousCommon({ "loadSceneFromMemory", fmt::format("", size), std::make_shared(std::move(data)), @@ -404,7 +528,7 @@ namespace ramses::internal return nullptr; } - return loadSceneSynchonousCommon(SceneCreationConfig{ + return loadSceneSynchronousCommon(SceneCreationConfig{ "loadSceneFromFileDescriptor", fmt::format("", fd, offset, length), std::make_shared(fd, offset, length), @@ -413,7 +537,7 @@ namespace ramses::internal }); } - ramses::Scene* RamsesClientImpl::loadSceneSynchonousCommon(const SceneCreationConfig& cconfig) + ramses::Scene* RamsesClientImpl::loadSceneSynchronousCommon(const SceneCreationConfig& cconfig) { const uint64_t start = ramses::internal::PlatformTime::GetMillisecondsMonotonic(); auto scene = loadSceneFromCreationConfig(cconfig); @@ -429,6 +553,86 @@ namespace ramses::internal return scenePtr; } + bool RamsesClientImpl::mergeSceneFromFile(ramses::Scene & scene, std::string_view fileName) + { + if (fileName.empty()) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::mergeSceneFromFile: filename may not be empty"); + return false; + } + + return mergeSceneSynchronousCommon( + scene, + { + "mergeSceneFromFile", + std::string{fileName}, + std::make_shared(fileName), true, {} + }); + } + + // NOLINTNEXTLINE(modernize-avoid-c-arrays) + bool RamsesClientImpl::mergeSceneFromMemory(ramses::Scene& scene, std::unique_ptr data, size_t size) + { + if (!data) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::mergeSceneFromMemory: data may not be null"); + return false; + } + if (size == 0) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::mergeSceneFromMemory: size may not be 0"); + return false; + } + + return mergeSceneSynchronousCommon( + scene, + { + "mergeSceneFromMemory", + fmt::format("", size), + std::make_shared(std::move(data)), + false, + {} + }); + } + + bool RamsesClientImpl::mergeSceneFromFileDescriptor(ramses::Scene& scene, int fd, size_t offset, size_t length) + { + if (fd <= 0) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::mergeSceneFromFileDescriptor: filedescriptor must be valid {}", fd); + return false; + } + if (length == 0) + { + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::mergeSceneFromFileDescriptor: length may not be 0"); + return false; + } + + return mergeSceneSynchronousCommon( + scene, + SceneCreationConfig{ + "mergeSceneFromFileDescriptor", + fmt::format("", fd, offset, length), + std::make_shared(fd, offset, length), + true, + {} + }); + } + + bool RamsesClientImpl::mergeSceneSynchronousCommon(ramses::Scene& scene, const SceneCreationConfig& cconfig) + { + const uint64_t start = ramses::internal::PlatformTime::GetMillisecondsMonotonic(); + if (!mergeSceneFromCreationConfig(scene, cconfig)) + { + return false; + } + + const uint64_t end = ramses::internal::PlatformTime::GetMillisecondsMonotonic(); + LOG_INFO(CONTEXT_CLIENT, "RamsesClient::{} ramses::Scene merged from '{}' in {} ms", cconfig.caller, cconfig.dataSource, end - start); + + return true; + } + void RamsesClientImpl::finalizeLoadedScene(SceneOwningPtr scene) { // add to the known list of scenes @@ -488,9 +692,9 @@ namespace ramses::internal } LOG_INFO(CONTEXT_CLIENT, "RAMSES version in file '{}': [{}]; GitHash: [{}]; FeatureLevel: [{}];", verboseFileName, readVersion.versionString, readVersion.gitHash, featureLevelFromFile); - if (!ramses::internal::RamsesVersion::MatchesMajorMinor(::ramses_sdk::RAMSES_SDK_PROJECT_VERSION_MAJOR_INT, ::ramses_sdk::RAMSES_SDK_PROJECT_VERSION_MINOR_INT, readVersion)) + if (::ramses_sdk::RAMSES_SDK_PROJECT_VERSION_MAJOR_INT != readVersion.major) { - LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::ReadRamsesVersionAndPrintWarningOnMismatch: Version of file {} does not match MAJOR.MINOR of this build. Cannot load the file.", verboseFileName); + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::ReadRamsesVersionAndPrintWarningOnMismatch: Version of file {} does not match MAJOR of this build. Cannot load the file.", verboseFileName); LOG_ERROR(CONTEXT_CLIENT, "SDK version of loader: [{}]; GitHash: [{}]", ::ramses_sdk::RAMSES_SDK_RAMSES_VERSION, ::ramses_sdk::RAMSES_SDK_GIT_COMMIT_HASH); return false; } @@ -797,19 +1001,20 @@ namespace ramses::internal const std::vector& mipLevelData, bool generateMipChain, const TextureSwizzle& swizzle, std::string_view name); - ramses::internal::ManagedResource RamsesClientImpl::createManagedEffect(const EffectDescription& effectDesc, std::string_view name, std::string& errorMessages) + ramses::internal::ManagedResource RamsesClientImpl::createManagedEffect(const EffectDescription& effectDesc, ERenderBackendCompatibility compatibility, std::string_view name, std::string& errorMessages) { //create effect using vertex and fragment shaders ramses::internal::GlslEffect effectBlock(effectDesc.getVertexShader(), effectDesc.getFragmentShader(), effectDesc.getGeometryShader(), effectDesc.impl().getCompilerDefines(), - effectDesc.impl().getSemanticsMap(), name); + effectDesc.impl().getSemanticsMap(), compatibility, name); errorMessages.clear(); - ramses::internal::EffectResource* effectResource = effectBlock.createEffectResource(); + auto effectResource = effectBlock.createEffectResource(getFramework().getFeatureLevel()); if (!effectResource) { errorMessages = effectBlock.getEffectErrorMessages(); - LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::createEffect Failed to create effect resource (name: '{}') :\n {}", name, effectBlock.getEffectErrorMessages()); + LOG_ERROR(CONTEXT_CLIENT, "RamsesClient::createEffect: Failed to create effect resource (name: '{}') :\n {}", name, effectBlock.getEffectErrorMessages()); return {}; } - return manageResource(effectResource); + + return manageResource(effectResource.release()); } } diff --git a/src/client/impl/RamsesClientImpl.h b/src/client/impl/RamsesClientImpl.h index ea432594d..935e3bcaa 100644 --- a/src/client/impl/RamsesClientImpl.h +++ b/src/client/impl/RamsesClientImpl.h @@ -35,9 +35,11 @@ #include "internal/Core/TaskFramework/EnqueueOnlyOneAtATimeQueue.h" #include "internal/Core/TaskFramework/TaskForwardingQueue.h" #include "internal/PlatformAbstraction/Collections/HashMap.h" +#include "internal/glslEffectBlock/GlslangInitializer.h" #include "impl/RamsesFrameworkTypesImpl.h" #include "impl/SceneImpl.h" #include "impl/SceneConfigImpl.h" +#include "impl/SaveFileConfigImpl.h" #include #include @@ -58,6 +60,8 @@ namespace ramses::internal { class IInputStream; class PrintSceneList; + class SetProperty; + class SetPropertyAll; class FlushSceneVersion; class BinaryFileOutputStream; class BinaryFileInputStream; @@ -107,6 +111,11 @@ namespace ramses::internal bool loadSceneFromFileAsync(std::string_view fileName, const SceneConfigImpl& config); + bool mergeSceneFromFile(ramses::Scene& scene, std::string_view fileName); + // NOLINTNEXTLINE(modernize-avoid-c-arrays) + bool mergeSceneFromMemory(ramses::Scene& scene, std::unique_ptr data, size_t size); + bool mergeSceneFromFileDescriptor(ramses::Scene& scene, int fd, size_t offset, size_t length); + bool dispatchEvents(IClientEventHandler& clientEventHandler); const SceneVector& getListOfScenes() const; @@ -135,7 +144,7 @@ namespace ramses::internal ramses::internal::ManagedResource createManagedArrayResource(size_t numElements, ramses::EDataType type, const void* arrayData, std::string_view name); template ramses::internal::ManagedResource createManagedTexture(ramses::internal::EResourceType textureType, uint32_t width, uint32_t height, uint32_t depth, ETextureFormat format, const std::vector& mipLevelData, bool generateMipChain, const TextureSwizzle& swizzle, std::string_view name); - ramses::internal::ManagedResource createManagedEffect(const EffectDescription& effectDesc, std::string_view name, std::string& errorMessages); + ramses::internal::ManagedResource createManagedEffect(const EffectDescription& effectDesc, ERenderBackendCompatibility compatibility, std::string_view name, std::string& errorMessages); void writeLowLevelResourcesToStream(const ResourceObjects& resources, ramses::internal::IOutputStream& resourceOutputStream, bool compress) const; static bool ReadRamsesVersionAndPrintWarningOnMismatch(ramses::internal::IInputStream& inputStream, std::string_view verboseFileName, EFeatureLevel featureLevel); @@ -144,6 +153,10 @@ namespace ramses::internal static bool GetFeatureLevelFromFile(int fd, size_t offset, size_t length, EFeatureLevel& detectedFeatureLevel); private: + // This make sure that glslang init/deinit is called maximum once per client to reduce overhead + // i.e., since init/deinit internally get called in glslang only when ref-count is Zero + GlslangInitializer m_glslangInitializer; + struct SceneCreationConfig { std::string caller; @@ -185,12 +198,22 @@ namespace ramses::internal ramses::internal::ManagedResource manageResource(const ramses::internal::IResource* res); - Scene* loadSceneSynchonousCommon(const SceneCreationConfig& cconf); + Scene* loadSceneSynchronousCommon(const SceneCreationConfig& cconf); SceneOwningPtr loadSceneFromCreationConfig(const SceneCreationConfig& cconf); SceneOwningPtr loadSceneObjectFromStream(const std::string& caller, std::string const& filename, ramses::internal::IInputStream& inputStream, const SceneConfigImpl& config); void finalizeLoadedScene(SceneOwningPtr scene); + bool readInitialSceneInformation(const SceneCreationConfig& cconfig, SaveFileConfigImpl::ExporterVersion& exporter, std::vector& sceneData); + void readAndRegisterResourceFile(IInputStream& inputStream, ramses::Scene& scene, const SceneCreationConfig& cconfig); + + bool mergeSceneSynchronousCommon(ramses::Scene& scene, const SceneCreationConfig& cconfig); + bool mergeSceneFromCreationConfig(ramses::Scene& scene, const SceneCreationConfig& cconfig); + bool mergeSceneObjectFromStream(ramses::Scene& scene, + const std::string& caller, + std::string const& filename, + ramses::internal::IInputStream& inputStream, + const SceneConfigImpl& config); void validateScenes(ValidationReportImpl& report) const; @@ -203,6 +226,8 @@ namespace ramses::internal SceneVector m_scenes; std::shared_ptr m_cmdPrintSceneList; + std::shared_ptr m_cmdSetProperty; + std::shared_ptr m_cmdSetPropertyAll; std::shared_ptr m_cmdPrintValidation; std::shared_ptr m_cmdFlushSceneVersion; std::shared_ptr m_cmdDumpSceneToFile; diff --git a/src/client/impl/RamsesClientTypesImpl.h b/src/client/impl/RamsesClientTypesImpl.h index 4f6e74466..87c15f3e0 100644 --- a/src/client/impl/RamsesClientTypesImpl.h +++ b/src/client/impl/RamsesClientTypesImpl.h @@ -54,7 +54,8 @@ namespace ramses "TextureSampler3D", "TextureSamplerCube", "TextureSamplerExternal", + "UniformBuffer", }; } -MAKE_ENUM_CLASS_PRINTABLE(ramses::EDataType, "EDataType", ramses::DataTypeNames, ramses::EDataType::TextureSamplerExternal); +MAKE_ENUM_CLASS_PRINTABLE(ramses::EDataType, "EDataType", ramses::DataTypeNames, ramses::EDataType::UniformBuffer); diff --git a/src/client/impl/RenderBufferImpl.cpp b/src/client/impl/RenderBufferImpl.cpp index 552dd53f0..a7253055c 100644 --- a/src/client/impl/RenderBufferImpl.cpp +++ b/src/client/impl/RenderBufferImpl.cpp @@ -10,6 +10,7 @@ #include "impl/TextureUtils.h" #include "impl/TextureEnumsImpl.h" #include "impl/ErrorReporting.h" +#include "impl/SerializationContext.h" #include "internal/SceneGraph/Scene/ClientScene.h" namespace ramses::internal @@ -80,7 +81,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_renderBufferHandle; + serializationContext.deserializeAndMap(inStream, m_renderBufferHandle); return true; } @@ -103,6 +104,7 @@ namespace ramses::internal } bool usedInRenderPass = false; + bool renderPassEnabled = false; ramses::internal::RenderTargetHandle rtHandle; for (ramses::internal::RenderTargetHandle rt(0u); rt < iscene.getRenderTargetCount() && !rtHandle.isValid(); ++rt) { @@ -122,10 +124,18 @@ namespace ramses::internal { for (ramses::internal::RenderPassHandle rp(0u); rp < iscene.getRenderPassCount(); ++rp) { - if (iscene.isRenderPassAllocated(rp) && iscene.getRenderPass(rp).renderTarget == rtHandle && iscene.getRenderPass(rp).isEnabled) + if (iscene.isRenderPassAllocated(rp)) { - usedInRenderPass = true; - break; + auto& renderPass = iscene.getRenderPass(rp); + if (renderPass.renderTarget == rtHandle) + { + usedInRenderPass = true; + if (renderPass.isEnabled) + { + renderPassEnabled = true; + break; + } + } } } } @@ -153,35 +163,30 @@ namespace ramses::internal } } - bool hasIssue = false; - // explicitly warn about usage of potentially uninitialized buffer - if (usedAsTexture && !(usedInRenderPass || usedAsBlitDestination)) + if (!usedInRenderPass && !usedAsBlitDestination) { - report.add(EIssueType::Warning, - "RenderBuffer is used in a TextureSampler for reading but is not set as destination in any RenderPass or BlitPass, this can lead to usage of " + if (usedAsBlitSource || usedAsTexture) + { + // explicitly warn about usage of potentially uninitialized buffer + report.add(EIssueType::Warning, + "RenderBuffer is used in a TextureSampler or BlitPass for reading, but is not set as destination in any RenderPass or BlitPass. This can lead to usage of " "uninitialized data.", &getRamsesObject()); - hasIssue = true; + } + else + { + report.add(EIssueType::Warning, "RenderBuffer is not set as destination in any RenderPass or BlitPass, destroy it if not needed.", &getRamsesObject()); + } } - if (!usedInRenderPass && !usedAsBlitDestination) + if ((usedAsBlitSource || usedAsTexture) && usedInRenderPass && !renderPassEnabled && !usedAsBlitDestination) { - hasIssue = true; - report.add(EIssueType::Warning, "RenderBuffer is not set as destination in any RenderPass or BlitPass, destroy it if not needed.", &getRamsesObject()); + report.add(EIssueType::Warning, "RenderBuffer is used in a TextureSampler or BlitPass for reading, but assigned RenderPass is not enabled. This can lead to usage of uninitialized data.", &getRamsesObject()); } if (!usedAsTexture && !usedAsBlitSource && isColorBuffer) // depth/stencil buffer does not need to be validated for usage as texture { - hasIssue = true; report.add(EIssueType::Warning, "RenderBuffer is neither used in a TextureSampler for reading nor set as source in a BlitPass, destroy it if not needed.", &getRamsesObject()); } - - if (hasIssue) - { - ramses::internal::StringOutputStream rbDesc; - const ramses::internal::RenderBuffer& rb = getIScene().getRenderBuffer(m_renderBufferHandle); - rbDesc << " [" << rb.width << "x" << rb.height << "; " << ramses::internal::EnumToString(rb.format) << "; " << EnumToString(rb.accessMode) << "; " << rb.sampleCount << " samples]"; - return report.add(EIssueType::Warning, rbDesc.release(), &getRamsesObject()); - } } bool RenderBufferImpl::setProperties(uint32_t width, uint32_t height, uint32_t sampleCount) diff --git a/src/client/impl/RenderGroupImpl.cpp b/src/client/impl/RenderGroupImpl.cpp index dc4282791..4e50ce64e 100644 --- a/src/client/impl/RenderGroupImpl.cpp +++ b/src/client/impl/RenderGroupImpl.cpp @@ -74,7 +74,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_renderGroupHandle; + serializationContext.deserializeAndMap(inStream, m_renderGroupHandle); deserializeObjects(inStream, serializationContext, m_meshes); deserializeObjects(inStream, serializationContext, m_renderGroups); @@ -106,9 +106,6 @@ namespace ramses::internal { SceneObjectImpl::onValidate(report); - if (m_meshes.empty() && m_renderGroups.empty()) - report.add(EIssueType::Warning, "rendergroup does not contain any meshes", &getRamsesObject()); - for (const auto& element : m_meshes) report.addDependentObject(*this, *element); diff --git a/src/client/impl/RenderPassImpl.cpp b/src/client/impl/RenderPassImpl.cpp index 02d37d708..644c9bb84 100644 --- a/src/client/impl/RenderPassImpl.cpp +++ b/src/client/impl/RenderPassImpl.cpp @@ -73,7 +73,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_renderPassHandle; + serializationContext.deserializeAndMap(inStream, m_renderPassHandle); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_cameraImpl); DeserializationContext::ReadDependentPointerAndStoreAsID(inStream, m_renderTargetImpl); diff --git a/src/client/impl/RenderTargetImpl.cpp b/src/client/impl/RenderTargetImpl.cpp index 96496db8c..57cab4efe 100644 --- a/src/client/impl/RenderTargetImpl.cpp +++ b/src/client/impl/RenderTargetImpl.cpp @@ -8,6 +8,7 @@ #include "impl/RenderTargetImpl.h" #include "impl/RenderTargetDescriptionImpl.h" +#include "impl/SerializationContext.h" #include "internal/SceneGraph/Scene/ClientScene.h" namespace ramses::internal @@ -86,7 +87,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_renderTargetHandle; + serializationContext.deserializeAndMap(inStream, m_renderTargetHandle); return true; } diff --git a/src/client/impl/ResourceImpl.cpp b/src/client/impl/ResourceImpl.cpp index b333809e3..8619a0226 100644 --- a/src/client/impl/ResourceImpl.cpp +++ b/src/client/impl/ResourceImpl.cpp @@ -17,7 +17,6 @@ #include "internal/ClientApplicationLogic.h" #include "internal/Components/ManagedResource.h" -#include "internal/PlatformAbstraction/Collections/StringOutputStream.h" #include "internal/Core/Utils/BinaryOutputStream.h" #include "impl/RamsesObjectTypeUtils.h" #include "city.h" diff --git a/src/client/impl/SceneConfig.cpp b/src/client/impl/SceneConfig.cpp index bd469d234..181b94e3a 100644 --- a/src/client/impl/SceneConfig.cpp +++ b/src/client/impl/SceneConfig.cpp @@ -20,11 +20,12 @@ namespace ramses { } - SceneConfig::SceneConfig(sceneId_t sceneId, EScenePublicationMode publicationMode) + SceneConfig::SceneConfig(sceneId_t sceneId, EScenePublicationMode publicationMode, ERenderBackendCompatibility renderBackendCompatibility) : m_impl{ std::make_unique() } { m_impl->setSceneId(sceneId); m_impl->setPublicationMode(publicationMode); + m_impl->setRenderBackendCompatibility(renderBackendCompatibility); } SceneConfig::~SceneConfig() = default; @@ -71,4 +72,10 @@ namespace ramses m_impl->setMemoryVerificationEnabled(enabled); LOG_HL_CLIENT_API1(true, enabled); } + + void SceneConfig::setRenderBackendCompatibility(ERenderBackendCompatibility renderBackendCompatibility) + { + m_impl->setRenderBackendCompatibility(renderBackendCompatibility); + LOG_HL_CLIENT_API1(true, renderBackendCompatibility); + } } diff --git a/src/client/impl/SceneConfigImpl.cpp b/src/client/impl/SceneConfigImpl.cpp index edd76efc4..3873f7e58 100644 --- a/src/client/impl/SceneConfigImpl.cpp +++ b/src/client/impl/SceneConfigImpl.cpp @@ -39,4 +39,14 @@ namespace ramses::internal { return m_memoryVerificationEnabled; } + + void SceneConfigImpl::setRenderBackendCompatibility(ERenderBackendCompatibility renderBackendCompatibility) + { + m_renderBackendCompatibility = renderBackendCompatibility; + } + + ERenderBackendCompatibility SceneConfigImpl::getRenderBackendCompatibility() const + { + return m_renderBackendCompatibility; + } } diff --git a/src/client/impl/SceneConfigImpl.h b/src/client/impl/SceneConfigImpl.h index b115ba70d..4245237ba 100644 --- a/src/client/impl/SceneConfigImpl.h +++ b/src/client/impl/SceneConfigImpl.h @@ -10,6 +10,7 @@ #include "ramses/framework/RamsesFrameworkTypes.h" #include "ramses/framework/EScenePublicationMode.h" +#include "ramses/framework/ERenderBackendCompatibility.h" namespace ramses::internal { @@ -19,14 +20,17 @@ namespace ramses::internal void setPublicationMode(EScenePublicationMode publicationMode); void setMemoryVerificationEnabled(bool enabled); void setSceneId(sceneId_t sceneId); + void setRenderBackendCompatibility(ERenderBackendCompatibility renderBackendCompatibility); [[nodiscard]] EScenePublicationMode getPublicationMode() const; [[nodiscard]] bool getMemoryVerificationEnabled() const; [[nodiscard]] sceneId_t getSceneId() const; + [[nodiscard]] ERenderBackendCompatibility getRenderBackendCompatibility() const; private: EScenePublicationMode m_publicationMode = EScenePublicationMode::LocalOnly; sceneId_t m_sceneId; bool m_memoryVerificationEnabled = true; + ERenderBackendCompatibility m_renderBackendCompatibility = ERenderBackendCompatibility::OpenGL; }; } diff --git a/src/client/impl/SceneFactory.cpp b/src/client/impl/SceneFactory.cpp index 28f41af2c..d984d7f29 100644 --- a/src/client/impl/SceneFactory.cpp +++ b/src/client/impl/SceneFactory.cpp @@ -12,7 +12,7 @@ namespace ramses::internal { - ClientScene* SceneFactory::createScene(const SceneInfo& sceneInfo) + ClientScene* SceneFactory::createScene(const SceneInfo& sceneInfo, EFeatureLevel featureLevel) { if (m_scenes.count(sceneInfo.sceneID) != 0) { @@ -20,7 +20,7 @@ namespace ramses::internal return nullptr; } - auto newScene = std::make_unique(sceneInfo); + auto newScene = std::make_unique(sceneInfo, featureLevel); auto* newScenePtr = newScene.get(); m_scenes.insert({ newScene->getSceneId(), std::move(newScene) }); diff --git a/src/client/impl/SceneFactory.h b/src/client/impl/SceneFactory.h index c3e0b18b2..a8bc9f689 100644 --- a/src/client/impl/SceneFactory.h +++ b/src/client/impl/SceneFactory.h @@ -9,6 +9,7 @@ #pragma once #include "internal/SceneGraph/SceneAPI/IScene.h" +#include "ramses/framework/EFeatureLevel.h" #include namespace ramses::internal @@ -19,7 +20,7 @@ namespace ramses::internal class SceneFactory { public: - ClientScene* createScene(const SceneInfo& sceneInfo); + ClientScene* createScene(const SceneInfo& sceneInfo, EFeatureLevel featureLevel); InternalSceneOwningPtr releaseScene(SceneId id); private: diff --git a/src/client/impl/SceneImpl.cpp b/src/client/impl/SceneImpl.cpp index 0f842ca0c..70414f5a8 100644 --- a/src/client/impl/SceneImpl.cpp +++ b/src/client/impl/SceneImpl.cpp @@ -44,6 +44,13 @@ #include "ramses/client/ramses-utils.h" #include "ramses/client/logic/LogicEngine.h" #include "ramses/client/logic/LogicObject.h" +#include "ramses/client/logic/AppearanceBinding.h" +#include "ramses/client/logic/CameraBinding.h" +#include "ramses/client/logic/MeshNodeBinding.h" +#include "ramses/client/logic/NodeBinding.h" +#include "ramses/client/logic/RenderBufferBinding.h" +#include "ramses/client/logic/RenderGroupBinding.h" +#include "ramses/client/logic/RenderPassBinding.h" #include "ramses/framework/EScenePublicationMode.h" #include "impl/CameraNodeImpl.h" @@ -80,6 +87,13 @@ #include "impl/SaveFileConfigImpl.h" #include "impl/logic/LogicObjectImpl.h" #include "impl/SerializationContext.h" +#include "impl/logic/AppearanceBindingImpl.h" +#include "impl/logic/CameraBindingImpl.h" +#include "impl/logic/MeshNodeBindingImpl.h" +#include "impl/logic/NodeBindingImpl.h" +#include "impl/logic/RenderBufferBindingImpl.h" +#include "impl/logic/RenderGroupBindingImpl.h" +#include "impl/logic/RenderPassBindingImpl.h" #include "internal/SceneGraph/Scene/Scene.h" #include "internal/SceneGraph/Scene/ScenePersistation.h" @@ -103,8 +117,10 @@ #include "ramses-sdk-build-config.h" #include "fmt/format.h" +#include #include #include +#include namespace ramses::internal { @@ -124,7 +140,7 @@ namespace ramses::internal SceneImpl::~SceneImpl() { LOG_INFO(CONTEXT_CLIENT, "SceneImpl::~SceneImpl"); - closeSceneFile(); + closeSceneFiles(); getClientImpl().getFramework().getPeriodicLogger().removeStatisticCollectionScene(m_scene.getSceneId()); } @@ -214,7 +230,7 @@ namespace ramses::internal { uint32_t count = 0u; const ERamsesObjectType type = SerializationHelper::DeserializeObjectTypeAndCount(inStream, count); - assert(m_objectRegistry.getNumberOfObjects(type) == 0u); + assert(serializationContext.getSceneMergeHandleMapping() || m_objectRegistry.getNumberOfObjects(type) == 0u); m_objectRegistry.reserveAdditionalObjectCapacity(type, count); objectCounts[i] = count; @@ -313,7 +329,12 @@ namespace ramses::internal return false; } - inStream >> m_lastSceneObjectId.getReference(); + sceneObjectId_t lastSceneObjectId; + inStream >> lastSceneObjectId.getReference(); + if (!serializationContext.getSceneMergeHandleMapping()) + { + m_lastSceneObjectId = lastSceneObjectId; + } LOG_DEBUG_F(CONTEXT_PROFILING, ([&](ramses::internal::StringOutputStream& sos) { sos << "SceneImpl::deserialize: HL scene object counts for SceneID " << m_scene.getSceneId() << "\n"; @@ -329,8 +350,68 @@ namespace ramses::internal return serializationContext.resolveDependencies(); } + bool SceneImpl::ValidateLogicBindingReferencesTo(const SceneObject* obj, const std::vector& lengines) + { + auto countBindingsIn = [obj](const auto& collections) { + size_t count = 0; + for (const auto* binding : collections) + { + if (binding->impl().getBoundObject().getSceneObjectId() == obj->getSceneObjectId()) + count++; + } + return count; + }; + + std::unordered_map counts; + for (const auto* le : lengines) + { + switch (obj->getType()) + { + case ERamsesObjectType::Appearance: + counts[ERamsesObjectType::Appearance] += countBindingsIn(le->getCollection()); + break; + case ERamsesObjectType::Camera: + case ERamsesObjectType::PerspectiveCamera: + case ERamsesObjectType::OrthographicCamera: + counts[ERamsesObjectType::Camera] += countBindingsIn(le->getCollection()); + counts[ERamsesObjectType::Node] += countBindingsIn(le->getCollection()); + break; + case ERamsesObjectType::MeshNode: + counts[ERamsesObjectType::MeshNode] += countBindingsIn(le->getCollection()); + counts[ERamsesObjectType::Node] += countBindingsIn(le->getCollection()); + break; + case ERamsesObjectType::Node: + counts[ERamsesObjectType::Node] += countBindingsIn(le->getCollection()); + break; + case ERamsesObjectType::RenderBuffer: + counts[ERamsesObjectType::RenderBuffer] += countBindingsIn(le->getCollection()); + break; + case ERamsesObjectType::RenderGroup: + counts[ERamsesObjectType::RenderGroup] += countBindingsIn(le->getCollection()); + break; + case ERamsesObjectType::RenderPass: + counts[ERamsesObjectType::RenderPass] += countBindingsIn(le->getCollection()); + break; + default: + break; + } + } + + for (const auto& count : counts) + { + if (count.second > 1) + return false; + } + return true; + } + void SceneImpl::onValidate(ValidationReportImpl& report) const { + std::vector lengines; + SceneObjectRegistryIterator lengineIter(getObjectRegistry(), ERamsesObjectType::LogicEngine); + while (const auto* obj = lengineIter.getNext()) + lengines.push_back(obj->as()); + for (size_t i = 0u; i < RamsesObjectTypeCount; ++i) { const auto type = static_cast(i); @@ -341,6 +422,8 @@ namespace ramses::internal while (const auto* obj = iter.getNext()) { obj->impl().validate(report); + if (!ValidateLogicBindingReferencesTo(obj, lengines)) + report.add(EIssueType::Error, "Multiple logic bindings reference this object, this will lead to one overwriting values from the other", obj); } } } @@ -607,12 +690,12 @@ namespace ramses::internal { if (isPublished()) { - getErrorReporting().set((ramses::internal::StringOutputStream() << "Scene(" << m_scene.getSceneId() << ")::publish: ignored, scene is already published").c_str(), *this); + getErrorReporting().set(fmt::format("Scene({})::publish: ignored, scene is already published", m_scene.getSceneId()), *this); return false; } if (requestedPublicationMode == EScenePublicationMode::LocalAndRemote && m_futurePublicationMode == EScenePublicationMode::LocalOnly) { - getErrorReporting().set((ramses::internal::StringOutputStream() << "Scene(" << m_scene.getSceneId() << ")::publish: Enabled local only optimisations from SceneConfig, cannot remote publish later").c_str(), *this); + getErrorReporting().set(fmt::format("Scene({})::publish: Enabled local only optimisations from SceneConfig, cannot remote publish later", m_scene.getSceneId()), *this); return false; } if (requestedPublicationMode != EScenePublicationMode::LocalOnly && !getClientImpl().getFramework().isConnected()) @@ -627,7 +710,7 @@ namespace ramses::internal { if (!isPublished()) { - getErrorReporting().set((ramses::internal::StringOutputStream() << "Scene(" << m_scene.getSceneId() << ")::unpublish ignored, scene is not published.").c_str(), *this); + getErrorReporting().set(fmt::format("Scene({})::unpublish ignored, scene is not published.", m_scene.getSceneId()), *this); return false; } @@ -1758,7 +1841,8 @@ namespace ramses::internal Effect* SceneImpl::createEffect(const EffectDescription& effectDesc, std::string_view name) { - ramses::internal::ManagedResource res = getClientImpl().createManagedEffect(effectDesc, name, m_effectErrorMessages); + const auto compatibility = getIScene().getRenderBackendCompatibility(); + ramses::internal::ManagedResource res = getClientImpl().createManagedEffect(effectDesc, compatibility, name, m_effectErrorMessages); if (!res) { LOG_ERROR(CONTEXT_CLIENT, "Scene::createEffect: failed to create managed effect resource: {}", m_effectErrorMessages); @@ -1817,8 +1901,8 @@ namespace ramses::internal bool SceneImpl::writeSceneObjectsToStream(ramses::internal::IOutputStream& outputStream, const SaveFileConfigImpl& saveConfig) const { - ramses::internal::ScenePersistation::WriteSceneMetadataToStream(outputStream, getIScene()); - ramses::internal::ScenePersistation::WriteSceneToStream(outputStream, getIScene()); + ramses::internal::ScenePersistation::WriteSceneMetadataToStream(outputStream, getIScene(), m_hlClient.impl().getFramework().getFeatureLevel()); + ramses::internal::ScenePersistation::WriteSceneToStream(outputStream, getIScene(), m_hlClient.impl().getFramework().getFeatureLevel()); SerializationContext serializationContext{saveConfig}; return serialize(outputStream, serializationContext); @@ -1914,24 +1998,29 @@ namespace ramses::internal return true; } - void SceneImpl::setSceneFileHandle(ramses::internal::SceneFileHandle handle) + void SceneImpl::addSceneFileHandle(ramses::internal::SceneFileHandle handle) { - m_sceneFileHandle = handle; + assert(handle.isValid()); + if (std::find(m_sceneFileHandles.begin(), m_sceneFileHandles.end(), handle) == m_sceneFileHandles.end()) + { + m_sceneFileHandles.push_back(handle); + } } - void SceneImpl::closeSceneFile() + void SceneImpl::closeSceneFiles() { - if (!m_sceneFileHandle.isValid()) - return; - - getClientImpl().getClientApplication().removeResourceFile(m_sceneFileHandle); - LOG_INFO(CONTEXT_CLIENT, "SceneImpl::closeSceneFile closed: {}", m_sceneFileHandle); - m_sceneFileHandle = ramses::internal::SceneFileHandle::Invalid(); + for (const auto& sceneFileHandle: m_sceneFileHandles) + { + assert(sceneFileHandle.isValid()); + getClientImpl().getClientApplication().removeResourceFile(sceneFileHandle); + LOG_INFO(CONTEXT_CLIENT, "SceneImpl::closeSceneFiles closed: {}", sceneFileHandle); + } + m_sceneFileHandles.clear(); } - ramses::internal::SceneFileHandle SceneImpl::getSceneFileHandle() const + const std::vector& SceneImpl::getSceneFileHandles() const { - return m_sceneFileHandle; + return m_sceneFileHandles; } bool SceneImpl::removeResourceWithIdFromResources(resourceId_t const& id, Resource& resource) diff --git a/src/client/impl/SceneImpl.h b/src/client/impl/SceneImpl.h index a978b5ca4..cb746a894 100644 --- a/src/client/impl/SceneImpl.h +++ b/src/client/impl/SceneImpl.h @@ -39,6 +39,7 @@ #include "impl/RamsesFrameworkTypesImpl.h" #include +#include #include #include @@ -252,9 +253,9 @@ namespace ramses::internal template bool createAndDeserializeObjectImpls(ramses::internal::IInputStream& inStream, DeserializationContext& serializationContext, uint32_t count); - void setSceneFileHandle(ramses::internal::SceneFileHandle handle); - void closeSceneFile(); - ramses::internal::SceneFileHandle getSceneFileHandle() const; + void addSceneFileHandle(ramses::internal::SceneFileHandle handle); + void closeSceneFiles(); + const std::vector& getSceneFileHandles() const; void updateResourceId(resourceId_t const& oldId, Resource& resourceWithNewId); @@ -313,6 +314,9 @@ namespace ramses::internal bool removeResourceWithIdFromResources(resourceId_t const& id, Resource& resource); + // Validate logic bindings only. Return true for objects that are not logic bindings + static bool ValidateLogicBindingReferencesTo(const SceneObject* obj, const std::vector& lengines); + ramses::internal::ClientScene& m_scene; ramses::internal::SceneCommandBuffer m_commandBuffer; sceneVersionTag_t m_nextSceneVersion; @@ -334,7 +338,7 @@ namespace ramses::internal std::string m_effectErrorMessages; - ramses::internal::SceneFileHandle m_sceneFileHandle; + std::vector m_sceneFileHandles; bool m_sendEffectTimeSync = false; }; diff --git a/src/client/impl/SceneObjectImpl.cpp b/src/client/impl/SceneObjectImpl.cpp index 9685429ad..0c05bf2e4 100644 --- a/src/client/impl/SceneObjectImpl.cpp +++ b/src/client/impl/SceneObjectImpl.cpp @@ -67,13 +67,27 @@ namespace ramses::internal bool SceneObjectImpl::deserialize(ramses::internal::IInputStream& inStream, DeserializationContext& serializationContext) { if (!RamsesObjectImpl::deserialize(inStream, serializationContext)) - return true; + return false; sceneObjectId_t id; inStream >> id.getReference(); - if (id.isValid()) + if (!id.isValid()) + { + LOG_ERROR(CONTEXT_CLIENT, "Fatal: deserialized invalid scene object ID."); + return false; + } + + auto* mapping = serializationContext.getSceneMergeHandleMapping(); + if (mapping) + { + mapping->addMapping(id, m_sceneObjectId); + // we keep the generated id + } + else + { m_sceneObjectId = std::move(id); + } return true; } diff --git a/src/client/impl/SceneReferenceImpl.cpp b/src/client/impl/SceneReferenceImpl.cpp index eaf21623e..1de6dda25 100644 --- a/src/client/impl/SceneReferenceImpl.cpp +++ b/src/client/impl/SceneReferenceImpl.cpp @@ -14,6 +14,7 @@ #include "impl/SceneObjectImpl.h" #include "impl/SceneImpl.h" #include "impl/ErrorReporting.h" +#include "impl/SerializationContext.h" namespace ramses::internal { @@ -47,7 +48,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_sceneReferenceHandle; + serializationContext.deserializeAndMap(inStream, m_sceneReferenceHandle); return true; } diff --git a/src/client/impl/Texture2DBufferImpl.cpp b/src/client/impl/Texture2DBufferImpl.cpp index 5c6f1b7e6..bdb43692d 100644 --- a/src/client/impl/Texture2DBufferImpl.cpp +++ b/src/client/impl/Texture2DBufferImpl.cpp @@ -55,7 +55,7 @@ namespace ramses::internal if (!SceneObjectImpl::deserialize(inStream, serializationContext)) return false; - inStream >> m_textureBufferHandle; + serializationContext.deserializeAndMap(inStream, m_textureBufferHandle); return true; } diff --git a/src/client/impl/TextureSamplerImpl.cpp b/src/client/impl/TextureSamplerImpl.cpp index 3bc911ff2..5b80792f3 100644 --- a/src/client/impl/TextureSamplerImpl.cpp +++ b/src/client/impl/TextureSamplerImpl.cpp @@ -24,6 +24,7 @@ #include "impl/TextureUtils.h" #include "impl/SceneObjectRegistryIterator.h" #include "impl/ErrorReporting.h" +#include "impl/SerializationContext.h" #include "internal/SceneGraph/Scene/ClientScene.h" #include "internal/DataSlotUtils.h" @@ -230,7 +231,7 @@ namespace ramses::internal inStream >> value; m_textureType = static_cast(value); - inStream >> m_textureSamplerHandle; + serializationContext.deserializeAndMap(inStream, m_textureSamplerHandle); return true; } diff --git a/src/client/impl/UniformInput.cpp b/src/client/impl/UniformInput.cpp index 7d0ea96a0..18735b865 100644 --- a/src/client/impl/UniformInput.cpp +++ b/src/client/impl/UniformInput.cpp @@ -35,4 +35,13 @@ namespace ramses { return m_impl->getElementCount(); } + + std::optional UniformInput::getUniformBufferBinding() const + { + const auto uboBinding = m_impl->getUniformBufferBinding(); + if (uboBinding.isValid()) + return uboBinding.getValue(); + + return std::nullopt; + } } diff --git a/src/client/impl/logic/AppearanceBindingImpl.cpp b/src/client/impl/logic/AppearanceBindingImpl.cpp index 5155ca3b3..cb28bec65 100644 --- a/src/client/impl/logic/AppearanceBindingImpl.cpp +++ b/src/client/impl/logic/AppearanceBindingImpl.cpp @@ -27,7 +27,7 @@ namespace ramses::internal { AppearanceBindingImpl::AppearanceBindingImpl(SceneImpl& scene, ramses::Appearance& ramsesAppearance, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, ramsesAppearance } , m_ramsesAppearance(ramsesAppearance) { const auto& effect = m_ramsesAppearance.get().getEffect(); diff --git a/src/client/impl/logic/CameraBindingImpl.cpp b/src/client/impl/logic/CameraBindingImpl.cpp index f399e2e81..1924412b3 100644 --- a/src/client/impl/logic/CameraBindingImpl.cpp +++ b/src/client/impl/logic/CameraBindingImpl.cpp @@ -27,7 +27,7 @@ namespace ramses::internal { CameraBindingImpl::CameraBindingImpl(SceneImpl& scene, ramses::Camera& ramsesCamera, bool withFrustumPlanes, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, ramsesCamera } , m_ramsesCamera(ramsesCamera) , m_hasFrustumPlanesProperties{ ramsesCamera.isOfType(ramses::ERamsesObjectType::OrthographicCamera) || withFrustumPlanes } { diff --git a/src/client/impl/logic/LogicEngineImpl.cpp b/src/client/impl/logic/LogicEngineImpl.cpp index 8609fa916..d65091726 100644 --- a/src/client/impl/logic/LogicEngineImpl.cpp +++ b/src/client/impl/logic/LogicEngineImpl.cpp @@ -436,7 +436,11 @@ namespace ramses::internal // force dirty all timer nodes, anchor points and skinbindings setNodeToBeAlwaysUpdatedDirty(); - const bool success = updateNodes(*sortedNodes); + bool success = updateNodes(*sortedNodes); + + // update skin bindings only if updating the other nodes succeeded + if (success) + success = updateSkinBindings(); if (m_statisticsEnabled || m_updateReportEnabled) { @@ -455,7 +459,8 @@ namespace ramses::internal { LogicNodeImpl& node = *nodeIter; - if (!node.isDirty()) + // skip also processing of SkinBindings, since they will be processed after updating everything else + if (!node.isDirty() || dynamic_cast(&node)) { if (m_updateReportEnabled) m_updateReport.nodeSkippedExecution(node); @@ -464,33 +469,50 @@ namespace ramses::internal continue; } - if (m_updateReportEnabled) - m_updateReport.nodeExecutionStarted(node); - if (m_statisticsEnabled) - m_statistics.nodeExecuted(); + if (!updateNode(node)) + return false; + } - const std::optional potentialError = node.update(); - if (potentialError) - { - getErrorReporting().set(potentialError->message, &node.getLogicObject()); + return true; + } + + bool LogicEngineImpl::updateSkinBindings() + { + for (SkinBinding* skinBinding : m_apiObjects->getApiObjectContainer()) { + if (!updateNode(skinBinding->impl())) { return false; } + } + return true; + } - Property* outputs = node.getOutputs(); - if (outputs != nullptr) - { - const size_t activatedLinks = activateLinksRecursive(outputs->impl()); + bool LogicEngineImpl::updateNode(LogicNodeImpl& node) + { + if (m_updateReportEnabled) + m_updateReport.nodeExecutionStarted(node); + if (m_statisticsEnabled) + m_statistics.nodeExecuted(); - if (m_statisticsEnabled || m_updateReportEnabled) - m_updateReport.linksActivated(activatedLinks); - } + const std::optional potentialError = node.update(); + if (potentialError) + { + getErrorReporting().set(potentialError->message, &node.getLogicObject()); + return false; + } - if (m_updateReportEnabled) - m_updateReport.nodeExecutionFinished(); + Property* outputs = node.getOutputs(); + if (outputs != nullptr) + { + const size_t activatedLinks = activateLinksRecursive(outputs->impl()); - node.setDirty(false); + if (m_statisticsEnabled || m_updateReportEnabled) + m_updateReport.linksActivated(activatedLinks); } + if (m_updateReportEnabled) + m_updateReport.nodeExecutionFinished(); + node.setDirty(false); + return true; } @@ -502,9 +524,6 @@ namespace ramses::internal // force anchor points dirty because they depend on set of ramses states which cannot be monitored for (AnchorPoint* anchorPoint : m_apiObjects->getApiObjectContainer()) anchorPoint->impl().setDirty(true); - // force skinbindings dirty because they depend on set of ramses states which cannot be monitored - for (SkinBinding* skinBinding : m_apiObjects->getApiObjectContainer()) - skinBinding->impl().setDirty(true); } void LogicEngineImpl::onValidate(ValidationReportImpl& report) const @@ -516,7 +535,7 @@ namespace ramses::internal m_apiObjects->validateDanglingNodes(report); } - bool LogicEngineImpl::loadFromByteData(const void* byteData, size_t byteSize, bool enableMemoryVerification, const std::string& dataSourceDescription) + bool LogicEngineImpl::loadFromByteData(const void* byteData, size_t byteSize, bool enableMemoryVerification, const std::string& dataSourceDescription, const SceneMergeHandleMapping* mapping) { if (byteSize < 8) { @@ -553,7 +572,7 @@ namespace ramses::internal return false; } - RamsesObjectResolver ramsesResolver{ getErrorReporting(), getSceneImpl() }; + RamsesObjectResolver ramsesResolver{ getErrorReporting(), getSceneImpl(), mapping }; std::unique_ptr deserializedObjects = ApiObjects::Deserialize(getSceneImpl(), *logicEngine->apiObjects(), ramsesResolver, dataSourceDescription, getErrorReporting(), m_featureLevel); if (!deserializedObjects) @@ -701,7 +720,7 @@ namespace ramses::internal bool LogicEngineImpl::resolveDeserializationDependencies(DeserializationContext& serializationContext) { const bool enableMemoryVerification = serializationContext.getLoadConfig().getMemoryVerificationEnabled(); - if (!loadFromByteData(m_byteBuffer.data(), m_byteBuffer.size(), enableMemoryVerification, fmt::format("data buffer '{}' (size: {})", m_byteBuffer.data(), m_byteBuffer.size()))) + if (!loadFromByteData(m_byteBuffer.data(), m_byteBuffer.size(), enableMemoryVerification, fmt::format("data buffer '{}' (size: {})", m_byteBuffer.data(), m_byteBuffer.size()), serializationContext.getSceneMergeHandleMapping())) return false; std::vector().swap(m_byteBuffer); diff --git a/src/client/impl/logic/LogicEngineImpl.h b/src/client/impl/logic/LogicEngineImpl.h index 3c59859a6..9fd1180df 100644 --- a/src/client/impl/logic/LogicEngineImpl.h +++ b/src/client/impl/logic/LogicEngineImpl.h @@ -9,6 +9,7 @@ #pragma once #include "impl/SceneObjectImpl.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" #include "ramses/client/logic/AnimationTypes.h" #include "ramses/client/logic/LogicEngine.h" #include "ramses/client/logic/LogicEngineReport.h" @@ -70,6 +71,7 @@ namespace ramses::internal class RamsesBindingImpl; class ValidationReportImpl; class ApiObjects; + class SceneMergeHandleMapping; class LogicEngineImpl : public SceneObjectImpl { @@ -141,7 +143,10 @@ namespace ramses::internal [[nodiscard]] bool updateNodes(const NodeVector& nodes); - [[nodiscard]] bool loadFromByteData(const void* byteData, size_t byteSize, bool enableMemoryVerification, const std::string& dataSourceDescription); + [[nodiscard]] bool updateSkinBindings(); + [[nodiscard]] bool updateNode(LogicNodeImpl& node); + + [[nodiscard]] bool loadFromByteData(const void* byteData, size_t byteSize, bool enableMemoryVerification, const std::string& dataSourceDescription, const SceneMergeHandleMapping* mapping); EFeatureLevel m_featureLevel; diff --git a/src/client/impl/logic/MeshNodeBindingImpl.cpp b/src/client/impl/logic/MeshNodeBindingImpl.cpp index d35c1201f..2e552914e 100644 --- a/src/client/impl/logic/MeshNodeBindingImpl.cpp +++ b/src/client/impl/logic/MeshNodeBindingImpl.cpp @@ -19,7 +19,7 @@ namespace ramses::internal { MeshNodeBindingImpl::MeshNodeBindingImpl(SceneImpl& scene, ramses::MeshNode& ramsesMeshNode, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, ramsesMeshNode } , m_ramsesMeshNode{ ramsesMeshNode } { } diff --git a/src/client/impl/logic/NodeBindingImpl.cpp b/src/client/impl/logic/NodeBindingImpl.cpp index 4edc146a2..c5751ce4c 100644 --- a/src/client/impl/logic/NodeBindingImpl.cpp +++ b/src/client/impl/logic/NodeBindingImpl.cpp @@ -24,7 +24,7 @@ namespace ramses::internal { NodeBindingImpl::NodeBindingImpl(SceneImpl& scene, ramses::Node& ramsesNode, ramses::ERotationType rotationType, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, ramsesNode } , m_ramsesNode{ ramsesNode } , m_rotationType{ rotationType } { diff --git a/src/client/impl/logic/RamsesBindingImpl.cpp b/src/client/impl/logic/RamsesBindingImpl.cpp index 5eb3ad622..e81816ef2 100644 --- a/src/client/impl/logic/RamsesBindingImpl.cpp +++ b/src/client/impl/logic/RamsesBindingImpl.cpp @@ -15,8 +15,9 @@ namespace ramses::internal { - RamsesBindingImpl::RamsesBindingImpl(SceneImpl& scene, std::string_view name, sceneObjectId_t id) noexcept + RamsesBindingImpl::RamsesBindingImpl(SceneImpl& scene, std::string_view name, sceneObjectId_t id, SceneObject& boundObject) noexcept : LogicNodeImpl{ scene, name, id } + , m_boundObject{ boundObject } { // Bindings are not supposed to do anything unless user set an actual value to them // Thus, they are not dirty by default! @@ -37,6 +38,11 @@ namespace ramses::internal return ramsesRef; } + const SceneObject& RamsesBindingImpl::getBoundObject() const + { + return m_boundObject; + } + void RamsesBindingImpl::setRootInputs(std::unique_ptr rootInputs) { setRootProperties(std::move(rootInputs), {}); diff --git a/src/client/impl/logic/RamsesBindingImpl.h b/src/client/impl/logic/RamsesBindingImpl.h index c8f4fa5f1..bb07d49b3 100644 --- a/src/client/impl/logic/RamsesBindingImpl.h +++ b/src/client/impl/logic/RamsesBindingImpl.h @@ -32,7 +32,9 @@ namespace ramses::internal class RamsesBindingImpl : public LogicNodeImpl { public: - explicit RamsesBindingImpl(SceneImpl& scene, std::string_view name, sceneObjectId_t id) noexcept; + explicit RamsesBindingImpl(SceneImpl& scene, std::string_view name, sceneObjectId_t id, SceneObject& boundObject) noexcept; + + [[nodiscard]] const SceneObject& getBoundObject() const; protected: // Used by subclasses to handle serialization @@ -40,6 +42,8 @@ namespace ramses::internal void setRootInputs(std::unique_ptr rootInputs); + std::reference_wrapper m_boundObject; + private: using LogicNodeImpl::setRootProperties; }; diff --git a/src/client/impl/logic/RenderBufferBindingImpl.cpp b/src/client/impl/logic/RenderBufferBindingImpl.cpp index 3277313e4..3e2332c3a 100644 --- a/src/client/impl/logic/RenderBufferBindingImpl.cpp +++ b/src/client/impl/logic/RenderBufferBindingImpl.cpp @@ -20,7 +20,7 @@ namespace ramses::internal { RenderBufferBindingImpl::RenderBufferBindingImpl(SceneImpl& scene, ramses::RenderBuffer& renderBuffer, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, renderBuffer } , m_renderBuffer{ renderBuffer } { } diff --git a/src/client/impl/logic/RenderGroupBindingImpl.cpp b/src/client/impl/logic/RenderGroupBindingImpl.cpp index 248d27d5e..df1933bf0 100644 --- a/src/client/impl/logic/RenderGroupBindingImpl.cpp +++ b/src/client/impl/logic/RenderGroupBindingImpl.cpp @@ -20,7 +20,7 @@ namespace ramses::internal { RenderGroupBindingImpl::RenderGroupBindingImpl(SceneImpl& scene, ramses::RenderGroup& ramsesRenderGroup, const RenderGroupBindingElementsImpl& elements, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, ramsesRenderGroup } , m_ramsesRenderGroup{ ramsesRenderGroup } , m_elements{ elements.getElements() } { diff --git a/src/client/impl/logic/RenderPassBindingImpl.cpp b/src/client/impl/logic/RenderPassBindingImpl.cpp index 9caafba34..7f4f1e5a8 100644 --- a/src/client/impl/logic/RenderPassBindingImpl.cpp +++ b/src/client/impl/logic/RenderPassBindingImpl.cpp @@ -22,7 +22,7 @@ namespace ramses::internal { RenderPassBindingImpl::RenderPassBindingImpl(SceneImpl& scene, ramses::RenderPass& ramsesRenderPass, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, ramsesRenderPass } , m_ramsesRenderPass{ ramsesRenderPass } { } diff --git a/src/client/impl/logic/SkinBindingImpl.cpp b/src/client/impl/logic/SkinBindingImpl.cpp index 848551bff..aa25f4dda 100644 --- a/src/client/impl/logic/SkinBindingImpl.cpp +++ b/src/client/impl/logic/SkinBindingImpl.cpp @@ -29,7 +29,7 @@ namespace ramses::internal const ramses::UniformInput& jointMatInput, std::string_view name, sceneObjectId_t id) - : RamsesBindingImpl{ scene, name, id } + : RamsesBindingImpl{ scene, name, id, appearanceBinding.getRamsesAppearance() } , m_joints{ std::move(joints) } , m_inverseBindMatrices(inverseBindMatrices) , m_appearanceBinding{ appearanceBinding } @@ -67,7 +67,7 @@ namespace ramses::internal inverseBindMatData.reserve(skinBinding.m_inverseBindMatrices.size() * 16u); for (const auto& mat : skinBinding.m_inverseBindMatrices) { - inverseBindMatData.insert(inverseBindMatData.begin(), begin(mat), end(mat)); + inverseBindMatData.insert(inverseBindMatData.end(), begin(mat), end(mat)); } const auto fbInverseBindMatData = builder.CreateVector(inverseBindMatData); diff --git a/src/client/internal/CMakeLists.txt b/src/client/internal/CMakeLists.txt index ec3098a26..39fecc4f5 100644 --- a/src/client/internal/CMakeLists.txt +++ b/src/client/internal/CMakeLists.txt @@ -7,20 +7,10 @@ # ------------------------------------------------------------------------- if(ramses-sdk_TEXT_SUPPORT) - list(APPEND CLIENT_INTERNAL_LIBS freetype + list(APPEND TEXT_INTERNAL_LIBS freetype harfbuzz) endif() -if(ramses-sdk_ENABLE_LOGIC) - list(APPEND CLIENT_INTERNAL_SOURCES logic/*.h - logic/*.cpp - logic/flatbuffers/generated/*.h - logic/flatbuffers/schemas/*.fbs) - list(APPEND CLIENT_INTERNAL_LIBS sol2::sol2 - lua::lua - ramses::flatbuffers - fmt::fmt) -endif() createModule( NAME ramses-client-internal @@ -34,11 +24,18 @@ createModule( glslEffectBlock/*.cpp ClientCommands/*.h ClientCommands/*.cpp - ${CLIENT_INTERNAL_SOURCES} + logic/*.h + logic/*.cpp + logic/flatbuffers/generated/*.h + logic/flatbuffers/schemas/*.fbs DEPENDENCIES ramses-api ramses-framework-internal ramses-glslang - ${CLIENT_INTERNAL_LIBS} + sol2::sol2 + lua::lua + ramses::flatbuffers + fmt::fmt + ${TEXT_INTERNAL_LIBS} ) if(TARGET FlatbufGen) diff --git a/src/client/internal/ClientCommands/LogMemoryUtils.cpp b/src/client/internal/ClientCommands/LogMemoryUtils.cpp index 96cba9e96..a7ca46d85 100644 --- a/src/client/internal/ClientCommands/LogMemoryUtils.cpp +++ b/src/client/internal/ClientCommands/LogMemoryUtils.cpp @@ -43,25 +43,20 @@ namespace ramses::internal if (nullptr != resourceObject) { - StringOutputStream stream; - stream << "Resource \"" << resource.getName() << "\"\t"; - stream << "type " << EnumToString(resourceObject->getTypeID()) << " "; - stream << "mem compressed " << resourceObject->getCompressedDataSize() << " "; - stream << "uncompressed " << resourceObject->getDecompressedDataSize() << " "; - MemoryInfo info; info.memoryUsage = resourceObject->getCompressedDataSize() + resourceObject->getDecompressedDataSize(); - info.logInfoMesage = stream.release(); + info.logInfoMesage = fmt::format("Resource \"{}\"\ttype {} mem compressed {} uncompressed {} ", + resource.getName(), + EnumToString(resourceObject->getTypeID()), + resourceObject->getCompressedDataSize(), + resourceObject->getDecompressedDataSize()); memoryInfos.push_back(info); } } auto createMemInfo = [](const auto& logMessage, uint32_t numElements, const std::function< size_t(uint32_t) >& sizeOfIndividualElement){ - StringOutputStream stream; - stream << numElements << " " << logMessage << " allocated"; - MemoryInfo info; - info.logInfoMesage = stream.release(); + info.logInfoMesage = fmt::format("{} {} allocated", numElements, logMessage); for(uint32_t i = 0; i < numElements; ++i) { diff --git a/src/client/internal/ClientCommands/SceneCommandBuffer.h b/src/client/internal/ClientCommands/SceneCommandBuffer.h index 7007b899f..485c0b0ed 100644 --- a/src/client/internal/ClientCommands/SceneCommandBuffer.h +++ b/src/client/internal/ClientCommands/SceneCommandBuffer.h @@ -9,6 +9,7 @@ #pragma once #include "ramses/framework/RamsesFrameworkTypes.h" +#include "ramses/framework/RamsesObjectTypes.h" #include "ramses/framework/Issue.h" #include "internal/PlatformAbstraction/VariantWrapper.h" @@ -22,6 +23,8 @@ namespace ramses::internal struct SceneCommandFlushSceneVersion { sceneVersionTag_t sceneVersion = 0u; + // work around unsolved gcc bug https://bugzilla.redhat.com/show_bug.cgi?id=1507359 + uint32_t _dummyValue = 0u; }; struct SceneCommandValidationRequest @@ -30,6 +33,14 @@ namespace ramses::internal std::string optionalObjectName; }; + struct SceneCommandSetProperty + { + sceneObjectId_t id; + ERamsesObjectType type = ERamsesObjectType::Invalid; + std::string prop; + std::string value; + }; + struct SceneCommandDumpSceneToFile { std::string fileName; @@ -39,7 +50,8 @@ namespace ramses::internal struct SceneCommandLogResourceMemoryUsage { // work around unsolved gcc bug https://bugzilla.redhat.com/show_bug.cgi?id=1507359 - bool _dummyValue = false; + uint64_t _dummyValue = 0u; + uint32_t _dummyValue2 = 0u; }; @@ -55,6 +67,7 @@ namespace ramses::internal private: using CommandVariant = std::variant; diff --git a/src/client/internal/ClientCommands/SceneCommandVisitor.cpp b/src/client/internal/ClientCommands/SceneCommandVisitor.cpp index fb05088eb..b6aa77e50 100644 --- a/src/client/internal/ClientCommands/SceneCommandVisitor.cpp +++ b/src/client/internal/ClientCommands/SceneCommandVisitor.cpp @@ -12,13 +12,155 @@ #include "impl/SceneImpl.h" #include "impl/RamsesClientImpl.h" #include "impl/SaveFileConfigImpl.h" +#include "impl/SceneObjectRegistryIterator.h" #include "LogMemoryUtils.h" +#include "ramses/client/Node.h" +#include "ramses/client/Effect.h" +#include "ramses/client/UniformInput.h" +#include "ramses/client/SceneObject.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Core/Utils/File.h" +#include "SetProperty.h" #include namespace ramses::internal { + void setProperty(ramses::SceneObject* obj, const std::string& prop, const std::string& value) + { + const auto id = obj->getSceneObjectId(); + switch (SetProperty::GetPropertyType(obj->getType(), prop)) + { + case SetProperty::Type::Visible: + { + assert(obj->isOfType(ramses::ERamsesObjectType::Node)); + auto nodeObj = static_cast(obj); + if (value == "0" || value == "off") + { + nodeObj->setVisibility(ramses::EVisibilityMode::Off); + } + else if (value == "1" || value.find("inv") == 0) + { + nodeObj->setVisibility(ramses::EVisibilityMode::Invisible); + } + else if (value == "2" || value.find("vis") == 0) + { + nodeObj->setVisibility(ramses::EVisibilityMode::Visible); + } + else + { + LOG_ERROR(CONTEXT_CLIENT, "Invalid value for <{}>::{}. Must be (off,inv,vis) or (0,1,2).", id.getValue(), prop); + return; + } + break; + } + case SetProperty::Type::DepthFunc: { + assert(obj->isOfType(ERamsesObjectType::Appearance)); + auto appObj = static_cast(obj); + if (value == "disabled") + { + appObj->setDepthFunction(EDepthFunc::Disabled); + } + else if (value == "always") + { + appObj->setDepthFunction(EDepthFunc::Always); + } + else if (value == "less") + { + appObj->setDepthFunction(EDepthFunc::Less); + } + else if (value == "lessEqual") + { + appObj->setDepthFunction(EDepthFunc::LessEqual); + } + else + { + LOG_ERROR(CONTEXT_CLIENT, "Invalid value for <{}>::{}. Must be (disabled,always,less,lessEqual).", id.getValue(), prop); + return; + } + break; + } + case SetProperty::Type::DepthWrite: + { + assert(obj->isOfType(ERamsesObjectType::Appearance)); + auto appObj = static_cast(obj); + if (value == "off" || value == "0") + { + appObj->setDepthWrite(EDepthWrite::Disabled); + } + else if (value == "on" || value == "1") + { + appObj->setDepthWrite(EDepthWrite::Enabled); + } + else + { + LOG_ERROR(CONTEXT_CLIENT, "Invalid value for <{}>::{}. Must be (off,on) or (0,1).", id.getValue(), prop); + return; + } + break; + } + case SetProperty::Type::Uniform: + { + assert(obj->isOfType(ERamsesObjectType::Appearance)); + auto appObj = static_cast(obj); + const auto name = prop.substr(8); + auto& effect = appObj->getEffect(); + + auto uniform = effect.findUniformInput(name); + if (!uniform.has_value()) + { + LOG_ERROR(CONTEXT_CLIENT, "Unknown uniform '{}' for <{}>", name, id.getValue()); + return; + } + if (uniform->getDataType() != ramses::EDataType::Float || uniform->getElementCount() != 1) + { + LOG_ERROR(CONTEXT_CLIENT, "only float[1] uniforms supported currently"); + return; + } + float uniformValue = 0.f; + if (!ArgumentConverter::tryConvert(value, uniformValue)) + { + LOG_ERROR(CONTEXT_CLIENT, "conversion to float failed: {}", value); + return; + } + appObj->setInputValue(*uniform, uniformValue); + break; + } + case SetProperty::Type::Invalid: + LOG_ERROR(CONTEXT_CLIENT, "Unsupported property:'{}' (obj <{}> is of type {}).", + prop, + id.getValue(), + RamsesObjectTypeUtils::GetRamsesObjectTypeName(obj->getType())); + break; + } + } + + void SceneCommandVisitor::operator()(const SceneCommandSetProperty& cmd) + { + LOG_INFO(CONTEXT_CLIENT, "SceneCommandVisitor::execute: set property on <{}>: {} -> {}", + cmd.id.getValue(), + cmd.prop, + cmd.value); + + if (cmd.id.isValid()) + { + auto* obj = m_scene.findObjectById(cmd.id); + if (!obj) + { + LOG_ERROR(CONTEXT_CLIENT, "Object not found: {}", cmd.id.getValue()); + return; + } + setProperty(obj, cmd.prop, cmd.value); + } + else + { + SceneObjectRegistryIterator iter(m_scene.getObjectRegistry(), cmd.type); + while (auto* obj = iter.getNextNonConst()) + { + setProperty(obj, cmd.prop, cmd.value); + } + } + } + void SceneCommandVisitor::operator()(const SceneCommandFlushSceneVersion& cmd) { diff --git a/src/client/internal/ClientCommands/SceneCommandVisitor.h b/src/client/internal/ClientCommands/SceneCommandVisitor.h index dfe7bfbf6..3e7c9c644 100644 --- a/src/client/internal/ClientCommands/SceneCommandVisitor.h +++ b/src/client/internal/ClientCommands/SceneCommandVisitor.h @@ -15,6 +15,7 @@ namespace ramses::internal { class SceneImpl; + struct SceneCommandSetProperty; struct SceneCommandFlushSceneVersion; struct SceneCommandValidationRequest; struct SceneCommandDumpSceneToFile; @@ -27,6 +28,7 @@ namespace ramses::internal : m_scene(scene) {} + void operator()(const SceneCommandSetProperty& cmd); void operator()(const SceneCommandFlushSceneVersion& cmd); void operator()(const SceneCommandValidationRequest& cmd); void operator()(const SceneCommandDumpSceneToFile& cmd) const; diff --git a/src/client/internal/ClientCommands/SetProperty.cpp b/src/client/internal/ClientCommands/SetProperty.cpp new file mode 100644 index 000000000..6320ea62c --- /dev/null +++ b/src/client/internal/ClientCommands/SetProperty.cpp @@ -0,0 +1,182 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW Car IT GmbH +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "SetProperty.h" +#include "ramses/client/Scene.h" +#include "impl/SceneImpl.h" +#include "impl/RamsesClientImpl.h" +#include "impl/RamsesObjectTypeUtils.h" +#include "internal/Core/Utils/LogMacros.h" +#include + +namespace ramses::internal +{ + namespace + { + std::array SetPropertyTypeNames = {"visible", "uniform.*", "depth.write", "depth.func"}; + + struct SupportedObjectType + { + std::string typeName; + ERamsesObjectType type; + std::vector properties; + }; + + const std::vector& GetSupportedProperties() + { + static std::vector properties = { + {"node", ERamsesObjectType::Node, {SetProperty::Type::Visible}}, + {"meshnode", ERamsesObjectType::MeshNode, {SetProperty::Type::Visible}}, + {"appearance", ERamsesObjectType::Appearance, {SetProperty::Type::Uniform, SetProperty::Type::DepthWrite, SetProperty::Type::DepthFunc}}, + }; + return properties; + } + + std::vector GetObjectTypeNames() + { + auto& supportedProperties = GetSupportedProperties(); + std::vector result; + result.reserve(supportedProperties.size()); + for (const auto& t : supportedProperties) + result.push_back(t.typeName); + return result; + } + + ERamsesObjectType FindObjectType(const char* name) + { + ERamsesObjectType found = ERamsesObjectType::Invalid; + auto& supportedProperties = GetSupportedProperties(); + for (auto& t : supportedProperties) + { + if (t.typeName.find(name) == 0) + { + if (found != ERamsesObjectType::Invalid) + return ERamsesObjectType::Invalid; // ambiguous result + found = t.type; + } + } + return found; + } + + SetProperty::Type FindProperty(const SupportedObjectType& t, const std::string& name) + { + SetProperty::Type found = SetProperty::Type::Invalid; + for (auto& p : t.properties) + { + std::string fullName = SetPropertyTypeNames[static_cast(p)]; + bool wildcardMatch = (fullName.back() == '*' && name.find(fullName.substr(0, fullName.size() - 1)) == 0); + if (fullName.find(name) == 0 || wildcardMatch) + { + if (found != SetProperty::Type::Invalid) + return SetProperty::Type::Invalid; // ambigous result + found = p; + } + } + return found; + } + } +} + +namespace ramses::internal +{ + SetProperty::SetProperty(RamsesClientImpl& client) + : m_client(client) + { + description = fmt::format("Usage: sceneId sceneObjId {} value - modifies a scene object", fmt::join(SetPropertyTypeNames, "|")); + registerKeyword("setprop"); + } + + bool SetProperty::executeInput(const std::vector& input) + { + if (input.size() != 5) + { + LOG_ERROR(CONTEXT_RAMSH, "{}", description); + return false; + } + ramses::sceneId_t sceneId; + ArgumentConverter::tryConvert(input[1], sceneId.getReference()); + if (!sceneId.isValid()) + { + LOG_ERROR(CONTEXT_RAMSH, "Invalid SceneId: {}", input[1]); + return false; + } + ramses::sceneObjectId_t objectId; + ArgumentConverter::tryConvert(input[2], objectId.getReference()); + if (!objectId.isValid()) + { + LOG_ERROR(CONTEXT_RAMSH, "Invalid SceneObjectId: {}", input[2]); + return false; + } + + SceneCommandSetProperty command; + command.prop = input[3]; + command.value = input[4]; + command.id = ramses::sceneObjectId_t(objectId); + m_client.enqueueSceneCommand(ramses::sceneId_t(sceneId), std::move(command)); + return true; + } + + SetProperty::Type SetProperty::GetPropertyType(ramses::ERamsesObjectType objType, const std::string& name) + { + SetProperty::Type found = SetProperty::Type::Invalid; + auto& supportedProperties = GetSupportedProperties(); + for (auto& t : supportedProperties) + { + if (RamsesObjectTypeUtils::IsTypeMatchingBaseType(objType, t.type)) + { + found = FindProperty(t, name); + if (found != SetProperty::Type::Invalid) + return found; // continue if not found: there may be a more specialized type + } + } + return found; + } +} + +namespace ramses::internal +{ + SetPropertyAll::SetPropertyAll(RamsesClientImpl& client) + : m_client(client) + { + registerKeyword("setall"); + description = fmt::format("Usage: sceneId objType {} value - modifies all scene objects of given type", fmt::join(SetPropertyTypeNames, "|")); + } + + bool SetPropertyAll::executeInput(const std::vector& input) + { + if (input.size() != 5) + { + LOG_ERROR(CONTEXT_RAMSH, "{}", description); + return false; + } + ramses::sceneId_t sceneId; + ArgumentConverter::tryConvert(input[1], sceneId.getReference()); + if (!sceneId.isValid()) + { + LOG_ERROR(CONTEXT_RAMSH, "Invalid SceneId: {}", input[1]); + return false; + } + SceneCommandSetProperty command; + auto type = input[2]; + command.prop = input[3]; + command.value = input[4]; + command.type = FindObjectType(type.c_str()); + if (command.type == ERamsesObjectType::Invalid) + { + LOG_ERROR(CONTEXT_RAMSH, "Invalid typename:{}. Must be one of ({})", type, fmt::join(GetObjectTypeNames(), "|")); + return false; + } + if (SetProperty::GetPropertyType(command.type, command.prop) == SetProperty::Type::Invalid) + { + LOG_ERROR(CONTEXT_RAMSH, "Unsupported property '{}' for type {}", command.prop, type); + return false; + } + m_client.enqueueSceneCommand(sceneId, std::move(command)); + return true; + } +} diff --git a/src/client/internal/ClientCommands/SetProperty.h b/src/client/internal/ClientCommands/SetProperty.h new file mode 100644 index 000000000..25d394dea --- /dev/null +++ b/src/client/internal/ClientCommands/SetProperty.h @@ -0,0 +1,48 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "ramses/framework/RamsesFrameworkTypes.h" +#include "ramses/framework/RamsesObjectTypes.h" +#include "internal/Ramsh/RamshCommand.h" + +namespace ramses::internal +{ + class RamsesClientImpl; + + class SetProperty : public RamshCommand + { + public: + enum class Type + { + Visible, + Uniform, + DepthWrite, + DepthFunc, + Invalid, + }; + + static Type GetPropertyType(ramses::ERamsesObjectType objType, const std::string& name); + + explicit SetProperty(RamsesClientImpl& client); + bool executeInput(const std::vector& input) override; + private: + RamsesClientImpl& m_client; + }; + + class SetPropertyAll : public RamshCommand + { + public: + explicit SetPropertyAll(RamsesClientImpl& client); + bool executeInput(const std::vector& input) override; + private: + RamsesClientImpl& m_client; + }; +} + diff --git a/src/client/internal/RamsesVersion.cpp b/src/client/internal/RamsesVersion.cpp index eef9d8758..8ec125893 100644 --- a/src/client/internal/RamsesVersion.cpp +++ b/src/client/internal/RamsesVersion.cpp @@ -9,7 +9,6 @@ #include "internal/RamsesVersion.h" #include "internal/PlatformAbstraction/Collections/IOutputStream.h" #include "internal/PlatformAbstraction/Collections/IInputStream.h" -#include "internal/PlatformAbstraction/Collections/StringOutputStream.h" #include "internal/PlatformAbstraction/PlatformStringUtils.h" #include "internal/Core/Utils/LogMacros.h" #include "ramses-sdk-build-config.h" @@ -24,8 +23,7 @@ namespace ramses::internal void WriteToStream(IOutputStream& stream, std::string_view versionString, std::string_view gitHash, EFeatureLevel featureLevel) { LOG_INFO(CONTEXT_CLIENT, "RamsesVersion::WriteToStream: Version: {} Git Hash: {} Feature Level: {}", versionString, gitHash, featureLevel); - StringOutputStream out; - out << "[RamsesVersion:" << versionString << "]\n[GitHash:" << gitHash << "]\n[FeatureLevel:" << featureLevel << "]\n"; + auto out = fmt::format("[RamsesVersion:{}]\n[GitHash:{}]\n[FeatureLevel:{}]\n", versionString, gitHash, featureLevel); stream.write(out.c_str(), out.size()); } @@ -172,13 +170,5 @@ namespace ramses::internal return true; } - - bool MatchesMajorMinor(uint32_t currentMajor, uint32_t currentMinor, const VersionInfo& in) - { - return (in.major == currentMajor && - in.minor == currentMinor) || - (currentMajor == 0 && - currentMinor == 0); - } } } diff --git a/src/client/internal/RamsesVersion.h b/src/client/internal/RamsesVersion.h index 4c1427570..d3622587c 100644 --- a/src/client/internal/RamsesVersion.h +++ b/src/client/internal/RamsesVersion.h @@ -31,6 +31,5 @@ namespace ramses::internal void WriteToStream(IOutputStream& stream, std::string_view versionString, std::string_view gitHash, EFeatureLevel featureLevel); bool ReadFromStream(IInputStream& stream, VersionInfo& outVersion, EFeatureLevel& outFeatureLevel); - bool MatchesMajorMinor(uint32_t currentMajor, uint32_t currentMinor, const VersionInfo& in); } } diff --git a/src/client/internal/glslEffectBlock/GLSlang.h b/src/client/internal/glslEffectBlock/GLSlang.h index 26ed7d60c..11a42a193 100644 --- a/src/client/internal/glslEffectBlock/GLSlang.h +++ b/src/client/internal/glslEffectBlock/GLSlang.h @@ -29,7 +29,6 @@ WARNING_DISABLE_GCC9(-Wdeprecated-copy) #include "Include/intermediate.h" #include "Include/InitializeGlobals.h" #include "MachineIndependent/localintermediate.h" -#include "OGLCompilersDLL/InitializeDll.h" WARNINGS_POP diff --git a/src/client/internal/glslEffectBlock/GlslEffect.cpp b/src/client/internal/glslEffectBlock/GlslEffect.cpp index 7b79f8b8d..45b80bb8b 100644 --- a/src/client/internal/glslEffectBlock/GlslEffect.cpp +++ b/src/client/internal/glslEffectBlock/GlslEffect.cpp @@ -16,55 +16,26 @@ namespace ramses::internal { - /* - wrapper for glslang process wide initializer and finalizer. - constructed once in this file. it is global and lives longer - than main. will not work if global static objects start using - effects but this should never happen. - */ - class GlslangInitAndFinalizeOnceHelper - { - public: - GlslangInitAndFinalizeOnceHelper() - { - glslang::InitializeProcess(); - glslang::InitProcess(); - } - - ~GlslangInitAndFinalizeOnceHelper() - { - glslang::DetachProcess(); - glslang::FinalizeProcess(); - } - }; - static GlslangInitAndFinalizeOnceHelper glslangInitializer; - - GlslEffect::GlslEffect(std::string_view vertexShader, std::string_view fragmentShader, std::string_view geometryShader, std::vector compilerDefines, - const HashMap& semanticInputs, + SemanticsMap semanticInputs, + ERenderBackendCompatibility compatibility, std::string_view name) : m_vertexShader(vertexShader) , m_fragmentShader(fragmentShader) , m_geometryShader(geometryShader) , m_compilerDefines(std::move(compilerDefines)) - , m_semanticInputs(semanticInputs) + , m_semanticInputs(std::move(semanticInputs)) + , m_renderBackendCompatibility(compatibility) , m_name(name) { } - GlslEffect::~GlslEffect() = default; - - EffectResource* GlslEffect::createEffectResource() + std::unique_ptr GlslEffect::createEffectResource(EFeatureLevel featureLevel) { - if (m_effectResource) - { - return m_effectResource; - } - - GlslParser parser{m_vertexShader, m_fragmentShader, m_geometryShader, m_compilerDefines}; + GlslParser parser{m_vertexShader, m_fragmentShader, m_geometryShader, m_compilerDefines, m_renderBackendCompatibility}; if (!parser.valid()) { m_errorMessages << parser.getErrors(); @@ -92,8 +63,25 @@ namespace ramses::internal const EffectInputInformationVector& attributeInputs = glslToEffectConverter.getAttributeInputs(); const auto geomInputType = glslToEffectConverter.getGeometryShaderInputType(); - m_effectResource = new EffectResource(parser.getVertexShader(), parser.getFragmentShader(), parser.getGeometryShader(), geomInputType, uniformInputs, attributeInputs, m_name); - return m_effectResource; + // forbid effect creation with UBOs below FL02 + if (featureLevel < EFeatureLevel_02) + { + if (std::any_of(uniformInputs.cbegin(), uniformInputs.cend(), [](const auto& uniform) { return uniform.uniformBufferBinding.isValid(); })) + { + m_errorMessages << "Uniform buffer objects are supported only with feature level 02 or higher"; + return nullptr; + } + } + + return std::make_unique(parser.getVertexShader(), + parser.getFragmentShader(), + parser.getGeometryShader(), + parser.getSPIRVShaders(), + geomInputType, + uniformInputs, + attributeInputs, + m_name, + featureLevel); } bool GlslEffect::extractAndCheckShaderVersions(const glslang::TProgram* program) @@ -166,7 +154,6 @@ namespace ramses::internal uint32_t GlslEffect::getShadingLanguageVersion() const { - assert(m_effectResource); return m_shadingLanguageVersion; } diff --git a/src/client/internal/glslEffectBlock/GlslEffect.h b/src/client/internal/glslEffectBlock/GlslEffect.h index de7be7b90..0a479d54d 100644 --- a/src/client/internal/glslEffectBlock/GlslEffect.h +++ b/src/client/internal/glslEffectBlock/GlslEffect.h @@ -13,6 +13,8 @@ #include "internal/SceneGraph/SceneAPI/EFixedSemantics.h" #include "internal/SceneGraph/Resource/EffectResource.h" +#include "ramses/framework/ERenderBackendCompatibility.h" + #include #include #include @@ -36,12 +38,11 @@ namespace ramses::internal std::string_view fragmentShader, std::string_view geometryShader, std::vector compilerDefines, - const HashMap& semanticInputs, + SemanticsMap semanticInputs, + ERenderBackendCompatibility compatibility, std::string_view name); - ~GlslEffect(); - - [[nodiscard]] EffectResource* createEffectResource(); + [[nodiscard]] std::unique_ptr createEffectResource(EFeatureLevel featureLevel); [[nodiscard]] uint32_t getShadingLanguageVersion() const; [[nodiscard]] std::string getEffectErrorMessages() const; @@ -51,11 +52,11 @@ namespace ramses::internal const std::string m_fragmentShader; const std::string m_geometryShader; const std::vector m_compilerDefines; - const HashMap m_semanticInputs; + const SemanticsMap m_semanticInputs; + const ERenderBackendCompatibility m_renderBackendCompatibility; const std::string m_name; - mutable StringOutputStream m_errorMessages; - EffectResource* m_effectResource{nullptr}; + StringOutputStream m_errorMessages; uint32_t m_shadingLanguageVersion{0}; bool extractAndCheckShaderVersions(const glslang::TProgram* program); diff --git a/src/client/internal/glslEffectBlock/GlslLimits.h b/src/client/internal/glslEffectBlock/GlslLimits.h index 89d5e762c..aba9d02e5 100644 --- a/src/client/internal/glslEffectBlock/GlslLimits.h +++ b/src/client/internal/glslEffectBlock/GlslLimits.h @@ -97,6 +97,7 @@ namespace ramses::internal glslCompilationResources.limits.generalSamplerIndexing = true; glslCompilationResources.limits.generalVariableIndexing = true; glslCompilationResources.limits.generalConstantMatrixVectorIndexing = true; + glslCompilationResources.maxDualSourceDrawBuffersEXT = 1; } static void SetLimitsOpenGL_2_0(TBuiltInResource& glslCompilationResources) diff --git a/src/client/internal/glslEffectBlock/GlslParser.cpp b/src/client/internal/glslEffectBlock/GlslParser.cpp index f1b14cbdf..3baabf94a 100644 --- a/src/client/internal/glslEffectBlock/GlslParser.cpp +++ b/src/client/internal/glslEffectBlock/GlslParser.cpp @@ -7,10 +7,12 @@ // ------------------------------------------------------------------------- #include "internal/glslEffectBlock/GlslParser.h" +#include "internal/SceneGraph/SceneAPI/EVulkanVersion.h" #include "GlslLimits.h" #include "fmt/format.h" #include "internal/PlatformAbstraction/FmtBase.h" #include "impl/EffectDescriptionImpl.h" +#include "SPIRV/GlslangToSpv.h" template <> struct fmt::formatter : public ramses::internal::SimpleFormatterBase { @@ -171,7 +173,7 @@ namespace namespace ramses::internal { - GlslParser::GlslParser(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader, const std::vector& compilerDefines) + GlslParser::GlslParser(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader, const std::vector& compilerDefines, ERenderBackendCompatibility compatibility) { m_vertexShader = std::make_unique(EShLangVertex); m_fragmentShader = std::make_unique(EShLangFragment); @@ -179,6 +181,7 @@ namespace ramses::internal { m_geometryShader = std::make_unique(EShLangGeometry); } + setShadersCompatibility(compatibility); const auto defineString = CreateDefineString(compilerDefines); const bool hasGeometryShader = (m_geometryShader != nullptr); @@ -215,6 +218,7 @@ namespace ramses::internal m_fragmentShaderFromParts = MergeShaderParts(fragmentShaderParts); m_geometryShaderFromParts = MergeShaderParts(geometryShaderParts); } + generateSPIRV(compatibility); } bool GlslParser::linkProgram() @@ -240,6 +244,17 @@ namespace ramses::internal return true; } + void GlslParser::generateSPIRV(ERenderBackendCompatibility compatibility) + { + if (compatibility == ERenderBackendCompatibility::VulkanAndOpenGL) + { + glslang::GlslangToSpv(*m_program->getIntermediate(EShLangVertex), m_spirvShaders.m_vertexSPIRVBlob); + glslang::GlslangToSpv(*m_program->getIntermediate(EShLangFragment), m_spirvShaders.m_fragmentSPIRVBlob); + if (m_geometryShader) + glslang::GlslangToSpv(*m_program->getIntermediate(EShLangGeometry), m_spirvShaders.m_geometrySPIRVBlob); + } + } + std::string GlslParser::getErrors() const { return m_errorMessages.c_str(); @@ -327,6 +342,29 @@ namespace ramses::internal return std::string(result.release()); } + void GlslParser::setShadersCompatibility(ERenderBackendCompatibility compatibility) + { + auto setShaderTargetVulkan = [](glslang::TShader& shader) + { + static_assert(TargetVulkanApiVersion == EVulkanAPIVersion::Version_1_0, "Update target Vulkan API version passed to glslang"); + static_assert(TargetSPIRVVersion == ESPIRVVersion::Version_1_0, "Update target SPIRV version passed to glslang"); + shader.setEnvTarget(glslang::EShTargetLanguage::EShTargetSpv, glslang::EShTargetLanguageVersion::EShTargetSpv_1_0); + shader.setEnvClient(glslang::EShClient::EShClientVulkan, glslang::EshTargetClientVersion::EShTargetVulkan_1_0); + }; + + switch (compatibility) + { + case ramses::ERenderBackendCompatibility::OpenGL: + break; + case ramses::ERenderBackendCompatibility::VulkanAndOpenGL: + setShaderTargetVulkan(*m_vertexShader); + setShaderTargetVulkan(*m_fragmentShader); + if (m_geometryShader) + setShaderTargetVulkan(*m_geometryShader); + break; + } + } + bool GlslParser::createShaderParts(ShaderParts& outParts, const std::string& defineString, const std::string& userShader, const std::string& shaderName) const { size_t versionStringStart = 0; @@ -381,10 +419,13 @@ namespace ramses::internal return m_geometryShaderFromParts; } + const SPIRVShaders& GlslParser::getSPIRVShaders() const + { + return m_spirvShaders; + } + std::string GlslParser::MergeShaderParts(const ShaderParts& shaderParts) { - StringOutputStream str; - str << shaderParts.version << shaderParts.defines << shaderParts.userCode; - return str.release(); + return fmt::format("{}{}{}", shaderParts.version, shaderParts.defines, shaderParts.userCode); } } diff --git a/src/client/internal/glslEffectBlock/GlslParser.h b/src/client/internal/glslEffectBlock/GlslParser.h index da3350fa4..deb71b5ab 100644 --- a/src/client/internal/glslEffectBlock/GlslParser.h +++ b/src/client/internal/glslEffectBlock/GlslParser.h @@ -12,6 +12,9 @@ #include "internal/SceneGraph/SceneAPI/EShaderStage.h" #include "internal/SceneGraph/SceneAPI/EShaderWarningCategory.h" #include "internal/PlatformAbstraction/Collections/StringOutputStream.h" +#include "internal/SceneGraph/Resource/SPIRVShaders.h" + +#include "ramses/framework/ERenderBackendCompatibility.h" #include #include @@ -31,7 +34,7 @@ namespace ramses::internal }; using Warnings = std::vector; - GlslParser(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader = {}, const std::vector& compilerDefines = {}); + GlslParser(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader = {}, const std::vector& compilerDefines = {}, ERenderBackendCompatibility compatibility = ERenderBackendCompatibility::OpenGL); [[nodiscard]] bool valid() const; @@ -39,6 +42,8 @@ namespace ramses::internal [[nodiscard]] const std::string& getFragmentShader() const; [[nodiscard]] const std::string& getGeometryShader() const; + [[nodiscard]] const SPIRVShaders& getSPIRVShaders() const; + [[nodiscard]] Warnings generateWarnings() const; [[nodiscard]] std::string getErrors() const; @@ -54,9 +59,11 @@ namespace ramses::internal }; static std::string CreateDefineString(const std::vector& compilerDefines); + void setShadersCompatibility(ERenderBackendCompatibility compatibility); bool createShaderParts(ShaderParts& outParts, const std::string& defineString, const std::string& userShader, const std::string& shaderName) const; bool parseShader(glslang::TShader& tShader, const TBuiltInResource& glslCompilationResources, const ShaderParts& shaderParts, const std::string& shaderName); inline bool linkProgram(); + void generateSPIRV(ERenderBackendCompatibility compatibility); static std::string MergeShaderParts(const ShaderParts& shaderParts); mutable StringOutputStream m_errorMessages; @@ -68,5 +75,7 @@ namespace ramses::internal std::string m_vertexShaderFromParts; std::string m_fragmentShaderFromParts; std::string m_geometryShaderFromParts; + + SPIRVShaders m_spirvShaders; }; } diff --git a/src/client/internal/glslEffectBlock/GlslToEffectConverter.cpp b/src/client/internal/glslEffectBlock/GlslToEffectConverter.cpp index 0766478ec..b5c12c60c 100644 --- a/src/client/internal/glslEffectBlock/GlslToEffectConverter.cpp +++ b/src/client/internal/glslEffectBlock/GlslToEffectConverter.cpp @@ -12,8 +12,8 @@ namespace ramses::internal { - GlslToEffectConverter::GlslToEffectConverter(const HashMap& semanticInputs) - : m_semanticInputs(semanticInputs) + GlslToEffectConverter::GlslToEffectConverter(SemanticsMap semanticInputs) + : m_semanticInputs(std::move(semanticInputs)) { } @@ -27,6 +27,7 @@ namespace ramses::internal if(geomShader != nullptr) CHECK_RETURN_ERR(parseLinkerObjectsForStage(geomShader->getTreeRoot(), EShaderStage::Geometry)); // Parse data for geometry stage CHECK_RETURN_ERR(replaceVertexAttributeWithBufferVariant()); // Post-process vertex attributes + CHECK_RETURN_ERR(checkIncompatibleUniformBufferRedifinitions()); CHECK_RETURN_ERR(makeUniformsUnique()); // Post-process uniforms which are present in both stages if (geomShader) @@ -128,11 +129,11 @@ namespace ramses::internal if (storageQualifier == glslang::EvqVaryingIn && stage == EShaderStage::Vertex) // 'VaryingIn' means vertex attribute { - return setInputTypeFromType(symbol->getType(), symbol->getName(), m_attributeInputs); + return createEffectInputsRecursivelyIfNeeded(symbol->getType(), symbol->getName(), {}, 0u); } if (storageQualifier == glslang::EvqUniform) { - return setInputTypeFromType(symbol->getType(), symbol->getName(), m_uniformInputs); + return createEffectInputsRecursivelyIfNeeded(symbol->getType(), symbol->getName(), {}, 0u); } return true; @@ -146,17 +147,21 @@ namespace ramses::internal for (size_t i = 0; i < temp.size(); i++) { const EffectInputInformation& A = temp[i]; + const auto& aType = m_uniformInputsGlslangTypes[i].get(); bool add = true; for (size_t j = i + 1; j < temp.size(); j++) { const EffectInputInformation& B = temp[j]; + const auto& bType = m_uniformInputsGlslangTypes[j].get(); if (A.inputName == B.inputName) { - if (A == B) // Same name and data: This is allowed, but only a single occurrence is added + //check inputs are same, but also check glslang type, which does a recursive check in case of structs (and UBOs) + if (A == B && aType == bType) { + // Same name and type: This is allowed, but only a single occurrence is added add = false; break; } @@ -174,7 +179,28 @@ namespace ramses::internal return true; } - bool GlslToEffectConverter::setInputTypeFromType(const glslang::TType& type, std::string_view inputName, EffectInputInformationVector& outputVector) const + bool GlslToEffectConverter::checkIncompatibleUniformBufferRedifinitions() const + { + EffectInputInformationVector uboInputs; + std::copy_if(m_uniformInputs.cbegin(), m_uniformInputs.cend(), std::back_inserter(uboInputs), [](const auto& input) { return input.dataType == EDataType::UniformBuffer; }); + + auto sortByBinding = [](const auto& ubo1, const auto& ubo2) { return ubo1.uniformBufferBinding.getValue() < ubo2.uniformBufferBinding.getValue(); }; + std::sort(uboInputs.begin(), uboInputs.end(), sortByBinding); + + //check if non-identical UBOs exist with same binding + auto incompatibleUBOs = [](const auto& ubo1, const auto& ubo2) { return ubo1.uniformBufferBinding == ubo2.uniformBufferBinding && ubo1 != ubo2; }; + auto badIt = std::adjacent_find(uboInputs.begin(), uboInputs.end(), incompatibleUBOs); + + if (badIt != uboInputs.end()) + { + m_message << badIt->inputName << ": several uniform buffers with same binding but different definition at binding: " << badIt->uniformBufferBinding.getValue(); + return false; + } + + return true; + } + + bool GlslToEffectConverter::createEffectInputsRecursivelyIfNeeded(const glslang::TType& type, std::string_view inputName, std::optional uniformBuffer, uint32_t offset) { uint32_t elementCount = 0; CHECK_RETURN_ERR(getElementCountFromType(type, inputName, elementCount)); @@ -184,31 +210,71 @@ namespace ramses::internal if (!type.isStruct()) { - CHECK_RETURN_ERR(createEffectInputType(type, inputName, elementCount, outputVector)); + CHECK_RETURN_ERR(createEffectInput(type, inputName, elementCount, uniformBuffer, 0u)); } else // Structs and especially arrays of structs are a bit more complicated { - const glslang::TTypeList* structFields = type.getStruct(); + if (type.getBasicType() == glslang::EbtBlock) + { + assert(!uniformBuffer && offset == 0u && "New uniform block is not expected to be defined within a uniform block"); + if (type.getQualifier().layoutPacking != glslang::ElpStd140) + { + // UBO layout must be explicitly set to "std140", which guarantees a specific packing + // of UBO elements in memory. + // Otherwise there is no guarantee on the layout of elements when setting UBO on GPU in case of OpenGL. + // Vulkan guarantees a layout that is compatible with std140 by default. + + m_message << "Failed creating effect input for uniform block " << inputName + << " of type " << type.getTypeName() << ". Layout must be explicitly set to std140"; + return false; + } + + if (type.isArray()) + { + // Arrays have harsh alignment rules in std140 that are known to be mis-interpreted. + // Forbidding UBO arrays in favor of having a less complicated implementation + // and more stable support for most crucial features of UBOs + m_message << "Failed creating effect input for uniform block " << inputName + << "[] of type " << type.getTypeName() << ". Uniform block arrays are not supported"; + return false; + } + + // Create an input representing the UBO input itself + // (shadow) inputs will be creating to represent each field of the UBO + // as if it were a normal struct, but those inputs should not be used + // for data layout/instance or LL scene. They should be used only to + // represent offsets within the UBO input created in the next line + CHECK_RETURN_ERR(createEffectInput(type, inputName, elementCount, {}, 0u)); + uniformBuffer = m_uniformInputs.back(); + } + + const auto uniformBufferElementSize = GetElementPaddedSizeFromType(type); + + const glslang::TTypeList& structFields = *type.getStruct(); for (uint32_t i = 0; i < elementCount; i++) { - for(const auto& structField : *structFields) + for(std::size_t fieldIdx = 0u; fieldIdx < structFields.size(); ++fieldIdx) { - const glslang::TType& fieldType = *structField.type; + const auto& field = structFields[fieldIdx]; + const glslang::TType& fieldType = *field.type; const auto subName = GetStructFieldIdentifier(inputName, fieldType.getFieldName(), type.isArray() ? static_cast(i) : -1); + const auto fieldOffsetWithinParent = glslang::TIntermediate::getOffset(type, static_cast(fieldIdx)); + const auto fieldOffset = offset + i * uniformBufferElementSize + fieldOffsetWithinParent; + // Get the element count for the field - uint32_t newElementCount = 0; - CHECK_RETURN_ERR(getElementCountFromType(fieldType, inputName, newElementCount)); + uint32_t fieldElementCount = 0; + CHECK_RETURN_ERR(getElementCountFromType(fieldType, inputName, fieldElementCount)); if (fieldType.isStruct()) { // Recursive case: Nested struct - CHECK_RETURN_ERR(setInputTypeFromType(fieldType, subName, outputVector)); + CHECK_RETURN_ERR(createEffectInputsRecursivelyIfNeeded(fieldType, subName, uniformBuffer, fieldOffset)); } else { - CHECK_RETURN_ERR(createEffectInputType(fieldType, subName, newElementCount, outputVector)); + CHECK_RETURN_ERR(createEffectInput(fieldType, subName, fieldElementCount, uniformBuffer, fieldOffset)); } } } @@ -220,7 +286,8 @@ namespace ramses::internal std::string GlslToEffectConverter::GetStructFieldIdentifier(std::string_view baseName, std::string_view fieldName, const int32_t arrayIndex) { StringOutputStream stream; - stream << baseName; + if(!IsUniformAnonymous(baseName)) + stream << baseName; if (arrayIndex != -1) { @@ -229,22 +296,60 @@ namespace ramses::internal stream << ']'; } - stream << '.'; + if(!IsUniformAnonymous(baseName)) + stream << '.'; stream << fieldName; return stream.release(); } - bool GlslToEffectConverter::createEffectInputType(const glslang::TType& type, std::string_view inputName, uint32_t elementCount, EffectInputInformationVector& outputVector) const + bool GlslToEffectConverter::IsUniformAnonymous(std::string_view uniformName) + { + return uniformName.find("anon@") != std::string_view::npos; + } + + std::string GlslToEffectConverter::MakeNameForAnonymousUniformBuffer(UniformBufferBinding binding) + { + //GLSLang gives names to anonymous UBOs that have the prefix "anon@" and a postfix of an integer + //that represents the order of their definition in the shader. + //This function creates a name which has the layout binding as a postfix so it is possible + //to make checks and filtration easier + assert(binding.isValid()); + return std::string("anon@ubo_binding=") + std::to_string(binding.getValue()); + } + + bool GlslToEffectConverter::createEffectInput(const glslang::TType& type, std::string_view inputName, uint32_t elementCount, std::optional parentUniformBuffer, uint32_t offset) { EffectInputInformation input; - input.inputName = inputName; + input.inputName = IsUniformAnonymous(inputName) ? MakeNameForAnonymousUniformBuffer(UniformBufferBinding{ type.getQualifier().layoutBinding }) : inputName;; input.elementCount = elementCount; - CHECK_RETURN_ERR(setInputTypeFromType(type, input)); - CHECK_RETURN_ERR(setSemanticsOnInput(input)); + if (type.getBasicType() == glslang::EbtBlock) + { + input.uniformBufferBinding = UniformBufferBinding{ type.getQualifier().layoutBinding }; + input.uniformBufferElementSize = UniformBufferElementSize{ GetElementPaddedSizeFromType(type) }; + } + + if (parentUniformBuffer) + { + input.uniformBufferBinding = UniformBufferBinding{ parentUniformBuffer->uniformBufferBinding }; + input.uniformBufferFieldOffset = UniformBufferFieldOffset{ offset }; + input.uniformBufferElementSize = UniformBufferElementSize{ GetElementPaddedSizeFromType(type) }; + } + + CHECK_RETURN_ERR(setEffectInputType(type, input)); + CHECK_RETURN_ERR(setEffectInputSemantics(type, parentUniformBuffer.has_value(), input)); + + if (IsAttributeType(type)) + { + m_attributeInputs.push_back(input); + } + else + { + m_uniformInputs.push_back(input); + m_uniformInputsGlslangTypes.emplace_back(type); + } - outputVector.push_back(input); return true; } @@ -278,10 +383,10 @@ namespace ramses::internal return true; } - bool GlslToEffectConverter::setInputTypeFromType(const glslang::TType& type, EffectInputInformation& input) const + bool GlslToEffectConverter::setEffectInputType(const glslang::TType& type, EffectInputInformation& input) const { assert(!input.inputName.empty()); - assert(!type.isStruct()); + assert(!type.isStruct() || type.getBasicType() == glslang::EbtBlock); const glslang::TBasicType basicType = type.getBasicType(); @@ -404,6 +509,9 @@ namespace ramses::internal case glslang::EbtUint: input.dataType = EDataType::UInt32; return true; + case glslang::EbtBlock: + input.dataType = EDataType::UniformBuffer; + return true; default: m_message << input.inputName << ": unknown scalar base type " << type.getBasicTypeString().c_str(); } @@ -412,17 +520,37 @@ namespace ramses::internal return false; } - bool GlslToEffectConverter::setSemanticsOnInput(EffectInputInformation& input) const + bool GlslToEffectConverter::setEffectInputSemantics(const glslang::TType& type, bool uniformBufferField, EffectInputInformation& input) const { assert(!input.inputName.empty()); - if (const EFixedSemantics* semantic = m_semanticInputs.get(input.inputName)) + // find input semantic by name or uniform buffer binding + auto semanticIt = m_semanticInputs.find(input.inputName); + if (semanticIt == m_semanticInputs.end() && input.dataType == EDataType::UniformBuffer) + semanticIt = m_semanticInputs.find(input.uniformBufferBinding); + + if (semanticIt != m_semanticInputs.end()) { - if (!IsSemanticCompatibleWithDataType(*semantic, input.dataType)) + const auto semantic = semanticIt->second; + if (uniformBufferField) { - m_message << input.inputName << ": input type " << EnumToString(input.dataType) << " not compatible with semantic " << *semantic; + m_message << input.inputName << ": can not have semantic because it is declared in a uniform block"; return false; } - input.semantics = *semantic; + + if (!IsSemanticCompatibleWithDataType(semantic, input.dataType)) + { + m_message << input.inputName << ": input type " << EnumToString(input.dataType) << " not compatible with semantic " << semantic; + return false; + } + + if (input.dataType == EDataType::UniformBuffer + && !IsSemanticCompatibleWithUniformBufferDefinition(semantic, type)) + { + m_message << input.inputName << ": is a uniform buffer that does not have correct format for semantic :" << semantic; + return false; + } + + input.semantics = semantic; } return true; } @@ -445,4 +573,77 @@ namespace ramses::internal return true; } + + uint32_t GlslToEffectConverter::GetElementPaddedSizeFromType(const glslang::TType& type) + { + int uniformBufferElementSize = 0; + + if (type.getBasicType() == glslang::EbtBlock) + { + uniformBufferElementSize = glslang::TIntermediate::getBlockSize(type); + } + else + { + int totalSize = 0; // in case of array this is size for all elements + int arrayStride = 0; // in case of array this is equal to (aligned) size for a single element (with padding), otherwise zero + glslang::TIntermediate::getBaseAlignment(type, totalSize, arrayStride, glslang::ElpStd140, type.getQualifier().layoutMatrix == glslang::ElmRowMajor); + uniformBufferElementSize = type.isArray() ? arrayStride : totalSize; + } + + return uint32_t(uniformBufferElementSize); + } + + bool GlslToEffectConverter::IsSemanticCompatibleWithUniformBufferDefinition(const EFixedSemantics semantic, const glslang::TType& type) + { + assert(type.isStruct()); + const auto& structTypes = *type.getStruct(); + + auto checkType = [&structTypes](std::size_t index, auto basicType, auto vectorSize, auto matrixCols, auto matrixRows) { + const auto& typeToCheck = *structTypes[index].type; + return typeToCheck.getBasicType() == basicType + && typeToCheck.getVectorSize() == vectorSize + && typeToCheck.getMatrixCols() == matrixCols + && typeToCheck.getMatrixRows() == matrixRows; + }; + + auto isMat44Type = [&checkType](std::size_t index) { + return checkType(index, glslang::EbtFloat, 0, 4, 4); + }; + + auto isVec3Type = [&checkType](std::size_t index) { + return checkType(index, glslang::EbtFloat, 3, 0, 0); + }; + + switch (semantic) + { + case EFixedSemantics::ModelBlock: + return structTypes.size() == 1u + && isMat44Type(0u); + case EFixedSemantics::CameraBlock: + return structTypes.size() == 3u + && isMat44Type(0u) + && isMat44Type(1u) + && isVec3Type(2u); + case EFixedSemantics::ModelCameraBlock: + return structTypes.size() == 3u + && isMat44Type(0u) + && isMat44Type(1u) + && isMat44Type(2u); + case EFixedSemantics::FramebufferBlock: + case EFixedSemantics::SceneBlock: + return false; // TODO _SEMANTICUBO_ + default: + assert(false); + } + + return false; + } + + bool GlslToEffectConverter::IsAttributeType(const glslang::TType& type) + { + const auto storageQualifier = type.getQualifier().storage; + //In GLSLang "EvqVaryingIn" is any stages' per vertex input, which is the case for vertex stage's "in" variables aka attributes + //but not for uniforms. + return (storageQualifier == glslang::EvqVaryingIn); + } } diff --git a/src/client/internal/glslEffectBlock/GlslToEffectConverter.h b/src/client/internal/glslEffectBlock/GlslToEffectConverter.h index 429a506fd..fc09fc81c 100644 --- a/src/client/internal/glslEffectBlock/GlslToEffectConverter.h +++ b/src/client/internal/glslEffectBlock/GlslToEffectConverter.h @@ -26,7 +26,7 @@ namespace ramses::internal class GlslToEffectConverter { public: - explicit GlslToEffectConverter(const HashMap& semanticInputs); + explicit GlslToEffectConverter(SemanticsMap semanticInputs); ~GlslToEffectConverter(); [[nodiscard]] bool parseShaderProgram(const glslang::TProgram* program); @@ -38,25 +38,32 @@ namespace ramses::internal [[nodiscard]] std::optional getGeometryShaderInputType() const; private: - HashMap m_semanticInputs; - mutable StringOutputStream m_message; - - EffectInputInformationVector m_uniformInputs; - EffectInputInformationVector m_attributeInputs; - - std::optional m_geometryShaderInputType; - bool parseLinkerObjectsForStage(const TIntermNode* node, EShaderStage stage); const glslang::TIntermSequence* getLinkerObjectSequence(const TIntermNode* node) const; bool handleSymbol(const glslang::TIntermSymbol* symbol, EShaderStage stage); - bool getElementCountFromType(const glslang::TType& type, std::string_view inputName, uint32_t& elementCount) const; - bool setInputTypeFromType(const glslang::TType& type, std::string_view inputName, EffectInputInformationVector& outputVector) const; - bool setInputTypeFromType(const glslang::TType& type, EffectInputInformation& input) const; bool replaceVertexAttributeWithBufferVariant(); - bool setSemanticsOnInput(EffectInputInformation& input) const; bool makeUniformsUnique(); - bool createEffectInputType(const glslang::TType& type, std::string_view inputName, uint32_t elementCount, EffectInputInformationVector& outputVector) const; + bool checkIncompatibleUniformBufferRedifinitions() const; + bool createEffectInputsRecursivelyIfNeeded(const glslang::TType& type, std::string_view inputName, std::optional uniformBuffer, uint32_t offset); + bool createEffectInput(const glslang::TType& type, std::string_view inputName, uint32_t elementCount, std::optional uniformBuffer, uint32_t offset); + bool setEffectInputType(const glslang::TType& type, EffectInputInformation& input) const; + bool setEffectInputSemantics(const glslang::TType& type, bool uniformBufferField, EffectInputInformation& input) const; + static std::string GetStructFieldIdentifier(std::string_view baseName, std::string_view fieldName, const int32_t arrayIndex); + static uint32_t GetElementPaddedSizeFromType(const glslang::TType& type); + static bool IsUniformAnonymous(std::string_view uniformName); + static std::string MakeNameForAnonymousUniformBuffer(UniformBufferBinding binding); + static bool IsSemanticCompatibleWithUniformBufferDefinition(const EFixedSemantics semantic, const glslang::TType& type); + static bool IsAttributeType(const glslang::TType& type); + + const SemanticsMap m_semanticInputs; + mutable StringOutputStream m_message; + + EffectInputInformationVector m_uniformInputs; + EffectInputInformationVector m_attributeInputs; + std::vector> m_uniformInputsGlslangTypes; + + std::optional m_geometryShaderInputType; }; } diff --git a/src/client/internal/glslEffectBlock/GlslangInitializer.cpp b/src/client/internal/glslEffectBlock/GlslangInitializer.cpp new file mode 100644 index 000000000..fa9430600 --- /dev/null +++ b/src/client/internal/glslEffectBlock/GlslangInitializer.cpp @@ -0,0 +1,31 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + + +#include "GlslangInitializer.h" +#include "GLSlang.h" +#include "glslang/build_info.h" + +namespace ramses::internal +{ + GlslangInitializer::GlslangInitializer() + { + // The function internally has ref counting, which means calling it several times + // is actually safe, desptite being very inefficient. + // Unfortunately this behavior relies on internal implementation of glslang, so it must be + // checked with any glslang update that this behavior can still be relied on, and act accordingly + static_assert(GLSLANG_VERSION_MAJOR == 14 && GLSLANG_VERSION_MINOR == 1 && GLSLANG_VERSION_PATCH == 0, + "Check glslang::InitializeProcess() has ref-counting of connected clients for any glslang update"); + glslang::InitializeProcess(); + } + + GlslangInitializer::~GlslangInitializer() + { + glslang::FinalizeProcess(); + } +} diff --git a/tests/unittests/client/logic/shared/FeatureLevelTestValues.h b/src/client/internal/glslEffectBlock/GlslangInitializer.h similarity index 64% rename from tests/unittests/client/logic/shared/FeatureLevelTestValues.h rename to src/client/internal/glslEffectBlock/GlslangInitializer.h index 9c2347245..dd41b6d1c 100644 --- a/tests/unittests/client/logic/shared/FeatureLevelTestValues.h +++ b/src/client/internal/glslEffectBlock/GlslangInitializer.h @@ -1,5 +1,5 @@ // ------------------------------------------------------------------------- -// Copyright (C) 2022 BMW AG +// Copyright (C) 2024 BMW AG // ------------------------------------------------------------------------- // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -8,15 +8,14 @@ #pragma once -#include "gtest/gtest.h" -#include "ramses/framework/EFeatureLevel.h" +#include namespace ramses::internal { - static - ::testing::internal::ValueArray - GetFeatureLevelTestValues() + class GlslangInitializer { - return ::testing::Values(ramses::EFeatureLevel_01); - } + public: + GlslangInitializer(); + ~GlslangInitializer(); + }; } diff --git a/src/client/internal/logic/ApiObjects.cpp b/src/client/internal/logic/ApiObjects.cpp index f005d1fb6..c72e3bc58 100644 --- a/src/client/internal/logic/ApiObjects.cpp +++ b/src/client/internal/logic/ApiObjects.cpp @@ -238,7 +238,12 @@ namespace ramses::internal { auto impl = std::make_unique(m_scene, std::move(joints), inverseBindMatrices, appearanceBinding, jointMatInput, name, sceneObjectId_t{}); impl->createRootProperties(); - return &createAndRegisterObject(std::move(impl)); + auto& skin = createAndRegisterObject(std::move(impl)); + + for (auto& joint: skin.impl().getJoints()) + m_logicNodeDependencies.addBindingDependency(const_cast(*joint), skin.m_impl); + + return &skin; } template diff --git a/src/client/internal/logic/FileUtils.cpp b/src/client/internal/logic/FileUtils.cpp index 1ca208459..a349a09f7 100644 --- a/src/client/internal/logic/FileUtils.cpp +++ b/src/client/internal/logic/FileUtils.cpp @@ -7,9 +7,11 @@ // ------------------------------------------------------------------------- #include "FileUtils.h" -#include "StdFilesystemWrapper.h" +#include #include +namespace fs = std::filesystem; + namespace ramses::internal { bool FileUtils::SaveBinary(const std::string& filename, const void* binaryBuffer, size_t bufferLength) diff --git a/src/client/internal/logic/LogicNodeUpdateStatistics.cpp b/src/client/internal/logic/LogicNodeUpdateStatistics.cpp index 3d7f3fb5b..d7522e1d3 100644 --- a/src/client/internal/logic/LogicNodeUpdateStatistics.cpp +++ b/src/client/internal/logic/LogicNodeUpdateStatistics.cpp @@ -17,7 +17,7 @@ namespace ramses::internal { LogicNodeUpdateStatistics::LogicNodeUpdateStatistics() { - m_slowestNodes.fill({ nullptr, std::chrono::microseconds(-1) }); + m_slowestNodes.fill({sceneObjectId_t{}, {}, std::chrono::microseconds(-1)}); } void LogicNodeUpdateStatistics::clear() @@ -29,7 +29,7 @@ namespace ramses::internal m_currentStatisticsFrame = 0u; m_totalNodesCount = 0u; m_lastTimeUpdateDataAdded = std::nullopt; - m_slowestNodes.fill({nullptr, std::chrono::microseconds(-1)}); + m_slowestNodes.fill({sceneObjectId_t{}, {}, std::chrono::microseconds(-1)}); } void LogicNodeUpdateStatistics::collect(const UpdateReport& report, size_t totalNodesCount) @@ -42,19 +42,20 @@ namespace ramses::internal m_nodesExecutedCurrentUpdate = 0u; m_activatedLinks.add(static_cast(report.getLinkActivations())); - auto isLongerTime = [](const LogicNodeTimed& a, const LogicNodeTimed& b) { return a.second > b.second; }; + auto isLongerTime = [](const NodeTime& a, const NodeTime& b) { return a.time > b.time; }; for (auto& newNode : report.getNodesExecuted()) { - if (isLongerTime(newNode, m_slowestNodes.back())) + if (newNode.second > m_slowestNodes.back().time) { - auto it = std::find_if(m_slowestNodes.begin(), m_slowestNodes.end(), [&newNode](const auto& slowNode) { return newNode.first == slowNode.first; }); + auto newNodeId = newNode.first->getSceneObjectId(); + auto it = std::find_if(m_slowestNodes.begin(), m_slowestNodes.end(), [&newNodeId](const auto& slowNode) { return newNodeId == slowNode.id; }); if (it == m_slowestNodes.end()) { - m_slowestNodes.back() = newNode; + m_slowestNodes.back() = NodeTime{newNodeId, newNode.first->getName(), newNode.second}; } else { - it->second = std::max(newNode.second, it->second); + it->time = std::max(newNode.second, it->time); } std::sort(m_slowestNodes.begin(), m_slowestNodes.end(), isLongerTime); @@ -151,14 +152,14 @@ namespace ramses::internal void LogicNodeUpdateStatistics::logSlowestNodes() { - if (m_slowestNodes[0].first == nullptr) + if (!m_slowestNodes[0].id.isValid()) return; std::string nodes; for (auto& node : m_slowestNodes) { - if (node.first != nullptr) - nodes += fmt::format(" [{}:{}]", node.first->getName(), node.second.count()); + if (node.id.isValid()) + nodes += fmt::format(" [{}:{}]", node.name, node.time.count()); } LOG_INFO(CONTEXT_PERIODIC, "Slowest nodes [name:time_us]:{}", nodes); } diff --git a/src/client/internal/logic/LogicNodeUpdateStatistics.h b/src/client/internal/logic/LogicNodeUpdateStatistics.h index 4e3ec3dd3..75c00c051 100644 --- a/src/client/internal/logic/LogicNodeUpdateStatistics.h +++ b/src/client/internal/logic/LogicNodeUpdateStatistics.h @@ -28,7 +28,12 @@ namespace ramses::internal [[nodiscard]] bool checkUpdateFrameFinished() const; private: - using LogicNodeTimed = UpdateReport::LogicNodeTimed; + struct NodeTime + { + sceneObjectId_t id; + std::string name; + UpdateReport::ReportTimeUnits time; + }; struct StatisticProperty { @@ -73,6 +78,6 @@ namespace ramses::internal StatisticProperty m_nodesExecuted; StatisticProperty m_activatedLinks; - std::array m_slowestNodes; + std::array m_slowestNodes; }; } diff --git a/src/client/internal/logic/RamsesHelper.h b/src/client/internal/logic/RamsesHelper.h index 3c50cce09..73304eb9d 100644 --- a/src/client/internal/logic/RamsesHelper.h +++ b/src/client/internal/logic/RamsesHelper.h @@ -49,6 +49,7 @@ namespace ramses::internal case ramses::EDataType::TextureSampler2DMS: case ramses::EDataType::TextureSamplerExternal: case ramses::EDataType::ByteBlob: + case ramses::EDataType::UniformBuffer: return std::nullopt; } diff --git a/src/client/internal/logic/RamsesObjectResolver.cpp b/src/client/internal/logic/RamsesObjectResolver.cpp index 953cd7316..b4324f36c 100644 --- a/src/client/internal/logic/RamsesObjectResolver.cpp +++ b/src/client/internal/logic/RamsesObjectResolver.cpp @@ -10,6 +10,7 @@ #include "impl/ErrorReporting.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" #include "ramses/client/Node.h" #include "ramses/client/Camera.h" #include "ramses/client/Appearance.h" @@ -24,9 +25,10 @@ namespace ramses::internal { - RamsesObjectResolver::RamsesObjectResolver(ErrorReporting& errorReporting, SceneImpl& scene) + RamsesObjectResolver::RamsesObjectResolver(ErrorReporting& errorReporting, SceneImpl& scene, const SceneMergeHandleMapping* mapping) : m_errors(errorReporting) , m_scene(scene) + , m_mapping(mapping) { } @@ -63,21 +65,22 @@ namespace ramses::internal template T* RamsesObjectResolver::findRamsesObjectInScene(std::string_view logicNodeName, ramses::sceneObjectId_t objectId) const { - ramses::SceneObject* sceneObject = m_scene.findObjectById(objectId); + const auto newObjectId = m_mapping ? m_mapping->getMapping(objectId) : objectId; + auto* sceneObject = m_scene.findObjectById(newObjectId); if (sceneObject == nullptr) { m_errors.set( - fmt::format("Fatal error during loading from file! Serialized Ramses Logic object '{}' points to a Ramses object (id: {}) which couldn't be found in the provided scene!", - logicNodeName, objectId.getValue()), nullptr); + fmt::format("Fatal error during loading from file! Serialized Ramses Logic object '{}' points to a Ramses object (id: {}|{}) which couldn't be found in the provided scene!", + logicNodeName, objectId.getValue(), newObjectId.getValue()), nullptr); return nullptr; } T* concreteObject = sceneObject->as(); if (concreteObject == nullptr) { - m_errors.set(fmt::format("Fatal error during loading from file! Ramses binding '{}' points to a Ramses scene object (id: {}) which is not of the same type!", - logicNodeName, objectId.getValue()), nullptr); + m_errors.set(fmt::format("Fatal error during loading from file! Ramses binding '{}' points to a Ramses scene object (id: {}|{}) which is not of the same type!", + logicNodeName, objectId.getValue(), newObjectId.getValue()), nullptr); return nullptr; } diff --git a/src/client/internal/logic/RamsesObjectResolver.h b/src/client/internal/logic/RamsesObjectResolver.h index 367e7d0c9..888a0381c 100644 --- a/src/client/internal/logic/RamsesObjectResolver.h +++ b/src/client/internal/logic/RamsesObjectResolver.h @@ -25,6 +25,7 @@ namespace ramses::internal { class ErrorReporting; class SceneImpl; + class SceneMergeHandleMapping; class IRamsesObjectResolver { @@ -42,7 +43,7 @@ namespace ramses::internal class RamsesObjectResolver final : public IRamsesObjectResolver { public: - explicit RamsesObjectResolver(ErrorReporting& errorReporting, SceneImpl& scene); + explicit RamsesObjectResolver(ErrorReporting& errorReporting, SceneImpl& scene, const SceneMergeHandleMapping* mapping); [[nodiscard]] ramses::Node* findRamsesNodeInScene(std::string_view logicNodeName, ramses::sceneObjectId_t objectId) const override; [[nodiscard]] ramses::Appearance* findRamsesAppearanceInScene(std::string_view logicNodeName, ramses::sceneObjectId_t objectId) const override; @@ -57,5 +58,6 @@ namespace ramses::internal ErrorReporting& m_errors; SceneImpl& m_scene; + const SceneMergeHandleMapping* m_mapping = nullptr; }; } diff --git a/src/client/internal/logic/StdFilesystemWrapper.h b/src/client/internal/logic/StdFilesystemWrapper.h deleted file mode 100644 index 45feae694..000000000 --- a/src/client/internal/logic/StdFilesystemWrapper.h +++ /dev/null @@ -1,36 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (C) 2021 BMW AG -// ------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// ------------------------------------------------------------------------- - -#pragma once - -#if defined(RLOGIC_STD_FILESYSTEM_EXPERIMENTAL) -#include -namespace fs = std::experimental::filesystem; - -#elif defined(RLOGIC_STD_FILESYSTEM_EMULATION) - -// add more emulation methods when needed -#include -#include -#include -#include - -namespace fs -{ - bool is_directory(const std::string& path) - { - struct stat tmp; - return stat(path.c_str(), &tmp) == 0 && S_ISDIR(tmp.st_mode); - } -} - -#else -#include -namespace fs = std::filesystem; -#endif - diff --git a/src/framework/impl/DataTypeUtils.h b/src/framework/impl/DataTypeUtils.h index 13bc7e664..e8a3cbc81 100644 --- a/src/framework/impl/DataTypeUtils.h +++ b/src/framework/impl/DataTypeUtils.h @@ -52,6 +52,8 @@ namespace ramses return EDataType::Matrix44F; case ramses::internal::EDataType::ByteBlob: return EDataType::ByteBlob; + case ramses::internal::EDataType::UniformBuffer: + return EDataType::UniformBuffer; // internal attribure array types are converted back to their element type on public API case ramses::internal::EDataType::UInt16Buffer: @@ -116,6 +118,8 @@ namespace ramses return ramses::internal::EDataType::Matrix44F; case EDataType::ByteBlob: return ramses::internal::EDataType::ByteBlob; + case EDataType::UniformBuffer: + return ramses::internal::EDataType::UniformBuffer; case EDataType::TextureSampler2D: return ramses::internal::EDataType::TextureSampler2D; case EDataType::TextureSampler2DMS: diff --git a/src/framework/impl/RamsesFrameworkConfigImpl.cpp b/src/framework/impl/RamsesFrameworkConfigImpl.cpp index 2ef0812a9..fab5dcce5 100644 --- a/src/framework/impl/RamsesFrameworkConfigImpl.cpp +++ b/src/framework/impl/RamsesFrameworkConfigImpl.cpp @@ -211,8 +211,6 @@ namespace ramses::internal void RamsesFrameworkConfigImpl::setFeatureLevelNoCheck(EFeatureLevel featureLevel) { - static_assert(EFeatureLevel_Latest == EFeatureLevel_01, - "remove this method which is used only for testing while there is no valid mismatching feature level yet"); m_featureLevel = featureLevel; } } diff --git a/src/framework/impl/RamsesFrameworkConfigImpl.h b/src/framework/impl/RamsesFrameworkConfigImpl.h index 0ea3172d0..ac45ca8ad 100644 --- a/src/framework/impl/RamsesFrameworkConfigImpl.h +++ b/src/framework/impl/RamsesFrameworkConfigImpl.h @@ -73,6 +73,7 @@ namespace ramses::internal RamsesLoggerConfig loggerConfig; uint32_t periodicLogTimeout = 2u; + // useful for tests to check invalid feature levels void setFeatureLevelNoCheck(EFeatureLevel featureLevel); private: diff --git a/src/framework/impl/RamsesFrameworkImpl.cpp b/src/framework/impl/RamsesFrameworkImpl.cpp index 896b829da..db1e63ce0 100644 --- a/src/framework/impl/RamsesFrameworkImpl.cpp +++ b/src/framework/impl/RamsesFrameworkImpl.cpp @@ -37,7 +37,7 @@ namespace ramses::internal , m_threadWatchdogConfig(config.m_watchdogConfig) // NOTE: ThreadedTaskExecutor must always be constructed after CommunicationSystem , m_threadedTaskExecutor(3, config.m_watchdogConfig) - , m_resourceComponent(m_statisticCollection, m_frameworkLock) + , m_resourceComponent(m_statisticCollection, m_frameworkLock, config.getFeatureLevel()) , m_scenegraphComponent( m_participantAddress.getParticipantId(), *m_communicationSystem, @@ -89,7 +89,7 @@ namespace ramses::internal } LOG_INFO(CONTEXT_FRAMEWORK, "RamsesFramework::createRamsesRenderer"); - m_ramsesRenderer = FrameworkFactoryRegistry::GetInstance().getRendererFactory()->createRenderer(*this, config); + m_ramsesRenderer = FrameworkFactoryRegistry::GetInstance().getRendererFactory()->createRenderer(*this, config, RamsesLogger::GetPrefixInstance()); return m_ramsesRenderer.get(); } @@ -325,7 +325,7 @@ namespace ramses::internal std::unique_ptr RamsesFrameworkImpl::CreateImpl(const RamsesFrameworkConfig& config) { - RamsesLogger::SetPrefixes(config.impl().getLoggingInstanceName(), "main"); + RamsesLoggerPrefixes::SetRamsesLoggerPrefixes(config.impl().getLoggingInstanceName(), "main"); GetRamsesLogger().initialize(config.impl().loggerConfig, false, config.impl().getDltApplicationRegistrationEnabled()); Guid myGuid = config.impl().getUserProvidedGuid(); diff --git a/src/framework/impl/RamsesLoggerImpl.cpp b/src/framework/impl/RamsesLoggerImpl.cpp index b67f633a5..2bb39a67d 100644 --- a/src/framework/impl/RamsesLoggerImpl.cpp +++ b/src/framework/impl/RamsesLoggerImpl.cpp @@ -15,4 +15,14 @@ namespace ramses::internal static RamsesLogger logger; return logger; } + + void RamsesLoggerPrefixesExported::SetRamsesLoggerPrefixesExported(std::string_view instance, std::string_view thread, std::string_view additional) + { + RamsesLogger::SetPrefixes(instance, thread, additional); + } + + void RamsesLoggerPrefixesExported::SetRamsesLoggerPrefixAdditionalExported(std::string_view additional) + { + RamsesLogger::SetPrefixAdditional(additional); + } } diff --git a/src/framework/impl/RamsesLoggerImpl.h b/src/framework/impl/RamsesLoggerImpl.h index 8c0e1aa82..71377ef1f 100644 --- a/src/framework/impl/RamsesLoggerImpl.h +++ b/src/framework/impl/RamsesLoggerImpl.h @@ -10,10 +10,22 @@ #include "ramses/framework/APIExport.h" #include "internal/Core/Utils/RamsesLogger.h" +#include namespace ramses::internal { class RamsesLogger; RAMSES_IMPL_EXPORT RamsesLogger& GetRamsesLogger(); + + // These are only helpers to solve thread local storage across shared libraries for logging prefixes and not meant to be used, + // use RamsesLoggerPrefixes instead. + class RamsesLoggerPrefixesExported + { + private: + RAMSES_IMPL_EXPORT static void SetRamsesLoggerPrefixesExported(std::string_view instance, std::string_view thread, std::string_view additional = {}); + RAMSES_IMPL_EXPORT static void SetRamsesLoggerPrefixAdditionalExported(std::string_view additional); + + friend class RamsesLoggerPrefixes; + }; } diff --git a/src/framework/impl/RamsesObjectFactoryInterfaces.h b/src/framework/impl/RamsesObjectFactoryInterfaces.h index 013e638ca..f36904aea 100644 --- a/src/framework/impl/RamsesObjectFactoryInterfaces.h +++ b/src/framework/impl/RamsesObjectFactoryInterfaces.h @@ -41,7 +41,7 @@ namespace ramses public: virtual ~IRendererFactory() = default; - virtual RendererUniquePtr createRenderer(internal::RamsesFrameworkImpl& framework, const RendererConfig& config) const = 0; + virtual RendererUniquePtr createRenderer(internal::RamsesFrameworkImpl& framework, const RendererConfig& config, std::string_view loggingInstanceName) const = 0; }; } diff --git a/src/framework/impl/RamsesObjectImpl.cpp b/src/framework/impl/RamsesObjectImpl.cpp index 873430852..ab0e37915 100644 --- a/src/framework/impl/RamsesObjectImpl.cpp +++ b/src/framework/impl/RamsesObjectImpl.cpp @@ -11,7 +11,6 @@ #include "impl/SerializationContext.h" #include "internal/PlatformAbstraction/Collections/IOutputStream.h" #include "internal/PlatformAbstraction/Collections/IInputStream.h" -#include "internal/PlatformAbstraction/Collections/StringOutputStream.h" namespace ramses::internal { diff --git a/src/framework/impl/SerializationContext.cpp b/src/framework/impl/SerializationContext.cpp index 69d7aba05..accedab26 100644 --- a/src/framework/impl/SerializationContext.cpp +++ b/src/framework/impl/SerializationContext.cpp @@ -9,6 +9,8 @@ #include "impl/SerializationContext.h" #include "RamsesObjectImpl.h" #include "ramses/framework/RamsesObject.h" +#include "ramses/framework/RamsesObjectTypes.h" +#include namespace ramses::internal { @@ -28,8 +30,9 @@ namespace ramses::internal return ObjectIDType(0u); } - DeserializationContext::DeserializationContext(const SceneConfigImpl& loadConfig) + DeserializationContext::DeserializationContext(const SceneConfigImpl& loadConfig, SceneMergeHandleMapping* mapping) : m_loadConfig(loadConfig) + , m_mapping(mapping) { } @@ -79,10 +82,29 @@ namespace ramses::internal bool DeserializationContext::resolveDependencies() { - for (auto obj : m_dependingObjects) + // resolve dependencies for all object types BEFORE LogicEngine + std::vector logicEngines; + for (auto* obj: m_dependingObjects) + { + if (obj->getType() != ERamsesObjectType::LogicEngine) + { + if (!obj->resolveDeserializationDependencies(*this)) + { + return false; + } + } + else + { + logicEngines.push_back(obj); + } + } + + for (auto* obj: logicEngines) { if (!obj->resolveDeserializationDependencies(*this)) + { return false; + } } return true; @@ -90,6 +112,7 @@ namespace ramses::internal void DeserializationContext::addNodeHandleToNodeImplMapping(NodeHandle nodeHandle, NodeImpl* node) { + assert(nodeHandle.isValid()); assert(nodeHandle < m_nodeMap.size()); m_nodeMap[nodeHandle.asMemoryHandle()] = node; } @@ -111,4 +134,14 @@ namespace ramses::internal { return m_loadConfig; } + + SceneMergeHandleMapping* DeserializationContext::getSceneMergeHandleMapping() + { + return m_mapping; + } + + const SceneMergeHandleMapping* DeserializationContext::getSceneMergeHandleMapping() const + { + return m_mapping; + } } diff --git a/src/framework/impl/SerializationContext.h b/src/framework/impl/SerializationContext.h index 67b394d2f..a4a7e0f60 100644 --- a/src/framework/impl/SerializationContext.h +++ b/src/framework/impl/SerializationContext.h @@ -8,6 +8,7 @@ #pragma once +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" #include "ramses/framework/RamsesFrameworkTypes.h" #include "internal/PlatformAbstraction/Collections/HashMap.h" #include "internal/PlatformAbstraction/Collections/HashSet.h" @@ -29,7 +30,7 @@ namespace ramses::internal using RamsesObjectImplSet = HashSet; public: - explicit DeserializationContext(const SceneConfigImpl& loadConfig); + explicit DeserializationContext(const SceneConfigImpl& loadConfig, SceneMergeHandleMapping* mapping = nullptr); void resize(uint32_t totalObjects, uint32_t nodeCount); static ObjectIDType GetObjectIDNull(); @@ -46,17 +47,24 @@ namespace ramses::internal // phase 2: resolve dependencies bool resolveDependencies(); + template + void deserializeAndMap(IInputStream& inStream, TypedMemoryHandle& handle); + template void resolveDependencyIDImplAndStoreAsPointer(OBJECT_TYPE*& ptrId) const; [[nodiscard]] NodeImpl* getNodeImplForHandle(NodeHandle /*nodeHandle*/) const; [[nodiscard]] const SceneConfigImpl& getLoadConfig() const; + [[nodiscard]] SceneMergeHandleMapping* getSceneMergeHandleMapping(); + [[nodiscard]] const SceneMergeHandleMapping* getSceneMergeHandleMapping() const; + private: std::vector m_objectImpls; std::vector m_nodeMap; RamsesObjectImplSet m_dependingObjects; const SceneConfigImpl& m_loadConfig; + SceneMergeHandleMapping* m_mapping = nullptr; }; class SerializationContext @@ -98,4 +106,21 @@ namespace ramses::internal // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) ptr really stores an id here ptr = reinterpret_cast(size_t(objID)); } + + template + inline void DeserializationContext::deserializeAndMap(IInputStream& inStream, TypedMemoryHandle& handle) + { + TypedMemoryHandle tmpHandle; + inStream >> tmpHandle; + auto* mapping = getSceneMergeHandleMapping(); + if (mapping && tmpHandle.isValid()) + { + handle = mapping->getMapping(tmpHandle); + assert(handle.isValid()); + } + else + { + handle = tmpHandle; + } + } } diff --git a/src/framework/internal/Communication/TransportCommon/RamsesTransportProtocolVersion.h b/src/framework/internal/Communication/TransportCommon/RamsesTransportProtocolVersion.h index ffbf23a26..3b8cdfb46 100644 --- a/src/framework/internal/Communication/TransportCommon/RamsesTransportProtocolVersion.h +++ b/src/framework/internal/Communication/TransportCommon/RamsesTransportProtocolVersion.h @@ -8,4 +8,4 @@ #pragma once -#define RAMSES_TRANSPORT_PROTOCOL_VERSION_MAJOR 126 +#define RAMSES_TRANSPORT_PROTOCOL_VERSION_MAJOR 137 diff --git a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.cpp b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.cpp index 9eb36e552..0f44f6b18 100644 --- a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.cpp +++ b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.cpp @@ -96,7 +96,7 @@ namespace ramses::internal HasEffectTimeSync = 2u }; - absl::Span SerializeInfos(const FlushInformation& flushInfos, std::vector& workingMemory) + absl::Span SerializeInfos(const FlushInformation& flushInfos, std::vector& workingMemory, EFeatureLevel featureLevel) { const size_t estimatedDataSize = sizeof(flushInfos.containsValidInformation) + @@ -132,6 +132,8 @@ namespace ramses::internal os << flushInfos.sizeInfo.renderStateCount; os << flushInfos.sizeInfo.datalayoutCount; os << flushInfos.sizeInfo.datainstanceCount; + if (featureLevel >= EFeatureLevel_02) + os << flushInfos.sizeInfo.uniformBufferCount; os << flushInfos.sizeInfo.renderGroupCount; os << flushInfos.sizeInfo.renderPassCount; os << flushInfos.sizeInfo.blitPassCount; @@ -167,7 +169,7 @@ namespace ramses::internal return workingMemory; } - FlushInformation Deserialize(absl::Span flushInfoBlob) + FlushInformation Deserialize(absl::Span flushInfoBlob, EFeatureLevel featureLevel) { assert(flushInfoBlob.size() >= FlushInformation::getMinimumSize()); BinaryInputStream is(flushInfoBlob.data()); @@ -188,6 +190,8 @@ namespace ramses::internal is >> infos.sizeInfo.renderStateCount; is >> infos.sizeInfo.datalayoutCount; is >> infos.sizeInfo.datainstanceCount; + if (featureLevel >= EFeatureLevel_02) + is >> infos.sizeInfo.uniformBufferCount; is >> infos.sizeInfo.renderGroupCount; is >> infos.sizeInfo.renderPassCount; is >> infos.sizeInfo.blitPassCount; @@ -251,13 +255,13 @@ namespace ramses::internal return {}; } - std::unique_ptr Deserialize(absl::Span description, absl::Span data) + std::unique_ptr Deserialize(absl::Span description, absl::Span data, EFeatureLevel featureLevel) { BinaryInputStream is(description.data()); ResourceContentHash hash; is >> hash; ResourceSerializationHelper::DeserializedResourceHeader header = - ResourceSerializationHelper::ResourceFromMetadataStream(is); + ResourceSerializationHelper::ResourceFromMetadataStream(is, featureLevel); const size_t expectedDataSize = header.compressionStatus == EResourceCompressionStatus::Compressed ? header.compressedSize : header.decompressedSize; diff --git a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.h b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.h index 9520ddea0..e00b5af96 100644 --- a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.h +++ b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializationHelper.h @@ -8,8 +8,8 @@ #pragma once +#include "ramses/framework/EFeatureLevel.h" #include "absl/types/span.h" - #include #include #include @@ -33,12 +33,12 @@ namespace ramses::internal absl::Span SerializeDescription(const IResource& resource, std::vector& workingMemory); absl::Span SerializeData(const IResource& resource); - std::unique_ptr Deserialize(absl::Span description, absl::Span data); + std::unique_ptr Deserialize(absl::Span description, absl::Span data, EFeatureLevel featureLevel); } namespace FlushInformationSerialization { - absl::Span SerializeInfos(const FlushInformation& flushInfos, std::vector& workingMemory); - FlushInformation Deserialize(absl::Span flushInfoBlob); + absl::Span SerializeInfos(const FlushInformation& flushInfos, std::vector& workingMemory, EFeatureLevel featureLevel); + FlushInformation Deserialize(absl::Span flushInfoBlob, EFeatureLevel featureLevel); } } diff --git a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.cpp b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.cpp index a6b9c3161..e3d227c5a 100644 --- a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.cpp +++ b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.cpp @@ -11,15 +11,16 @@ namespace ramses::internal { - SceneUpdateSerializer::SceneUpdateSerializer(const SceneUpdate& update, StatisticCollectionScene& sceneStatistics) + SceneUpdateSerializer::SceneUpdateSerializer(const SceneUpdate& update, StatisticCollectionScene& sceneStatistics, EFeatureLevel featureLevel) : m_update(update) , m_sceneStatistics(sceneStatistics) + , m_featureLevel{ featureLevel } { } bool SceneUpdateSerializer::writeToPackets(absl::Span packetMem, const std::function& writeDoneFunc) const { - SingleSceneUpdateWriter writer(m_update, packetMem, writeDoneFunc, m_sceneStatistics); + SingleSceneUpdateWriter writer(m_update, packetMem, writeDoneFunc, m_sceneStatistics, m_featureLevel); return writer.write(); } diff --git a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.h b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.h index fdc33d01e..26a255948 100644 --- a/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.h +++ b/src/framework/internal/Communication/TransportCommon/SceneUpdateSerializer.h @@ -9,6 +9,7 @@ #pragma once #include "internal/Communication/TransportCommon/ISceneUpdateSerializer.h" +#include "ramses/framework/EFeatureLevel.h" namespace ramses::internal { @@ -18,13 +19,15 @@ namespace ramses::internal class SceneUpdateSerializer : public ISceneUpdateSerializer { public: - explicit SceneUpdateSerializer(const SceneUpdate& update, StatisticCollectionScene& sceneStatistics); + SceneUpdateSerializer(const SceneUpdate& update, StatisticCollectionScene& sceneStatistics, EFeatureLevel featureLevel); bool writeToPackets(absl::Span packetMem, const std::function& writeDoneFunc) const override; [[nodiscard]] const SceneUpdate& getUpdate() const; [[nodiscard]] const StatisticCollectionScene& getStatisticCollection() const; + private: const SceneUpdate& m_update; StatisticCollectionScene& m_sceneStatistics; + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; }; } diff --git a/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.cpp b/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.cpp index d58504ff8..7611ddb6a 100644 --- a/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.cpp +++ b/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.cpp @@ -14,6 +14,11 @@ namespace ramses::internal { + SceneUpdateStreamDeserializer::SceneUpdateStreamDeserializer(EFeatureLevel featureLevel) + : m_featureLevel{ featureLevel } + { + } + SceneUpdateStreamDeserializer::Result SceneUpdateStreamDeserializer::processData(absl::Span data) { // check state + input @@ -200,7 +205,7 @@ namespace ramses::internal >> dataSize; m_currentResult.resources.push_back(ResourceSerialization::Deserialize(absl::Span(is.readPosition(), descSize), - absl::Span(is.readPosition() + descSize, dataSize))); + absl::Span(is.readPosition() + descSize, dataSize), m_featureLevel)); return true; } @@ -223,7 +228,7 @@ namespace ramses::internal return false; } - m_currentResult.flushInfos = FlushInformationSerialization::Deserialize(absl::Span(is.readPosition(), dataSize)); + m_currentResult.flushInfos = FlushInformationSerialization::Deserialize(absl::Span(is.readPosition(), dataSize), m_featureLevel); return true; } diff --git a/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.h b/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.h index 741a20739..3187f8c65 100644 --- a/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.h +++ b/src/framework/internal/Communication/TransportCommon/SceneUpdateStreamDeserializer.h @@ -10,6 +10,7 @@ #include "internal/SceneGraph/Scene/SceneActionCollection.h" #include "internal/Components/FlushInformation.h" +#include "ramses/framework/EFeatureLevel.h" #include "absl/types/span.h" namespace ramses::internal @@ -20,6 +21,8 @@ namespace ramses::internal class SceneUpdateStreamDeserializer { public: + explicit SceneUpdateStreamDeserializer(EFeatureLevel featureLevel); + enum class ResultType { Failed, @@ -60,5 +63,7 @@ namespace ramses::internal uint32_t m_blockType = 0; std::vector m_currentBlock; Result m_currentResult; + + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; }; } diff --git a/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.cpp b/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.cpp index 5bef2eeab..c862c654a 100644 --- a/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.cpp +++ b/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.cpp @@ -15,12 +15,18 @@ namespace ramses::internal { - SingleSceneUpdateWriter::SingleSceneUpdateWriter(const SceneUpdate& update, absl::Span packetMem, const std::function& writeDoneFunc, StatisticCollectionScene& sceneStatistics) + SingleSceneUpdateWriter::SingleSceneUpdateWriter( + const SceneUpdate& update, + absl::Span packetMem, + const std::function& writeDoneFunc, + StatisticCollectionScene& sceneStatistics, + EFeatureLevel featureLevel) : m_update(update) , m_packetMem(packetMem) , m_writeDoneFunc(writeDoneFunc) , m_packetWriter(m_packetMem.data(), static_cast(m_packetMem.size())) , m_sceneStatistics(sceneStatistics) + , m_featureLevel{ featureLevel } { /* Packet format @@ -114,7 +120,7 @@ namespace ramses::internal bool SingleSceneUpdateWriter::writeFlushInfos(const FlushInformation& infos) { m_temporaryMemToSerializeDescription.clear(); - const auto descSpan = FlushInformationSerialization::SerializeInfos(infos, m_temporaryMemToSerializeDescription); + const auto descSpan = FlushInformationSerialization::SerializeInfos(infos, m_temporaryMemToSerializeDescription, m_featureLevel); std::array header{}; RawBinaryOutputStream os(header.data(), header.size()); diff --git a/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.h b/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.h index 24d0deda8..81ca890f5 100644 --- a/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.h +++ b/src/framework/internal/Communication/TransportCommon/SingleSceneUpdateWriter.h @@ -10,6 +10,7 @@ #include "internal/Components/SceneUpdate.h" #include "internal/Core/Utils/RawBinaryOutputStream.h" +#include "ramses/framework/EFeatureLevel.h" #include "absl/types/span.h" namespace ramses::internal @@ -19,7 +20,12 @@ namespace ramses::internal class SingleSceneUpdateWriter { public: - SingleSceneUpdateWriter(const SceneUpdate& update, absl::Span packetMem, const std::function& writeDoneFunc, StatisticCollectionScene& sceneStatistics); + SingleSceneUpdateWriter( + const SceneUpdate& update, + absl::Span packetMem, + const std::function& writeDoneFunc, + StatisticCollectionScene& sceneStatistics, + EFeatureLevel featureLevel); bool write(); @@ -52,5 +58,6 @@ namespace ramses::internal std::vector m_temporaryMemToSerializeDescription; // optimization to avoid allocations StatisticCollectionScene& m_sceneStatistics; uint64_t m_overallSize{0}; + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; }; } diff --git a/src/framework/internal/Communication/TransportTCP/TCPConnectionSystem.cpp b/src/framework/internal/Communication/TransportTCP/TCPConnectionSystem.cpp index 907f829f4..dff02524b 100644 --- a/src/framework/internal/Communication/TransportTCP/TCPConnectionSystem.cpp +++ b/src/framework/internal/Communication/TransportTCP/TCPConnectionSystem.cpp @@ -948,6 +948,13 @@ namespace ramses::internal << s.friendlyName; } msg.stream << static_cast(featureLevel); + + if (featureLevel >= EFeatureLevel_02) + { + for (const auto& sceneInfo : newScenes) + msg.stream << sceneInfo.renderBackendCompatibility << sceneInfo.vulkanAPIVersion << sceneInfo.spirvVersion; + } + return postMessageForSending(std::move(msg)); } @@ -968,6 +975,13 @@ namespace ramses::internal << s.friendlyName; } msg.stream << static_cast(featureLevel); + + if (featureLevel >= EFeatureLevel_02) + { + for (const auto& sceneInfo : availableScenes) + msg.stream << sceneInfo.renderBackendCompatibility << sceneInfo.vulkanAPIVersion << sceneInfo.spirvVersion; + } + return postMessageForSending(std::move(msg)); } @@ -993,6 +1007,12 @@ namespace ramses::internal stream >> featureLevelInt; const auto featureLevel = static_cast(featureLevelInt); + if (featureLevel >= EFeatureLevel_02) + { + for (auto& sceneInfo : newScenes) + stream >> sceneInfo.renderBackendCompatibility >> sceneInfo.vulkanAPIVersion >> sceneInfo.spirvVersion; + } + LOG_DEBUG_F(CONTEXT_COMMUNICATION, ([&](StringOutputStream& sos) { sos << "TCPConnectionSystem(" << m_participantAddress.getParticipantName() << ")::handlePublishScene: from " << pp->address.getParticipantId() << " ["; for (const auto& s : newScenes) diff --git a/src/framework/internal/Components/ClientSceneLogicBase.cpp b/src/framework/internal/Components/ClientSceneLogicBase.cpp index df4d7edb5..df9982bd3 100644 --- a/src/framework/internal/Components/ClientSceneLogicBase.cpp +++ b/src/framework/internal/Components/ClientSceneLogicBase.cpp @@ -21,12 +21,13 @@ namespace ramses::internal { - ClientSceneLogicBase::ClientSceneLogicBase(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress) + ClientSceneLogicBase::ClientSceneLogicBase(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress, EFeatureLevel featureLevel) : m_scenegraphSender(sceneGraphSender) , m_resourceComponent(res) , m_myID(clientAddress) , m_sceneId(scene.getSceneId()) , m_scene(scene) + , m_featureLevel{ featureLevel } { std::fill(m_resourceCount.begin(), m_resourceCount.end(), 0); std::fill(m_resourceMaxSize.begin(), m_resourceMaxSize.end(), 0); @@ -43,7 +44,8 @@ namespace ramses::internal if (!m_scenePublicationMode.has_value()) { m_scenePublicationMode = publicationMode; - m_scenegraphSender.sendPublishScene(m_sceneId, publicationMode, m_scene.getName()); + SceneInfo sceneInfo{ m_sceneId, m_scene.getName(), publicationMode, m_scene.getRenderBackendCompatibility(), m_scene.getVulkanAPIVersion(), m_scene.getSPIRVVersion() }; + m_scenegraphSender.sendPublishScene(sceneInfo); } } @@ -114,7 +116,7 @@ namespace ramses::internal } SceneUpdate sceneUpdate; - SceneActionCollectionCreator creator(sceneUpdate.actions); + SceneActionCollectionCreator creator(sceneUpdate.actions, m_featureLevel); SceneDescriber::describeScene(scene, creator); m_resourceChangesSinceLastFlush.clear(); @@ -136,7 +138,8 @@ namespace ramses::internal assert(m_scenePublicationMode.has_value()); for(const auto& subscriber : m_subscribersWaitingForScene) { - m_scenegraphSender.sendCreateScene(subscriber, m_sceneId, *m_scenePublicationMode); + SceneInfo sceneInfo{ m_sceneId, scene.getName(), *m_scenePublicationMode, scene.getRenderBackendCompatibility(), scene.getVulkanAPIVersion(), scene.getSPIRVVersion() }; + m_scenegraphSender.sendCreateScene(subscriber, sceneInfo); } m_scene.getStatisticCollection().statSceneActionsSent.incCounter(sceneUpdate.actions.numberOfActions()*static_cast(m_subscribersWaitingForScene.size())); m_scenegraphSender.sendSceneUpdate(m_subscribersWaitingForScene, std::move(sceneUpdate), m_sceneId, *m_scenePublicationMode, m_scene.getStatisticCollection()); diff --git a/src/framework/internal/Components/ClientSceneLogicBase.h b/src/framework/internal/Components/ClientSceneLogicBase.h index e1d5acc80..4d528aa98 100644 --- a/src/framework/internal/Components/ClientSceneLogicBase.h +++ b/src/framework/internal/Components/ClientSceneLogicBase.h @@ -24,7 +24,7 @@ namespace ramses::internal class ClientSceneLogicBase { public: - ClientSceneLogicBase(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress); + ClientSceneLogicBase(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress, EFeatureLevel featureLevel); virtual ~ClientSceneLogicBase(); void publish(EScenePublicationMode publicationMode); @@ -73,6 +73,8 @@ namespace ramses::internal ResourceChanges m_resourceChangesSinceLastFlush; // keep container memory allocated ResourceContentHashVector m_currentFlushResourcesInUse; // keep container memory allocated + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; + // resource statistics gathered while flushing the last time std::array m_resourceCount{}; std::array m_resourceDataSize{}; diff --git a/src/framework/internal/Components/ClientSceneLogicDirect.cpp b/src/framework/internal/Components/ClientSceneLogicDirect.cpp index 8f92ee2a1..e0882a288 100644 --- a/src/framework/internal/Components/ClientSceneLogicDirect.cpp +++ b/src/framework/internal/Components/ClientSceneLogicDirect.cpp @@ -21,8 +21,8 @@ namespace ramses::internal { - ClientSceneLogicDirect::ClientSceneLogicDirect(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress) - : ClientSceneLogicBase(sceneGraphSender, scene, res, clientAddress) + ClientSceneLogicDirect::ClientSceneLogicDirect(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress, EFeatureLevel featureLevel) + : ClientSceneLogicBase(sceneGraphSender, scene, res, clientAddress, featureLevel) , m_previousSceneSizes(m_scene.getSceneSizeInformation()) { } @@ -48,18 +48,14 @@ namespace ramses::internal if (m_flushCounter == 0) { - LOG_INFO_F(CONTEXT_CLIENT, ([&](StringOutputStream& sos) { - sos << "ClientSceneLogicDirect::flushSceneActions: first flush, sceneId " << m_sceneId - << ", numActions " << sceneUpdate.actions.numberOfActions() << ", published " << isPublished() - << ", numResources " << sceneUpdate.resources.size() - << ", subsActive ["; - for (const auto& sub : m_subscribersActive) - sos << sub << " "; - sos << "], subsWaiting ["; - for (const auto& sub : m_subscribersWaitingForScene) - sos << sub << " "; - sos << "]"; - })); + LOG_INFO(CONTEXT_CLIENT, + "ClientSceneLogicDirect::flushSceneActions: first flush, sceneId {}, numActions {}, published {}, numResources {}, subsActive [{}], subsWaiting [{}]", + m_sceneId, + sceneUpdate.actions.numberOfActions(), + isPublished(), + sceneUpdate.resources.size(), + fmt::join(m_subscribersActive, " "), + fmt::join(m_subscribersWaitingForScene, " ")); } const bool expirationChanged = updateExpirationAndCheckIfChanged(flushTimeInfo); diff --git a/src/framework/internal/Components/ClientSceneLogicDirect.h b/src/framework/internal/Components/ClientSceneLogicDirect.h index 7f26b2ee0..b932dfe07 100644 --- a/src/framework/internal/Components/ClientSceneLogicDirect.h +++ b/src/framework/internal/Components/ClientSceneLogicDirect.h @@ -16,7 +16,7 @@ namespace ramses::internal class ClientSceneLogicDirect final : public ClientSceneLogicBase { public: - ClientSceneLogicDirect(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress); + ClientSceneLogicDirect(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress, EFeatureLevel featureLevel); bool flushSceneActions(const FlushTimeInformation& flushTimeInfo, SceneVersionTag versionTag) override; diff --git a/src/framework/internal/Components/ClientSceneLogicShadowCopy.cpp b/src/framework/internal/Components/ClientSceneLogicShadowCopy.cpp index 84372c667..995d7d57d 100644 --- a/src/framework/internal/Components/ClientSceneLogicShadowCopy.cpp +++ b/src/framework/internal/Components/ClientSceneLogicShadowCopy.cpp @@ -20,9 +20,9 @@ namespace ramses::internal { - ClientSceneLogicShadowCopy::ClientSceneLogicShadowCopy(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress) - : ClientSceneLogicBase(sceneGraphSender, scene, res, clientAddress) - , m_sceneShadowCopy(SceneInfo(scene.getSceneId(), scene.getName())) + ClientSceneLogicShadowCopy::ClientSceneLogicShadowCopy(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress, EFeatureLevel featureLevel) + : ClientSceneLogicBase(sceneGraphSender, scene, res, clientAddress, featureLevel) + , m_sceneShadowCopy(SceneInfo{ scene.getSceneId(), scene.getName(), EScenePublicationMode::LocalOnly, scene.getRenderBackendCompatibility(), scene.getVulkanAPIVersion(), scene.getSPIRVVersion() }) { m_sceneShadowCopy.preallocateSceneSize(m_scene.getSceneSizeInformation()); } @@ -55,17 +55,14 @@ namespace ramses::internal if (m_flushCounter == 0) { - LOG_INFO_F(CONTEXT_CLIENT, ([&](StringOutputStream& sos) { - sos << "ClientSceneLogicShadowCopy::flushSceneActions: first flush, sceneId " << m_sceneId << ", numActions " << sceneUpdate.actions.numberOfActions() << ", published " << isPublished() - << ", numResources " << sceneUpdate.resources.size() - << ", subsActive ["; - for (const auto& sub : m_subscribersActive) - sos << sub << " "; - sos << "], subsWaiting ["; - for (const auto& sub : m_subscribersWaitingForScene) - sos << sub << " "; - sos << "]"; - })); + LOG_INFO(CONTEXT_CLIENT, + "ClientSceneLogicShadowCopy::flushSceneActions: first flush, sceneId {}, numActions {}, published {}, numResources {}, subsActive [{}], subsWaiting [{}]", + m_sceneId, + sceneUpdate.actions.numberOfActions(), + isPublished(), + sceneUpdate.resources.size(), + fmt::join(m_subscribersActive, " "), + fmt::join(m_subscribersWaitingForScene, " ")); } const bool expirationChanged = updateExpirationAndCheckIfChanged(flushTimeInfo); @@ -82,7 +79,7 @@ namespace ramses::internal if (hasNewActions) { m_sceneShadowCopy.preallocateSceneSize(sceneSizes); - SceneActionApplier::ApplyActionsOnScene(m_sceneShadowCopy, sceneUpdate.actions); + SceneActionApplier::ApplyActionsOnScene(m_sceneShadowCopy, sceneUpdate.actions, m_featureLevel); m_scene.getStatisticCollection().statSceneActionsGenerated.incCounter(sceneUpdate.actions.numberOfActions()); m_scene.getStatisticCollection().statSceneActionsGeneratedSize.incCounter(static_cast(sceneUpdate.actions.collectionData().size())); } diff --git a/src/framework/internal/Components/ClientSceneLogicShadowCopy.h b/src/framework/internal/Components/ClientSceneLogicShadowCopy.h index 2cc779d20..807d4da03 100644 --- a/src/framework/internal/Components/ClientSceneLogicShadowCopy.h +++ b/src/framework/internal/Components/ClientSceneLogicShadowCopy.h @@ -17,7 +17,7 @@ namespace ramses::internal class ClientSceneLogicShadowCopy final : public ClientSceneLogicBase { public: - ClientSceneLogicShadowCopy(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress); + ClientSceneLogicShadowCopy(ISceneGraphSender& sceneGraphSender, ClientScene& scene, IResourceProviderComponent& res, const Guid& clientAddress, EFeatureLevel featureLevel); bool flushSceneActions(const FlushTimeInformation& flushTimeInfo, SceneVersionTag versionTag) override; diff --git a/src/framework/internal/Components/ISceneGraphSender.h b/src/framework/internal/Components/ISceneGraphSender.h index 61defd7d5..93e7c9a36 100644 --- a/src/framework/internal/Components/ISceneGraphSender.h +++ b/src/framework/internal/Components/ISceneGraphSender.h @@ -22,9 +22,9 @@ namespace ramses::internal { public: virtual ~ISceneGraphSender() = default; - virtual void sendPublishScene (SceneId sceneId, EScenePublicationMode publicationMode, std::string_view name) = 0; + virtual void sendPublishScene (const SceneInfo& sceneInfo) = 0; virtual void sendUnpublishScene (SceneId sceneId, EScenePublicationMode publicationMode) = 0; - virtual void sendCreateScene (const Guid& to, const SceneId& sceneId, EScenePublicationMode publicationMode) = 0; + virtual void sendCreateScene (const Guid& to, const SceneInfo& sceneInfo) = 0; virtual void sendSceneUpdate (const std::vector& to, SceneUpdate&& sceneUpdate, SceneId sceneId, EScenePublicationMode mode, StatisticCollectionScene& sceneStatistics) = 0; }; } diff --git a/src/framework/internal/Components/ResourceComponent.cpp b/src/framework/internal/Components/ResourceComponent.cpp index a4778ebd6..a20ada101 100644 --- a/src/framework/internal/Components/ResourceComponent.cpp +++ b/src/framework/internal/Components/ResourceComponent.cpp @@ -14,9 +14,10 @@ namespace ramses::internal { - ResourceComponent::ResourceComponent(StatisticCollectionFramework& statistics, PlatformLock& frameworkLock) - : m_resourceStorage(frameworkLock, statistics) - , m_statistics(statistics) + ResourceComponent::ResourceComponent(StatisticCollectionFramework& statistics, PlatformLock& frameworkLock, EFeatureLevel featureLevel) + : m_resourceStorage{ frameworkLock, statistics } + , m_statistics{ statistics } + , m_featureLevel{ featureLevel } { } @@ -110,7 +111,7 @@ namespace ramses::internal try { - lowLevelResource = ResourcePersistation::RetrieveResourceFromStream(*resourceStream, entry); + lowLevelResource = ResourcePersistation::RetrieveResourceFromStream(*resourceStream, entry, m_featureLevel); } catch(std::exception const& e) { diff --git a/src/framework/internal/Components/ResourceComponent.h b/src/framework/internal/Components/ResourceComponent.h index 75f814f82..26363e7c8 100644 --- a/src/framework/internal/Components/ResourceComponent.h +++ b/src/framework/internal/Components/ResourceComponent.h @@ -20,7 +20,7 @@ namespace ramses::internal class ResourceComponent : public IResourceProviderComponent { public: - ResourceComponent(StatisticCollectionFramework& statistics, PlatformLock& frameworkLock); + ResourceComponent(StatisticCollectionFramework& statistics, PlatformLock& frameworkLock, EFeatureLevel featureLevel); ~ResourceComponent() override; // implement IResourceProviderComponent @@ -49,5 +49,6 @@ namespace ramses::internal ResourceFilesRegistry m_resourceFiles; StatisticCollectionFramework& m_statistics; + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; }; } diff --git a/src/framework/internal/Components/ResourcePersistation.cpp b/src/framework/internal/Components/ResourcePersistation.cpp index d9df3e8bc..853f15b2b 100644 --- a/src/framework/internal/Components/ResourcePersistation.cpp +++ b/src/framework/internal/Components/ResourcePersistation.cpp @@ -28,9 +28,9 @@ namespace ramses::internal SingleResourceSerialization::SerializeResource(outStream, *resource.get()); } - std::unique_ptr ResourcePersistation::ReadOneResourceFromStream(IInputStream& inStream, const ResourceContentHash& hash) + std::unique_ptr ResourcePersistation::ReadOneResourceFromStream(IInputStream& inStream, const ResourceContentHash& hash, EFeatureLevel featureLevel) { - return SingleResourceSerialization::DeserializeResource(inStream, hash); + return SingleResourceSerialization::DeserializeResource(inStream, hash, featureLevel); } void ResourcePersistation::WriteNamedResourcesWithTOCToStream(IOutputStream& outStream, const ManagedResourceVector& resourcesForFile, bool compress) @@ -91,7 +91,7 @@ namespace ramses::internal } } - std::unique_ptr ResourcePersistation::RetrieveResourceFromStream(IInputStream& inStream, const ResourceFileEntry& fileEntry) + std::unique_ptr ResourcePersistation::RetrieveResourceFromStream(IInputStream& inStream, const ResourceFileEntry& fileEntry, EFeatureLevel featureLevel) { LOG_DEBUG(CONTEXT_FRAMEWORK, "ResourcePersistation::RetrieveResourceFromStream: Hash {}, Size {}, Offset {}", fileEntry.resourceInfo.hash, fileEntry.sizeInBytes, fileEntry.offsetInBytes); @@ -102,7 +102,7 @@ namespace ramses::internal return {}; } - std::unique_ptr resource = ReadOneResourceFromStream(inStream, fileEntry.resourceInfo.hash); + std::unique_ptr resource = ReadOneResourceFromStream(inStream, fileEntry.resourceInfo.hash, featureLevel); if (!resource) return {}; diff --git a/src/framework/internal/Components/ResourcePersistation.h b/src/framework/internal/Components/ResourcePersistation.h index 8390035f1..426470498 100644 --- a/src/framework/internal/Components/ResourcePersistation.h +++ b/src/framework/internal/Components/ResourcePersistation.h @@ -11,6 +11,7 @@ #include "internal/PlatformAbstraction/Collections/Vector.h" #include "ManagedResource.h" #include "internal/PlatformAbstraction/Collections/Pair.h" +#include "ramses/framework/EFeatureLevel.h" #include namespace ramses::internal @@ -26,7 +27,7 @@ namespace ramses::internal static void WriteNamedResourcesWithTOCToStream(IOutputStream& outStream, const ManagedResourceVector& resourcesForFile, bool compress); static void WriteOneResourceToStream(IOutputStream& outStream, const ManagedResource& resource); - static std::unique_ptr ReadOneResourceFromStream(IInputStream& inStream, const ResourceContentHash& hash); - static std::unique_ptr RetrieveResourceFromStream(IInputStream& inStream, const ResourceFileEntry& entry); + static std::unique_ptr ReadOneResourceFromStream(IInputStream& inStream, const ResourceContentHash& hash, EFeatureLevel featureLevel); + static std::unique_ptr RetrieveResourceFromStream(IInputStream& inStream, const ResourceFileEntry& entry, EFeatureLevel featureLevel); }; } diff --git a/src/framework/internal/Components/ResourceSerializationHelper.cpp b/src/framework/internal/Components/ResourceSerializationHelper.cpp index ec2d817ac..8ffdfa80d 100644 --- a/src/framework/internal/Components/ResourceSerializationHelper.cpp +++ b/src/framework/internal/Components/ResourceSerializationHelper.cpp @@ -39,7 +39,7 @@ namespace ramses::internal return static_cast(stream.getSize()); } - DeserializedResourceHeader ResourceFromMetadataStream(IInputStream& input) + DeserializedResourceHeader ResourceFromMetadataStream(IInputStream& input, EFeatureLevel featureLevel) { uint32_t resourceTypeValue = 0; std::string name; @@ -69,7 +69,7 @@ namespace ramses::internal resource = ArrayResource::CreateResourceFromMetadataStream(input, resourceType, name); break; case EResourceType::Effect: - resource = EffectResource::CreateResourceFromMetadataStream(input, name); + resource = EffectResource::CreateResourceFromMetadataStream(input, name, featureLevel); break; default: LOG_ERROR(CONTEXT_FRAMEWORK, "ResourceSerializationHelper::ResourceFromMetadataStream: Failed for unknown resource type {}", resourceType); diff --git a/src/framework/internal/Components/ResourceSerializationHelper.h b/src/framework/internal/Components/ResourceSerializationHelper.h index 53c68fcf3..11056d730 100644 --- a/src/framework/internal/Components/ResourceSerializationHelper.h +++ b/src/framework/internal/Components/ResourceSerializationHelper.h @@ -10,7 +10,7 @@ #include "internal/SceneGraph/Resource/EResourceCompressionStatus.h" #include "internal/SceneGraph/Resource/IResource.h" - +#include "ramses/framework/EFeatureLevel.h" #include namespace ramses::internal @@ -32,6 +32,6 @@ namespace ramses::internal void SerializeResourceMetadata(IOutputStream& output, const IResource& resource); uint32_t ResourceMetadataSize(const IResource& resource); - DeserializedResourceHeader ResourceFromMetadataStream(IInputStream& input); + DeserializedResourceHeader ResourceFromMetadataStream(IInputStream& input, EFeatureLevel featureLevel); } } diff --git a/src/framework/internal/Components/SceneGraphComponent.cpp b/src/framework/internal/Components/SceneGraphComponent.cpp index 24622e8f0..6cfe97a18 100644 --- a/src/framework/internal/Components/SceneGraphComponent.cpp +++ b/src/framework/internal/Components/SceneGraphComponent.cpp @@ -89,15 +89,14 @@ namespace ramses::internal } } - // TODO(tobias) remove mode, already given with publish - void SceneGraphComponent::sendCreateScene(const Guid& to, const SceneId& sceneId, [[maybe_unused]] EScenePublicationMode mode) + void SceneGraphComponent::sendCreateScene(const Guid& to, const SceneInfo& sceneInfo) { - LOG_INFO(CONTEXT_FRAMEWORK, "SceneGraphComponent::sendCreateScene: sceneId {}, to {}", sceneId, to); + LOG_INFO(CONTEXT_FRAMEWORK, "SceneGraphComponent::sendCreateScene: sceneId {}, to {}", sceneInfo.sceneID, to); - const SceneInfo* info = m_locallyPublishedScenes.get(sceneId); + const SceneInfo* info = m_locallyPublishedScenes.get(sceneInfo.sceneID); if (!info) { - LOG_ERROR(CONTEXT_FRAMEWORK, "SceneGraphComponent::sendCreateScene: scene not published, sceneId {}", sceneId); + LOG_ERROR(CONTEXT_FRAMEWORK, "SceneGraphComponent::sendCreateScene: scene not published, sceneId {}", sceneInfo.sceneID); // return; // TODO: lots of tests must be fixed for this check } @@ -111,14 +110,14 @@ namespace ramses::internal } else { - m_sceneRendererHandler->handleInitializeScene(SceneInfo(sceneId, "", mode), m_myID); + m_sceneRendererHandler->handleInitializeScene(sceneInfo, m_myID); } } } else { - assert(mode != EScenePublicationMode::LocalOnly); - m_communicationSystem.sendInitializeScene(to, sceneId); + assert(sceneInfo.publicationMode != EScenePublicationMode::LocalOnly); + m_communicationSystem.sendInitializeScene(to, sceneInfo.sceneID); } } @@ -143,7 +142,7 @@ namespace ramses::internal } alreadyCompressed = true; } - m_communicationSystem.sendSceneUpdate(to, sceneId, SceneUpdateSerializer(sceneUpdate, sceneStatistics)); + m_communicationSystem.sendSceneUpdate(to, sceneId, SceneUpdateSerializer(sceneUpdate, sceneStatistics, m_featureLevel)); } } @@ -152,19 +151,17 @@ namespace ramses::internal m_sceneRendererHandler->handleSceneUpdate(sceneId, std::move(sceneUpdate), m_myID); } - void SceneGraphComponent::sendPublishScene(SceneId sceneId, EScenePublicationMode mode, std::string_view name) + void SceneGraphComponent::sendPublishScene(const SceneInfo& sceneInfo) { - LOG_INFO(CONTEXT_FRAMEWORK, "SceneGraphComponent::publishScene: publishing scene: {} mode: {}", sceneId, EnumToString(mode)); - - SceneInfo info(sceneId, name, mode); + LOG_INFO(CONTEXT_FRAMEWORK, "SceneGraphComponent::publishScene: publishing scene: {} mode: {}", sceneInfo.sceneID, EnumToString(sceneInfo.publicationMode)); if (m_sceneRendererHandler) - m_sceneRendererHandler->handleNewSceneAvailable(info, m_myID); + m_sceneRendererHandler->handleNewSceneAvailable(sceneInfo, m_myID); - if (mode != EScenePublicationMode::LocalOnly && m_connected) - m_communicationSystem.broadcastNewScenesAvailable({info}, m_featureLevel); + if (sceneInfo.publicationMode != EScenePublicationMode::LocalOnly && m_connected) + m_communicationSystem.broadcastNewScenesAvailable({ sceneInfo }, m_featureLevel); - m_locallyPublishedScenes.put(sceneId, info); + m_locallyPublishedScenes.put(sceneInfo.sceneID, sceneInfo); } void SceneGraphComponent::sendUnpublishScene(SceneId sceneId, EScenePublicationMode mode) @@ -301,12 +298,12 @@ namespace ramses::internal if (enableLocalOnlyOptimization) { LOG_INFO(CONTEXT_CLIENT, "SceneGraphComponent::handleCreateScene: creating scene {} (direct)", scene.getSceneId()); - sceneLogic = new ClientSceneLogicDirect(*this, scene, m_resourceComponent, m_myID); + sceneLogic = new ClientSceneLogicDirect(*this, scene, m_resourceComponent, m_myID, m_featureLevel); } else { LOG_INFO(CONTEXT_CLIENT, "SceneGraphComponent::handleCreateScene: creating scene {} (shadow copy)", scene.getSceneId()); - sceneLogic = new ClientSceneLogicShadowCopy(*this, scene, m_resourceComponent, m_myID); + sceneLogic = new ClientSceneLogicShadowCopy(*this, scene, m_resourceComponent, m_myID, m_featureLevel); } m_sceneEventConsumers.put(sceneId, &eventConsumer); m_clientSceneLogicMap.put(sceneId, sceneLogic); @@ -515,7 +512,7 @@ namespace ramses::internal // start with fresh deinitializer // TODO(tobias) should already be cleared when unsub was sent ou for this scene - it->second.sceneUpdateDeserializer = std::make_unique(); + it->second.sceneUpdateDeserializer = std::make_unique(m_featureLevel); m_sceneRendererHandler->handleInitializeScene(it->second.info, providerID); } @@ -598,8 +595,9 @@ namespace ramses::internal m_remoteScenes[newScene.sceneID] = ReceivedScene{ newScene, providerID, nullptr }; + assert(newScene.publicationMode == EScenePublicationMode::LocalAndRemote); if (m_sceneRendererHandler) - m_sceneRendererHandler->handleNewSceneAvailable(SceneInfo(newScene.sceneID, newScene.friendlyName, EScenePublicationMode::LocalAndRemote), providerID); + m_sceneRendererHandler->handleNewSceneAvailable(newScene, providerID); } else { diff --git a/src/framework/internal/Components/SceneGraphComponent.h b/src/framework/internal/Components/SceneGraphComponent.h index 2d4dccf56..fe0e49096 100644 --- a/src/framework/internal/Components/SceneGraphComponent.h +++ b/src/framework/internal/Components/SceneGraphComponent.h @@ -58,9 +58,9 @@ namespace ramses::internal void setSceneRendererHandler(ISceneRendererHandler* sceneRendererHandler) override; // ISceneGraphSender - void sendCreateScene(const Guid& to, const SceneId& sceneId, EScenePublicationMode mode) override; + void sendCreateScene(const Guid& to, const SceneInfo& sceneInfo) override; void sendSceneUpdate(const std::vector& toVec, SceneUpdate&& sceneUpdate, SceneId sceneId, EScenePublicationMode mode, StatisticCollectionScene& sceneStatistics) override; - void sendPublishScene(SceneId sceneId, EScenePublicationMode mode, std::string_view name) override; + void sendPublishScene(const SceneInfo& sceneInfo) override; void sendUnpublishScene(SceneId sceneId, EScenePublicationMode mode) override; // ISceneGraphConsumerComponent @@ -122,7 +122,7 @@ namespace ramses::internal IResourceProviderComponent& m_resourceComponent; - EFeatureLevel m_featureLevel = EFeatureLevel_01; + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; struct ReceivedScene { diff --git a/src/framework/internal/Components/SingleResourceSerialization.cpp b/src/framework/internal/Components/SingleResourceSerialization.cpp index 46fc72094..edd1cfc56 100644 --- a/src/framework/internal/Components/SingleResourceSerialization.cpp +++ b/src/framework/internal/Components/SingleResourceSerialization.cpp @@ -44,10 +44,10 @@ namespace ramses::internal } } - std::unique_ptr SingleResourceSerialization::DeserializeResource(IInputStream& input, ResourceContentHash hash) + std::unique_ptr SingleResourceSerialization::DeserializeResource(IInputStream& input, ResourceContentHash hash, EFeatureLevel featureLevel) { // header - ResourceSerializationHelper::DeserializedResourceHeader header = ResourceSerializationHelper::ResourceFromMetadataStream(input); + ResourceSerializationHelper::DeserializedResourceHeader header = ResourceSerializationHelper::ResourceFromMetadataStream(input, featureLevel); if (!header.resource) return {}; diff --git a/src/framework/internal/Components/SingleResourceSerialization.h b/src/framework/internal/Components/SingleResourceSerialization.h index d3aaa5f4f..1e8b19554 100644 --- a/src/framework/internal/Components/SingleResourceSerialization.h +++ b/src/framework/internal/Components/SingleResourceSerialization.h @@ -9,7 +9,7 @@ #pragma once #include "internal/SceneGraph/SceneAPI/ResourceContentHash.h" - +#include "ramses/framework/EFeatureLevel.h" #include #include @@ -25,6 +25,6 @@ namespace ramses::internal static uint32_t SizeOfSerializedResource(const IResource& resource); static void SerializeResource(IOutputStream& output, const IResource& resource); - static std::unique_ptr DeserializeResource(IInputStream& input, ResourceContentHash hash); + static std::unique_ptr DeserializeResource(IInputStream& input, ResourceContentHash hash, EFeatureLevel featureLevel); }; } diff --git a/src/framework/internal/Core/Utils/EnumTraits.h b/src/framework/internal/Core/Utils/EnumTraits.h index 7295196e2..bdd181e7a 100644 --- a/src/framework/internal/Core/Utils/EnumTraits.h +++ b/src/framework/internal/Core/Utils/EnumTraits.h @@ -41,22 +41,29 @@ namespace ramses::internal // Examples: // Possible __FUNCSIG__/__PRETTY_FUNCTION__ for a known (valid) enum value: // "bool ramses::internal::EnumTraits::internal::IsValid(void)" - // ^-- separatorIndex + // ^-- separatorIndex // "bool ramses::internal::EnumTraits::internal::IsValid() [E = ramses::EFoo, V = ramses::EFoo::Value1] - // ^-- separatorIndex + // ^-- separatorIndex + // "bool ramses::internal::EnumTraits::internal::IsValid() [E = ramses::(anonymous namespace)::EFoo, V = ramses::(anonymous namespace)::EFoo::Value1] + // ^-- separatorIndex // // Possible __FUNCSIG__/__PRETTY_FUNCTION__ for an unknown (invalid) enum value: // "bool ramses::internal::EnumTraits::internal::IsValid(void)" - // ^-- separatorIndex + // ^-- separatorIndex // "bool ramses::internal::EnumTraits::internal::IsValid() [E = ramses::EFoo, V = 15] - // ^-- separatorIndex + // ^-- separatorIndex // "bool ramses::internal::EnumTraits::internal::IsValid() [E = ramses::EFoo, V = -3] - // ^-- separatorIndex + // ^-- separatorIndex + // "bool ramses::internal::EnumTraits::internal::IsValid() [E = ramses::(anonymous namespace)::EFoo, V = -3] + // ^-- separatorIndex // // separatorIndex identifies the position of the enum value (template parameter V) #if defined(__GNUC__) const std::string_view name = __PRETTY_FUNCTION__; - const auto separatorIndex = name.rfind(' '); + const auto valueIndex = name.rfind("V = "); + if (valueIndex == std::string_view::npos) + return false; + const auto separatorIndex = valueIndex + 3; #elif defined (_MSC_VER) const std::string_view name = __FUNCSIG__; const auto separatorIndex = name.rfind(','); diff --git a/src/framework/internal/Core/Utils/RamsesLogger.h b/src/framework/internal/Core/Utils/RamsesLogger.h index c1d9f7143..b67518f6a 100644 --- a/src/framework/internal/Core/Utils/RamsesLogger.h +++ b/src/framework/internal/Core/Utils/RamsesLogger.h @@ -76,8 +76,6 @@ namespace ramses::internal void setLogHandler(const LogHandlerFunc& logHandlerFunc); static const char* GetLogLevelText(ELogLevel logLevel); - static void SetPrefixes(std::string_view instance, std::string_view thread, std::string_view additional = {}); - static void SetPrefixAdditional(std::string_view additional); static const std::string& GetPrefixInstance(); private: @@ -88,6 +86,8 @@ namespace ramses::internal static thread_local std::string PrefixThread; static thread_local std::string PrefixAdditional; static thread_local std::string PrefixCombined; + static void SetPrefixes(std::string_view instance, std::string_view thread, std::string_view additional = {}); + static void SetPrefixAdditional(std::string_view additional); void applyContextFilter(const std::string& context, ELogLevel logLevel); @@ -103,5 +103,8 @@ namespace ramses::internal std::map> m_logContexts; std::vector m_logAppenders; LogContext& m_fileTransferContext; + + friend class RamsesLoggerPrefixes; + friend class RamsesLoggerPrefixesExported; }; } diff --git a/src/framework/internal/Core/Utils/RamsesLoggerPrefixes.cpp b/src/framework/internal/Core/Utils/RamsesLoggerPrefixes.cpp new file mode 100644 index 000000000..e14fa07d1 --- /dev/null +++ b/src/framework/internal/Core/Utils/RamsesLoggerPrefixes.cpp @@ -0,0 +1,25 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "internal/Core/Utils/RamsesLoggerPrefixes.h" +#include "impl/RamsesLoggerImpl.h" + +namespace ramses::internal +{ + void RamsesLoggerPrefixes::SetRamsesLoggerPrefixes(std::string_view instance, std::string_view thread, std::string_view additional) + { + RamsesLoggerPrefixesExported::SetRamsesLoggerPrefixesExported(instance, thread, additional); + RamsesLogger::SetPrefixes(instance, thread, additional); + } + + void RamsesLoggerPrefixes::SetRamsesLoggerPrefixAdditional(std::string_view additional) + { + RamsesLoggerPrefixesExported::SetRamsesLoggerPrefixAdditionalExported(additional); + RamsesLogger::SetPrefixAdditional(additional); + } +} diff --git a/src/framework/internal/Core/Utils/RamsesLoggerPrefixes.h b/src/framework/internal/Core/Utils/RamsesLoggerPrefixes.h new file mode 100644 index 000000000..0cd2244ba --- /dev/null +++ b/src/framework/internal/Core/Utils/RamsesLoggerPrefixes.h @@ -0,0 +1,27 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include + +namespace ramses::internal +{ + // This construct is a workaround to solve thread local storage across shared libraries for logging prefixes. + // When these are called it will set the prefixes in both caller's side library (e.g. shared lib with renderer) + // and also the core library (shared headless). This is needed to have the correct prefixes in logs for code compiled + // into core library but invoked from renderer shared library (and vice versa if there was such case). + // The reason is that each shared library has own copy of thread local storage so the actual value does not only depend + // on thread but also which library is the log invoked from (this also seems to be the case on all platforms so far). + class RamsesLoggerPrefixes + { + public: + static void SetRamsesLoggerPrefixes(std::string_view instance, std::string_view thread, std::string_view additional = {}); + static void SetRamsesLoggerPrefixAdditional(std::string_view additional); + }; +} diff --git a/src/framework/internal/PlatformAbstraction/Collections/Guid.h b/src/framework/internal/PlatformAbstraction/Collections/Guid.h index 708d2a231..11b1ede9b 100644 --- a/src/framework/internal/PlatformAbstraction/Collections/Guid.h +++ b/src/framework/internal/PlatformAbstraction/Collections/Guid.h @@ -113,7 +113,7 @@ struct fmt::formatter } template - constexpr auto format(const ramses::internal::Guid& guid, FormatContext& ctx) + auto format(const ramses::internal::Guid& guid, FormatContext& ctx) const { const uint64_t v = guid.get(); if (v < 256) diff --git a/src/framework/internal/PlatformAbstraction/PlatformThread.h b/src/framework/internal/PlatformAbstraction/PlatformThread.h index e60420a6e..e05bfc8e8 100644 --- a/src/framework/internal/PlatformAbstraction/PlatformThread.h +++ b/src/framework/internal/PlatformAbstraction/PlatformThread.h @@ -9,7 +9,8 @@ #pragma once #include "internal/PlatformAbstraction/Runnable.h" -#include "impl/RamsesLoggerImpl.h" +#include "internal/Core/Utils/RamsesLogger.h" +#include "internal/Core/Utils/RamsesLoggerPrefixes.h" #include #include @@ -98,7 +99,7 @@ namespace ramses::internal m_isRunning = true; m_thread = internal::Thread(fmt::format("R_{}", m_name), [&]() { // set global instance and thread name to logger - RamsesLogger::SetPrefixes(m_loggingInstanceName, m_name); + RamsesLoggerPrefixes::SetRamsesLoggerPrefixes(m_loggingInstanceName, m_name); m_runnable->run(); m_isRunning = false; diff --git a/src/framework/internal/Ramsh/RamshCommandArgumentsDataProvider.h b/src/framework/internal/Ramsh/RamshCommandArgumentsDataProvider.h index f180af0e8..9ddb16505 100644 --- a/src/framework/internal/Ramsh/RamshCommandArgumentsDataProvider.h +++ b/src/framework/internal/Ramsh/RamshCommandArgumentsDataProvider.h @@ -273,9 +273,7 @@ namespace ramses::internal // if a default value is set, return a string representation, else the argument is mandatory if(m_defaultValue) { - StringOutputStream s; - s << *static_cast(m_defaultValue); - return s.c_str(); + return fmt::format("{}", *static_cast(m_defaultValue)); } return "required"; } diff --git a/src/framework/internal/SceneGraph/Resource/EffectInputInformation.h b/src/framework/internal/SceneGraph/Resource/EffectInputInformation.h index eaa2e55c3..9b646b5e6 100644 --- a/src/framework/internal/SceneGraph/Resource/EffectInputInformation.h +++ b/src/framework/internal/SceneGraph/Resource/EffectInputInformation.h @@ -11,9 +11,11 @@ #include "internal/PlatformAbstraction/Collections/Vector.h" #include "internal/SceneGraph/SceneAPI/EDataType.h" #include "internal/SceneGraph/SceneAPI/EFixedSemantics.h" +#include "internal/SceneGraph/SceneAPI/SceneTypes.h" #include #include +#include namespace ramses::internal { @@ -45,24 +47,48 @@ namespace ramses::internal struct EffectInputInformation { EffectInputInformation() = default; - inline EffectInputInformation(std::string_view inputName_, uint32_t elementCount_, EDataType dataType_, EFixedSemantics semantics_); + inline EffectInputInformation(std::string_view inputName_, + uint32_t elementCount_, + EDataType dataType_, + EFixedSemantics semantics_, + UniformBufferBinding uniformBufferBinding_ = {}, + UniformBufferElementSize uniformBufferElementSize_= {}, + UniformBufferFieldOffset uniformBufferFieldOffset_ = {} + ); inline friend bool operator==(const EffectInputInformation& a, const EffectInputInformation& b); inline friend bool operator!=(const EffectInputInformation& a, const EffectInputInformation& b); + static inline bool IsUniformBuffer(const EffectInputInformation& input); + static inline bool IsUniformBufferField(const EffectInputInformation& input); - std::string inputName; - uint32_t elementCount{1u}; - EDataType dataType{EDataType::Invalid}; - EFixedSemantics semantics{EFixedSemantics::Invalid}; + std::string inputName; + uint32_t elementCount{ std::numeric_limits::max() }; + EDataType dataType{EDataType::Invalid}; + EFixedSemantics semantics{EFixedSemantics::Invalid}; + + UniformBufferBinding uniformBufferBinding; + UniformBufferElementSize uniformBufferElementSize; + UniformBufferFieldOffset uniformBufferFieldOffset; + + DataFieldHandle dataFieldHandle{}; }; using EffectInputInformationVector = std::vector; - EffectInputInformation::EffectInputInformation(std::string_view inputName_, uint32_t elementCount_, EDataType dataType_, EFixedSemantics semantics_) + EffectInputInformation::EffectInputInformation(std::string_view inputName_, + uint32_t elementCount_, + EDataType dataType_, + EFixedSemantics semantics_, + UniformBufferBinding uniformBufferBinding_, + UniformBufferElementSize uniformBufferElementSize_, + UniformBufferFieldOffset uniformBufferFieldOffset_ ) : inputName(inputName_) , elementCount(elementCount_) , dataType(dataType_) , semantics(semantics_) + , uniformBufferBinding(uniformBufferBinding_) + , uniformBufferElementSize(uniformBufferElementSize_) + , uniformBufferFieldOffset(uniformBufferFieldOffset_) { } @@ -71,11 +97,24 @@ namespace ramses::internal return a.inputName == b.inputName && a.elementCount == b.elementCount && a.dataType == b.dataType && - a.semantics == b.semantics; + a.semantics == b.semantics && + a.uniformBufferBinding == b.uniformBufferBinding && + a.uniformBufferElementSize == b.uniformBufferElementSize && + a.uniformBufferFieldOffset == b.uniformBufferFieldOffset; } inline bool operator!=(const EffectInputInformation& a, const EffectInputInformation& b) { return !(a == b); } + + inline bool EffectInputInformation::IsUniformBuffer(const EffectInputInformation& input) + { + return input.dataType == EDataType::UniformBuffer; + } + + inline bool EffectInputInformation::IsUniformBufferField(const EffectInputInformation& input) + { + return input.uniformBufferBinding.isValid() && input.dataType != EDataType::UniformBuffer; + } } diff --git a/src/framework/internal/SceneGraph/Resource/EffectResource.cpp b/src/framework/internal/SceneGraph/Resource/EffectResource.cpp index 775008211..fe7c00943 100644 --- a/src/framework/internal/SceneGraph/Resource/EffectResource.cpp +++ b/src/framework/internal/SceneGraph/Resource/EffectResource.cpp @@ -10,7 +10,9 @@ #include "internal/PlatformAbstraction/PlatformMemory.h" #include "internal/Core/Utils/BinaryOutputStream.h" #include "internal/Core/Utils/BinaryInputStream.h" +#include "internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.h" #include "impl/AppearanceEnumsImpl.h" +#include "absl/algorithm/container.h" namespace ramses::internal { @@ -33,55 +35,104 @@ namespace ramses::internal } } - EffectResource::EffectResource(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader, - std::optional geometryShaderInputType, EffectInputInformationVector uniformInputs, - EffectInputInformationVector attributeInputs, std::string_view name) + EffectResource::EffectResource(const std::string& vertexShader, + const std::string& fragmentShader, + const std::string& geometryShader, + const SPIRVShaders& spirvShaders, + std::optional geometryShaderInputType, + EffectInputInformationVector uniformInputs, + EffectInputInformationVector attributeInputs, + std::string_view name, + EFeatureLevel featureLevel) : ResourceBase(EResourceType::Effect, name) , m_uniformInputs(std::move(uniformInputs)) , m_attributeInputs(std::move(attributeInputs)) - , m_fragmentShaderOffset(static_cast(vertexShader.size() + 1)) - , m_geometryShaderOffset(m_fragmentShaderOffset+static_cast(fragmentShader.size() + 1)) + , m_byteOffsets(CreateByteOffsets(vertexShader, fragmentShader, geometryShader, spirvShaders)) , m_geometryShaderInputType(geometryShaderInputType) + , m_featureLevel{ featureLevel } { assert((geometryShader.empty() != geometryShaderInputType.has_value())); - const auto dataLength = static_cast(vertexShader.size() + 1 + fragmentShader.size() + 1 + geometryShader.size() + 1); // including 3x terminating '0' + assert(absl::c_none_of(m_uniformInputs, [](const auto& input) { return input.elementCount == std::numeric_limits::max(); })); + assert(absl::c_none_of(m_attributeInputs, [](const auto& input) { return input.elementCount == std::numeric_limits::max(); })); + + const auto dataLength = m_byteOffsets[EByteOffsetIndex_EndOfData]; ResourceBlob blob(dataLength); - std::memcpy(blob.data(), vertexShader.c_str(), vertexShader.size() + 1); - std::memcpy(blob.data() + m_fragmentShaderOffset, fragmentShader.c_str(), fragmentShader.size() + 1); - std::memcpy(blob.data() + m_geometryShaderOffset, geometryShader.c_str(), geometryShader.size() + 1); + std::memcpy(blob.data() + m_byteOffsets[EByteOffsetIndex_VertexShader], vertexShader.c_str(), vertexShader.size() + 1); + std::memcpy(blob.data() + m_byteOffsets[EByteOffsetIndex_FragmentShader], fragmentShader.c_str(), fragmentShader.size() + 1); + std::memcpy(blob.data() + m_byteOffsets[EByteOffsetIndex_GeometryShader], geometryShader.c_str(), geometryShader.size() + 1); + + if(getVertexShaderSPIRVSize() > 0u) + std::memcpy(blob.data() + m_byteOffsets[EByteOffsetIndex_VertexSPIRV], spirvShaders.m_vertexSPIRVBlob.data(), getVertexShaderSPIRVSize()); + if(getFragmentShaderSPIRVSize() > 0u) + std::memcpy(blob.data() + m_byteOffsets[EByteOffsetIndex_FragmentSPIRV], spirvShaders.m_fragmentSPIRVBlob.data(), getFragmentShaderSPIRVSize()); + if(getGeometryShaderSPIRVSize() > 0u) + std::memcpy(blob.data() + m_byteOffsets[EByteOffsetIndex_GeometrySPIRV], spirvShaders.m_geometrySPIRVBlob.data(), getGeometryShaderSPIRVSize()); + setResourceData(std::move(blob)); + + setDataFieldMappingForInputs(); } - EffectResource::EffectResource(EffectInputInformationVector&& uniformInputs, EffectInputInformationVector&& attributeInputs, std::optional geometryShaderInputType, - std::string_view name, uint32_t fragmentShaderOffset, uint32_t geometryShaderOffset) + EffectResource::EffectResource(EffectInputInformationVector&& uniformInputs, + EffectInputInformationVector&& attributeInputs, + std::optional geometryShaderInputType, + std::string_view name, + EffectByteOffsets&& byteOffsets, + EFeatureLevel featureLevel) : ResourceBase(EResourceType::Effect, name) , m_uniformInputs(std::move(uniformInputs)) , m_attributeInputs(std::move(attributeInputs)) - , m_fragmentShaderOffset(fragmentShaderOffset) - , m_geometryShaderOffset(geometryShaderOffset) + , m_byteOffsets(std::move(byteOffsets)) , m_geometryShaderInputType(geometryShaderInputType) + , m_featureLevel{ featureLevel } { + setDataFieldMappingForInputs(); + } + + EffectResource::EffectByteOffsets EffectResource::CreateByteOffsets(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader, const SPIRVShaders& spirvShaders) + { + const auto vertSPIRVSize = static_cast(spirvShaders.m_vertexSPIRVBlob.size() * sizeof(uint32_t)); + const auto fragSPIRVSize = static_cast(spirvShaders.m_fragmentSPIRVBlob.size() * sizeof(uint32_t)); + const auto geomSPIRVSize = static_cast(spirvShaders.m_geometrySPIRVBlob.size() * sizeof(uint32_t)); + const auto vertShaderSize = static_cast(vertexShader.size() + 1u); + const auto fragShaderSize = static_cast(fragmentShader.size() + 1u); + const auto geomShaderSize = static_cast(geometryShader.size() + 1u); + + // Effect resource blob ends up having SPIRV (uint32_t) and Glsl shader string (char), which have + // different alignment requirements. Care needs to be taken when if/when making changes or adding + // so that data can be accessed with respect to alignment requirements + + EffectByteOffsets byteOffsets = { 0u }; + byteOffsets[EByteOffsetIndex_VertexSPIRV] = 0u; + byteOffsets[EByteOffsetIndex_FragmentSPIRV] = vertSPIRVSize; + byteOffsets[EByteOffsetIndex_GeometrySPIRV] = byteOffsets[EByteOffsetIndex_FragmentSPIRV] + fragSPIRVSize; + byteOffsets[EByteOffsetIndex_VertexShader] = byteOffsets[EByteOffsetIndex_GeometrySPIRV] + geomSPIRVSize; + byteOffsets[EByteOffsetIndex_FragmentShader] = byteOffsets[EByteOffsetIndex_VertexShader] + vertShaderSize; + byteOffsets[EByteOffsetIndex_GeometryShader] = byteOffsets[EByteOffsetIndex_FragmentShader] + fragShaderSize; + byteOffsets[EByteOffsetIndex_EndOfData] = byteOffsets[EByteOffsetIndex_GeometryShader] + geomShaderSize; + + return byteOffsets; } const char* EffectResource::getVertexShader() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) safe to get char* from blob const char* data = reinterpret_cast(getResourceData().data()); - return data; + return data + m_byteOffsets[EByteOffsetIndex_VertexShader];; } const char* EffectResource::getFragmentShader() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) safe to get char* from blob const char* data = reinterpret_cast(getResourceData().data()); - return data + m_fragmentShaderOffset; + return data + m_byteOffsets[EByteOffsetIndex_FragmentShader]; } const char* EffectResource::getGeometryShader() const { // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) safe to get char* from blob const char* data = reinterpret_cast(getResourceData().data()); - return data + m_geometryShaderOffset; + return data + m_byteOffsets[EByteOffsetIndex_GeometryShader]; } std::optional EffectResource::getGeometryShaderInputType() const @@ -89,6 +140,45 @@ namespace ramses::internal return m_geometryShaderInputType; } + uint32_t EffectResource::getVertexShaderSPIRVSize() const + { + return m_byteOffsets[EByteOffsetIndex_FragmentSPIRV] - m_byteOffsets[EByteOffsetIndex_VertexSPIRV]; + } + + uint32_t EffectResource::getFragmentShaderSPIRVSize() const + { + return m_byteOffsets[EByteOffsetIndex_GeometrySPIRV] - m_byteOffsets[EByteOffsetIndex_FragmentSPIRV]; + } + + uint32_t EffectResource::getGeometryShaderSPIRVSize() const + { + return m_byteOffsets[EByteOffsetIndex_VertexShader] - m_byteOffsets[EByteOffsetIndex_GeometrySPIRV]; + } + + const uint32_t* EffectResource::getVertexShaderSPIRV() const + { + assert(getVertexShaderSPIRVSize() > 0u); + const auto* data = getResourceData().data(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + return reinterpret_cast(data + m_byteOffsets[EByteOffsetIndex_VertexSPIRV]); + } + + const uint32_t* EffectResource::getFragmentShaderSPIRV() const + { + assert(getFragmentShaderSPIRVSize() > 0u); + const auto* data = getResourceData().data(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + return reinterpret_cast(data + m_byteOffsets[EByteOffsetIndex_FragmentSPIRV]); + } + + const uint32_t* EffectResource::getGeometryShaderSPIRV() const + { + assert(getGeometryShaderSPIRVSize() > 0u); + const auto* data = getResourceData().data(); + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) + return reinterpret_cast(data + m_byteOffsets[EByteOffsetIndex_GeometrySPIRV]); + } + const EffectInputInformationVector& EffectResource::getUniformInputs() const { return m_uniformInputs; @@ -125,10 +215,11 @@ namespace ramses::internal void EffectResource::serializeResourceMetadataToStream(IOutputStream& output) const { - WriteInputVector(output, m_uniformInputs); - WriteInputVector(output, m_attributeInputs); - output << m_fragmentShaderOffset; - output << m_geometryShaderOffset; + WriteInputVector(output, m_uniformInputs, m_featureLevel); + WriteInputVector(output, m_attributeInputs, m_featureLevel); + output << m_byteOffsets[EByteOffsetIndex_FragmentShader]; + output << m_byteOffsets[EByteOffsetIndex_GeometryShader]; + if (m_geometryShaderInputType.has_value()) { output << m_geometryShaderInputType.value(); @@ -139,55 +230,88 @@ namespace ramses::internal static_assert(DrawModeNames.size() < maxValue, "Last enum value is reserved"); output << maxValue; } + + if (m_featureLevel >= EFeatureLevel_02) + { + output << m_byteOffsets[EByteOffsetIndex_VertexShader]; + output << m_byteOffsets[EByteOffsetIndex_VertexSPIRV]; + output << m_byteOffsets[EByteOffsetIndex_FragmentSPIRV]; + output << m_byteOffsets[EByteOffsetIndex_GeometrySPIRV]; + output << m_byteOffsets[EByteOffsetIndex_EndOfData]; + } } - std::unique_ptr EffectResource::CreateResourceFromMetadataStream(IInputStream& input, std::string_view name) + std::unique_ptr EffectResource::CreateResourceFromMetadataStream(IInputStream& input, std::string_view name, EFeatureLevel featureLevel) { EffectInputInformationVector uniformInputs; - ReadInputVector(input, uniformInputs); + ReadInputVector(input, uniformInputs, featureLevel); EffectInputInformationVector attributeInputs; - ReadInputVector(input, attributeInputs); + ReadInputVector(input, attributeInputs, featureLevel); - uint32_t fragementShaderOffset = 0; - input >> fragementShaderOffset; - uint32_t geometryShaderOffset = 0; - input >> geometryShaderOffset; + EffectByteOffsets byteOffsets = { 0u }; + input >> byteOffsets[EByteOffsetIndex_FragmentShader]; + input >> byteOffsets[EByteOffsetIndex_GeometryShader]; std::underlying_type_t gsInputTypeValue = 0; input >> gsInputTypeValue; + if (featureLevel >= EFeatureLevel_02) + { + input >> byteOffsets[EByteOffsetIndex_VertexShader]; + input >> byteOffsets[EByteOffsetIndex_VertexSPIRV]; + input >> byteOffsets[EByteOffsetIndex_FragmentSPIRV]; + input >> byteOffsets[EByteOffsetIndex_GeometrySPIRV]; + input >> byteOffsets[EByteOffsetIndex_EndOfData]; + } + std::optional gsInputType; if (IsValidDrawmode(gsInputTypeValue)) { gsInputType = static_cast(gsInputTypeValue); } - return std::unique_ptr(new EffectResource(std::move(uniformInputs), std::move(attributeInputs), gsInputType, name, fragementShaderOffset, geometryShaderOffset)); + return std::unique_ptr(new EffectResource(std::move(uniformInputs), std::move(attributeInputs), gsInputType, name, std::move(byteOffsets), featureLevel)); } - void EffectResource::WriteInputVector(IOutputStream& stream, const EffectInputInformationVector& inputVector) + void EffectResource::WriteInputVector(IOutputStream& stream, const EffectInputInformationVector& inputVector, EFeatureLevel featureLevel) { + const bool serializeUBO = (featureLevel >= EFeatureLevel_02); const auto length = static_cast(inputVector.size()); stream << length; for (uint32_t i = 0; i < length; ++i) { const EffectInputInformation& input = inputVector[i]; stream << input.inputName << input.elementCount << static_cast(input.dataType) << static_cast(input.semantics); + if (serializeUBO) + stream << input.uniformBufferBinding.getValue() << input.uniformBufferElementSize.getValue() << input.uniformBufferFieldOffset.getValue(); } } - void EffectResource::ReadInputVector(IInputStream& stream, EffectInputInformationVector& inputVector) + void EffectResource::ReadInputVector(IInputStream& stream, EffectInputInformationVector& inputVector, EFeatureLevel featureLevel) { + const bool deserializeUBO = (featureLevel >= EFeatureLevel_02); uint32_t length = 0; stream >> length; inputVector.reserve(length); for (uint32_t i = 0; i < length; ++i) { EffectInputInformation input; - uint32_t typeTmp = 0; - uint32_t semanticTmp = 0; - stream >> input.inputName >> input.elementCount >> typeTmp >> semanticTmp; - input.dataType = static_cast(typeTmp); - input.semantics = static_cast(semanticTmp); + stream >> input.inputName >> input.elementCount; + + uint32_t tmpVal{}; + stream >> tmpVal; + input.dataType = static_cast(tmpVal); + stream >> tmpVal; + input.semantics = static_cast(tmpVal); + + if (deserializeUBO) + stream >> input.uniformBufferBinding.getReference() >> input.uniformBufferElementSize.getReference() >> input.uniformBufferFieldOffset.getReference(); + inputVector.push_back(input); } } + + void EffectResource::setDataFieldMappingForInputs() + { + DataLayoutCreationHelper::SetDataFieldMappingForUniformInputs(m_uniformInputs); + DataLayoutCreationHelper::SetDataFieldMappingForAttributeInputs(m_attributeInputs); + } } diff --git a/src/framework/internal/SceneGraph/Resource/EffectResource.h b/src/framework/internal/SceneGraph/Resource/EffectResource.h index 28ef11aed..e176b0839 100644 --- a/src/framework/internal/SceneGraph/Resource/EffectResource.h +++ b/src/framework/internal/SceneGraph/Resource/EffectResource.h @@ -10,8 +10,9 @@ #include "internal/SceneGraph/Resource/ResourceBase.h" #include "internal/SceneGraph/Resource/EffectInputInformation.h" +#include "ramses/framework/EFeatureLevel.h" +#include "SPIRVShaders.h" #include - #include #include @@ -23,9 +24,15 @@ namespace ramses::internal class EffectResource : public ResourceBase { public: - EffectResource(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader, - std::optional geometryShaderInputType, EffectInputInformationVector uniformInputs, - EffectInputInformationVector attributeInputs, std::string_view name); + EffectResource(const std::string& vertexShader, + const std::string& fragmentShader, + const std::string& geometryShader, + const SPIRVShaders& spirvShaders, + std::optional geometryShaderInputType, + EffectInputInformationVector uniformInputs, + EffectInputInformationVector attributeInputs, + std::string_view name, + EFeatureLevel featureLevel); const char* getVertexShader() const; const char* getFragmentShader() const; @@ -33,6 +40,13 @@ namespace ramses::internal std::optional getGeometryShaderInputType() const; + uint32_t getVertexShaderSPIRVSize() const; + uint32_t getFragmentShaderSPIRVSize() const; + uint32_t getGeometryShaderSPIRVSize() const; + const uint32_t* getVertexShaderSPIRV() const; + const uint32_t* getFragmentShaderSPIRV() const; + const uint32_t* getGeometryShaderSPIRV() const; + const EffectInputInformationVector& getUniformInputs() const; const EffectInputInformationVector& getAttributeInputs() const; @@ -40,20 +54,41 @@ namespace ramses::internal DataFieldHandle getAttributeDataFieldHandleByName(std::string_view name) const; void serializeResourceMetadataToStream(IOutputStream& output) const override; - static std::unique_ptr CreateResourceFromMetadataStream(IInputStream& input, std::string_view name); + static std::unique_ptr CreateResourceFromMetadataStream(IInputStream& input, std::string_view name, EFeatureLevel featureLevel); private: - EffectResource(EffectInputInformationVector&& uniformInputs, EffectInputInformationVector&& attributeInputs, std::optional geometryShaderInputType, - std::string_view name, uint32_t fragmentShaderOffset, uint32_t geometryShaderOffset); + enum EByteOffsetIndex + { + EByteOffsetIndex_VertexSPIRV =0, + EByteOffsetIndex_FragmentSPIRV, + EByteOffsetIndex_GeometrySPIRV, + EByteOffsetIndex_VertexShader, + EByteOffsetIndex_FragmentShader, + EByteOffsetIndex_GeometryShader, + EByteOffsetIndex_EndOfData + }; + static constexpr std::size_t OffsetCount = EByteOffsetIndex_EndOfData + 1u; + using EffectByteOffsets = std::array; + + EffectResource(EffectInputInformationVector&& uniformInputs, + EffectInputInformationVector&& attributeInputs, + std::optional geometryShaderInputType, + std::string_view name, + EffectByteOffsets&& byteOffsets, + EFeatureLevel featureLevel); + + static EffectByteOffsets CreateByteOffsets(const std::string& vertexShader, const std::string& fragmentShader, const std::string& geometryShader, const SPIRVShaders& spirvShaders); + + void setDataFieldMappingForInputs(); - static void WriteInputVector(IOutputStream& stream, const EffectInputInformationVector& inputVector); - static void ReadInputVector(IInputStream& stream, EffectInputInformationVector& inputVector); + static void WriteInputVector(IOutputStream& stream, const EffectInputInformationVector& inputVector, EFeatureLevel featureLevel); + static void ReadInputVector(IInputStream& stream, EffectInputInformationVector& inputVector, EFeatureLevel featureLevel); - const EffectInputInformationVector m_uniformInputs; - const EffectInputInformationVector m_attributeInputs; - const uint32_t m_fragmentShaderOffset; - const uint32_t m_geometryShaderOffset; - const std::optional m_geometryShaderInputType; + EffectInputInformationVector m_uniformInputs; + EffectInputInformationVector m_attributeInputs; + EffectByteOffsets m_byteOffsets = { 0 }; + std::optional m_geometryShaderInputType; + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; }; } diff --git a/src/framework/internal/SceneGraph/Resource/SPIRVShaders.h b/src/framework/internal/SceneGraph/Resource/SPIRVShaders.h new file mode 100644 index 000000000..dd1db9c27 --- /dev/null +++ b/src/framework/internal/SceneGraph/Resource/SPIRVShaders.h @@ -0,0 +1,24 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include + +namespace ramses::internal +{ + // According SPIRV spec: SPIRV is a stream of words, not a stream of bytes. A word is defined to be uint32_t (effectively) + using SPIRVShaderBlob = std::vector; + + struct SPIRVShaders + { + SPIRVShaderBlob m_vertexSPIRVBlob; + SPIRVShaderBlob m_fragmentSPIRVBlob; + SPIRVShaderBlob m_geometrySPIRVBlob; + }; +} diff --git a/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.cpp b/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.cpp index 4d2cbde84..f0e7749b7 100644 --- a/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.cpp +++ b/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.cpp @@ -10,118 +10,124 @@ namespace ramses::internal { - ActionCollectingScene::ActionCollectingScene(const SceneInfo& sceneInfo) - : ResourceChangeCollectingScene(sceneInfo) + ActionCollectingScene::ActionCollectingScene(const SceneInfo& sceneInfo, EFeatureLevel featureLevel) + : BaseT(sceneInfo) , m_collection(20000, 512) - , m_creator(m_collection) + , m_creator(m_collection, featureLevel) { } void ActionCollectingScene::preallocateSceneSize(const SceneSizeInformation& sizeInfo) { - ResourceChangeCollectingScene::preallocateSceneSize(sizeInfo); + BaseT::preallocateSceneSize(sizeInfo); m_creator.preallocateSceneSize(sizeInfo); } void ActionCollectingScene::setDataResource(DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) { - ResourceChangeCollectingScene::setDataResource(containerHandle, field, hash, dataBuffer, instancingDivisor, offsetWithinElementInBytes, stride); + BaseT::setDataResource(containerHandle, field, hash, dataBuffer, instancingDivisor, offsetWithinElementInBytes, stride); m_creator.setDataResource(containerHandle, field, hash, dataBuffer, instancingDivisor, offsetWithinElementInBytes, stride); } void ActionCollectingScene::setDataTextureSamplerHandle(DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) { - ResourceChangeCollectingScene::setDataTextureSamplerHandle(containerHandle, field, samplerHandle); + BaseT::setDataTextureSamplerHandle(containerHandle, field, samplerHandle); m_creator.setDataTextureSamplerHandle(containerHandle, field, samplerHandle); } void ActionCollectingScene::setDataReference(DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef) { - ResourceChangeCollectingScene::setDataReference(containerHandle, field, dataRef); + BaseT::setDataReference(containerHandle, field, dataRef); m_creator.setDataReference(containerHandle, field, dataRef); } + void ActionCollectingScene::setDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) + { + BaseT::setDataUniformBuffer(containerHandle, field, uniformBufferHandle); + m_creator.setDataUniformBuffer(containerHandle, field, uniformBufferHandle); + } + void ActionCollectingScene::setDataVector4iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec4* data) { - ResourceChangeCollectingScene::setDataVector4iArray(containerHandle, field, elementCount, data); + BaseT::setDataVector4iArray(containerHandle, field, elementCount, data); m_creator.setDataVector4iArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataMatrix22fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat2* data) { - ResourceChangeCollectingScene::setDataMatrix22fArray(containerHandle, field, elementCount, data); + BaseT::setDataMatrix22fArray(containerHandle, field, elementCount, data); m_creator.setDataMatrix22fArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataMatrix33fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat3* data) { - ResourceChangeCollectingScene::setDataMatrix33fArray(containerHandle, field, elementCount, data); + BaseT::setDataMatrix33fArray(containerHandle, field, elementCount, data); m_creator.setDataMatrix33fArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataMatrix44fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat4* data) { - ResourceChangeCollectingScene::setDataMatrix44fArray(containerHandle, field, elementCount, data); + BaseT::setDataMatrix44fArray(containerHandle, field, elementCount, data); m_creator.setDataMatrix44fArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataVector3iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec3* data) { - ResourceChangeCollectingScene::setDataVector3iArray(containerHandle, field, elementCount, data); + BaseT::setDataVector3iArray(containerHandle, field, elementCount, data); m_creator.setDataVector3iArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataVector2iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec2* data) { - ResourceChangeCollectingScene::setDataVector2iArray(containerHandle, field, elementCount, data); + BaseT::setDataVector2iArray(containerHandle, field, elementCount, data); m_creator.setDataVector2iArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataBooleanArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const bool* data) { - ResourceChangeCollectingScene::setDataBooleanArray(containerHandle, field, elementCount, data); + BaseT::setDataBooleanArray(containerHandle, field, elementCount, data); m_creator.setDataBooleanArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataIntegerArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const int32_t* data) { - ResourceChangeCollectingScene::setDataIntegerArray(containerHandle, field, elementCount, data); + BaseT::setDataIntegerArray(containerHandle, field, elementCount, data); m_creator.setDataIntegerArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataVector4fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec4* data) { - ResourceChangeCollectingScene::setDataVector4fArray(containerHandle, field, elementCount, data); + BaseT::setDataVector4fArray(containerHandle, field, elementCount, data); m_creator.setDataVector4fArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataVector3fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec3* data) { - ResourceChangeCollectingScene::setDataVector3fArray(containerHandle, field, elementCount, data); + BaseT::setDataVector3fArray(containerHandle, field, elementCount, data); m_creator.setDataVector3fArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataVector2fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec2* data) { - ResourceChangeCollectingScene::setDataVector2fArray(containerHandle, field, elementCount, data); + BaseT::setDataVector2fArray(containerHandle, field, elementCount, data); m_creator.setDataVector2fArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::setDataFloatArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const float* data) { - ResourceChangeCollectingScene::setDataFloatArray(containerHandle, field, elementCount, data); + BaseT::setDataFloatArray(containerHandle, field, elementCount, data); m_creator.setDataFloatArray(containerHandle, field, elementCount, data); } void ActionCollectingScene::releaseDataInstance(DataInstanceHandle containerHandle) { - ResourceChangeCollectingScene::releaseDataInstance(containerHandle); + BaseT::releaseDataInstance(containerHandle); m_creator.releaseDataInstance(containerHandle); } DataInstanceHandle ActionCollectingScene::allocateDataInstance(DataLayoutHandle finishedLayoutHandle, DataInstanceHandle instanceHandle) { - DataInstanceHandle handle = ResourceChangeCollectingScene::allocateDataInstance(finishedLayoutHandle, instanceHandle); + DataInstanceHandle handle = BaseT::allocateDataInstance(finishedLayoutHandle, instanceHandle); m_creator.allocateDataInstance(finishedLayoutHandle, handle); return handle; @@ -129,13 +135,13 @@ namespace ramses::internal void ActionCollectingScene::releaseDataLayout(DataLayoutHandle layoutHandle) { - ResourceChangeCollectingScene::releaseDataLayout(layoutHandle); + BaseT::releaseDataLayout(layoutHandle); m_creator.releaseDataLayout(layoutHandle); } DataLayoutHandle ActionCollectingScene::allocateDataLayout(const DataFieldInfoVector& dataFields, const ResourceContentHash& effectHash, DataLayoutHandle handle) { - DataLayoutHandle handleActual = ResourceChangeCollectingScene::allocateDataLayout(dataFields, effectHash, handle); + DataLayoutHandle handleActual = BaseT::allocateDataLayout(dataFields, effectHash, handle); m_creator.allocateDataLayout(dataFields, effectHash, handleActual); return handleActual; @@ -143,43 +149,43 @@ namespace ramses::internal void ActionCollectingScene::setScaling(TransformHandle handle, const glm::vec3& scaling) { - ResourceChangeCollectingScene::setScaling(handle, scaling); + BaseT::setScaling(handle, scaling); m_creator.setScaling(handle, scaling); } void ActionCollectingScene::setRotation(TransformHandle handle, const glm::vec4& rotation, ERotationType rotationType) { - ResourceChangeCollectingScene::setRotation(handle, rotation, rotationType); + BaseT::setRotation(handle, rotation, rotationType); m_creator.setRotation(handle, rotation, rotationType); } void ActionCollectingScene::setTranslation(TransformHandle handle, const glm::vec3& translation) { - ResourceChangeCollectingScene::setTranslation(handle, translation); + BaseT::setTranslation(handle, translation); m_creator.setTranslation(handle, translation); } void ActionCollectingScene::removeChildFromNode(NodeHandle parent, NodeHandle child) { - ResourceChangeCollectingScene::removeChildFromNode(parent, child); + BaseT::removeChildFromNode(parent, child); m_creator.removeChildFromNode(parent, child); } void ActionCollectingScene::addChildToNode(NodeHandle parent, NodeHandle child) { - ResourceChangeCollectingScene::addChildToNode(parent, child); + BaseT::addChildToNode(parent, child); m_creator.addChildToNode(parent, child); } void ActionCollectingScene::releaseTransform(TransformHandle transform) { - ResourceChangeCollectingScene::releaseTransform(transform); + BaseT::releaseTransform(transform); m_creator.releaseTransform(transform); } TransformHandle ActionCollectingScene::allocateTransform(NodeHandle nodeHandle, TransformHandle handle) { - const TransformHandle handleActual = ResourceChangeCollectingScene::allocateTransform(nodeHandle, handle); + const TransformHandle handleActual = BaseT::allocateTransform(nodeHandle, handle); m_creator.allocateTransform(nodeHandle, handleActual); return handleActual; @@ -187,20 +193,20 @@ namespace ramses::internal void ActionCollectingScene::releaseNode(NodeHandle nodeHandle) { - ResourceChangeCollectingScene::releaseNode(nodeHandle); + BaseT::releaseNode(nodeHandle); m_creator.releaseNode(nodeHandle); } NodeHandle ActionCollectingScene::allocateNode(uint32_t childrenCount, NodeHandle handle) { - NodeHandle handleActual = ResourceChangeCollectingScene::allocateNode(childrenCount, handle); + NodeHandle handleActual = BaseT::allocateNode(childrenCount, handle); m_creator.allocateNode(childrenCount, handleActual); return handleActual; } CameraHandle ActionCollectingScene::allocateCamera(ECameraProjectionType type, NodeHandle nodeHandle, DataInstanceHandle dataInstance, CameraHandle handle) { - CameraHandle handleActual = ResourceChangeCollectingScene::allocateCamera(type, nodeHandle, dataInstance, handle); + CameraHandle handleActual = BaseT::allocateCamera(type, nodeHandle, dataInstance, handle); m_creator.allocateCamera(type, nodeHandle, dataInstance, handleActual); return handleActual; @@ -208,103 +214,103 @@ namespace ramses::internal void ActionCollectingScene::releaseCamera(CameraHandle cameraHandle) { - ResourceChangeCollectingScene::releaseCamera(cameraHandle); + BaseT::releaseCamera(cameraHandle); m_creator.releaseCamera(cameraHandle); } void ActionCollectingScene::setRenderStateStencilOps(RenderStateHandle stateHandle, EStencilOp sfail, EStencilOp dpfail, EStencilOp dppass) { - ResourceChangeCollectingScene::setRenderStateStencilOps(stateHandle, sfail, dpfail, dppass); + BaseT::setRenderStateStencilOps(stateHandle, sfail, dpfail, dppass); m_creator.setRenderStateStencilOps(stateHandle, sfail, dpfail, dppass); } void ActionCollectingScene::setRenderStateStencilFunc(RenderStateHandle stateHandle, EStencilFunc func, uint8_t ref, uint8_t mask) { - ResourceChangeCollectingScene::setRenderStateStencilFunc(stateHandle, func, ref, mask); + BaseT::setRenderStateStencilFunc(stateHandle, func, ref, mask); m_creator.setRenderStateStencilFunc(stateHandle, func, ref, mask); } void ActionCollectingScene::setRenderStateDepthWrite(RenderStateHandle stateHandle, EDepthWrite flag) { - ResourceChangeCollectingScene::setRenderStateDepthWrite(stateHandle, flag); + BaseT::setRenderStateDepthWrite(stateHandle, flag); m_creator.setRenderStateDepthWrite(stateHandle, flag); } void ActionCollectingScene::setRenderStateDepthFunc(RenderStateHandle stateHandle, EDepthFunc func) { - ResourceChangeCollectingScene::setRenderStateDepthFunc(stateHandle, func); + BaseT::setRenderStateDepthFunc(stateHandle, func); m_creator.setRenderStateDepthFunc(stateHandle, func); } void ActionCollectingScene::setRenderStateScissorTest(RenderStateHandle stateHandle, EScissorTest flag, const RenderState::ScissorRegion& region) { - ResourceChangeCollectingScene::setRenderStateScissorTest(stateHandle, flag, region); + BaseT::setRenderStateScissorTest(stateHandle, flag, region); m_creator.setRenderStateScissorTest(stateHandle, flag, region); } void ActionCollectingScene::setRenderStateCullMode(RenderStateHandle stateHandle, ECullMode cullMode) { - if (ResourceChangeCollectingScene::getRenderState(stateHandle).cullMode != cullMode) + if (BaseT::getRenderState(stateHandle).cullMode != cullMode) { - ResourceChangeCollectingScene::setRenderStateCullMode(stateHandle, cullMode); + BaseT::setRenderStateCullMode(stateHandle, cullMode); m_creator.setRenderStateCullMode(stateHandle, cullMode); } } void ActionCollectingScene::setRenderStateDrawMode(RenderStateHandle stateHandle, EDrawMode drawMode) { - if (ResourceChangeCollectingScene::getRenderState(stateHandle).drawMode != drawMode) + if (BaseT::getRenderState(stateHandle).drawMode != drawMode) { - ResourceChangeCollectingScene::setRenderStateDrawMode(stateHandle, drawMode); + BaseT::setRenderStateDrawMode(stateHandle, drawMode); m_creator.setRenderStateDrawMode(stateHandle, drawMode); } } void ActionCollectingScene::setRenderStateBlendOperations(RenderStateHandle stateHandle, EBlendOperation operationColor, EBlendOperation operationAlpha) { - ResourceChangeCollectingScene::setRenderStateBlendOperations(stateHandle, operationColor, operationAlpha); + BaseT::setRenderStateBlendOperations(stateHandle, operationColor, operationAlpha); m_creator.setRenderStateBlendOperations(stateHandle, operationColor, operationAlpha); } void ActionCollectingScene::setRenderStateBlendColor(RenderStateHandle stateHandle, const glm::vec4& color) { - ResourceChangeCollectingScene::setRenderStateBlendColor(stateHandle, color); + BaseT::setRenderStateBlendColor(stateHandle, color); m_creator.setRenderStateBlendColor(stateHandle, color); } void ActionCollectingScene::setRenderStateBlendFactors(RenderStateHandle stateHandle, EBlendFactor srcColor, EBlendFactor destColor, EBlendFactor srcAlpha, EBlendFactor destAlpha) { - const RenderState& rs = ResourceChangeCollectingScene::getRenderState(stateHandle); + const RenderState& rs = BaseT::getRenderState(stateHandle); const EBlendFactor dstA = rs.blendFactorDstAlpha; const EBlendFactor srcA = rs.blendFactorSrcAlpha; const EBlendFactor dstC = rs.blendFactorDstColor; const EBlendFactor srcC = rs.blendFactorSrcColor; if (dstA != destAlpha || srcA != srcAlpha || dstC != destColor || srcC != srcColor) { - ResourceChangeCollectingScene::setRenderStateBlendFactors(stateHandle, srcColor, destColor, srcAlpha, destAlpha); + BaseT::setRenderStateBlendFactors(stateHandle, srcColor, destColor, srcAlpha, destAlpha); m_creator.setRenderStateBlendFactors(stateHandle, srcColor, destColor, srcAlpha, destAlpha); } } void ActionCollectingScene::setRenderStateColorWriteMask(RenderStateHandle stateHandle, ColorWriteMask colorMask) { - const ColorWriteMask previousMask = ResourceChangeCollectingScene::getRenderState(stateHandle).colorWriteMask; + const ColorWriteMask previousMask = BaseT::getRenderState(stateHandle).colorWriteMask; if (colorMask != previousMask) { - ResourceChangeCollectingScene::setRenderStateColorWriteMask(stateHandle, colorMask); + BaseT::setRenderStateColorWriteMask(stateHandle, colorMask); m_creator.setRenderStateColorWriteMask(stateHandle, colorMask); } } void ActionCollectingScene::releaseRenderState(RenderStateHandle stateHandle) { - ResourceChangeCollectingScene::releaseRenderState(stateHandle); + BaseT::releaseRenderState(stateHandle); m_creator.releaseRenderState(stateHandle); } RenderStateHandle ActionCollectingScene::allocateRenderState(RenderStateHandle stateHandle) { - RenderStateHandle handle = ResourceChangeCollectingScene::allocateRenderState(stateHandle); + RenderStateHandle handle = BaseT::allocateRenderState(stateHandle); m_creator.allocateRenderState(handle); return handle; @@ -312,72 +318,72 @@ namespace ramses::internal void ActionCollectingScene::setRenderableRenderState(RenderableHandle renderableHandle, RenderStateHandle stateHandle) { - ResourceChangeCollectingScene::setRenderableRenderState(renderableHandle, stateHandle); + BaseT::setRenderableRenderState(renderableHandle, stateHandle); m_creator.setRenderableRenderState(renderableHandle, stateHandle); } void ActionCollectingScene::setRenderableIndexCount(RenderableHandle renderableHandle, uint32_t indexCount) { - if (ResourceChangeCollectingScene::getRenderable(renderableHandle).indexCount != indexCount) + if (BaseT::getRenderable(renderableHandle).indexCount != indexCount) { - ResourceChangeCollectingScene::setRenderableIndexCount(renderableHandle, indexCount); + BaseT::setRenderableIndexCount(renderableHandle, indexCount); m_creator.setRenderableIndexCount(renderableHandle, indexCount); } } void ActionCollectingScene::setRenderableStartIndex(RenderableHandle renderableHandle, uint32_t startIndex) { - if (ResourceChangeCollectingScene::getRenderable(renderableHandle).startIndex != startIndex) + if (BaseT::getRenderable(renderableHandle).startIndex != startIndex) { - ResourceChangeCollectingScene::setRenderableStartIndex(renderableHandle, startIndex); + BaseT::setRenderableStartIndex(renderableHandle, startIndex); m_creator.setRenderableStartIndex(renderableHandle, startIndex); } } void ActionCollectingScene::setRenderableVisibility(RenderableHandle renderableHandle, EVisibilityMode visibility) { - if (ResourceChangeCollectingScene::getRenderable(renderableHandle).visibilityMode != visibility) + if (BaseT::getRenderable(renderableHandle).visibilityMode != visibility) { - ResourceChangeCollectingScene::setRenderableVisibility(renderableHandle, visibility); + BaseT::setRenderableVisibility(renderableHandle, visibility); m_creator.setRenderableVisibility(renderableHandle, visibility); } } void ActionCollectingScene::setRenderableInstanceCount(RenderableHandle renderableHandle, uint32_t instanceCount) { - ResourceChangeCollectingScene::setRenderableInstanceCount(renderableHandle, instanceCount); + BaseT::setRenderableInstanceCount(renderableHandle, instanceCount); m_creator.setRenderableInstanceCount(renderableHandle, instanceCount); } void ActionCollectingScene::setRenderableStartVertex(RenderableHandle renderableHandle, uint32_t startVertex) { - ResourceChangeCollectingScene::setRenderableStartVertex(renderableHandle, startVertex); + BaseT::setRenderableStartVertex(renderableHandle, startVertex); m_creator.setRenderableStartVertex(renderableHandle, startVertex); } void ActionCollectingScene::setRenderableUniformsDataInstanceAndState(RenderableHandle renderableHandle, DataInstanceHandle newDataInstance, RenderStateHandle stateHandle) { - ResourceChangeCollectingScene::setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Uniforms, newDataInstance); - ResourceChangeCollectingScene::setRenderableRenderState(renderableHandle, stateHandle); + BaseT::setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Uniforms, newDataInstance); + BaseT::setRenderableRenderState(renderableHandle, stateHandle); m_creator.compoundRenderableData(renderableHandle, newDataInstance, stateHandle); } void ActionCollectingScene::setRenderableDataInstance(RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) { - ResourceChangeCollectingScene::setRenderableDataInstance(renderableHandle, slot, newDataInstance); + BaseT::setRenderableDataInstance(renderableHandle, slot, newDataInstance); m_creator.setRenderableDataInstance(renderableHandle, slot, newDataInstance); } void ActionCollectingScene::releaseRenderable(RenderableHandle renderableHandle) { - ResourceChangeCollectingScene::releaseRenderable(renderableHandle); + BaseT::releaseRenderable(renderableHandle); m_creator.releaseRenderable(renderableHandle); } RenderableHandle ActionCollectingScene::allocateRenderable(NodeHandle nodeHandle, RenderableHandle handle) { - const RenderableHandle handleActual = ResourceChangeCollectingScene::allocateRenderable(nodeHandle, handle); + const RenderableHandle handleActual = BaseT::allocateRenderable(nodeHandle, handle); m_creator.allocateRenderable(nodeHandle, handleActual); return handleActual; @@ -385,7 +391,7 @@ namespace ramses::internal RenderGroupHandle ActionCollectingScene::allocateRenderGroup(uint32_t renderableCount, uint32_t nestedGroupCount, RenderGroupHandle groupHandle) { - const RenderGroupHandle handleActual = ResourceChangeCollectingScene::allocateRenderGroup(renderableCount, nestedGroupCount, groupHandle); + const RenderGroupHandle handleActual = BaseT::allocateRenderGroup(renderableCount, nestedGroupCount, groupHandle); m_creator.allocateRenderGroup(renderableCount, nestedGroupCount, handleActual); return handleActual; @@ -393,243 +399,243 @@ namespace ramses::internal void ActionCollectingScene::releaseRenderGroup(RenderGroupHandle groupHandle) { - ResourceChangeCollectingScene::releaseRenderGroup(groupHandle); + BaseT::releaseRenderGroup(groupHandle); m_creator.releaseRenderGroup(groupHandle); } void ActionCollectingScene::addRenderableToRenderGroup(RenderGroupHandle groupHandle, RenderableHandle renderableHandle, int32_t order) { - ResourceChangeCollectingScene::addRenderableToRenderGroup(groupHandle, renderableHandle, order); + BaseT::addRenderableToRenderGroup(groupHandle, renderableHandle, order); m_creator.addRenderableToRenderGroup(groupHandle, renderableHandle, order); } void ActionCollectingScene::addRenderGroupToRenderGroup(RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild, int32_t order) { - ResourceChangeCollectingScene::addRenderGroupToRenderGroup(groupHandleParent, groupHandleChild, order); + BaseT::addRenderGroupToRenderGroup(groupHandleParent, groupHandleChild, order); m_creator.addRenderGroupToRenderGroup(groupHandleParent, groupHandleChild, order); } void ActionCollectingScene::removeRenderableFromRenderGroup(RenderGroupHandle groupHandle, RenderableHandle renderableHandle) { - ResourceChangeCollectingScene::removeRenderableFromRenderGroup(groupHandle, renderableHandle); + BaseT::removeRenderableFromRenderGroup(groupHandle, renderableHandle); m_creator.removeRenderableFromRenderGroup(groupHandle, renderableHandle); } void ActionCollectingScene::removeRenderGroupFromRenderGroup(RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild) { - ResourceChangeCollectingScene::removeRenderGroupFromRenderGroup(groupHandleParent, groupHandleChild); + BaseT::removeRenderGroupFromRenderGroup(groupHandleParent, groupHandleChild); m_creator.removeRenderGroupFromRenderGroup(groupHandleParent, groupHandleChild); } RenderPassHandle ActionCollectingScene::allocateRenderPass(uint32_t renderGroupCount, RenderPassHandle handle /*= InvalidRenderPassHandle*/) { - const RenderPassHandle handleActual = ResourceChangeCollectingScene::allocateRenderPass(renderGroupCount, handle); + const RenderPassHandle handleActual = BaseT::allocateRenderPass(renderGroupCount, handle); m_creator.allocateRenderPass(renderGroupCount, handleActual); return handleActual; } void ActionCollectingScene::releaseRenderPass(RenderPassHandle handle) { - ResourceChangeCollectingScene::releaseRenderPass(handle); + BaseT::releaseRenderPass(handle); m_creator.releaseRenderPass(handle); } void ActionCollectingScene::setRenderPassCamera(RenderPassHandle passHandle, CameraHandle cameraHandle) { - ResourceChangeCollectingScene::setRenderPassCamera(passHandle, cameraHandle); + BaseT::setRenderPassCamera(passHandle, cameraHandle); m_creator.setRenderPassCamera(passHandle, cameraHandle); } void ActionCollectingScene::setRenderPassRenderTarget(RenderPassHandle passHandle, RenderTargetHandle targetHandle) { - ResourceChangeCollectingScene::setRenderPassRenderTarget(passHandle, targetHandle); + BaseT::setRenderPassRenderTarget(passHandle, targetHandle); m_creator.setRenderPassRenderTarget(passHandle, targetHandle); } void ActionCollectingScene::setRenderPassRenderOrder(RenderPassHandle passHandle, int32_t renderOrder) { - ResourceChangeCollectingScene::setRenderPassRenderOrder(passHandle, renderOrder); + BaseT::setRenderPassRenderOrder(passHandle, renderOrder); m_creator.setRenderPassRenderOrder(passHandle, renderOrder); } void ActionCollectingScene::setRenderPassEnabled(RenderPassHandle passHandle, bool isEnabled) { - ResourceChangeCollectingScene::setRenderPassEnabled(passHandle, isEnabled); + BaseT::setRenderPassEnabled(passHandle, isEnabled); m_creator.setRenderPassEnabled(passHandle, isEnabled); } void ActionCollectingScene::setRenderPassRenderOnce(RenderPassHandle passHandle, bool enable) { - ResourceChangeCollectingScene::setRenderPassRenderOnce(passHandle, enable); + BaseT::setRenderPassRenderOnce(passHandle, enable); m_creator.setRenderPassRenderOnce(passHandle, enable); } void ActionCollectingScene::retriggerRenderPassRenderOnce(RenderPassHandle passHandle) { - ResourceChangeCollectingScene::retriggerRenderPassRenderOnce(passHandle); + BaseT::retriggerRenderPassRenderOnce(passHandle); m_creator.retriggerRenderPassRenderOnce(passHandle); } void ActionCollectingScene::addRenderGroupToRenderPass(RenderPassHandle passHandle, RenderGroupHandle groupHandle, int32_t order) { - ResourceChangeCollectingScene::addRenderGroupToRenderPass(passHandle, groupHandle, order); + BaseT::addRenderGroupToRenderPass(passHandle, groupHandle, order); m_creator.addRenderGroupToRenderPass(passHandle, groupHandle, order); } void ActionCollectingScene::removeRenderGroupFromRenderPass(RenderPassHandle passHandle, RenderGroupHandle groupHandle) { - ResourceChangeCollectingScene::removeRenderGroupFromRenderPass(passHandle, groupHandle); + BaseT::removeRenderGroupFromRenderPass(passHandle, groupHandle); m_creator.removeRenderGroupFromRenderPass(passHandle, groupHandle); } BlitPassHandle ActionCollectingScene::allocateBlitPass(RenderBufferHandle sourceRenderBufferHandle, RenderBufferHandle destinationRenderBufferHandle, BlitPassHandle passHandle /*= BlitPassHandle::Invalid()*/) { - const BlitPassHandle handleActual = ResourceChangeCollectingScene::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); + const BlitPassHandle handleActual = BaseT::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); m_creator.allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, handleActual); return handleActual; } void ActionCollectingScene::releaseBlitPass(BlitPassHandle passHandle) { - ResourceChangeCollectingScene::releaseBlitPass(passHandle); + BaseT::releaseBlitPass(passHandle); m_creator.releaseBlitPass(passHandle); } void ActionCollectingScene::setBlitPassRenderOrder(BlitPassHandle passHandle, int32_t renderOrder) { - ResourceChangeCollectingScene::setBlitPassRenderOrder(passHandle, renderOrder); + BaseT::setBlitPassRenderOrder(passHandle, renderOrder); m_creator.setBlitPassRenderOrder(passHandle, renderOrder); } void ActionCollectingScene::setBlitPassEnabled(BlitPassHandle passHandle, bool isEnabled) { - ResourceChangeCollectingScene::setBlitPassEnabled(passHandle, isEnabled); + BaseT::setBlitPassEnabled(passHandle, isEnabled); m_creator.setBlitPassEnabled(passHandle, isEnabled); } void ActionCollectingScene::setBlitPassRegions(BlitPassHandle passHandle, const PixelRectangle& sourceRegion, const PixelRectangle& destinationRegion) { - ResourceChangeCollectingScene::setBlitPassRegions(passHandle, sourceRegion, destinationRegion); + BaseT::setBlitPassRegions(passHandle, sourceRegion, destinationRegion); m_creator.setBlitPassRegions(passHandle, sourceRegion, destinationRegion); } PickableObjectHandle ActionCollectingScene::allocatePickableObject(DataBufferHandle geometryHandle, NodeHandle nodeHandle, PickableObjectId id, PickableObjectHandle pickableHandle) { - const PickableObjectHandle handleActual = ResourceChangeCollectingScene::allocatePickableObject(geometryHandle, nodeHandle, id, pickableHandle); + const PickableObjectHandle handleActual = BaseT::allocatePickableObject(geometryHandle, nodeHandle, id, pickableHandle); m_creator.allocatePickableObject(geometryHandle, nodeHandle, id, handleActual); return handleActual; } void ActionCollectingScene::releasePickableObject(PickableObjectHandle pickableHandle) { - ResourceChangeCollectingScene::releasePickableObject(pickableHandle); + BaseT::releasePickableObject(pickableHandle); m_creator.releasePickableObject(pickableHandle); } void ActionCollectingScene::setPickableObjectId(PickableObjectHandle pickableHandle, PickableObjectId id) { - ResourceChangeCollectingScene::setPickableObjectId(pickableHandle, id); + BaseT::setPickableObjectId(pickableHandle, id); m_creator.setPickableObjectId(pickableHandle, id); } void ActionCollectingScene::setPickableObjectCamera(PickableObjectHandle pickableHandle, CameraHandle cameraHandle) { - ResourceChangeCollectingScene::setPickableObjectCamera(pickableHandle, cameraHandle); + BaseT::setPickableObjectCamera(pickableHandle, cameraHandle); m_creator.setPickableObjectCamera(pickableHandle, cameraHandle); } void ActionCollectingScene::setPickableObjectEnabled(PickableObjectHandle pickableHandle, bool isEnabled) { - ResourceChangeCollectingScene::setPickableObjectEnabled(pickableHandle, isEnabled); + BaseT::setPickableObjectEnabled(pickableHandle, isEnabled); m_creator.setPickableObjectEnabled(pickableHandle, isEnabled); } DataSlotHandle ActionCollectingScene::allocateDataSlot(const DataSlot& dataSlot, DataSlotHandle handle /*= DataSlotHandle::Invalid()*/) { - const DataSlotHandle handleActual = ResourceChangeCollectingScene::allocateDataSlot(dataSlot, handle); + const DataSlotHandle handleActual = BaseT::allocateDataSlot(dataSlot, handle); m_creator.allocateDataSlot(dataSlot, handleActual); return handleActual; } void ActionCollectingScene::releaseDataSlot(DataSlotHandle handle) { - ResourceChangeCollectingScene::releaseDataSlot(handle); + BaseT::releaseDataSlot(handle); m_creator.releaseDataSlot(handle); } void ActionCollectingScene::setDataSlotTexture(DataSlotHandle handle, const ResourceContentHash& texture) { - ResourceChangeCollectingScene::setDataSlotTexture(handle, texture); + BaseT::setDataSlotTexture(handle, texture); m_creator.setDataSlotTexture(handle, texture); } TextureSamplerHandle ActionCollectingScene::allocateTextureSampler(const TextureSampler& sampler, TextureSamplerHandle handle) { - const TextureSamplerHandle handleActual = ResourceChangeCollectingScene::allocateTextureSampler(sampler, handle); + const TextureSamplerHandle handleActual = BaseT::allocateTextureSampler(sampler, handle); m_creator.allocateTextureSampler(sampler, handleActual); return handleActual; } void ActionCollectingScene::releaseTextureSampler(TextureSamplerHandle handle) { - ResourceChangeCollectingScene::releaseTextureSampler(handle); + BaseT::releaseTextureSampler(handle); m_creator.releaseTextureSampler(handle); } // Render targets RenderTargetHandle ActionCollectingScene::allocateRenderTarget(RenderTargetHandle targetHandle) { - const RenderTargetHandle handleActual = ResourceChangeCollectingScene::allocateRenderTarget(targetHandle); + const RenderTargetHandle handleActual = BaseT::allocateRenderTarget(targetHandle); m_creator.allocateRenderTarget(handleActual); return handleActual; } void ActionCollectingScene::releaseRenderTarget (RenderTargetHandle targetHandle) { - ResourceChangeCollectingScene::releaseRenderTarget( targetHandle ); + BaseT::releaseRenderTarget( targetHandle ); m_creator.releaseRenderTarget(targetHandle); } RenderBufferHandle ActionCollectingScene::allocateRenderBuffer(const RenderBuffer& renderBuffer, RenderBufferHandle handle) { - const RenderBufferHandle handleActual = ResourceChangeCollectingScene::allocateRenderBuffer(renderBuffer, handle); + const RenderBufferHandle handleActual = BaseT::allocateRenderBuffer(renderBuffer, handle); m_creator.allocateRenderBuffer(renderBuffer, handleActual); return handleActual; } void ActionCollectingScene::releaseRenderBuffer(RenderBufferHandle handle) { - ResourceChangeCollectingScene::releaseRenderBuffer(handle); + BaseT::releaseRenderBuffer(handle); m_creator.releaseRenderBuffer(handle); } void ActionCollectingScene::setRenderBufferProperties(RenderBufferHandle handle, uint32_t width, uint32_t height, uint32_t sampleCount) { - ResourceChangeCollectingScene::setRenderBufferProperties(handle, width, height, sampleCount); + BaseT::setRenderBufferProperties(handle, width, height, sampleCount); m_creator.setRenderBufferProperties(handle, width, height, sampleCount); } void ActionCollectingScene::addRenderTargetRenderBuffer(RenderTargetHandle targetHandle, RenderBufferHandle bufferHandle) { - ResourceChangeCollectingScene::addRenderTargetRenderBuffer(targetHandle, bufferHandle); + BaseT::addRenderTargetRenderBuffer(targetHandle, bufferHandle); m_creator.addRenderTargetRenderBuffer(targetHandle, bufferHandle); } void ActionCollectingScene::setRenderPassClearColor(RenderPassHandle pass, const glm::vec4& clearColor) { - ResourceChangeCollectingScene::setRenderPassClearColor(pass, clearColor); + BaseT::setRenderPassClearColor(pass, clearColor); m_creator.setRenderPassClearColor(pass, clearColor); } void ActionCollectingScene::setRenderPassClearFlag(RenderPassHandle pass, ClearFlags clearFlag) { - ResourceChangeCollectingScene::setRenderPassClearFlag(pass, clearFlag); + BaseT::setRenderPassClearFlag(pass, clearFlag); m_creator.setRenderPassClearFlag(pass, clearFlag); } DataBufferHandle ActionCollectingScene::allocateDataBuffer(EDataBufferType dataBufferType, EDataType dataType, uint32_t maximumSizeInBytes, DataBufferHandle handle) { - const DataBufferHandle allocatedHandle = ResourceChangeCollectingScene::allocateDataBuffer(dataBufferType, dataType, maximumSizeInBytes, handle); + const DataBufferHandle allocatedHandle = BaseT::allocateDataBuffer(dataBufferType, dataType, maximumSizeInBytes, handle); m_creator.allocateDataBuffer(dataBufferType, dataType, maximumSizeInBytes, allocatedHandle); return allocatedHandle; @@ -637,19 +643,38 @@ namespace ramses::internal void ActionCollectingScene::releaseDataBuffer(DataBufferHandle handle) { - ResourceChangeCollectingScene::releaseDataBuffer(handle); + BaseT::releaseDataBuffer(handle); m_creator.releaseDataBuffer(handle); } void ActionCollectingScene::updateDataBuffer(DataBufferHandle handle, uint32_t offsetInBytes, uint32_t dataSizeInBytes, const std::byte* data) { - ResourceChangeCollectingScene::updateDataBuffer(handle, offsetInBytes, dataSizeInBytes, data); + BaseT::updateDataBuffer(handle, offsetInBytes, dataSizeInBytes, data); m_creator.updateDataBuffer(handle, offsetInBytes, dataSizeInBytes, data); } + UniformBufferHandle ActionCollectingScene::allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) + { + const auto allocatedHandle = BaseT::allocateUniformBuffer(size, handle); + m_creator.allocateUniformBuffer(size, allocatedHandle); + return allocatedHandle; + } + + void ActionCollectingScene::releaseUniformBuffer(UniformBufferHandle handle) + { + BaseT::releaseUniformBuffer(handle); + m_creator.releaseUniformBuffer(handle); + } + + void ActionCollectingScene::updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) + { + BaseT::updateUniformBuffer(uniformBufferHandle, offset, size, data); + m_creator.updateUniformBuffer(uniformBufferHandle, offset, size, data); + } + TextureBufferHandle ActionCollectingScene::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle /*= TextureBufferHandle::Invalid()*/) { - const TextureBufferHandle allocatedHandle = ResourceChangeCollectingScene::allocateTextureBuffer(textureFormat, mipMapDimensions, handle); + const TextureBufferHandle allocatedHandle = BaseT::allocateTextureBuffer(textureFormat, mipMapDimensions, handle); m_creator.allocateTextureBuffer(textureFormat, mipMapDimensions, allocatedHandle); return allocatedHandle; @@ -657,45 +682,45 @@ namespace ramses::internal void ActionCollectingScene::releaseTextureBuffer(TextureBufferHandle handle) { - ResourceChangeCollectingScene::releaseTextureBuffer(handle); + BaseT::releaseTextureBuffer(handle); m_creator.releaseTextureBuffer(handle); } void ActionCollectingScene::updateTextureBuffer(TextureBufferHandle handle, uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const std::byte* data) { - ResourceChangeCollectingScene::updateTextureBuffer(handle, mipLevel, x, y, width, height, data); + BaseT::updateTextureBuffer(handle, mipLevel, x, y, width, height, data); const uint32_t dataSize = width * height * GetTexelSizeFromFormat(getTextureBuffer(handle).textureFormat); m_creator.updateTextureBuffer(handle, mipLevel, x, y, width, height, data, dataSize); } SceneReferenceHandle ActionCollectingScene::allocateSceneReference(SceneId sceneId, SceneReferenceHandle handle) { - const auto actualHandle = ResourceChangeCollectingScene::allocateSceneReference(sceneId, handle); + const auto actualHandle = BaseT::allocateSceneReference(sceneId, handle); m_creator.allocateSceneReference(sceneId, actualHandle); return actualHandle; } void ActionCollectingScene::releaseSceneReference(SceneReferenceHandle handle) { - ResourceChangeCollectingScene::releaseSceneReference(handle); + BaseT::releaseSceneReference(handle); m_creator.releaseSceneReference(handle); } void ActionCollectingScene::requestSceneReferenceState(SceneReferenceHandle handle, RendererSceneState state) { - ResourceChangeCollectingScene::requestSceneReferenceState(handle, state); + BaseT::requestSceneReferenceState(handle, state); m_creator.requestSceneReferenceState(handle, state); } void ActionCollectingScene::requestSceneReferenceFlushNotifications(SceneReferenceHandle handle, bool enable) { - ResourceChangeCollectingScene::requestSceneReferenceFlushNotifications(handle, enable); + BaseT::requestSceneReferenceFlushNotifications(handle, enable); m_creator.requestSceneReferenceFlushNotifications(handle, enable); } void ActionCollectingScene::setSceneReferenceRenderOrder(SceneReferenceHandle handle, int32_t renderOrder) { - ResourceChangeCollectingScene::setSceneReferenceRenderOrder(handle, renderOrder); + BaseT::setSceneReferenceRenderOrder(handle, renderOrder); m_creator.setSceneReferenceRenderOrder(handle, renderOrder); } diff --git a/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.h b/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.h index cf8a75e9a..7baa7570a 100644 --- a/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.h +++ b/src/framework/internal/SceneGraph/Scene/ActionCollectingScene.h @@ -16,8 +16,10 @@ namespace ramses::internal { class ActionCollectingScene : public ResourceChangeCollectingScene { + using BaseT = ResourceChangeCollectingScene; + public: - explicit ActionCollectingScene(const SceneInfo& sceneInfo = SceneInfo()); + explicit ActionCollectingScene(const SceneInfo& sceneInfo = {}, EFeatureLevel featureLevel = EFeatureLevel_Latest); void preallocateSceneSize (const SceneSizeInformation& sizeInfo) override; @@ -92,6 +94,7 @@ namespace ramses::internal void setDataResource (DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) override; void setDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) override; void setDataReference (DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef) override; + void setDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) override; // Texture sampler description TextureSamplerHandle allocateTextureSampler (const TextureSampler& sampler, TextureSamplerHandle handle) override; @@ -149,6 +152,10 @@ namespace ramses::internal void releaseDataBuffer (DataBufferHandle handle) override; void updateDataBuffer (DataBufferHandle handle, uint32_t offsetInBytes, uint32_t dataSizeInBytes, const std::byte* data) override; + UniformBufferHandle allocateUniformBuffer (uint32_t size, UniformBufferHandle handle) override; + void releaseUniformBuffer (UniformBufferHandle uniformBufferHandle) override; + void updateUniformBuffer (UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) override; + TextureBufferHandle allocateTextureBuffer (EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) override; void releaseTextureBuffer (TextureBufferHandle handle) override; void updateTextureBuffer (TextureBufferHandle handle, uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const std::byte* data) override; diff --git a/src/framework/internal/SceneGraph/Scene/ClientScene.h b/src/framework/internal/SceneGraph/Scene/ClientScene.h index a7ca48739..c99fe9a26 100644 --- a/src/framework/internal/SceneGraph/Scene/ClientScene.h +++ b/src/framework/internal/SceneGraph/Scene/ClientScene.h @@ -18,9 +18,11 @@ namespace ramses::internal // together with some additional data used in client side logic class ClientScene final : public DataLayoutCachedScene { + using BaseT = DataLayoutCachedScene; + public: - explicit ClientScene(const SceneInfo& sceneInfo = {}) - : DataLayoutCachedScene(sceneInfo) + explicit ClientScene(const SceneInfo& sceneInfo = {}, EFeatureLevel featureLevel = EFeatureLevel_Latest) + : BaseT(sceneInfo, featureLevel) { } diff --git a/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.cpp b/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.cpp index 745e6f967..8ab8d4afb 100644 --- a/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.cpp +++ b/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.cpp @@ -10,8 +10,8 @@ namespace ramses::internal { - DataLayoutCachedScene::DataLayoutCachedScene(const SceneInfo& sceneInfo) - : ActionCollectingScene(sceneInfo) + DataLayoutCachedScene::DataLayoutCachedScene(const SceneInfo& sceneInfo, EFeatureLevel featureLevel) + : BaseT(sceneInfo, featureLevel) , m_dataLayoutCache(32u) { } @@ -32,7 +32,7 @@ namespace ramses::internal void DataLayoutCachedScene::releaseDataLayout(DataLayoutHandle handle) { - const size_t fieldCount = ActionCollectingScene::getDataLayout(handle).getFieldCount(); + const size_t fieldCount = BaseT::getDataLayout(handle).getFieldCount(); assert(fieldCount < m_dataLayoutCache.size()); DataLayoutCacheGroup& dataLayouts = m_dataLayoutCache[fieldCount]; @@ -43,14 +43,14 @@ namespace ramses::internal entry.m_usageCount--; if (entry.m_usageCount == 0u) { - ActionCollectingScene::releaseDataLayout(handle); + BaseT::releaseDataLayout(handle); dataLayouts.remove(handle); } } DataLayoutHandle DataLayoutCachedScene::allocateAndCacheDataLayout(const DataFieldInfoVector& dataFields, const ResourceContentHash& effectHash, DataLayoutHandle handle) { - const DataLayoutHandle actualHandle = ActionCollectingScene::allocateDataLayout(dataFields, effectHash, handle); + const DataLayoutHandle actualHandle = BaseT::allocateDataLayout(dataFields, effectHash, handle); const size_t fieldCount = dataFields.size(); if (m_dataLayoutCache.size() <= fieldCount) diff --git a/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.h b/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.h index 4812c8ec6..25b4e1728 100644 --- a/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.h +++ b/src/framework/internal/SceneGraph/Scene/DataLayoutCachedScene.h @@ -16,8 +16,10 @@ namespace ramses::internal { class DataLayoutCachedScene : public ActionCollectingScene { + using BaseT = ActionCollectingScene; + public: - explicit DataLayoutCachedScene(const SceneInfo& sceneInfo = SceneInfo()); + explicit DataLayoutCachedScene(const SceneInfo& sceneInfo = {}, EFeatureLevel featureLevel = EFeatureLevel_Latest); DataLayoutHandle allocateDataLayout(const DataFieldInfoVector& dataFields, const ResourceContentHash& effectHash, DataLayoutHandle handle) override; void releaseDataLayout(DataLayoutHandle handle) override; diff --git a/src/framework/internal/SceneGraph/Scene/ESceneActionId.h b/src/framework/internal/SceneGraph/Scene/ESceneActionId.h index 239352c65..7c794ec28 100644 --- a/src/framework/internal/SceneGraph/Scene/ESceneActionId.h +++ b/src/framework/internal/SceneGraph/Scene/ESceneActionId.h @@ -192,6 +192,12 @@ namespace ramses::internal Incomplete, + // Uniform Buffer + AllocateUniformBuffer, + ReleaseUniformBuffer, + UpdateUniformBuffer, + SetDataUniformBuffer, + NUMBER_OF_TYPES }; @@ -236,6 +242,7 @@ case ENUMVALUE: return #ENUMVALUE CreateNameForEnumID(ESceneActionId::SetRenderableEffect); CreateNameForEnumID(ESceneActionId::SetDataTextureSamplerHandle); CreateNameForEnumID(ESceneActionId::SetDataReference); + CreateNameForEnumID(ESceneActionId::SetDataUniformBuffer); CreateNameForEnumID(ESceneActionId::SetDataMatrix22fArray); CreateNameForEnumID(ESceneActionId::SetDataMatrix33fArray); CreateNameForEnumID(ESceneActionId::SetDataMatrix44fArray); @@ -245,6 +252,11 @@ case ENUMVALUE: return #ENUMVALUE CreateNameForEnumID(ESceneActionId::ReleaseDataBuffer); CreateNameForEnumID(ESceneActionId::UpdateDataBuffer); + // Uniform buffer + CreateNameForEnumID(ESceneActionId::AllocateUniformBuffer); + CreateNameForEnumID(ESceneActionId::ReleaseUniformBuffer); + CreateNameForEnumID(ESceneActionId::UpdateUniformBuffer); + // Texture Buffer CreateNameForEnumID(ESceneActionId::AllocateTextureBuffer); CreateNameForEnumID(ESceneActionId::ReleaseTextureBuffer); diff --git a/src/framework/internal/SceneGraph/Scene/MergeScene.cpp b/src/framework/internal/SceneGraph/Scene/MergeScene.cpp new file mode 100644 index 000000000..7e0d52c2e --- /dev/null +++ b/src/framework/internal/SceneGraph/Scene/MergeScene.cpp @@ -0,0 +1,1446 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "MergeScene.h" +#include "internal/Core/Common/TypedMemoryHandle.h" +#include "internal/SceneGraph/Scene/DataLayoutCachedScene.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/SceneGraph/SceneAPI/SceneSizeInformation.h" +#include + +namespace ramses::internal +{ + template<> + [[nodiscard]] inline TypedMemoryHandle MergeScene::getMappedHandle(TypedMemoryHandle handle) const; + + MergeScene::MergeScene(IScene& originalScene, SceneMergeHandleMapping& mapping) + : m_originalScene{ originalScene } + , m_mapping{ mapping } + { + const auto originalSizeInfo = m_originalScene.getSceneSizeInformation(); + + m_offsetRenderableHandle = RenderableHandle{originalSizeInfo.renderableCount}; + m_offsetRenderStateHandle = RenderStateHandle(originalSizeInfo.renderStateCount); + m_offsetCameraHandle = CameraHandle(originalSizeInfo.cameraCount); + m_offsetNodeHandle = NodeHandle(originalSizeInfo.nodeCount); + m_offsetTransformHandle = TransformHandle(originalSizeInfo.transformCount); + m_offsetDataLayoutHandle = DataLayoutHandle(originalSizeInfo.datalayoutCount); + m_offsetDataInstanceHandle = DataInstanceHandle(originalSizeInfo.datainstanceCount); + m_offsetUniformBufferHandle = UniformBufferHandle(originalSizeInfo.uniformBufferCount); + m_offsetTextureSamplerHandle = TextureSamplerHandle(originalSizeInfo.textureSamplerCount); + m_offsetRenderGroupHandle = RenderGroupHandle(originalSizeInfo.renderGroupCount); + m_offsetRenderPassHandle = RenderPassHandle(originalSizeInfo.renderPassCount); + m_offsetBlitPassHandle = BlitPassHandle(originalSizeInfo.blitPassCount); + m_offsetPickableObjectHandle = PickableObjectHandle(originalSizeInfo.pickableObjectCount); + m_offsetRenderTargetHandle = RenderTargetHandle(originalSizeInfo.renderTargetCount); + m_offsetRenderBufferHandle = RenderBufferHandle(originalSizeInfo.renderBufferCount); + m_offsetDataBufferHandle = DataBufferHandle(originalSizeInfo.dataBufferCount); + m_offsetTextureBufferHandle = TextureBufferHandle(originalSizeInfo.textureBufferCount); + m_offsetDataSlotHandle = DataSlotHandle(originalSizeInfo.dataSlotCount); + m_offsetSceneReferenceHandle = SceneReferenceHandle(originalSizeInfo.sceneReferenceCount); + } + + const std::string& MergeScene::getName() const + { + return m_originalScene.getName(); + } + + SceneId MergeScene::getSceneId() const + { + return m_originalScene.getSceneId(); + } + + void MergeScene::setEffectTimeSync(FlushTime::Clock::time_point /*t*/) + { + // not set by a scene action + } + + ERenderBackendCompatibility MergeScene::getRenderBackendCompatibility() const + { + return m_originalScene.getRenderBackendCompatibility(); + } + + EVulkanAPIVersion MergeScene::getVulkanAPIVersion() const + { + return m_originalScene.getVulkanAPIVersion(); + } + + ESPIRVVersion MergeScene::getSPIRVVersion() const + { + return m_originalScene.getSPIRVVersion(); + } + + FlushTime::Clock::time_point MergeScene::getEffectTimeSync() const + { + return m_originalScene.getEffectTimeSync(); + } + + uint32_t MergeScene::getRenderableCount() const + { + return m_originalScene.getRenderableCount(); + } + + RenderableHandle MergeScene::allocateRenderable(NodeHandle nodeHandle, RenderableHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const RenderableHandle actualHandle = m_originalScene.allocateRenderable(getMappedHandle(nodeHandle), mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseRenderable(RenderableHandle renderableHandle) + { + assert(false); + m_originalScene.releaseRenderable(getMappedHandle(renderableHandle)); + } + + bool MergeScene::isRenderableAllocated(RenderableHandle renderableHandle) const + { + return m_originalScene.isRenderableAllocated(getMappedHandle(renderableHandle)); + } + + void MergeScene::setRenderableDataInstance(RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) + { + m_originalScene.setRenderableDataInstance(getMappedHandle(renderableHandle), slot, getMappedHandle(newDataInstance)); + } + + void MergeScene::setRenderableStartIndex(RenderableHandle renderableHandle, uint32_t startIndex) + { + m_originalScene.setRenderableStartIndex(getMappedHandle(renderableHandle), startIndex); + } + + void MergeScene::setRenderableIndexCount(RenderableHandle renderableHandle, uint32_t indexCount) + { + m_originalScene.setRenderableIndexCount(getMappedHandle(renderableHandle), indexCount); + } + + void MergeScene::setRenderableRenderState(RenderableHandle renderableHandle, RenderStateHandle stateHandle) + { + m_originalScene.setRenderableRenderState(getMappedHandle(renderableHandle), getMappedHandle(stateHandle)); + } + + void MergeScene::setRenderableVisibility(RenderableHandle renderableHandle, EVisibilityMode visible) + { + m_originalScene.setRenderableVisibility(getMappedHandle(renderableHandle), visible); + } + + void MergeScene::setRenderableInstanceCount(RenderableHandle renderableHandle, uint32_t instanceCount) + { + m_originalScene.setRenderableInstanceCount(getMappedHandle(renderableHandle), instanceCount); + } + + void MergeScene::setRenderableStartVertex(RenderableHandle renderableHandle, uint32_t startVertex) + { + m_originalScene.setRenderableStartVertex(getMappedHandle(renderableHandle), startVertex); + } + + const Renderable& MergeScene::getRenderable(RenderableHandle renderableHandle) const + { + return m_originalScene.getRenderable(getMappedHandle(renderableHandle)); + } + + uint32_t MergeScene::getRenderStateCount() const + { + return m_originalScene.getRenderStateCount(); + } + + RenderStateHandle MergeScene::allocateRenderState(RenderStateHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const RenderStateHandle actualHandle = m_originalScene.allocateRenderState(mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseRenderState(RenderStateHandle stateHandle) + { + assert(false); + m_originalScene.releaseRenderState(getMappedHandle(stateHandle)); + } + + bool MergeScene::isRenderStateAllocated(RenderStateHandle stateHandle) const + { + return m_originalScene.isRenderStateAllocated(getMappedHandle(stateHandle)); + } + + void MergeScene::setRenderStateBlendFactors(RenderStateHandle stateHandle, EBlendFactor srcColor, EBlendFactor destColor, EBlendFactor srcAlpha, EBlendFactor destAlpha) + { + m_originalScene.setRenderStateBlendFactors(getMappedHandle(stateHandle), srcColor, destColor, srcAlpha, destAlpha); + } + + void MergeScene::setRenderStateBlendOperations(RenderStateHandle stateHandle, EBlendOperation operationColor, EBlendOperation operationAlpha) + { + m_originalScene.setRenderStateBlendOperations(getMappedHandle(stateHandle), operationColor, operationAlpha); + } + + void MergeScene::setRenderStateBlendColor(RenderStateHandle stateHandle, const glm::vec4& color) + { + m_originalScene.setRenderStateBlendColor(getMappedHandle(stateHandle), color); + } + + void MergeScene::setRenderStateCullMode(RenderStateHandle stateHandle, ECullMode cullMode) + { + m_originalScene.setRenderStateCullMode(getMappedHandle(stateHandle), cullMode); + } + + void MergeScene::setRenderStateDrawMode(RenderStateHandle stateHandle, EDrawMode drawMode) + { + m_originalScene.setRenderStateDrawMode(getMappedHandle(stateHandle), drawMode); + } + + void MergeScene::setRenderStateDepthFunc(RenderStateHandle stateHandle, EDepthFunc func) + { + m_originalScene.setRenderStateDepthFunc(getMappedHandle(stateHandle), func); + } + + void MergeScene::setRenderStateDepthWrite(RenderStateHandle stateHandle, EDepthWrite flag) + { + m_originalScene.setRenderStateDepthWrite(getMappedHandle(stateHandle), flag); + } + + void MergeScene::setRenderStateScissorTest(RenderStateHandle stateHandle, EScissorTest flag, const RenderState::ScissorRegion& region) + { + m_originalScene.setRenderStateScissorTest(getMappedHandle(stateHandle), flag, region); + } + + void MergeScene::setRenderStateStencilFunc(RenderStateHandle stateHandle, EStencilFunc func, uint8_t ref, uint8_t mask) + { + m_originalScene.setRenderStateStencilFunc(getMappedHandle(stateHandle), func, ref, mask); + } + + void MergeScene::setRenderStateStencilOps(RenderStateHandle stateHandle, EStencilOp sfail, EStencilOp dpfail, EStencilOp dppass) + { + m_originalScene.setRenderStateStencilOps(getMappedHandle(stateHandle), sfail, dpfail, dppass); + } + + void MergeScene::setRenderStateColorWriteMask(RenderStateHandle stateHandle, ColorWriteMask colorMask) + { + m_originalScene.setRenderStateColorWriteMask(getMappedHandle(stateHandle), colorMask); + } + + const RenderState& MergeScene::getRenderState(RenderStateHandle stateHandle) const + { + return m_originalScene.getRenderState(getMappedHandle(stateHandle)); + } + + uint32_t MergeScene::getCameraCount() const + { + return m_originalScene.getCameraCount(); + } + + CameraHandle MergeScene::allocateCamera(ECameraProjectionType projType, NodeHandle nodeHandle, DataInstanceHandle dataInstance, CameraHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const CameraHandle actualHandle = m_originalScene.allocateCamera(projType, getMappedHandle(nodeHandle), getMappedHandle(dataInstance), mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseCamera(CameraHandle cameraHandle) + { + assert(false); + m_originalScene.releaseCamera(getMappedHandle(cameraHandle)); + } + + bool MergeScene::isCameraAllocated(CameraHandle handle) const + { + return m_originalScene.isCameraAllocated(getMappedHandle(handle)); + } + + const Camera& MergeScene::getCamera(CameraHandle cameraHandle) const + { + return m_originalScene.getCamera(getMappedHandle(cameraHandle)); + } + + uint32_t MergeScene::getNodeCount() const + { + return m_originalScene.getNodeCount(); + } + + NodeHandle MergeScene::allocateNode(uint32_t childrenCount, NodeHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const NodeHandle actualHandle = m_originalScene.allocateNode(childrenCount, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseNode(NodeHandle nodeHandle) + { + assert(false); + m_originalScene.releaseNode(getMappedHandle(nodeHandle)); + } + + bool MergeScene::isNodeAllocated(NodeHandle nodeHandle) const + { + return m_originalScene.isNodeAllocated(getMappedHandle(nodeHandle)); + } + + uint32_t MergeScene::getTransformCount() const + { + return m_originalScene.getTransformCount(); + } + + TransformHandle MergeScene::allocateTransform(NodeHandle nodeHandle, TransformHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const TransformHandle actualHandle = m_originalScene.allocateTransform(getMappedHandle(nodeHandle), mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseTransform(TransformHandle transform) + { + assert(false); + m_originalScene.releaseTransform(getMappedHandle(transform)); + } + + bool MergeScene::isTransformAllocated(TransformHandle transformHandle) const + { + return m_originalScene.isTransformAllocated(getMappedHandle(transformHandle)); + } + + NodeHandle MergeScene::getParent(NodeHandle nodeHandle) const + { + return m_originalScene.getParent(getMappedHandle(nodeHandle)); + } + + void MergeScene::addChildToNode(NodeHandle parent, NodeHandle child) + { + m_originalScene.addChildToNode(getMappedHandle(parent), getMappedHandle(child)); + } + + void MergeScene::removeChildFromNode(NodeHandle parent, NodeHandle child) + { + m_originalScene.removeChildFromNode(getMappedHandle(parent), getMappedHandle(child)); + } + + uint32_t MergeScene::getChildCount(NodeHandle parent) const + { + return m_originalScene.getChildCount(getMappedHandle(parent)); + } + + NodeHandle MergeScene::getChild(NodeHandle parent, uint32_t childNumber) const + { + return m_originalScene.getChild(getMappedHandle(parent), childNumber); + } + + NodeHandle MergeScene::getTransformNode(TransformHandle handle) const + { + return m_originalScene.getTransformNode(getMappedHandle(handle)); + } + + const glm::vec3& MergeScene::getTranslation(TransformHandle handle) const + { + return m_originalScene.getTranslation(getMappedHandle(handle)); + } + + const glm::vec4& MergeScene::getRotation(TransformHandle handle) const + { + return m_originalScene.getRotation(getMappedHandle(handle)); + } + + ERotationType MergeScene::getRotationType(TransformHandle handle) const + { + return m_originalScene.getRotationType(getMappedHandle(handle)); + } + + const glm::vec3& MergeScene::getScaling(TransformHandle handle) const + { + return m_originalScene.getScaling(getMappedHandle(handle)); + } + + void MergeScene::setTranslation(TransformHandle handle, const glm::vec3& translation) + { + m_originalScene.setTranslation(getMappedHandle(handle), translation); + } + + void MergeScene::setRotation(TransformHandle handle, const glm::vec4& rotation, ERotationType rotationType) + { + m_originalScene.setRotation(getMappedHandle(handle), rotation, rotationType); + } + + void MergeScene::setScaling(TransformHandle handle, const glm::vec3& scaling) + { + m_originalScene.setScaling(getMappedHandle(handle), scaling); + } + + uint32_t MergeScene::getDataLayoutCount() const + { + return m_originalScene.getDataLayoutCount(); + } + + DataLayoutHandle MergeScene::allocateDataLayout(const DataFieldInfoVector& dataFields, const ResourceContentHash& effectHash, DataLayoutHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const DataLayoutHandle actualHandle = m_originalScene.allocateDataLayout(dataFields, effectHash, mappedHandle); + // because of data layout caching the returned handle might be different + if (m_mapping.hasMapping(handle)) + { + assert(m_mapping.getMapping(handle) == actualHandle); + return actualHandle; + } + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseDataLayout(DataLayoutHandle layoutHandle) + { + assert(false); + m_originalScene.releaseDataLayout(getMappedHandle(layoutHandle)); + } + + bool MergeScene::isDataLayoutAllocated(DataLayoutHandle layoutHandle) const + { + return m_originalScene.isDataLayoutAllocated(getMappedHandle(layoutHandle)); + } + + const DataLayout& MergeScene::getDataLayout(DataLayoutHandle layoutHandle) const + { + return m_originalScene.getDataLayout(getMappedHandle(layoutHandle)); + } + + uint32_t MergeScene::getDataInstanceCount() const + { + return m_originalScene.getDataInstanceCount(); + } + + DataInstanceHandle MergeScene::allocateDataInstance(DataLayoutHandle finishedLayoutHandle, DataInstanceHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const auto actualHandle = m_originalScene.allocateDataInstance(getMappedHandle(finishedLayoutHandle), mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseDataInstance(DataInstanceHandle containerHandle) + { + assert(false); + m_originalScene.releaseDataInstance(getMappedHandle(containerHandle)); + } + + bool MergeScene::isDataInstanceAllocated(DataInstanceHandle containerHandle) const + { + return m_originalScene.isDataInstanceAllocated(getMappedHandle(containerHandle)); + } + + DataLayoutHandle MergeScene::getLayoutOfDataInstance(DataInstanceHandle containerHandle) const + { + return m_originalScene.getLayoutOfDataInstance(getMappedHandle(containerHandle)); + } + + const float* MergeScene::getDataFloatArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataFloatArray(getMappedHandle(containerHandle), field); + } + + const glm::vec2* MergeScene::getDataVector2fArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataVector2fArray(getMappedHandle(containerHandle), field); + } + + const glm::vec3* MergeScene::getDataVector3fArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataVector3fArray(getMappedHandle(containerHandle), field); + } + + const glm::vec4* MergeScene::getDataVector4fArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataVector4fArray(getMappedHandle(containerHandle), field); + } + + const bool* MergeScene::getDataBooleanArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataBooleanArray(getMappedHandle(containerHandle), field); + } + + const int32_t* MergeScene::getDataIntegerArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataIntegerArray(getMappedHandle(containerHandle), field); + } + + const glm::mat2* MergeScene::getDataMatrix22fArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataMatrix22fArray(getMappedHandle(containerHandle), field); + } + + const glm::mat3* MergeScene::getDataMatrix33fArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataMatrix33fArray(getMappedHandle(containerHandle), field); + } + + const glm::mat4* MergeScene::getDataMatrix44fArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataMatrix44fArray(getMappedHandle(containerHandle), field); + } + + const glm::ivec2* MergeScene::getDataVector2iArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataVector2iArray(getMappedHandle(containerHandle), field); + } + + const glm::ivec3* MergeScene::getDataVector3iArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataVector3iArray(getMappedHandle(containerHandle), field); + } + + const glm::ivec4* MergeScene::getDataVector4iArray(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataVector4iArray(getMappedHandle(containerHandle), field); + } + + const ResourceField& MergeScene::getDataResource(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataResource(getMappedHandle(containerHandle), field); + } + + TextureSamplerHandle MergeScene::getDataTextureSamplerHandle(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataTextureSamplerHandle(getMappedHandle(containerHandle), field); + } + + DataInstanceHandle MergeScene::getDataReference(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataReference(getMappedHandle(containerHandle), field); + } + + UniformBufferHandle MergeScene::getDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataUniformBuffer(getMappedHandle(containerHandle), field); + } + + float MergeScene::getDataSingleFloat(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleFloat(getMappedHandle(containerHandle), field); + } + + const glm::vec2& MergeScene::getDataSingleVector2f(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleVector2f(getMappedHandle(containerHandle), field); + } + + const glm::vec3& MergeScene::getDataSingleVector3f(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleVector3f(getMappedHandle(containerHandle), field); + } + + const glm::vec4& MergeScene::getDataSingleVector4f(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleVector4f(getMappedHandle(containerHandle), field); + } + + bool MergeScene::getDataSingleBoolean(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleBoolean(getMappedHandle(containerHandle), field); + } + + int32_t MergeScene::getDataSingleInteger(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleInteger(getMappedHandle(containerHandle), field); + } + + const glm::mat2& MergeScene::getDataSingleMatrix22f(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleMatrix22f(getMappedHandle(containerHandle), field); + } + + const glm::mat3& MergeScene::getDataSingleMatrix33f(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleMatrix33f(getMappedHandle(containerHandle), field); + } + + const glm::mat4& MergeScene::getDataSingleMatrix44f(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleMatrix44f(getMappedHandle(containerHandle), field); + } + + const glm::ivec2& MergeScene::getDataSingleVector2i(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleVector2i(getMappedHandle(containerHandle), field); + } + + const glm::ivec3& MergeScene::getDataSingleVector3i(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleVector3i(getMappedHandle(containerHandle), field); + } + + const glm::ivec4& MergeScene::getDataSingleVector4i(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_originalScene.getDataSingleVector4i(getMappedHandle(containerHandle), field); + } + + void MergeScene::setDataFloatArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const float* data) + { + m_originalScene.setDataFloatArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataVector2fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec2* data) + { + m_originalScene.setDataVector2fArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataVector3fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec3* data) + { + m_originalScene.setDataVector3fArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataVector4fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec4* data) + { + m_originalScene.setDataVector4fArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataMatrix22fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat2* data) + { + m_originalScene.setDataMatrix22fArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataMatrix33fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat3* data) + { + m_originalScene.setDataMatrix33fArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataMatrix44fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat4* data) + { + m_originalScene.setDataMatrix44fArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataBooleanArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const bool* data) + { + m_originalScene.setDataBooleanArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataIntegerArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const int32_t* data) + { + m_originalScene.setDataIntegerArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataVector2iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec2* data) + { + m_originalScene.setDataVector2iArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataVector3iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec3* data) + { + m_originalScene.setDataVector3iArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataVector4iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec4* data) + { + m_originalScene.setDataVector4iArray(getMappedHandle(containerHandle), field, elementCount, data); + } + + void MergeScene::setDataResource(DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) + { + m_originalScene.setDataResource(getMappedHandle(containerHandle), field, hash, getMappedHandle(dataBuffer), instancingDivisor, offsetWithinElementInBytes, stride); + } + + void MergeScene::setDataTextureSamplerHandle(DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) + { + m_originalScene.setDataTextureSamplerHandle(getMappedHandle(containerHandle), field, getMappedHandle(samplerHandle)); + } + + void MergeScene::setDataReference(DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef) + { + m_originalScene.setDataReference(getMappedHandle(containerHandle), field, getMappedHandle(dataRef)); + } + + void MergeScene::setDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) + { + m_originalScene.setDataUniformBuffer(getMappedHandle(containerHandle), field, getMappedHandle(uniformBufferHandle)); + } + + void MergeScene::setDataSingleFloat(DataInstanceHandle containerHandle, DataFieldHandle field, float data) + { + m_originalScene.setDataSingleFloat(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleVector2f(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::vec2& data) + { + m_originalScene.setDataSingleVector2f(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleVector3f(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::vec3& data) + { + m_originalScene.setDataSingleVector3f(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleVector4f(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::vec4& data) + { + m_originalScene.setDataSingleVector4f(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleBoolean(DataInstanceHandle containerHandle, DataFieldHandle field, bool data) + { + m_originalScene.setDataSingleBoolean(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleInteger(DataInstanceHandle containerHandle, DataFieldHandle field, int32_t data) + { + m_originalScene.setDataSingleInteger(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleVector2i(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::ivec2& data) + { + m_originalScene.setDataSingleVector2i(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleVector3i(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::ivec3& data) + { + m_originalScene.setDataSingleVector3i(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleVector4i(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::ivec4& data) + { + m_originalScene.setDataSingleVector4i(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleMatrix22f(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat2& data) + { + m_originalScene.setDataSingleMatrix22f(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleMatrix33f(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat3& data) + { + m_originalScene.setDataSingleMatrix33f(getMappedHandle(containerHandle), field, data); + } + + void MergeScene::setDataSingleMatrix44f(DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat4& data) + { + m_originalScene.setDataSingleMatrix44f(getMappedHandle(containerHandle), field, data); + } + + TextureSamplerHandle MergeScene::allocateTextureSampler(const TextureSampler& sampler, TextureSamplerHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + + auto mappedSampler = sampler; + switch (sampler.contentType) + { + case TextureSampler::ContentType::TextureBuffer: + mappedSampler.contentHandle = getMappedHandle(TextureBufferHandle(sampler.contentHandle)).asMemoryHandle(); + break; + case TextureSampler::ContentType::RenderBuffer: + case TextureSampler::ContentType::RenderBufferMS: + mappedSampler.contentHandle = getMappedHandle(RenderBufferHandle(sampler.contentHandle)).asMemoryHandle(); + break; + case TextureSampler::ContentType::None: + case TextureSampler::ContentType::ClientTexture: + case TextureSampler::ContentType::OffscreenBuffer: + case TextureSampler::ContentType::StreamBuffer: + case TextureSampler::ContentType::ExternalTexture: + break; + } + + const TextureSamplerHandle actualHandle = m_originalScene.allocateTextureSampler(mappedSampler, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseTextureSampler(TextureSamplerHandle handle) + { + assert(false); + m_originalScene.releaseTextureSampler(getMappedHandle(handle)); + } + + uint32_t MergeScene::getTextureSamplerCount() const + { + return m_originalScene.getTextureSamplerCount(); + } + + const TextureSampler& MergeScene::getTextureSampler(TextureSamplerHandle handle) const + { + return m_originalScene.getTextureSampler(getMappedHandle(handle)); + } + + bool MergeScene::isTextureSamplerAllocated(TextureSamplerHandle samplerHandle) const + { + return m_originalScene.isTextureSamplerAllocated(getMappedHandle(samplerHandle)); + } + + SceneSizeInformation MergeScene::getSceneSizeInformation() const + { + return m_originalScene.getSceneSizeInformation(); + } + + RenderGroupHandle MergeScene::allocateRenderGroup(uint32_t renderableCount, uint32_t nestedGroupCount, RenderGroupHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const RenderGroupHandle actualHandle = m_originalScene.allocateRenderGroup(renderableCount, nestedGroupCount, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseRenderGroup(RenderGroupHandle groupHandle) + { + assert(false); + m_originalScene.releaseRenderGroup(getMappedHandle(groupHandle)); + } + + bool MergeScene::isRenderGroupAllocated(RenderGroupHandle groupHandle) const + { + return m_originalScene.isRenderGroupAllocated(getMappedHandle(groupHandle)); + } + + uint32_t MergeScene::getRenderGroupCount() const + { + return m_originalScene.getRenderGroupCount(); + } + + void MergeScene::addRenderableToRenderGroup(RenderGroupHandle groupHandle, RenderableHandle renderableHandle, int32_t order) + { + m_originalScene.addRenderableToRenderGroup(getMappedHandle(groupHandle), getMappedHandle(renderableHandle), order); + } + + void MergeScene::removeRenderableFromRenderGroup(RenderGroupHandle groupHandle, RenderableHandle renderableHandle) + { + m_originalScene.removeRenderableFromRenderGroup(getMappedHandle(groupHandle), getMappedHandle(renderableHandle)); + } + + void MergeScene::addRenderGroupToRenderGroup(RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild, int32_t order) + { + m_originalScene.addRenderGroupToRenderGroup(getMappedHandle(groupHandleParent), getMappedHandle(groupHandleChild), order); + } + + void MergeScene::removeRenderGroupFromRenderGroup(RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild) + { + m_originalScene.removeRenderGroupFromRenderGroup(getMappedHandle(groupHandleParent), getMappedHandle(groupHandleChild)); + } + + const RenderGroup& MergeScene::getRenderGroup(RenderGroupHandle groupHandle) const + { + return m_originalScene.getRenderGroup(getMappedHandle(groupHandle)); + } + + RenderPassHandle MergeScene::allocateRenderPass(uint32_t renderGroupCount, RenderPassHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const RenderPassHandle actualHandle = m_originalScene.allocateRenderPass(renderGroupCount, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseRenderPass(RenderPassHandle handle) + { + assert(false); + m_originalScene.releaseRenderPass(getMappedHandle(handle)); + } + + bool MergeScene::isRenderPassAllocated(RenderPassHandle pass) const + { + return m_originalScene.isRenderPassAllocated(getMappedHandle(pass)); + } + + uint32_t MergeScene::getRenderPassCount() const + { + return m_originalScene.getRenderPassCount(); + } + + void MergeScene::setRenderPassCamera(RenderPassHandle pass, CameraHandle camera) + { + m_originalScene.setRenderPassCamera(getMappedHandle(pass), getMappedHandle(camera)); + } + + RenderTargetHandle MergeScene::allocateRenderTarget(RenderTargetHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const RenderTargetHandle actualHandle = m_originalScene.allocateRenderTarget(mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseRenderTarget(RenderTargetHandle targetHandle) + { + assert(false); + m_originalScene.releaseRenderTarget(getMappedHandle(targetHandle)); + } + + void MergeScene::addRenderTargetRenderBuffer(RenderTargetHandle targetHandle, RenderBufferHandle bufferHandle) + { + m_originalScene.addRenderTargetRenderBuffer(getMappedHandle(targetHandle), getMappedHandle(bufferHandle)); + } + + uint32_t MergeScene::getRenderTargetRenderBufferCount(RenderTargetHandle targetHandle) const + { + return m_originalScene.getRenderTargetRenderBufferCount(getMappedHandle(targetHandle)); + } + + RenderBufferHandle MergeScene::getRenderTargetRenderBuffer(RenderTargetHandle targetHandle, uint32_t bufferIndex) const + { + return m_originalScene.getRenderTargetRenderBuffer(getMappedHandle(targetHandle), bufferIndex); + } + + RenderBufferHandle MergeScene::allocateRenderBuffer(const RenderBuffer& renderBuffer, RenderBufferHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const RenderBufferHandle actualHandle = m_originalScene.allocateRenderBuffer(renderBuffer, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseRenderBuffer(RenderBufferHandle handle) + { + assert(false); + m_originalScene.releaseRenderBuffer(getMappedHandle(handle)); + } + + void MergeScene::setRenderBufferProperties(RenderBufferHandle handle, uint32_t width, uint32_t height, uint32_t sampleCount) + { + m_originalScene.setRenderBufferProperties(getMappedHandle(handle), width, height, sampleCount); + } + + bool MergeScene::isRenderBufferAllocated(RenderBufferHandle handle) const + { + return m_originalScene.isRenderBufferAllocated(getMappedHandle(handle)); + } + + uint32_t MergeScene::getRenderBufferCount() const + { + return m_originalScene.getRenderBufferCount(); + } + + const RenderBuffer& MergeScene::getRenderBuffer(RenderBufferHandle handle) const + { + return m_originalScene.getRenderBuffer(getMappedHandle(handle)); + } + + DataBufferHandle MergeScene::allocateDataBuffer(EDataBufferType dataBufferType, EDataType dataType, uint32_t maximumSizeInBytes, DataBufferHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const DataBufferHandle actualHandle = m_originalScene.allocateDataBuffer(dataBufferType, dataType, maximumSizeInBytes, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseDataBuffer(DataBufferHandle handle) + { + assert(false); + m_originalScene.releaseDataBuffer(getMappedHandle(handle)); + } + + uint32_t MergeScene::getDataBufferCount() const + { + return m_originalScene.getDataBufferCount(); + } + + void MergeScene::updateDataBuffer(DataBufferHandle handle, uint32_t offsetInBytes, uint32_t dataSizeInBytes, const std::byte* data) + { + m_originalScene.updateDataBuffer(getMappedHandle(handle), offsetInBytes, dataSizeInBytes, data); + } + + bool MergeScene::isDataBufferAllocated(DataBufferHandle handle) const + { + return m_originalScene.isDataBufferAllocated(getMappedHandle(handle)); + } + + const GeometryDataBuffer& MergeScene::getDataBuffer(DataBufferHandle handle) const + { + return m_originalScene.getDataBuffer(getMappedHandle(handle)); + } + + UniformBufferHandle MergeScene::allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const auto actualHandle = m_originalScene.allocateUniformBuffer(size, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) + { + assert(false); + m_originalScene.releaseUniformBuffer(getMappedHandle(uniformBufferHandle)); + } + + void MergeScene::updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) + { + m_originalScene.updateUniformBuffer(getMappedHandle(uniformBufferHandle), offset, size, data); + } + + bool MergeScene::isUniformBufferAllocated(UniformBufferHandle uniformBufferHandle) const + { + return m_originalScene.isUniformBufferAllocated(getMappedHandle(uniformBufferHandle)); + } + + uint32_t MergeScene::getUniformBufferCount() const + { + return m_originalScene.getUniformBufferCount(); + } + + const UniformBuffer& MergeScene::getUniformBuffer(UniformBufferHandle uniformBufferHandle) const + { + return m_originalScene.getUniformBuffer(getMappedHandle(uniformBufferHandle)); + } + + TextureBufferHandle MergeScene::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const TextureBufferHandle actualHandle = m_originalScene.allocateTextureBuffer(textureFormat, mipMapDimensions, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseTextureBuffer(TextureBufferHandle handle) + { + assert(false); + m_originalScene.releaseTextureBuffer(getMappedHandle(handle)); + } + + uint32_t MergeScene::getTextureBufferCount() const + { + return m_originalScene.getTextureBufferCount(); + } + + void MergeScene::updateTextureBuffer(TextureBufferHandle handle, uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const std::byte* data) + { + m_originalScene.updateTextureBuffer(getMappedHandle(handle), mipLevel, x, y, width, height, data); + } + + const TextureBuffer& MergeScene::getTextureBuffer(TextureBufferHandle handle) const + { + return m_originalScene.getTextureBuffer(getMappedHandle(handle)); + } + + bool MergeScene::isTextureBufferAllocated(TextureBufferHandle handle) const + { + return m_originalScene.isTextureBufferAllocated(getMappedHandle(handle)); + } + + DataSlotHandle MergeScene::allocateDataSlot(const DataSlot& dataSlot, DataSlotHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const DataSlot mappedDataSlot{ + dataSlot.type, + dataSlot.id, + getMappedHandle(dataSlot.attachedNode), + getMappedHandle(dataSlot.attachedDataReference), + dataSlot.attachedTexture, + getMappedHandle(dataSlot.attachedTextureSampler) + }; + const DataSlotHandle actualHandle = m_originalScene.allocateDataSlot(mappedDataSlot, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::setDataSlotTexture(DataSlotHandle handle, const ResourceContentHash& texture) + { + m_originalScene.setDataSlotTexture(getMappedHandle(handle), texture); + } + + void MergeScene::releaseDataSlot(DataSlotHandle handle) + { + assert(false); + m_originalScene.releaseDataSlot(getMappedHandle(handle)); + } + + bool MergeScene::isDataSlotAllocated(DataSlotHandle handle) const + { + return m_originalScene.isDataSlotAllocated(getMappedHandle(handle)); + } + + uint32_t MergeScene::getDataSlotCount() const + { + return m_originalScene.getDataSlotCount(); + } + + const DataSlot& MergeScene::getDataSlot(DataSlotHandle handle) const + { + return m_originalScene.getDataSlot(getMappedHandle(handle)); + } + + SceneReferenceHandle MergeScene::allocateSceneReference(SceneId sceneId, SceneReferenceHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const auto actualHandle = m_originalScene.allocateSceneReference(sceneId, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseSceneReference(SceneReferenceHandle handle) + { + assert(false); + m_originalScene.releaseSceneReference(getMappedHandle(handle)); + } + + void MergeScene::requestSceneReferenceState(SceneReferenceHandle handle, RendererSceneState state) + { + m_originalScene.requestSceneReferenceState(getMappedHandle(handle), state); + } + + void MergeScene::requestSceneReferenceFlushNotifications(SceneReferenceHandle handle, bool enable) + { + m_originalScene.requestSceneReferenceFlushNotifications(getMappedHandle(handle), enable); + } + + void MergeScene::setSceneReferenceRenderOrder(SceneReferenceHandle handle, int32_t renderOrder) + { + m_originalScene.setSceneReferenceRenderOrder(getMappedHandle(handle), renderOrder); + } + + bool MergeScene::isSceneReferenceAllocated(SceneReferenceHandle handle) const + { + return m_originalScene.isSceneReferenceAllocated(getMappedHandle(handle)); + } + + uint32_t MergeScene::getSceneReferenceCount() const + { + return m_originalScene.getSceneReferenceCount(); + } + + const SceneReference& MergeScene::getSceneReference(SceneReferenceHandle handle) const + { + return m_originalScene.getSceneReference(getMappedHandle(handle)); + } + + void MergeScene::setRenderPassClearFlag(RenderPassHandle handle, ClearFlags clearFlag) + { + m_originalScene.setRenderPassClearFlag(getMappedHandle(handle), clearFlag); + } + + void MergeScene::setRenderPassClearColor(RenderPassHandle handle, const glm::vec4& clearColor) + { + m_originalScene.setRenderPassClearColor(getMappedHandle(handle), clearColor); + } + + void MergeScene::setRenderPassRenderTarget(RenderPassHandle pass, RenderTargetHandle targetHandle) + { + m_originalScene.setRenderPassRenderTarget(getMappedHandle(pass), getMappedHandle(targetHandle)); + } + + void MergeScene::setRenderPassRenderOrder(RenderPassHandle pass, int32_t renderOrder) + { + m_originalScene.setRenderPassRenderOrder(getMappedHandle(pass), renderOrder); + } + + void MergeScene::setRenderPassEnabled(RenderPassHandle pass, bool isEnabled) + { + m_originalScene.setRenderPassEnabled(getMappedHandle(pass), isEnabled); + } + + void MergeScene::setRenderPassRenderOnce(RenderPassHandle pass, bool enable) + { + m_originalScene.setRenderPassRenderOnce(getMappedHandle(pass), enable); + } + + void MergeScene::retriggerRenderPassRenderOnce(RenderPassHandle pass) + { + m_originalScene.retriggerRenderPassRenderOnce(getMappedHandle(pass)); + } + + void MergeScene::addRenderGroupToRenderPass(RenderPassHandle passHandle, RenderGroupHandle groupHandle, int32_t order) + { + m_originalScene.addRenderGroupToRenderPass(getMappedHandle(passHandle), getMappedHandle(groupHandle), order); + } + + void MergeScene::removeRenderGroupFromRenderPass(RenderPassHandle passHandle, RenderGroupHandle groupHandle) + { + m_originalScene.removeRenderGroupFromRenderPass(getMappedHandle(passHandle), getMappedHandle(groupHandle)); + } + + const RenderPass& MergeScene::getRenderPass(RenderPassHandle passHandle) const + { + return m_originalScene.getRenderPass(getMappedHandle(passHandle)); + } + + PickableObjectHandle MergeScene::allocatePickableObject(DataBufferHandle geometryHandle, NodeHandle nodeHandle, PickableObjectId id, PickableObjectHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const PickableObjectHandle actualHandle = m_originalScene.allocatePickableObject(getMappedHandle(geometryHandle), getMappedHandle(nodeHandle), id, mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releasePickableObject(PickableObjectHandle pickableHandle) + { + assert(false); + m_originalScene.releasePickableObject(getMappedHandle(pickableHandle)); + } + + bool MergeScene::isPickableObjectAllocated(PickableObjectHandle pickableHandle) const + { + return m_originalScene.isPickableObjectAllocated(getMappedHandle(pickableHandle)); + } + + uint32_t MergeScene::getPickableObjectCount() const + { + return m_originalScene.getPickableObjectCount(); + } + + void MergeScene::setPickableObjectId(PickableObjectHandle pickableHandle, PickableObjectId id) + { + m_originalScene.setPickableObjectId(getMappedHandle(pickableHandle), id); + } + + void MergeScene::setPickableObjectCamera(PickableObjectHandle pickableHandle, CameraHandle cameraHandle) + { + m_originalScene.setPickableObjectCamera(getMappedHandle(pickableHandle), getMappedHandle(cameraHandle)); + } + + void MergeScene::setPickableObjectEnabled(PickableObjectHandle pickableHandle, bool isEnabled) + { + m_originalScene.setPickableObjectEnabled(getMappedHandle(pickableHandle), isEnabled); + } + + const PickableObject& MergeScene::getPickableObject(PickableObjectHandle pickableHandle) const + { + return m_originalScene.getPickableObject(getMappedHandle(pickableHandle)); + } + + BlitPassHandle MergeScene::allocateBlitPass(RenderBufferHandle sourceRenderBufferHandle, RenderBufferHandle destinationRenderBufferHandle, BlitPassHandle handle) + { + assert(handle.isValid()); + const auto mappedHandle = getMappedHandle(handle); + const BlitPassHandle actualHandle = m_originalScene.allocateBlitPass(getMappedHandle(sourceRenderBufferHandle), getMappedHandle(destinationRenderBufferHandle), mappedHandle); + assert(mappedHandle == actualHandle); + return addMapping(handle, actualHandle); + } + + void MergeScene::releaseBlitPass(BlitPassHandle passHandle) + { + assert(false); + m_originalScene.releaseBlitPass(getMappedHandle(passHandle)); + } + + bool MergeScene::isBlitPassAllocated(BlitPassHandle passHandle) const + { + return m_originalScene.isBlitPassAllocated(getMappedHandle(passHandle)); + } + + uint32_t MergeScene::getBlitPassCount() const + { + return m_originalScene.getBlitPassCount(); + } + + void MergeScene::setBlitPassRenderOrder(BlitPassHandle passHandle, int32_t renderOrder) + { + m_originalScene.setBlitPassRenderOrder(getMappedHandle(passHandle), renderOrder); + } + + void MergeScene::setBlitPassEnabled(BlitPassHandle passHandle, bool isEnabled) + { + m_originalScene.setBlitPassEnabled(getMappedHandle(passHandle), isEnabled); + } + + void MergeScene::setBlitPassRegions(BlitPassHandle passHandle, const PixelRectangle& sourceRegion, const PixelRectangle& destinationRegion) + { + m_originalScene.setBlitPassRegions(getMappedHandle(passHandle), sourceRegion, destinationRegion); + } + + const BlitPass& MergeScene::getBlitPass(BlitPassHandle passHandle) const + { + return m_originalScene.getBlitPass(getMappedHandle(passHandle)); + } + + bool MergeScene::isRenderTargetAllocated(RenderTargetHandle targetHandle) const + { + return m_originalScene.isRenderTargetAllocated(getMappedHandle(targetHandle)); + } + + uint32_t MergeScene::getRenderTargetCount() const + { + return m_originalScene.getRenderTargetCount(); + } + + void MergeScene::preallocateSceneSize(const SceneSizeInformation& sizeInfo) + { + const SceneSizeInformation newSizeInfo{ + sizeInfo.nodeCount + m_offsetNodeHandle.asMemoryHandle(), + sizeInfo.cameraCount + m_offsetCameraHandle.asMemoryHandle(), + sizeInfo.transformCount + m_offsetTransformHandle.asMemoryHandle(), + sizeInfo.renderableCount + m_offsetRenderableHandle.asMemoryHandle(), + sizeInfo.renderStateCount + m_offsetRenderStateHandle.asMemoryHandle(), + sizeInfo.datalayoutCount + m_offsetDataLayoutHandle.asMemoryHandle(), + sizeInfo.datainstanceCount + m_offsetDataInstanceHandle.asMemoryHandle(), + sizeInfo.uniformBufferCount + m_offsetUniformBufferHandle.asMemoryHandle(), + sizeInfo.renderGroupCount + m_offsetRenderGroupHandle.asMemoryHandle(), + sizeInfo.renderPassCount + m_offsetRenderPassHandle.asMemoryHandle(), + sizeInfo.blitPassCount + m_offsetBlitPassHandle.asMemoryHandle(), + sizeInfo.renderTargetCount + m_offsetRenderTargetHandle.asMemoryHandle(), + sizeInfo.renderBufferCount + m_offsetRenderBufferHandle.asMemoryHandle(), + sizeInfo.textureSamplerCount + m_offsetTextureSamplerHandle.asMemoryHandle(), + sizeInfo.dataSlotCount + m_offsetDataSlotHandle.asMemoryHandle(), + sizeInfo.dataBufferCount + m_offsetDataBufferHandle.asMemoryHandle(), + sizeInfo.textureBufferCount + m_offsetTextureBufferHandle.asMemoryHandle(), + sizeInfo.pickableObjectCount + m_offsetPickableObjectHandle.asMemoryHandle(), + sizeInfo.sceneReferenceCount + m_offsetSceneReferenceHandle.asMemoryHandle(), + }; + + m_originalScene.preallocateSceneSize(newSizeInfo); + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetRenderableHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetRenderStateHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetCameraHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetNodeHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetTransformHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetDataLayoutHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetDataInstanceHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetUniformBufferHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetTextureSamplerHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetRenderGroupHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetRenderPassHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetBlitPassHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetPickableObjectHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetRenderTargetHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetRenderBufferHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetDataBufferHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetTextureBufferHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetDataSlotHandle; + } + + template<> + inline TypedMemoryHandle MergeScene::getOffsetHandle() const + { + return m_offsetSceneReferenceHandle; + } + + + template + [[nodiscard]] inline TypedMemoryHandle MergeScene::getMappedHandle(TypedMemoryHandle handle) const + { + if (handle.isValid()) + { + const auto offset = getOffsetHandle(); + assert(std::numeric_limits::Type>::max() - offset.asMemoryHandle() > handle.asMemoryHandle()); + return handle + offset.asMemoryHandle(); + } + return TypedMemoryHandle::Invalid(); + } + + template<> + [[nodiscard]] inline TypedMemoryHandle MergeScene::getMappedHandle(TypedMemoryHandle handle) const + { + if (handle.isValid()) + { + const auto mappedHandle = m_mapping.getMapping(handle); + if (mappedHandle.isValid()) + { + return mappedHandle; + } + const auto offset = getOffsetHandle(); + assert(std::numeric_limits::Type>::max() - offset.asMemoryHandle() > handle.asMemoryHandle()); + return handle + offset.asMemoryHandle(); + } + return TypedMemoryHandle::Invalid(); + } + + template + [[nodiscard]] inline TypedMemoryHandle MergeScene::addMapping(TypedMemoryHandle handle, TypedMemoryHandle newHandle) + { + if (handle.isValid()) + { + assert(newHandle.isValid()); + m_mapping.addMapping(handle, newHandle); + } + return newHandle; + } +} diff --git a/src/framework/internal/SceneGraph/Scene/MergeScene.h b/src/framework/internal/SceneGraph/Scene/MergeScene.h new file mode 100644 index 000000000..a981276a8 --- /dev/null +++ b/src/framework/internal/SceneGraph/Scene/MergeScene.h @@ -0,0 +1,320 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "internal/SceneGraph/SceneAPI/IScene.h" +#include "internal/SceneGraph/Scene/Scene.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" + +namespace ramses::internal +{ + class MergeScene : public IScene + { + public: + explicit MergeScene(IScene& originalScene, SceneMergeHandleMapping& mapping); + + [[nodiscard]] const std::string& getName () const override; + [[nodiscard]] SceneId getSceneId () const override; + [[nodiscard]] ERenderBackendCompatibility getRenderBackendCompatibility () const override; + [[nodiscard]] EVulkanAPIVersion getVulkanAPIVersion () const override; + [[nodiscard]] ESPIRVVersion getSPIRVVersion () const override; + + void setEffectTimeSync(FlushTime::Clock::time_point t) override; + [[nodiscard]] FlushTime::Clock::time_point getEffectTimeSync() const override; + + // Renderable + RenderableHandle allocateRenderable (NodeHandle nodeHandle, RenderableHandle handle) override; + void releaseRenderable (RenderableHandle renderableHandle) override; + [[nodiscard]] bool isRenderableAllocated (RenderableHandle renderableHandle) const override; + [[nodiscard]] uint32_t getRenderableCount () const override; + void setRenderableDataInstance (RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) override; + void setRenderableStartIndex (RenderableHandle renderableHandle, uint32_t startIndex) override; + void setRenderableIndexCount (RenderableHandle renderableHandle, uint32_t indexCount) override; + void setRenderableRenderState (RenderableHandle renderableHandle, RenderStateHandle stateHandle) override; + void setRenderableVisibility (RenderableHandle renderableHandle, EVisibilityMode visible) override; + void setRenderableInstanceCount (RenderableHandle renderableHandle, uint32_t instanceCount) override; + void setRenderableStartVertex (RenderableHandle renderableHandle, uint32_t startVertex) override; + [[nodiscard]] const Renderable& getRenderable (RenderableHandle renderableHandle) const override; + + // Render state + RenderStateHandle allocateRenderState (RenderStateHandle stateHandle) override; + void releaseRenderState (RenderStateHandle stateHandle) override; + [[nodiscard]] bool isRenderStateAllocated (RenderStateHandle stateHandle) const override; + [[nodiscard]] uint32_t getRenderStateCount () const override; + void setRenderStateBlendFactors (RenderStateHandle stateHandle, EBlendFactor srcColor, EBlendFactor destColor, EBlendFactor srcAlpha, EBlendFactor destAlpha) override; + void setRenderStateBlendOperations (RenderStateHandle stateHandle, EBlendOperation operationColor, EBlendOperation operationAlpha) override; + void setRenderStateBlendColor (RenderStateHandle stateHandle, const glm::vec4& color) override; + void setRenderStateCullMode (RenderStateHandle stateHandle, ECullMode cullMode) override; + void setRenderStateDrawMode (RenderStateHandle stateHandle, EDrawMode drawMode) override; + void setRenderStateDepthFunc (RenderStateHandle stateHandle, EDepthFunc func) override; + void setRenderStateDepthWrite (RenderStateHandle stateHandle, EDepthWrite flag) override; + void setRenderStateScissorTest (RenderStateHandle stateHandle, EScissorTest flag, const RenderState::ScissorRegion& region) override; + void setRenderStateStencilFunc (RenderStateHandle stateHandle, EStencilFunc func, uint8_t ref, uint8_t mask) override; + void setRenderStateStencilOps (RenderStateHandle stateHandle, EStencilOp sfail, EStencilOp dpfail, EStencilOp dppass) override; + void setRenderStateColorWriteMask (RenderStateHandle stateHandle, ColorWriteMask colorMask) override; + [[nodiscard]] const RenderState& getRenderState (RenderStateHandle stateHandle) const override; + + // Camera + CameraHandle allocateCamera (ECameraProjectionType type, NodeHandle nodeHandle, DataInstanceHandle dataInstance, CameraHandle handle) override; + void releaseCamera (CameraHandle cameraHandle) override; + [[nodiscard]] bool isCameraAllocated (CameraHandle handle) const override; + [[nodiscard]] uint32_t getCameraCount () const override; + [[nodiscard]] const Camera& getCamera (CameraHandle cameraHandle) const override; + + // Creation/Deletion + NodeHandle allocateNode (uint32_t childrenCount, NodeHandle handle) override; + void releaseNode (NodeHandle nodeHandle) override; + [[nodiscard]] bool isNodeAllocated (NodeHandle node) const override; + [[nodiscard]] uint32_t getNodeCount () const override; + + TransformHandle allocateTransform (NodeHandle nodeHandle, TransformHandle handle) override; + void releaseTransform (TransformHandle transform) override; + [[nodiscard]] bool isTransformAllocated (TransformHandle transformHandle) const override; + [[nodiscard]] uint32_t getTransformCount () const override; + [[nodiscard]] NodeHandle getTransformNode (TransformHandle handle) const override; + + // Parent-child relationship + [[nodiscard]] NodeHandle getParent (NodeHandle nodeHandle) const override; + void addChildToNode (NodeHandle parent, NodeHandle child) override; + void removeChildFromNode (NodeHandle parent, NodeHandle child) override; + [[nodiscard]] uint32_t getChildCount (NodeHandle parent) const override; + [[nodiscard]] NodeHandle getChild (NodeHandle parent, uint32_t childNumber) const override; + + // Transformation + [[nodiscard]] const glm::vec3& getTranslation (TransformHandle handle) const override; + [[nodiscard]] const glm::vec4& getRotation (TransformHandle handle) const override; + [[nodiscard]] ERotationType getRotationType (TransformHandle handle) const override; + [[nodiscard]] const glm::vec3& getScaling (TransformHandle handle) const override; + void setTranslation (TransformHandle handle, const glm::vec3& translation) override; + void setRotation (TransformHandle handle, const glm::vec4& rotation, ERotationType rotationType) override; + void setScaling (TransformHandle handle, const glm::vec3& scaling) override; + + DataLayoutHandle allocateDataLayout (const DataFieldInfoVector& dataFields, const ResourceContentHash& effectHash, DataLayoutHandle handle) override; + void releaseDataLayout (DataLayoutHandle layoutHandle) override; + [[nodiscard]] bool isDataLayoutAllocated (DataLayoutHandle layoutHandle) const override; + [[nodiscard]] uint32_t getDataLayoutCount () const override; + + [[nodiscard]] const DataLayout& getDataLayout (DataLayoutHandle layoutHandle) const override; + + DataInstanceHandle allocateDataInstance (DataLayoutHandle finishedLayoutHandle, DataInstanceHandle instanceHandle) override; + void releaseDataInstance (DataInstanceHandle containerHandle) override; + [[nodiscard]] bool isDataInstanceAllocated (DataInstanceHandle containerHandle) const override; + [[nodiscard]] uint32_t getDataInstanceCount () const override; + [[nodiscard]] DataLayoutHandle getLayoutOfDataInstance (DataInstanceHandle containerHandle) const override; + + [[nodiscard]] const float* getDataFloatArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::vec2* getDataVector2fArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::vec3* getDataVector3fArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::vec4* getDataVector4fArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const bool* getDataBooleanArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const int32_t* getDataIntegerArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::mat2* getDataMatrix22fArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::mat3* getDataMatrix33fArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::mat4* getDataMatrix44fArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::ivec2* getDataVector2iArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::ivec3* getDataVector3iArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::ivec4* getDataVector4iArray (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const ResourceField& getDataResource (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] TextureSamplerHandle getDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] DataInstanceHandle getDataReference (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] UniformBufferHandle getDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + + void setDataFloatArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const float* data) override; + void setDataVector2fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec2* data) override; + void setDataVector3fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec3* data) override; + void setDataVector4fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec4* data) override; + void setDataBooleanArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const bool* data) override; + void setDataIntegerArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const int32_t* data) override; + void setDataVector2iArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec2* data) override; + void setDataVector3iArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec3* data) override; + void setDataVector4iArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec4* data) override; + void setDataMatrix22fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat2* data) override; + void setDataMatrix33fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat3* data) override; + void setDataMatrix44fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat4* data) override; + void setDataResource (DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) override; + void setDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) override; + void setDataReference (DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef) override; + void setDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) override; + + // get/setData*Array wrappers for elementCount == 1 + [[nodiscard]] float getDataSingleFloat (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::vec2& getDataSingleVector2f (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::vec3& getDataSingleVector3f (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::vec4& getDataSingleVector4f (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] bool getDataSingleBoolean (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] int32_t getDataSingleInteger (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::mat2& getDataSingleMatrix22f (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::mat3& getDataSingleMatrix33f (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::mat4& getDataSingleMatrix44f (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::ivec3& getDataSingleVector3i (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::ivec4& getDataSingleVector4i (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] const glm::ivec2& getDataSingleVector2i (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + + void setDataSingleFloat (DataInstanceHandle containerHandle, DataFieldHandle field, float data) override; + void setDataSingleVector2f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::vec2& data) override; + void setDataSingleVector3f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::vec3& data) override; + void setDataSingleVector4f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::vec4& data) override; + void setDataSingleBoolean (DataInstanceHandle containerHandle, DataFieldHandle field, bool data) override; + void setDataSingleInteger (DataInstanceHandle containerHandle, DataFieldHandle field, int32_t data) override; + void setDataSingleVector2i (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::ivec2& data) override; + void setDataSingleVector3i (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::ivec3& data) override; + void setDataSingleVector4i (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::ivec4& data) override; + void setDataSingleMatrix22f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat2& data) override; + void setDataSingleMatrix33f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat3& data) override; + void setDataSingleMatrix44f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat4& data) override; + + // Texture sampler description + TextureSamplerHandle allocateTextureSampler (const TextureSampler& sampler, TextureSamplerHandle handle) override; + void releaseTextureSampler (TextureSamplerHandle handle) override; + [[nodiscard]] bool isTextureSamplerAllocated (TextureSamplerHandle handle) const override; + [[nodiscard]] uint32_t getTextureSamplerCount () const override; + [[nodiscard]] const TextureSampler& getTextureSampler (TextureSamplerHandle handle) const override; + + // Render groups + RenderGroupHandle allocateRenderGroup (uint32_t renderableCount, uint32_t nestedGroupCount, RenderGroupHandle groupHandle) override; + void releaseRenderGroup (RenderGroupHandle groupHandle) override; + [[nodiscard]] bool isRenderGroupAllocated (RenderGroupHandle groupHandle) const override; + [[nodiscard]] uint32_t getRenderGroupCount () const override; + void addRenderableToRenderGroup (RenderGroupHandle groupHandle, RenderableHandle renderableHandle, int32_t order) override; + void removeRenderableFromRenderGroup (RenderGroupHandle groupHandle, RenderableHandle renderableHandle) override; + void addRenderGroupToRenderGroup (RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild, int32_t order) override; + void removeRenderGroupFromRenderGroup(RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild) override; + [[nodiscard]] const RenderGroup& getRenderGroup (RenderGroupHandle groupHandle) const override; + + // Render passes + RenderPassHandle allocateRenderPass (uint32_t renderGroupCount, RenderPassHandle passHandle) override; + void releaseRenderPass (RenderPassHandle passHandle) override; + [[nodiscard]] bool isRenderPassAllocated (RenderPassHandle passHandle) const override; + [[nodiscard]] uint32_t getRenderPassCount () const override; + void setRenderPassClearColor (RenderPassHandle passHandle, const glm::vec4& clearColor) override; + void setRenderPassClearFlag (RenderPassHandle passHandle, ClearFlags clearFlag) override; + void setRenderPassCamera (RenderPassHandle passHandle, CameraHandle cameraHandle) override; + void setRenderPassRenderTarget (RenderPassHandle passHandle, RenderTargetHandle targetHandle) override; + void setRenderPassRenderOrder (RenderPassHandle passHandle, int32_t renderOrder) override; + void setRenderPassEnabled (RenderPassHandle passHandle, bool isEnabled) override; + void setRenderPassRenderOnce (RenderPassHandle passHandle, bool enable) override; + void retriggerRenderPassRenderOnce (RenderPassHandle passHandle) override; + void addRenderGroupToRenderPass (RenderPassHandle passHandle, RenderGroupHandle groupHandle, int32_t order) override; + void removeRenderGroupFromRenderPass (RenderPassHandle passHandle, RenderGroupHandle groupHandle) override; + [[nodiscard]] const RenderPass& getRenderPass (RenderPassHandle passHandle) const override; + + //Blit passes + BlitPassHandle allocateBlitPass (RenderBufferHandle sourceRenderBufferHandle, RenderBufferHandle destinationRenderBufferHandle, BlitPassHandle passHandle) override; + void releaseBlitPass (BlitPassHandle passHandle) override; + [[nodiscard]] bool isBlitPassAllocated (BlitPassHandle passHandle) const override; + [[nodiscard]] uint32_t getBlitPassCount () const override; + void setBlitPassRenderOrder (BlitPassHandle passHandle, int32_t renderOrder) override; + void setBlitPassEnabled (BlitPassHandle passHandle, bool isEnabled) override; + void setBlitPassRegions (BlitPassHandle passHandle, const PixelRectangle& sourceRegion, const PixelRectangle& destinationRegion) override; + [[nodiscard]] const BlitPass& getBlitPass (BlitPassHandle passHandle) const override; + + //Pickable object + PickableObjectHandle allocatePickableObject (DataBufferHandle geometryHandle, NodeHandle nodeHandle, PickableObjectId id, PickableObjectHandle pickableHandle) override; + void releasePickableObject (PickableObjectHandle pickableHandle) override; + [[nodiscard]] bool isPickableObjectAllocated (PickableObjectHandle pickableHandle) const final override; + [[nodiscard]] uint32_t getPickableObjectCount () const final override; + void setPickableObjectId (PickableObjectHandle pickableHandle, PickableObjectId id) override; + void setPickableObjectCamera (PickableObjectHandle pickableHandle, CameraHandle cameraHandle) override; + void setPickableObjectEnabled (PickableObjectHandle pickableHandle, bool isEnabled) override; + [[nodiscard]] const PickableObject& getPickableObject (PickableObjectHandle pickableHandle) const override; + + // Render targets + RenderTargetHandle allocateRenderTarget (RenderTargetHandle targetHandle) override; + void releaseRenderTarget (RenderTargetHandle targetHandle) override; + [[nodiscard]] bool isRenderTargetAllocated (RenderTargetHandle targetHandle) const override; + [[nodiscard]] uint32_t getRenderTargetCount () const override; + void addRenderTargetRenderBuffer (RenderTargetHandle targetHandle, RenderBufferHandle bufferHandle) override; + [[nodiscard]] uint32_t getRenderTargetRenderBufferCount(RenderTargetHandle targetHandle) const override; + [[nodiscard]] RenderBufferHandle getRenderTargetRenderBuffer (RenderTargetHandle targetHandle, uint32_t bufferIndex) const override; + + // Render buffers + RenderBufferHandle allocateRenderBuffer (const RenderBuffer& renderBuffer, RenderBufferHandle handle) override; + void releaseRenderBuffer (RenderBufferHandle handle) override; + void setRenderBufferProperties (RenderBufferHandle handle, uint32_t width, uint32_t height, uint32_t sampleCount) override; + [[nodiscard]] bool isRenderBufferAllocated (RenderBufferHandle handle) const override; + [[nodiscard]] uint32_t getRenderBufferCount () const override; + [[nodiscard]] const RenderBuffer& getRenderBuffer (RenderBufferHandle handle) const override; + + // Data buffers + DataBufferHandle allocateDataBuffer (EDataBufferType dataBufferType, EDataType dataType, uint32_t maximumSizeInBytes, DataBufferHandle handle) override; + void releaseDataBuffer (DataBufferHandle handle) override; + [[nodiscard]] uint32_t getDataBufferCount () const override; + void updateDataBuffer (DataBufferHandle handle, uint32_t offsetInBytes, uint32_t dataSizeInBytes, const std::byte* data) override; + [[nodiscard]] bool isDataBufferAllocated (DataBufferHandle handle) const override; + [[nodiscard]] const GeometryDataBuffer& getDataBuffer (DataBufferHandle handle) const override; + + // Uniform buffers + UniformBufferHandle allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) override; + void releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) override; + void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) override; + [[nodiscard]] bool isUniformBufferAllocated(UniformBufferHandle uniformBufferHandle) const override; + [[nodiscard]] uint32_t getUniformBufferCount() const override; + [[nodiscard]] const UniformBuffer& getUniformBuffer(UniformBufferHandle uniformBufferHandle) const override; + + //Texture buffers + TextureBufferHandle allocateTextureBuffer (EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) override; + void releaseTextureBuffer (TextureBufferHandle handle) override; + [[nodiscard]] bool isTextureBufferAllocated (TextureBufferHandle handle) const override; + [[nodiscard]] uint32_t getTextureBufferCount () const override; + void updateTextureBuffer (TextureBufferHandle handle, uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const std::byte* data) override; + [[nodiscard]] const TextureBuffer& getTextureBuffer (TextureBufferHandle handle) const override; + + DataSlotHandle allocateDataSlot (const DataSlot& dataSlot, DataSlotHandle handle) override; + void setDataSlotTexture (DataSlotHandle handle, const ResourceContentHash& texture) override; + void releaseDataSlot (DataSlotHandle handle) override; + [[nodiscard]] bool isDataSlotAllocated (DataSlotHandle handle) const override; + [[nodiscard]] uint32_t getDataSlotCount () const override; + [[nodiscard]] const DataSlot& getDataSlot (DataSlotHandle handle) const override; + + SceneReferenceHandle allocateSceneReference (SceneId sceneId, SceneReferenceHandle handle) override; + void releaseSceneReference (SceneReferenceHandle handle) override; + void requestSceneReferenceState (SceneReferenceHandle handle, RendererSceneState state) override; + void requestSceneReferenceFlushNotifications(SceneReferenceHandle handle, bool enable) override; + void setSceneReferenceRenderOrder (SceneReferenceHandle handle, int32_t renderOrder) override; + [[nodiscard]] bool isSceneReferenceAllocated (SceneReferenceHandle handle) const final override; + [[nodiscard]] uint32_t getSceneReferenceCount () const final override; + [[nodiscard]] const SceneReference& getSceneReference (SceneReferenceHandle handle) const final override; + + [[nodiscard]] SceneSizeInformation getSceneSizeInformation() const override; + void preallocateSceneSize(const SceneSizeInformation& sizeInfo) override; + + private: + template + [[nodiscard]] TypedMemoryHandle getOffsetHandle() const; + + template + [[nodiscard]] inline TypedMemoryHandle getMappedHandle(TypedMemoryHandle handle) const; + + template + [[nodiscard]] inline TypedMemoryHandle addMapping(TypedMemoryHandle handle, TypedMemoryHandle newHandle); + + IScene& m_originalScene; + SceneMergeHandleMapping& m_mapping; + + RenderableHandle m_offsetRenderableHandle{0u}; + RenderStateHandle m_offsetRenderStateHandle{0u}; + CameraHandle m_offsetCameraHandle{0u}; + NodeHandle m_offsetNodeHandle{0u}; + TransformHandle m_offsetTransformHandle{0u}; + DataLayoutHandle m_offsetDataLayoutHandle{0u}; + DataInstanceHandle m_offsetDataInstanceHandle{0u}; + UniformBufferHandle m_offsetUniformBufferHandle{0u}; + TextureSamplerHandle m_offsetTextureSamplerHandle{0u}; + RenderGroupHandle m_offsetRenderGroupHandle{0u}; + RenderPassHandle m_offsetRenderPassHandle{0u}; + BlitPassHandle m_offsetBlitPassHandle{0u}; + PickableObjectHandle m_offsetPickableObjectHandle{0u}; + RenderTargetHandle m_offsetRenderTargetHandle{0u}; + RenderBufferHandle m_offsetRenderBufferHandle{0u}; + DataBufferHandle m_offsetDataBufferHandle{0u}; + TextureBufferHandle m_offsetTextureBufferHandle{0u}; + DataSlotHandle m_offsetDataSlotHandle{0u}; + SceneReferenceHandle m_offsetSceneReferenceHandle{0u}; + }; +} diff --git a/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.cpp b/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.cpp index 7ce3eb356..253a17ec0 100644 --- a/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.cpp +++ b/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.cpp @@ -12,7 +12,7 @@ namespace ramses::internal { ResourceChangeCollectingScene::ResourceChangeCollectingScene(const SceneInfo& sceneInfo) - : TransformationCachedScene(sceneInfo) + : BaseT(sceneInfo) { } @@ -36,14 +36,14 @@ namespace ramses::internal void ResourceChangeCollectingScene::releaseRenderable(RenderableHandle renderableHandle) { m_resourcesChanged = true; - TransformationCachedScene::releaseRenderable(renderableHandle); + BaseT::releaseRenderable(renderableHandle); } void ResourceChangeCollectingScene::setRenderableDataInstance(RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) { m_resourcesChanged = true; - TransformationCachedScene::setRenderableDataInstance(renderableHandle, slot, newDataInstance); + BaseT::setRenderableDataInstance(renderableHandle, slot, newDataInstance); } void ResourceChangeCollectingScene::setRenderableVisibility(RenderableHandle renderableHandle, EVisibilityMode visibility) @@ -52,19 +52,19 @@ namespace ramses::internal if (oldVisibility != visibility && (oldVisibility == EVisibilityMode::Off || visibility == EVisibilityMode::Off)) m_resourcesChanged = true; - TransformationCachedScene::setRenderableVisibility(renderableHandle, visibility); + BaseT::setRenderableVisibility(renderableHandle, visibility); } void ResourceChangeCollectingScene::setDataResource(DataInstanceHandle dataInstanceHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) { m_resourcesChanged = true; - TransformationCachedScene::setDataResource(dataInstanceHandle, field, hash, dataBuffer, instancingDivisor, offsetWithinElementInBytes, stride); + BaseT::setDataResource(dataInstanceHandle, field, hash, dataBuffer, instancingDivisor, offsetWithinElementInBytes, stride); } void ResourceChangeCollectingScene::setDataTextureSamplerHandle(DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) { m_resourcesChanged = true; - TransformationCachedScene::setDataTextureSamplerHandle(containerHandle, field, samplerHandle); + BaseT::setDataTextureSamplerHandle(containerHandle, field, samplerHandle); } TextureSamplerHandle ResourceChangeCollectingScene::allocateTextureSampler(const TextureSampler& sampler, TextureSamplerHandle handle /*= TextureSamplerHandle::Invalid()*/) @@ -72,7 +72,7 @@ namespace ramses::internal if (sampler.textureResource.isValid()) m_resourcesChanged = true; - return TransformationCachedScene::allocateTextureSampler(sampler, handle); + return BaseT::allocateTextureSampler(sampler, handle); } void ResourceChangeCollectingScene::releaseTextureSampler(TextureSamplerHandle handle) @@ -80,20 +80,20 @@ namespace ramses::internal if (getTextureSampler(handle).textureResource.isValid()) m_resourcesChanged = true; - TransformationCachedScene::releaseTextureSampler(handle); + BaseT::releaseTextureSampler(handle); } DataSlotHandle ResourceChangeCollectingScene::allocateDataSlot(const DataSlot& dataSlot, DataSlotHandle handle /*= DataSlotHandle::Invalid()*/) { if (dataSlot.attachedTexture.isValid()) m_resourcesChanged = true; - return TransformationCachedScene::allocateDataSlot(dataSlot, handle); + return BaseT::allocateDataSlot(dataSlot, handle); } void ResourceChangeCollectingScene::setDataSlotTexture(DataSlotHandle providerHandle, const ResourceContentHash& texture) { m_resourcesChanged = true; - TransformationCachedScene::setDataSlotTexture(providerHandle, texture); + BaseT::setDataSlotTexture(providerHandle, texture); } void ResourceChangeCollectingScene::releaseDataSlot(DataSlotHandle handle) @@ -102,90 +102,109 @@ namespace ramses::internal if (textureHash.isValid()) m_resourcesChanged = true; - TransformationCachedScene::releaseDataSlot(handle); + BaseT::releaseDataSlot(handle); + } + + UniformBufferHandle ResourceChangeCollectingScene::allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) + { + const auto newHandle = BaseT::allocateUniformBuffer(size, handle); + m_sceneResourceActions.push_back({ newHandle.asMemoryHandle(), ESceneResourceAction_CreateUniformBuffer }); + return newHandle; + } + + void ResourceChangeCollectingScene::releaseUniformBuffer(UniformBufferHandle handle) + { + BaseT::releaseUniformBuffer(handle); + m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_DestroyUniformBuffer }); + } + + void ResourceChangeCollectingScene::updateUniformBuffer(UniformBufferHandle handle, uint32_t offset, uint32_t size, const std::byte* data) + { + BaseT::updateUniformBuffer(handle, offset, size, data); + m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_UpdateUniformBuffer }); } RenderTargetHandle ResourceChangeCollectingScene::allocateRenderTarget(RenderTargetHandle handle) { - const RenderTargetHandle newHandle = TransformationCachedScene::allocateRenderTarget(handle); + const RenderTargetHandle newHandle = BaseT::allocateRenderTarget(handle); m_sceneResourceActions.push_back({ newHandle.asMemoryHandle(), ESceneResourceAction_CreateRenderTarget }); return newHandle; } void ResourceChangeCollectingScene::releaseRenderTarget(RenderTargetHandle handle) { - TransformationCachedScene::releaseRenderTarget(handle); + BaseT::releaseRenderTarget(handle); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_DestroyRenderTarget }); } RenderBufferHandle ResourceChangeCollectingScene::allocateRenderBuffer(const RenderBuffer& renderBuffer, RenderBufferHandle handle) { - const RenderBufferHandle newHandle = TransformationCachedScene::allocateRenderBuffer(renderBuffer, handle); + const RenderBufferHandle newHandle = BaseT::allocateRenderBuffer(renderBuffer, handle); m_sceneResourceActions.push_back({ newHandle.asMemoryHandle(), ESceneResourceAction_CreateRenderBuffer }); return newHandle; } void ResourceChangeCollectingScene::releaseRenderBuffer(RenderBufferHandle handle) { - TransformationCachedScene::releaseRenderBuffer(handle); + BaseT::releaseRenderBuffer(handle); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_DestroyRenderBuffer }); } void ResourceChangeCollectingScene::setRenderBufferProperties(RenderBufferHandle handle, uint32_t width, uint32_t height, uint32_t sampleCount) { - TransformationCachedScene::setRenderBufferProperties(handle, width, height, sampleCount); + BaseT::setRenderBufferProperties(handle, width, height, sampleCount); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_UpdateRenderBufferProperties }); m_resourcesChanged = true; } BlitPassHandle ResourceChangeCollectingScene::allocateBlitPass(RenderBufferHandle sourceRenderBufferHandle, RenderBufferHandle destinationRenderBufferHandle, BlitPassHandle passHandle /*= BlitPassHandle::Invalid()*/) { - const BlitPassHandle newHandle = TransformationCachedScene::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); + const BlitPassHandle newHandle = BaseT::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); m_sceneResourceActions.push_back({ newHandle.asMemoryHandle(), ESceneResourceAction_CreateBlitPass }); return newHandle; } void ResourceChangeCollectingScene::releaseBlitPass(BlitPassHandle handle) { - TransformationCachedScene::releaseBlitPass(handle); + BaseT::releaseBlitPass(handle); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_DestroyBlitPass }); } DataBufferHandle ResourceChangeCollectingScene::allocateDataBuffer(EDataBufferType dataBufferType, EDataType dataType, uint32_t maximumSizeInBytes, DataBufferHandle handle) { - const DataBufferHandle newHandle = TransformationCachedScene::allocateDataBuffer(dataBufferType, dataType, maximumSizeInBytes, handle); + const DataBufferHandle newHandle = BaseT::allocateDataBuffer(dataBufferType, dataType, maximumSizeInBytes, handle); m_sceneResourceActions.push_back({ newHandle.asMemoryHandle(), ESceneResourceAction_CreateDataBuffer }); return newHandle; } void ResourceChangeCollectingScene::releaseDataBuffer(DataBufferHandle handle) { - TransformationCachedScene::releaseDataBuffer(handle); + BaseT::releaseDataBuffer(handle); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_DestroyDataBuffer }); } void ResourceChangeCollectingScene::updateDataBuffer(DataBufferHandle handle, uint32_t offsetInBytes, uint32_t dataSizeInBytes, const std::byte* data) { - TransformationCachedScene::updateDataBuffer(handle, offsetInBytes, dataSizeInBytes, data); + BaseT::updateDataBuffer(handle, offsetInBytes, dataSizeInBytes, data); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_UpdateDataBuffer }); } TextureBufferHandle ResourceChangeCollectingScene::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle /*= TextureBufferHandle::Invalid()*/) { - const TextureBufferHandle newHandle = TransformationCachedScene::allocateTextureBuffer(textureFormat, mipMapDimensions, handle); + const TextureBufferHandle newHandle = BaseT::allocateTextureBuffer(textureFormat, mipMapDimensions, handle); m_sceneResourceActions.push_back({ newHandle.asMemoryHandle(), ESceneResourceAction_CreateTextureBuffer}); return newHandle; } void ResourceChangeCollectingScene::releaseTextureBuffer(TextureBufferHandle handle) { - TransformationCachedScene::releaseTextureBuffer(handle); + BaseT::releaseTextureBuffer(handle); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_DestroyTextureBuffer }); } void ResourceChangeCollectingScene::updateTextureBuffer(TextureBufferHandle handle, uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const std::byte* data) { - TransformationCachedScene::updateTextureBuffer(handle, mipLevel, x, y, width, height, data); + BaseT::updateTextureBuffer(handle, mipLevel, x, y, width, height, data); m_sceneResourceActions.push_back({ handle.asMemoryHandle(), ESceneResourceAction_UpdateTextureBuffer }); } } diff --git a/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.h b/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.h index f4cf43765..0cbe357a0 100644 --- a/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.h +++ b/src/framework/internal/SceneGraph/Scene/ResourceChangeCollectingScene.h @@ -15,6 +15,7 @@ namespace ramses::internal { class ResourceChangeCollectingScene : public TransformationCachedScene { + using BaseT = TransformationCachedScene; public: explicit ResourceChangeCollectingScene(const SceneInfo& sceneInfo = SceneInfo()); @@ -27,6 +28,7 @@ namespace ramses::internal void setRenderableDataInstance(RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) override; void setRenderableVisibility(RenderableHandle renderableHandle, EVisibilityMode visibility) override; + void setDataResource(DataInstanceHandle dataInstanceHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) override; void setDataTextureSamplerHandle(DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) override; @@ -38,6 +40,10 @@ namespace ramses::internal void releaseDataSlot(DataSlotHandle handle) override; // functions which affect scene resources + UniformBufferHandle allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) override; + void releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) override; + void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) override; + RenderTargetHandle allocateRenderTarget(RenderTargetHandle targetHandle) override; void releaseRenderTarget(RenderTargetHandle handle) override; diff --git a/src/framework/internal/SceneGraph/Scene/ResourceChanges.h b/src/framework/internal/SceneGraph/Scene/ResourceChanges.h index eb372dce6..a7b01c3a4 100644 --- a/src/framework/internal/SceneGraph/Scene/ResourceChanges.h +++ b/src/framework/internal/SceneGraph/Scene/ResourceChanges.h @@ -37,6 +37,10 @@ namespace ramses::internal ESceneResourceAction_CreateTextureBuffer, ESceneResourceAction_UpdateTextureBuffer, ESceneResourceAction_DestroyTextureBuffer, + + ESceneResourceAction_CreateUniformBuffer, + ESceneResourceAction_DestroyUniformBuffer, + ESceneResourceAction_UpdateUniformBuffer, }; struct SceneResourceAction @@ -107,9 +111,12 @@ namespace ramses::internal "DestroyDataBuffer", "CreateTextureBuffer", "UpdateTextureBuffer", - "DestroyTextureBuffer" + "DestroyTextureBuffer", + "CreateUniformBuffer", + "DestroyUniformBuffer", + "UpdateUniformBuffer", }; - ENUM_TO_STRING(ESceneResourceAction, SceneResourceActionNames, ESceneResourceAction_DestroyTextureBuffer); + ENUM_TO_STRING(ESceneResourceAction, SceneResourceActionNames, ESceneResourceAction_UpdateUniformBuffer); } template <> diff --git a/src/framework/internal/SceneGraph/Scene/Scene.cpp b/src/framework/internal/SceneGraph/Scene/Scene.cpp index af317a2b7..ea134eb29 100644 --- a/src/framework/internal/SceneGraph/Scene/Scene.cpp +++ b/src/framework/internal/SceneGraph/Scene/Scene.cpp @@ -21,6 +21,9 @@ namespace ramses::internal SceneT::SceneT(const SceneInfo& sceneInfo) : m_name(sceneInfo.friendlyName) , m_sceneId(sceneInfo.sceneID) + , m_renderBackendCompatibility(sceneInfo.renderBackendCompatibility) + , m_vulkanAPIVersion(sceneInfo.vulkanAPIVersion) + , m_spirvVersion(sceneInfo.spirvVersion) , m_effectTimeSync(FlushTime::InvalidTimestamp) { } @@ -31,6 +34,24 @@ namespace ramses::internal m_effectTimeSync = t; } + template class MEMORYPOOL> + ERenderBackendCompatibility SceneT::getRenderBackendCompatibility() const + { + return m_renderBackendCompatibility; + } + + template class MEMORYPOOL> + EVulkanAPIVersion SceneT::getVulkanAPIVersion() const + { + return m_vulkanAPIVersion; + } + + template class MEMORYPOOL> + ESPIRVVersion SceneT::getSPIRVVersion() const + { + return m_spirvVersion; + } + template class MEMORYPOOL> RenderPassHandle SceneT::allocateRenderPass(uint32_t renderGroupCount, RenderPassHandle handle) { @@ -241,6 +262,56 @@ namespace ramses::internal return *m_dataBuffers.getMemory(handle); } + template class MEMORYPOOL> + UniformBufferHandle SceneT::allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) + { + const auto allocatedHandle = m_uniformBuffers.allocate(handle); + auto* uniformBuffer = m_uniformBuffers.getMemory(allocatedHandle); + uniformBuffer->data.resize(size); + + return allocatedHandle; + } + + template class MEMORYPOOL> + void SceneT::releaseUniformBuffer(UniformBufferHandle handle) + { + assert(m_uniformBuffers.isAllocated(handle)); + m_uniformBuffers.release(handle); + } + + template class MEMORYPOOL> + void SceneT::updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) + { + auto* uniformBuffer = m_uniformBuffers.getMemory(uniformBufferHandle); + assert(offset + size <= uniformBuffer->data.size()); + + PlatformMemory::Copy(uniformBuffer->data.data() + offset, data, size); + } + + template class MEMORYPOOL> + uint32_t SceneT::getUniformBufferCount() const + { + return m_uniformBuffers.getTotalCount(); + } + + template class MEMORYPOOL> + const UniformBuffer& SceneT::getUniformBuffer(UniformBufferHandle uniformBufferHandle) const + { + return *m_uniformBuffers.getMemory(uniformBufferHandle); + } + + template class MEMORYPOOL> + bool SceneT::isUniformBufferAllocated(UniformBufferHandle uniformBufferHandle) const + { + return m_uniformBuffers.isAllocated(uniformBufferHandle); + } + + template class MEMORYPOOL> + const typename SceneT::UniformBufferMemoryPool& SceneT::getUniformBuffers() const + { + return m_uniformBuffers; + } + template class MEMORYPOOL> TextureBufferHandle SceneT::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) { @@ -876,6 +947,12 @@ namespace ramses::internal setInstanceDataInternal(containerHandle, fieldId, 1, &dataRef); } + template class MEMORYPOOL> + void SceneT::setDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle fieldId, UniformBufferHandle uniformBufferHandle) + { + setInstanceDataInternal(containerHandle, fieldId, 1, &uniformBufferHandle); + } + template class MEMORYPOOL> DataInstanceHandle SceneT::allocateDataInstance(DataLayoutHandle layoutHandle, DataInstanceHandle instanceHandle) { @@ -1023,6 +1100,7 @@ namespace ramses::internal m_textureSamplers.preallocateSize(sizeInfo.textureSamplerCount); m_dataSlots.preallocateSize(sizeInfo.dataSlotCount); m_dataBuffers.preallocateSize(sizeInfo.dataBufferCount); + m_uniformBuffers.preallocateSize(sizeInfo.uniformBufferCount); m_textureBuffers.preallocateSize(sizeInfo.textureBufferCount); m_pickableObjects.preallocateSize(sizeInfo.pickableObjectCount); m_sceneReferences.preallocateSize(sizeInfo.sceneReferenceCount); @@ -1190,6 +1268,7 @@ namespace ramses::internal sizeInfo.textureSamplerCount = m_textureSamplers.getTotalCount(); sizeInfo.dataSlotCount = m_dataSlots.getTotalCount(); sizeInfo.dataBufferCount = m_dataBuffers.getTotalCount(); + sizeInfo.uniformBufferCount = m_uniformBuffers.getTotalCount(); sizeInfo.textureBufferCount = m_textureBuffers.getTotalCount(); sizeInfo.pickableObjectCount = m_pickableObjects.getTotalCount(); sizeInfo.sceneReferenceCount = m_sceneReferences.getTotalCount(); diff --git a/src/framework/internal/SceneGraph/Scene/Scene.h b/src/framework/internal/SceneGraph/Scene/Scene.h index 473a5e4d8..203833c75 100644 --- a/src/framework/internal/SceneGraph/Scene/Scene.h +++ b/src/framework/internal/SceneGraph/Scene/Scene.h @@ -51,6 +51,7 @@ namespace ramses::internal using TransformMemoryPool = MEMORYPOOL; using DataLayoutMemoryPool = MEMORYPOOL; using DataInstanceMemoryPool = MEMORYPOOL; + using UniformBufferMemoryPool = MEMORYPOOL; using RenderGroupMemoryPool = MEMORYPOOL; using RenderPassMemoryPool = MEMORYPOOL; using BlitPassMemoryPool = MEMORYPOOL; @@ -69,6 +70,9 @@ namespace ramses::internal [[nodiscard]] SceneId getSceneId () const final override; [[nodiscard]] const std::string& getName () const final override; + [[nodiscard]] ERenderBackendCompatibility getRenderBackendCompatibility() const override; + [[nodiscard]] EVulkanAPIVersion getVulkanAPIVersion () const override; + [[nodiscard]] ESPIRVVersion getSPIRVVersion () const override; void setEffectTimeSync(FlushTime::Clock::time_point t) override; [[nodiscard]] FlushTime::Clock::time_point getEffectTimeSync() const override; @@ -171,6 +175,7 @@ namespace ramses::internal [[nodiscard]] const ResourceField& getDataResource (DataInstanceHandle containerHandle, DataFieldHandle field) const final override; [[nodiscard]] TextureSamplerHandle getDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field) const final override; [[nodiscard]] DataInstanceHandle getDataReference (DataInstanceHandle containerHandle, DataFieldHandle field) const final override; + [[nodiscard]] UniformBufferHandle getDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field) const final override; void setDataFloatArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const float* data) override; void setDataVector2fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec2* data) override; @@ -187,6 +192,7 @@ namespace ramses::internal void setDataResource (DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) override; void setDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) override; void setDataReference (DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef) override; + void setDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) override; // get/setData*Array wrappers for elementCount == 1 [[nodiscard]] float getDataSingleFloat (DataInstanceHandle containerHandle, DataFieldHandle field) const final override; @@ -303,6 +309,15 @@ namespace ramses::internal [[nodiscard]] const GeometryDataBuffer& getDataBuffer (DataBufferHandle handle) const final override; [[nodiscard]] const DataBufferMemoryPool& getDataBuffers() const; + // Uniform buffers + UniformBufferHandle allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) override; + void releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) override; + void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) override; + [[nodiscard]] bool isUniformBufferAllocated(UniformBufferHandle uniformBufferHandle) const override; + [[nodiscard]] uint32_t getUniformBufferCount() const override; + [[nodiscard]] const UniformBuffer& getUniformBuffer(UniformBufferHandle uniformBufferHandle) const override; + [[nodiscard]] const UniformBufferMemoryPool& getUniformBuffers() const; + //Texture buffers TextureBufferHandle allocateTextureBuffer (EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) override; void releaseTextureBuffer (TextureBufferHandle handle) override; @@ -352,6 +367,7 @@ namespace ramses::internal TransformMemoryPool m_transforms; DataLayoutMemoryPool m_dataLayoutMemory; DataInstanceMemoryPool m_dataInstanceMemory; + UniformBufferMemoryPool m_uniformBuffers; RenderGroupMemoryPool m_renderGroups; RenderPassMemoryPool m_renderPasses; BlitPassMemoryPool m_blitPasses; @@ -367,6 +383,10 @@ namespace ramses::internal const std::string m_name; const SceneId m_sceneId; + const ERenderBackendCompatibility m_renderBackendCompatibility; + const EVulkanAPIVersion m_vulkanAPIVersion; + const ESPIRVVersion m_spirvVersion; + FlushTime::Clock::time_point m_effectTimeSync; }; @@ -743,6 +763,12 @@ namespace ramses::internal return *getInstanceDataInternal(containerHandle, fieldId); } + template class MEMORYPOOL> + inline UniformBufferHandle SceneT::getDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle fieldId) const + { + return *getInstanceDataInternal(containerHandle, fieldId); + } + template class MEMORYPOOL> inline const ResourceField& SceneT::getDataResource(DataInstanceHandle containerHandle, DataFieldHandle fieldId) const { diff --git a/src/framework/internal/SceneGraph/Scene/SceneActionApplier.cpp b/src/framework/internal/SceneGraph/Scene/SceneActionApplier.cpp index b23b18ad3..383a30351 100644 --- a/src/framework/internal/SceneGraph/Scene/SceneActionApplier.cpp +++ b/src/framework/internal/SceneGraph/Scene/SceneActionApplier.cpp @@ -20,7 +20,6 @@ #include "internal/Components/FlushTimeInformation.h" #include "internal/SceneGraph/Resource/IResource.h" #include "internal/Core/Utils/BinaryInputStream.h" -#include "internal/Core/Utils/LogMacros.h" #include "glm/gtx/range.hpp" #include @@ -32,10 +31,10 @@ namespace ramses::internal inline void AssertHandle([[maybe_unused]] const TypedMemoryHandle& actualHandle, [[maybe_unused]] const TypedMemoryHandle& handleToCheck) { assert(handleToCheck.isValid()); - assert(handleToCheck == actualHandle); + assert(actualHandle.isValid()); } - void SceneActionApplier::ApplySingleActionOnScene(IScene& scene, SceneActionCollection::SceneActionReader& action) + void SceneActionApplier::ApplySingleActionOnScene(IScene& scene, SceneActionCollection::SceneActionReader& action, EFeatureLevel featureLevel) { switch (action.type()) { @@ -306,6 +305,17 @@ namespace ramses::internal scene.setDataReference(handle, field, dataRef); break; } + case ESceneActionId::SetDataUniformBuffer: + { + DataInstanceHandle handle; + DataFieldHandle field; + UniformBufferHandle uniformBufferHandle; + action.read(handle); + action.read(field); + action.read(uniformBufferHandle); + scene.setDataUniformBuffer(handle, field, uniformBufferHandle); + break; + } case ESceneActionId::AllocateRenderable: { NodeHandle node; @@ -1027,6 +1037,34 @@ namespace ramses::internal scene.updateDataBuffer(handle, offsetInBytes, dataSizeInBytes, data); break; } + case ESceneActionId::AllocateUniformBuffer: + { + UniformBufferHandle handle; + uint32_t size{}; + action.read(handle); + action.read(size); + scene.allocateUniformBuffer(size, handle); + break; + } + case ESceneActionId::ReleaseUniformBuffer: + { + UniformBufferHandle handle; + action.read(handle); + scene.releaseUniformBuffer(handle); + break; + } + case ESceneActionId::UpdateUniformBuffer: + { + UniformBufferHandle handle; + uint32_t offset{}; + uint32_t size{}; + const std::byte* data = nullptr; + action.read(handle); + action.read(offset); + action.readWithoutCopy(data, size); + scene.updateUniformBuffer(handle, offset, size, data); + break; + } case ESceneActionId::AllocateTextureBuffer: { uint32_t textureFormat = 0; @@ -1126,7 +1164,7 @@ namespace ramses::internal case ESceneActionId::PreallocateSceneSize: { SceneSizeInformation sizeInfos; - GetSceneSizeInformation(action, sizeInfos); + GetSceneSizeInformation(action, sizeInfos, featureLevel); scene.preallocateSceneSize(sizeInfos); break; } @@ -1260,8 +1298,7 @@ namespace ramses::internal action.read(stencilOpDepthPass); action.read(colorWriteMask); - [[maybe_unused]] const RenderStateHandle stateHandleNew = scene.allocateRenderState(stateHandle); - assert(stateHandle == stateHandleNew); + AssertHandle(scene.allocateRenderState(stateHandle), stateHandle); scene.setRenderStateBlendFactors( stateHandle, bfSrcColor, bfDstColor, bfSrcAlpha, bfDstAlpha); scene.setRenderStateBlendOperations(stateHandle, boColor, boAlpha); @@ -1288,15 +1325,15 @@ namespace ramses::internal assert(action.isFullyRead()); } - void SceneActionApplier::ApplyActionsOnScene(IScene& scene, const SceneActionCollection& actions) + void SceneActionApplier::ApplyActionsOnScene(IScene& scene, const SceneActionCollection& actions, EFeatureLevel featureLevel) { for (auto& reader : actions) { - ApplySingleActionOnScene(scene, reader); + ApplySingleActionOnScene(scene, reader, featureLevel); } } - void SceneActionApplier::GetSceneSizeInformation(SceneActionCollection::SceneActionReader& action, SceneSizeInformation& sizeInfo) + void SceneActionApplier::GetSceneSizeInformation(SceneActionCollection::SceneActionReader& action, SceneSizeInformation& sizeInfo, EFeatureLevel featureLevel) { action.read(sizeInfo.nodeCount); action.read(sizeInfo.cameraCount); @@ -1305,6 +1342,8 @@ namespace ramses::internal action.read(sizeInfo.renderStateCount); action.read(sizeInfo.datalayoutCount); action.read(sizeInfo.datainstanceCount); + if (featureLevel >= EFeatureLevel_02) + action.read(sizeInfo.uniformBufferCount); action.read(sizeInfo.renderGroupCount); action.read(sizeInfo.renderPassCount); action.read(sizeInfo.blitPassCount); diff --git a/src/framework/internal/SceneGraph/Scene/SceneActionApplier.h b/src/framework/internal/SceneGraph/Scene/SceneActionApplier.h index 3857eae60..0e632cf21 100644 --- a/src/framework/internal/SceneGraph/Scene/SceneActionApplier.h +++ b/src/framework/internal/SceneGraph/Scene/SceneActionApplier.h @@ -12,6 +12,7 @@ #include "internal/SceneGraph/SceneAPI/SceneVersionTag.h" #include "internal/PlatformAbstraction/Collections/Vector.h" #include "internal/SceneReferencing/SceneReferenceAction.h" +#include "ramses/framework/EFeatureLevel.h" #include namespace ramses::internal @@ -27,10 +28,10 @@ namespace ramses::internal public: using ResourceVector = std::vector>; - static void ApplyActionsOnScene(IScene& scene, const SceneActionCollection& actions); + static void ApplyActionsOnScene(IScene& scene, const SceneActionCollection& actions, EFeatureLevel featureLevel); private: - static void GetSceneSizeInformation(SceneActionCollection::SceneActionReader& action, SceneSizeInformation& sizeInfo); - static void ApplySingleActionOnScene(IScene& scene, SceneActionCollection::SceneActionReader& action); + static void GetSceneSizeInformation(SceneActionCollection::SceneActionReader& action, SceneSizeInformation& sizeInfo, EFeatureLevel featureLevel); + static void ApplySingleActionOnScene(IScene& scene, SceneActionCollection::SceneActionReader& action, EFeatureLevel featureLevel); }; } diff --git a/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.cpp b/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.cpp index 9f7c24924..af37d704a 100644 --- a/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.cpp +++ b/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.cpp @@ -25,8 +25,9 @@ namespace ramses::internal { - SceneActionCollectionCreator::SceneActionCollectionCreator(SceneActionCollection& collection_) - : collection(collection_) + SceneActionCollectionCreator::SceneActionCollectionCreator(SceneActionCollection& collection_, EFeatureLevel featureLevel) + : collection{ collection_ } + , m_featureLevel{ featureLevel } { } @@ -647,6 +648,14 @@ namespace ramses::internal collection.write(dataRef); } + void SceneActionCollectionCreator::setDataUniformBuffer(DataInstanceHandle handle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) + { + collection.beginWriteSceneAction(ESceneActionId::SetDataUniformBuffer); + collection.write(handle); + collection.write(field); + collection.write(uniformBufferHandle); + } + void SceneActionCollectionCreator::allocateTextureSampler(const TextureSampler& sampler, TextureSamplerHandle handle) { collection.beginWriteSceneAction(ESceneActionId::AllocateTextureSampler); @@ -742,6 +751,27 @@ namespace ramses::internal collection.write(data, dataSizeInBytes); } + void SceneActionCollectionCreator::allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) + { + collection.beginWriteSceneAction(ESceneActionId::AllocateUniformBuffer); + collection.write(handle); + collection.write(size); + } + + void SceneActionCollectionCreator::releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) + { + collection.beginWriteSceneAction(ESceneActionId::ReleaseUniformBuffer); + collection.write(uniformBufferHandle); + } + + void SceneActionCollectionCreator::updateUniformBuffer(UniformBufferHandle handle, uint32_t offset, uint32_t size, const std::byte* data) + { + collection.beginWriteSceneAction(ESceneActionId::UpdateUniformBuffer); + collection.write(handle); + collection.write(offset); + collection.write(data, size); + } + void SceneActionCollectionCreator::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) { collection.beginWriteSceneAction(ESceneActionId::AllocateTextureBuffer); @@ -916,6 +946,8 @@ namespace ramses::internal collection.write(sizeInfo.renderStateCount); collection.write(sizeInfo.datalayoutCount); collection.write(sizeInfo.datainstanceCount); + if (m_featureLevel >= EFeatureLevel_02) + collection.write(sizeInfo.uniformBufferCount); collection.write(sizeInfo.renderGroupCount); collection.write(sizeInfo.renderPassCount); collection.write(sizeInfo.blitPassCount); diff --git a/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.h b/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.h index 0ea6bda48..5193db5df 100644 --- a/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.h +++ b/src/framework/internal/SceneGraph/Scene/SceneActionCollectionCreator.h @@ -30,7 +30,7 @@ #include "internal/SceneGraph/Resource/TextureMetaInfo.h" #include "internal/Components/FlushTimeInformation.h" #include "internal/SceneReferencing/SceneReferenceAction.h" - +#include "ramses/framework/EFeatureLevel.h" namespace ramses::internal { @@ -46,7 +46,7 @@ namespace ramses::internal class SceneActionCollectionCreator { public: - explicit SceneActionCollectionCreator(SceneActionCollection& collection_); + SceneActionCollectionCreator(SceneActionCollection& collection_, EFeatureLevel featureLevel); void preallocateSceneSize(const SceneSizeInformation& sizeInfo); @@ -121,6 +121,7 @@ namespace ramses::internal void setDataResource(DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride); void setDataTextureSamplerHandle(DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle); void setDataReference(DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef); + void setDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle); // Texture sampler description void allocateTextureSampler(const TextureSampler& sampler, TextureSamplerHandle handle); @@ -177,6 +178,11 @@ namespace ramses::internal void releaseDataBuffer(DataBufferHandle handle); void updateDataBuffer(DataBufferHandle handle, uint32_t offsetInBytes, uint32_t dataSizeInBytes, const std::byte* data); + // Uniform buffers + void allocateUniformBuffer(uint32_t size, UniformBufferHandle handle); + void releaseUniformBuffer(UniformBufferHandle uniformBufferHandle); + void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data); + // Texture buffers void allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle); void releaseTextureBuffer(TextureBufferHandle handle); @@ -205,5 +211,7 @@ namespace ramses::internal private: void putSceneSizeInformation(const SceneSizeInformation& sizeInfo); + + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; }; } diff --git a/src/framework/internal/SceneGraph/Scene/SceneDescriber.cpp b/src/framework/internal/SceneGraph/Scene/SceneDescriber.cpp index 0245d3cad..ab470089b 100644 --- a/src/framework/internal/SceneGraph/Scene/SceneDescriber.cpp +++ b/src/framework/internal/SceneGraph/Scene/SceneDescriber.cpp @@ -32,19 +32,20 @@ namespace ramses::internal RecreateNodes( source, collector); RecreateTransformNodes( source, collector); RecreateTransformations( source, collector); - RecreateRenderables( source, collector); - RecreateStates( source, collector); RecreateDataLayouts( source, collector); RecreateDataInstances( source, collector); + RecreateRenderables( source, collector); + RecreateStates( source, collector); RecreateCameras( source, collector); RecreateRenderGroups( source, collector); + RecreateRenderBuffersAndTargets( source, collector); RecreateRenderPasses( source, collector); RecreateBlitPasses( source, collector); RecreatePickableObjects( source, collector); RecreateDataBuffers( source, collector); + RecreateUniformBuffers( source, collector); RecreateTextureBuffers( source, collector); RecreateTextureSamplers( source, collector); - RecreateRenderBuffersAndTargets( source, collector); RecreateDataSlots( source, collector); RecreateSceneReferences( source, collector); } @@ -339,6 +340,11 @@ namespace ramses::internal } break; } + case EDataType::UniformBuffer: + { + collector.setDataUniformBuffer(i, f, source.getDataUniformBuffer(i, f)); + break; + } default: assert(false); break; @@ -435,6 +441,21 @@ namespace ramses::internal } } + void SceneDescriber::RecreateUniformBuffers(const IScene& source, SceneActionCollectionCreator& collector) + { + const auto uniformBufferTotalCount = source.getUniformBufferCount(); + for (UniformBufferHandle handle(0u); handle < uniformBufferTotalCount; ++handle) + { + if (source.isUniformBufferAllocated(handle)) + { + const auto& uniformBuffer = source.getUniformBuffer(handle); + const auto size = uint32_t(uniformBuffer.data.size()); + collector.allocateUniformBuffer(size, handle); + collector.updateUniformBuffer(handle, 0u, size, uniformBuffer.data.data()); + } + } + } + void SceneDescriber::RecreateTextureBuffers(const IScene& source, SceneActionCollectionCreator& collector) { std::vector tempForCopyingUsedTextureDataBuffer; diff --git a/src/framework/internal/SceneGraph/Scene/SceneDescriber.h b/src/framework/internal/SceneGraph/Scene/SceneDescriber.h index c0b902dc5..ff1165d3e 100644 --- a/src/framework/internal/SceneGraph/Scene/SceneDescriber.h +++ b/src/framework/internal/SceneGraph/Scene/SceneDescriber.h @@ -39,6 +39,7 @@ namespace ramses::internal static void RecreateBlitPasses(const IScene& source, SceneActionCollectionCreator& collector); static void RecreatePickableObjects(const IScene& source, SceneActionCollectionCreator& collector); static void RecreateDataBuffers(const IScene& source, SceneActionCollectionCreator& collector); + static void RecreateUniformBuffers(const IScene& source, SceneActionCollectionCreator& collector); static void RecreateTextureBuffers(const IScene& source, SceneActionCollectionCreator& collector); static void RecreateTextureSamplers(const IScene& source, SceneActionCollectionCreator& collector); static void RecreateRenderBuffersAndTargets(const IScene& source, SceneActionCollectionCreator& collector); diff --git a/src/framework/internal/SceneGraph/Scene/SceneMergeHandleMapping.h b/src/framework/internal/SceneGraph/Scene/SceneMergeHandleMapping.h new file mode 100644 index 000000000..b9d5cf1a1 --- /dev/null +++ b/src/framework/internal/SceneGraph/Scene/SceneMergeHandleMapping.h @@ -0,0 +1,255 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "ramses/framework/RamsesFrameworkTypes.h" + +#include + +namespace ramses::internal +{ + class SceneMergeHandleMapping + { + public: + SceneMergeHandleMapping() = default; + ~SceneMergeHandleMapping() = default; + + template + void addMapping(TypedMemoryHandle handle, TypedMemoryHandle newHandle); + void addMapping(sceneObjectId_t handle, sceneObjectId_t newHandle); + + template + [[nodiscard]] TypedMemoryHandle getMapping(TypedMemoryHandle handle) const; + [[nodiscard]] sceneObjectId_t getMapping(sceneObjectId_t handle) const; + + template + [[nodiscard]] bool hasMapping(TypedMemoryHandle handle) const; + [[nodiscard]] bool hasMapping(sceneObjectId_t handle) const; + + private: + template + using container_ll_t = std::unordered_map, TypedMemoryHandle>; + + template + using container_hl_t = std::unordered_map; + + template + container_ll_t& getMapping(); + + template + const container_ll_t& getMapping() const; + + container_ll_t m_nodeHandleMapping; + container_ll_t m_transformHandleMapping; + container_ll_t m_renderableHandleMapping; + container_ll_t m_dataInstanceHandleMapping; + container_ll_t m_textureSamplerHandleMapping; + container_ll_t m_renderBufferHandleMapping; + container_ll_t m_dataSlotHandleMapping; + container_ll_t m_renderGroupHandleMapping; + container_ll_t m_stateHandleMapping; + container_ll_t m_cameraHandleMapping; + container_ll_t m_renderPassHandleMapping; + container_ll_t m_blitPassHandleMapping; + container_ll_t m_pickableObjectHandleMapping; + container_ll_t m_renderTargetHandleMapping; + container_ll_t m_dataBufferHandleMapping; + container_ll_t m_textureBufferHandleMapping; + container_ll_t m_sceneReferenceHandleMapping; + container_ll_t m_dataLayoutHandleMapping; + container_ll_t m_uniformBufferHandleMapping; + + container_hl_t m_sceneObjectIdMapping; + }; + + template + inline void SceneMergeHandleMapping::addMapping(TypedMemoryHandle handle, TypedMemoryHandle newHandle) + { + assert(handle.isValid()); + assert(newHandle.isValid()); + auto& mapping = getMapping(); + assert(mapping.count(handle) == 0); + mapping[handle] = newHandle; + } + + inline void SceneMergeHandleMapping::addMapping(sceneObjectId_t handle, sceneObjectId_t newHandle) + { + assert(handle.isValid()); + assert(newHandle.isValid()); + assert(m_sceneObjectIdMapping.count(handle) == 0); + m_sceneObjectIdMapping[handle] = newHandle; + } + + template + inline TypedMemoryHandle SceneMergeHandleMapping::getMapping(TypedMemoryHandle handle) const + { + assert(handle.isValid()); + const auto& mapping = getMapping(); + auto findIt = mapping.find(handle); + if (findIt != mapping.end()) + { + return findIt->second; + } + return TypedMemoryHandle::Invalid(); + } + + inline sceneObjectId_t SceneMergeHandleMapping::getMapping(sceneObjectId_t handle) const + { + assert(handle.isValid()); + auto findIt = m_sceneObjectIdMapping.find(handle); + if (findIt != m_sceneObjectIdMapping.end()) + { + return findIt->second; + } + return sceneObjectId_t::Invalid(); + } + + template + inline bool SceneMergeHandleMapping::hasMapping(TypedMemoryHandle handle) const + { + if (!handle.isValid()) + { + return false; + } + + return getMapping().count(handle) > 0u; + } + + inline bool SceneMergeHandleMapping::hasMapping(sceneObjectId_t handle) const + { + if (!handle.isValid()) + { + return false; + } + + return m_sceneObjectIdMapping.count(handle) > 0u; + } + + template + inline const SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() const + { + auto* nonConstThis = const_cast(this); + return nonConstThis->getMapping(); + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_nodeHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_transformHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_renderableHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_dataInstanceHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_renderBufferHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_dataSlotHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_renderGroupHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_stateHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_cameraHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_renderPassHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_blitPassHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_pickableObjectHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_renderTargetHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_dataBufferHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_textureBufferHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_sceneReferenceHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_textureSamplerHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_dataLayoutHandleMapping; + } + + template<> + inline SceneMergeHandleMapping::container_ll_t& SceneMergeHandleMapping::getMapping() + { + return m_uniformBufferHandleMapping; + } +} diff --git a/src/framework/internal/SceneGraph/Scene/ScenePersistation.cpp b/src/framework/internal/SceneGraph/Scene/ScenePersistation.cpp index db6dc2c29..f2b55ef34 100644 --- a/src/framework/internal/SceneGraph/Scene/ScenePersistation.cpp +++ b/src/framework/internal/SceneGraph/Scene/ScenePersistation.cpp @@ -11,11 +11,13 @@ #include "internal/SceneGraph/Scene/SceneActionApplier.h" #include "internal/SceneGraph/Scene/SceneDescriber.h" #include "internal/SceneGraph/Scene/SceneActionCollectionCreator.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" #include "internal/Core/Utils/File.h" #include "internal/Core/Utils/BinaryFileOutputStream.h" #include "internal/Core/Utils/BinaryFileInputStream.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/SceneGraph/Scene/ClientScene.h" +#include "internal/SceneGraph/Scene/MergeScene.h" #include @@ -23,11 +25,11 @@ namespace ramses::internal { static const uint32_t gSceneMarker = 0x534d4152; // {'R', 'A', 'M', 'S'} - void ScenePersistation::ReadSceneMetadataFromStream(IInputStream& inStream, SceneCreationInformation& createInfo) + void ScenePersistation::ReadSceneMetadataFromStream(IInputStream& inStream, SceneCreationInformation& createInfo, EFeatureLevel featureLevel) { SceneId::BaseType sceneIdBaseType{}; inStream >> sceneIdBaseType; - createInfo.m_id = SceneId(sceneIdBaseType); + createInfo.m_sceneInfo.sceneID = SceneId(sceneIdBaseType); SceneSizeInformation sizeInfo; inStream >> sizeInfo.nodeCount; @@ -37,6 +39,8 @@ namespace ramses::internal inStream >> sizeInfo.renderStateCount; inStream >> sizeInfo.datalayoutCount; inStream >> sizeInfo.datainstanceCount; + if (featureLevel >= EFeatureLevel_02) + inStream >> sizeInfo.uniformBufferCount; inStream >> sizeInfo.renderGroupCount; inStream >> sizeInfo.renderPassCount; inStream >> sizeInfo.renderTargetCount; @@ -46,10 +50,17 @@ namespace ramses::internal inStream >> sizeInfo.textureBufferCount; createInfo.m_sizeInfo = sizeInfo; - inStream >> createInfo.m_name; + inStream >> createInfo.m_sceneInfo.friendlyName; + + if (featureLevel >= EFeatureLevel_02) + { + inStream >> createInfo.m_sceneInfo.renderBackendCompatibility; + inStream >> createInfo.m_sceneInfo.vulkanAPIVersion; + inStream >> createInfo.m_sceneInfo.spirvVersion; + } } - void ScenePersistation::WriteSceneMetadataToStream(IOutputStream& outStream, const IScene& scene) + void ScenePersistation::WriteSceneMetadataToStream(IOutputStream& outStream, const IScene& scene, EFeatureLevel featureLevel) { outStream << scene.getSceneId().getValue(); @@ -61,6 +72,8 @@ namespace ramses::internal outStream << sizeInfo.renderStateCount; outStream << sizeInfo.datalayoutCount; outStream << sizeInfo.datainstanceCount; + if (featureLevel >= EFeatureLevel_02) + outStream << sizeInfo.uniformBufferCount; outStream << sizeInfo.renderGroupCount; outStream << sizeInfo.renderPassCount; outStream << sizeInfo.renderTargetCount; @@ -70,12 +83,19 @@ namespace ramses::internal outStream << sizeInfo.textureBufferCount; outStream << scene.getName(); + + if (featureLevel >= EFeatureLevel_02) + { + outStream << scene.getRenderBackendCompatibility(); + outStream << scene.getVulkanAPIVersion(); + outStream << scene.getSPIRVVersion(); + } } - void ScenePersistation::WriteSceneToStream(IOutputStream& outStream, const ClientScene& scene) + void ScenePersistation::WriteSceneToStream(IOutputStream& outStream, const ClientScene& scene, EFeatureLevel featureLevel) { SceneActionCollection collection; - SceneActionCollectionCreator creator(collection); + SceneActionCollectionCreator creator(collection, featureLevel); creator.preallocateSceneSize(scene.getSceneSizeInformation()); SceneDescriber::describeScene(scene, creator); @@ -96,14 +116,14 @@ namespace ramses::internal } } - void ScenePersistation::WriteSceneToFile(std::string_view filename, const ClientScene& scene) + void ScenePersistation::WriteSceneToFile(std::string_view filename, const ClientScene& scene, EFeatureLevel featureLevel) { File f(filename); BinaryFileOutputStream stream(f); if (stream.getState() == EStatus::Ok) { - ScenePersistation::WriteSceneToStream(stream, scene); + ScenePersistation::WriteSceneToStream(stream, scene, featureLevel); } else { @@ -111,7 +131,7 @@ namespace ramses::internal } } - void ScenePersistation::ReadSceneFromStream(IInputStream& inStream, IScene& scene) + void ScenePersistation::ReadSceneFromStream(IInputStream& inStream, IScene& scene, EFeatureLevel featureLevel, SceneMergeHandleMapping* mapping) { uint32_t sceneMarker = 0; inStream >> sceneMarker; @@ -157,10 +177,18 @@ namespace ramses::internal } })); - SceneActionApplier::ApplyActionsOnScene(scene, actions); + if (mapping) + { + MergeScene mergeScene(scene, *mapping); + SceneActionApplier::ApplyActionsOnScene(mergeScene, actions, featureLevel); + } + else + { + SceneActionApplier::ApplyActionsOnScene(scene, actions, featureLevel); + } } - void ScenePersistation::ReadSceneFromFile(std::string_view filename, IScene& scene) + void ScenePersistation::ReadSceneFromFile(std::string_view filename, IScene& scene, EFeatureLevel featureLevel, SceneMergeHandleMapping* mapping) { File f(filename); if (!f.exists()) @@ -173,7 +201,7 @@ namespace ramses::internal const EStatus state = stream.getState(); if (EStatus::Ok == state) { - ScenePersistation::ReadSceneFromStream(stream, scene); + ScenePersistation::ReadSceneFromStream(stream, scene, featureLevel, mapping); } else { diff --git a/src/framework/internal/SceneGraph/Scene/ScenePersistation.h b/src/framework/internal/SceneGraph/Scene/ScenePersistation.h index 3ad01fde1..574ed445c 100644 --- a/src/framework/internal/SceneGraph/Scene/ScenePersistation.h +++ b/src/framework/internal/SceneGraph/Scene/ScenePersistation.h @@ -10,23 +10,25 @@ #include "internal/SceneGraph/SceneAPI/SceneSizeInformation.h" #include "internal/SceneGraph/SceneAPI/IScene.h" +#include "ramses/framework/EFeatureLevel.h" namespace ramses::internal { class ClientScene; class IOutputStream; class IInputStream; + class SceneMergeHandleMapping; struct SceneCreationInformation; class ScenePersistation { public: - static void WriteSceneMetadataToStream(IOutputStream& outStream, const IScene& scene); - static void WriteSceneToStream(IOutputStream& outStream, const ClientScene& scene); - static void WriteSceneToFile(std::string_view filename, const ClientScene& scene); + static void WriteSceneMetadataToStream(IOutputStream& outStream, const IScene& scene, EFeatureLevel featureLevel); + static void WriteSceneToStream(IOutputStream& outStream, const ClientScene& scene, EFeatureLevel featureLevel); + static void WriteSceneToFile(std::string_view filename, const ClientScene& scene, EFeatureLevel featureLevel); - static void ReadSceneMetadataFromStream(IInputStream& inStream, SceneCreationInformation& createInfo); - static void ReadSceneFromStream(IInputStream& inStream, IScene& scene); - static void ReadSceneFromFile(std::string_view filename, IScene& scene); + static void ReadSceneMetadataFromStream(IInputStream& inStream, SceneCreationInformation& createInfo, EFeatureLevel featureLevel); + static void ReadSceneFromStream(IInputStream& inStream, IScene& scene, EFeatureLevel featureLevel, SceneMergeHandleMapping* mapping); + static void ReadSceneFromFile(std::string_view filename, IScene& scene, EFeatureLevel featureLevel, SceneMergeHandleMapping* mapping); }; } diff --git a/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.cpp b/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.cpp index cee98ccd9..e76dfeee0 100644 --- a/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.cpp +++ b/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.cpp @@ -21,14 +21,14 @@ namespace ramses::internal { template class MEMORYPOOL> TransformationCachedSceneT::TransformationCachedSceneT(const SceneInfo& sceneInfo) - : SceneT(sceneInfo) + : BaseT(sceneInfo) { } template class MEMORYPOOL> void TransformationCachedSceneT::preallocateSceneSize(const SceneSizeInformation& sizeInfo) { - SceneT::preallocateSceneSize(sizeInfo); + BaseT::preallocateSceneSize(sizeInfo); m_nodeToTransformMap.reserve(sizeInfo.transformCount); m_matrixCachePool.preallocateSize(sizeInfo.nodeCount); @@ -38,21 +38,21 @@ namespace ramses::internal void TransformationCachedSceneT::removeChildFromNode(NodeHandle parent, NodeHandle child) { propagateDirty(child); - SceneT::removeChildFromNode(parent, child); + BaseT::removeChildFromNode(parent, child); } template class MEMORYPOOL> void TransformationCachedSceneT::addChildToNode(NodeHandle parent, NodeHandle child) { propagateDirty(child); - SceneT::addChildToNode(parent, child); + BaseT::addChildToNode(parent, child); } template class MEMORYPOOL> TransformHandle TransformationCachedSceneT::allocateTransform(NodeHandle nodeHandle, TransformHandle handle) { assert(nodeHandle.isValid()); - const TransformHandle actualHandle = SceneT::allocateTransform(nodeHandle, handle); + const TransformHandle actualHandle = BaseT::allocateTransform(nodeHandle, handle); m_nodeToTransformMap.put(nodeHandle, actualHandle); propagateDirty(nodeHandle); return actualHandle; @@ -63,7 +63,7 @@ namespace ramses::internal { const NodeHandle nodeHandle = this->getTransformNode(transform); assert(nodeHandle.isValid()); - SceneT::releaseTransform(transform); + BaseT::releaseTransform(transform); propagateDirty(nodeHandle); } @@ -74,7 +74,7 @@ namespace ramses::internal assert(nodeTransformIsConnectedTo.isValid()); getMatrixCacheEntry(nodeTransformIsConnectedTo).m_isIdentity = false; propagateDirty(nodeTransformIsConnectedTo); - SceneT::setTranslation(transform, translation); + BaseT::setTranslation(transform, translation); } template class MEMORYPOOL> @@ -84,7 +84,7 @@ namespace ramses::internal assert(nodeTransformIsConnectedTo.isValid()); getMatrixCacheEntry(nodeTransformIsConnectedTo).m_isIdentity = false; propagateDirty(nodeTransformIsConnectedTo); - SceneT::setRotation(transform, rotation, rotationType); + BaseT::setRotation(transform, rotation, rotationType); } template class MEMORYPOOL> @@ -94,13 +94,13 @@ namespace ramses::internal assert(nodeTransformIsConnectedTo.isValid()); getMatrixCacheEntry(nodeTransformIsConnectedTo).m_isIdentity = false; propagateDirty(nodeTransformIsConnectedTo); - SceneT::setScaling(transform, scaling); + BaseT::setScaling(transform, scaling); } template class MEMORYPOOL> NodeHandle TransformationCachedSceneT::allocateNode(uint32_t childrenCount, NodeHandle node) { - const NodeHandle _node = SceneT::allocateNode(childrenCount, node); + const NodeHandle _node = BaseT::allocateNode(childrenCount, node); m_matrixCachePool.allocate(_node); return _node; } @@ -110,7 +110,7 @@ namespace ramses::internal { m_matrixCachePool.release(node); m_nodeToTransformMap.remove(node); - SceneT::releaseNode(node); + BaseT::releaseNode(node); } template class MEMORYPOOL> @@ -133,7 +133,7 @@ namespace ramses::internal return cacheEntry.m_matrix[matrixType]; } dirtyNodes.push_back(currentNode); - currentNode = SceneT::getParent(currentNode); + currentNode = BaseT::getParent(currentNode); } return Identity; @@ -204,7 +204,7 @@ namespace ramses::internal // If it was already dirty, no need to propagate further if (!wasDirty) { - const NodeHandleVector& children = SceneT::getNode(node).children; + const NodeHandleVector& children = BaseT::getNode(node).children; m_dirtyPropagationTraversalBuffer.insert(m_dirtyPropagationTraversalBuffer.end(), children.cbegin(), children.cend()); } } @@ -229,7 +229,7 @@ namespace ramses::internal const TransformHandle* transformHandlePtr = m_nodeToTransformMap.get(node); if (transformHandlePtr != nullptr) { - const auto& transform = SceneT::getTransform(*transformHandlePtr); + const auto& transform = BaseT::getTransform(*transformHandlePtr); const auto matrix = glm::translate(transform.translation) * Math3d::Rotation(transform.rotation, transform.rotationType) * @@ -245,7 +245,7 @@ namespace ramses::internal const TransformHandle* transformHandlePtr = m_nodeToTransformMap.get(node); if (transformHandlePtr != nullptr) { - const auto& transform = SceneT::getTransform(*transformHandlePtr); + const auto& transform = BaseT::getTransform(*transformHandlePtr); const auto matrix = glm::scale(glm::vec3(1.f) / transform.scaling) * glm::transpose(Math3d::Rotation(transform.rotation, transform.rotationType)) * diff --git a/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.h b/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.h index 5c774c3e2..43fc03c13 100644 --- a/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.h +++ b/src/framework/internal/SceneGraph/Scene/TransformationCachedScene.h @@ -26,6 +26,8 @@ namespace ramses::internal template class MEMORYPOOL> class TransformationCachedSceneT : public SceneT { + using BaseT = SceneT; + public: explicit TransformationCachedSceneT(const SceneInfo& sceneInfo = SceneInfo()); diff --git a/src/renderer/internal/Platform/OpenGL/Device_GL_platform.cpp b/src/framework/internal/SceneGraph/Scene/UniformBuffer.h similarity index 77% rename from src/renderer/internal/Platform/OpenGL/Device_GL_platform.cpp rename to src/framework/internal/SceneGraph/Scene/UniformBuffer.h index 4c089eab9..793fce283 100644 --- a/src/renderer/internal/Platform/OpenGL/Device_GL_platform.cpp +++ b/src/framework/internal/SceneGraph/Scene/UniformBuffer.h @@ -1,14 +1,19 @@ // ------------------------------------------------------------------------- -// Copyright (C) 2018 BMW Car IT GmbH +// Copyright (C) 2024 BMW AG // ------------------------------------------------------------------------- // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "internal/Platform/OpenGL/Device_GL_platform.h" +#pragma once + +#include namespace ramses::internal { - DEFINE_ALL_API_PROCS; + struct UniformBuffer + { + std::vector data; + }; } diff --git a/src/framework/internal/SceneGraph/SceneAPI/DataFieldInfo.h b/src/framework/internal/SceneGraph/SceneAPI/DataFieldInfo.h index def09b4d8..21781cde3 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/DataFieldInfo.h +++ b/src/framework/internal/SceneGraph/SceneAPI/DataFieldInfo.h @@ -10,13 +10,17 @@ #include "internal/SceneGraph/SceneAPI/EDataType.h" #include "internal/SceneGraph/SceneAPI/EFixedSemantics.h" +#include "internal/SceneGraph/SceneAPI/SceneTypes.h" #include "internal/PlatformAbstraction/Collections/Vector.h" +#include "SceneTypes.h" namespace ramses::internal { struct DataFieldInfo { - explicit DataFieldInfo(EDataType dataType_ = EDataType::Invalid, uint32_t elementCount_ = 1u, EFixedSemantics semantics_ = EFixedSemantics::Invalid) + explicit DataFieldInfo(EDataType dataType_ = EDataType::Invalid, + uint32_t elementCount_ = 1u, + EFixedSemantics semantics_ = EFixedSemantics::Invalid) : dataType(dataType_) , elementCount(elementCount_) , semantics(semantics_) diff --git a/src/framework/internal/SceneGraph/SceneAPI/EDataType.h b/src/framework/internal/SceneGraph/SceneAPI/EDataType.h index fddcac88e..643b2e61a 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/EDataType.h +++ b/src/framework/internal/SceneGraph/SceneAPI/EDataType.h @@ -61,6 +61,8 @@ WARNING_DISABLE_GCC(-Wshadow) ByteBlob, TextureSamplerExternal, + + UniformBuffer, }; WARNINGS_POP @@ -94,10 +96,11 @@ WARNINGS_POP "DATATYPE_VECTOR3BUFFER", "DATATYPE_VECTOR4BUFFER", "DATATYPE_BYTE_BLOB", - "DATATYPE_TEXTURESAMPLEREXTERNAL" + "DATATYPE_TEXTURESAMPLEREXTERNAL", + "DATATYPE_UNIFORMBUFFER" }; - ENUM_TO_STRING(EDataType, DataTypeNames, EDataType::TextureSamplerExternal); + ENUM_TO_STRING(EDataType, DataTypeNames, EDataType::UniformBuffer); inline constexpr uint32_t EnumToNumComponents(EDataType type) { @@ -181,6 +184,7 @@ WARNINGS_POP case EDataType::Vector2Buffer : return sizeof(ResourceField); case EDataType::Vector3Buffer : return sizeof(ResourceField); case EDataType::Vector4Buffer : return sizeof(ResourceField); + case EDataType::UniformBuffer : return sizeof(UniformBufferHandle); case EDataType::Invalid: break; @@ -221,6 +225,7 @@ WARNINGS_POP case EDataType::Vector2Buffer : return alignof(ResourceField); case EDataType::Vector3Buffer : return alignof(ResourceField); case EDataType::Vector4Buffer : return alignof(ResourceField); + case EDataType::UniformBuffer : return alignof(UniformBufferHandle); default: assert(false); return 0; @@ -251,6 +256,12 @@ WARNINGS_POP { }; + template <> + struct TypeToEDataTypeTraits < UniformBufferHandle > + { + static const EDataType DataType = EDataType::UniformBuffer; + }; + template <> struct TypeToEDataTypeTraits < bool > { diff --git a/src/framework/internal/SceneGraph/SceneAPI/EFixedSemantics.h b/src/framework/internal/SceneGraph/SceneAPI/EFixedSemantics.h index e7af23b3c..6cac86786 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/EFixedSemantics.h +++ b/src/framework/internal/SceneGraph/SceneAPI/EFixedSemantics.h @@ -9,9 +9,12 @@ #pragma once #include "internal/SceneGraph/SceneAPI/EDataType.h" +#include "internal/SceneGraph/SceneAPI/SceneTypes.h" #include "internal/Core/Utils/LoggingUtils.h" #include +#include +#include namespace ramses::internal { @@ -37,8 +40,16 @@ namespace ramses::internal TextPositionsAttribute, TextTextureCoordinatesAttribute, TimeMs, + + ModelBlock, + CameraBlock, + ModelCameraBlock, + FramebufferBlock, + SceneBlock, }; + using SemanticsMap = std::unordered_map, EFixedSemantics>; + const std::array EFixedSemanticsNames = { "Invalid", @@ -56,12 +67,23 @@ namespace ramses::internal "TextPositionsAttribute", "TextTextureCoordinatesAttribute", "TimeMs", + "ModelBlock", + "CameraBlock", + "ModelCameraBlock", + "FramebufferBlock", + "SceneBlock", }; inline bool IsSemanticCompatibleWithDataType(EFixedSemantics semantics, EDataType dataType) { switch (semantics) { + case EFixedSemantics::ModelBlock: + case EFixedSemantics::CameraBlock: + case EFixedSemantics::ModelCameraBlock: + case EFixedSemantics::FramebufferBlock: + case EFixedSemantics::SceneBlock: + return dataType == EDataType::UniformBuffer; case EFixedSemantics::ProjectionMatrix: case EFixedSemantics::ViewMatrix: case EFixedSemantics::ModelMatrix: @@ -97,4 +119,4 @@ namespace ramses::internal MAKE_ENUM_CLASS_PRINTABLE(ramses::internal::EFixedSemantics, "EFixedSemantics", ramses::internal::EFixedSemanticsNames, - ramses::internal::EFixedSemantics::TimeMs); + ramses::internal::EFixedSemantics::SceneBlock); diff --git a/src/framework/internal/SceneGraph/SceneAPI/EVulkanVersion.h b/src/framework/internal/SceneGraph/SceneAPI/EVulkanVersion.h new file mode 100644 index 000000000..fbc043712 --- /dev/null +++ b/src/framework/internal/SceneGraph/SceneAPI/EVulkanVersion.h @@ -0,0 +1,38 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include + +namespace ramses::internal +{ + enum class EVulkanAPIVersion : uint8_t + { + Invalid, + Version_1_0, + Version_1_1, + Version_1_2, + Version_1_3, + }; + + enum class ESPIRVVersion : uint8_t + { + Invalid, + Version_1_0, + Version_1_1, + Version_1_2, + Version_1_3, + Version_1_4, + Version_1_5, + Version_1_6, + }; + + static constexpr EVulkanAPIVersion TargetVulkanApiVersion = EVulkanAPIVersion::Version_1_0; + static constexpr ESPIRVVersion TargetSPIRVVersion = ESPIRVVersion::Version_1_0; +} diff --git a/src/framework/internal/SceneGraph/SceneAPI/Handles.h b/src/framework/internal/SceneGraph/SceneAPI/Handles.h index 690cff708..eabb2b4b1 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/Handles.h +++ b/src/framework/internal/SceneGraph/SceneAPI/Handles.h @@ -69,4 +69,7 @@ namespace ramses::internal struct SceneReferenceHandleTag {}; using SceneReferenceHandle = TypedMemoryHandle; + + struct UniformBufferHandleTag {}; + using UniformBufferHandle = TypedMemoryHandle; } diff --git a/src/framework/internal/SceneGraph/SceneAPI/IScene.h b/src/framework/internal/SceneGraph/SceneAPI/IScene.h index 47fd25ac3..27c99acb8 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/IScene.h +++ b/src/framework/internal/SceneGraph/SceneAPI/IScene.h @@ -22,12 +22,16 @@ #include "internal/SceneGraph/SceneAPI/Renderable.h" #include "internal/SceneGraph/SceneAPI/RendererSceneState.h" #include "internal/SceneGraph/SceneAPI/ERotationType.h" +#include "internal/SceneGraph/SceneAPI/EVulkanVersion.h" +#include "internal/SceneGraph/Scene/UniformBuffer.h" #include "internal/PlatformAbstraction/Collections/HashMap.h" #include "internal/PlatformAbstraction/Collections/Vector.h" #include "internal/Components/FlushTimeInformation.h" #include "impl/DataTypesImpl.h" +#include "ramses/framework/ERenderBackendCompatibility.h" + #include namespace ramses::internal @@ -62,6 +66,9 @@ namespace ramses::internal [[nodiscard]] virtual const std::string& getName () const = 0; [[nodiscard]] virtual SceneId getSceneId () const = 0; + [[nodiscard]] virtual ERenderBackendCompatibility getRenderBackendCompatibility () const = 0; + [[nodiscard]] virtual EVulkanAPIVersion getVulkanAPIVersion () const = 0; + [[nodiscard]] virtual ESPIRVVersion getSPIRVVersion () const = 0; virtual void setEffectTimeSync(FlushTime::Clock::time_point t) = 0; [[nodiscard]] virtual FlushTime::Clock::time_point getEffectTimeSync() const = 0; @@ -163,6 +170,7 @@ namespace ramses::internal [[nodiscard]] virtual const ResourceField& getDataResource (DataInstanceHandle containerHandle, DataFieldHandle field) const = 0; [[nodiscard]] virtual TextureSamplerHandle getDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field) const = 0; [[nodiscard]] virtual DataInstanceHandle getDataReference (DataInstanceHandle containerHandle, DataFieldHandle field) const = 0; + [[nodiscard]] virtual UniformBufferHandle getDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field) const = 0; virtual void setDataFloatArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const float* data) = 0; virtual void setDataVector2fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec2* data) = 0; @@ -179,6 +187,7 @@ namespace ramses::internal virtual void setDataResource (DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) = 0; virtual void setDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) = 0; virtual void setDataReference (DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef) = 0; + virtual void setDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) = 0; // get/setData*Array wrappers for elementCount == 1 [[nodiscard]] virtual float getDataSingleFloat (DataInstanceHandle containerHandle, DataFieldHandle field) const = 0; @@ -207,6 +216,14 @@ namespace ramses::internal virtual void setDataSingleMatrix33f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat3& data) = 0; virtual void setDataSingleMatrix44f (DataInstanceHandle containerHandle, DataFieldHandle field, const glm::mat4& data) = 0; + // Uniform buffers + virtual UniformBufferHandle allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) = 0; + virtual void releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) = 0; + virtual void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) = 0; + [[nodiscard]] virtual bool isUniformBufferAllocated(UniformBufferHandle uniformBufferHandle) const = 0; + [[nodiscard]] virtual uint32_t getUniformBufferCount() const = 0; + [[nodiscard]] virtual const UniformBuffer& getUniformBuffer(UniformBufferHandle uniformBufferHandle) const = 0; + // Texture sampler description virtual TextureSamplerHandle allocateTextureSampler (const TextureSampler& sampler, TextureSamplerHandle handle) = 0; virtual void releaseTextureSampler (TextureSamplerHandle handle) = 0; diff --git a/src/framework/internal/SceneGraph/SceneAPI/SceneCreationInformation.h b/src/framework/internal/SceneGraph/SceneAPI/SceneCreationInformation.h index f15adaaa0..5961da5e6 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/SceneCreationInformation.h +++ b/src/framework/internal/SceneGraph/SceneAPI/SceneCreationInformation.h @@ -19,17 +19,14 @@ namespace ramses::internal struct SceneCreationInformation { explicit SceneCreationInformation( - SceneId id = SceneId(), - std::string_view name = {}, - const SceneSizeInformation& sizeInfo = SceneSizeInformation()) - : m_id(id) - , m_name(name) - , m_sizeInfo(sizeInfo) + SceneInfo sceneInfo = SceneInfo{}, + SceneSizeInformation sizeInfo = SceneSizeInformation()) + : m_sceneInfo(std::move(sceneInfo)) + , m_sizeInfo(std::move(sizeInfo)) { } - SceneId m_id; - std::string m_name; - SceneSizeInformation m_sizeInfo; + SceneInfo m_sceneInfo; + SceneSizeInformation m_sizeInfo; }; } diff --git a/src/framework/internal/SceneGraph/SceneAPI/SceneId.h b/src/framework/internal/SceneGraph/SceneAPI/SceneId.h index 107f11d6d..a74c88188 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/SceneId.h +++ b/src/framework/internal/SceneGraph/SceneAPI/SceneId.h @@ -12,6 +12,9 @@ #include "internal/Core/Common/StronglyTypedValue.h" #include "internal/PlatformAbstraction/Collections/Vector.h" #include "internal/SceneGraph/Scene/EScenePublicationMode.h" +#include "EVulkanVersion.h" + +#include "ramses/framework/ERenderBackendCompatibility.h" #include #include @@ -26,27 +29,12 @@ namespace ramses::internal struct SceneInfo { - SceneInfo() = default; - - explicit SceneInfo(const SceneId& sceneID_, std::string_view friendlyName_ = {}, EScenePublicationMode mode = EScenePublicationMode::LocalAndRemote) - : sceneID(sceneID_) - , friendlyName(friendlyName_) - , publicationMode(mode) - {} - - friend bool operator==(const SceneInfo& a, const SceneInfo& b) - { - return a.sceneID == b.sceneID && a.friendlyName == b.friendlyName; - } - - friend bool operator!=(const SceneInfo& a, const SceneInfo& b) - { - return !(a == b); - } - - SceneId sceneID; - std::string friendlyName; - EScenePublicationMode publicationMode = EScenePublicationMode::LocalAndRemote; + SceneId sceneID; + std::string friendlyName {}; + EScenePublicationMode publicationMode = EScenePublicationMode::LocalAndRemote; + ERenderBackendCompatibility renderBackendCompatibility = ERenderBackendCompatibility::OpenGL; + EVulkanAPIVersion vulkanAPIVersion = EVulkanAPIVersion::Invalid; + ESPIRVVersion spirvVersion = ESPIRVVersion::Invalid; }; using SceneInfoVector = std::vector; } diff --git a/src/framework/internal/SceneGraph/SceneAPI/SceneSizeInformation.h b/src/framework/internal/SceneGraph/SceneAPI/SceneSizeInformation.h index 2d5f66595..d9a80bbd7 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/SceneSizeInformation.h +++ b/src/framework/internal/SceneGraph/SceneAPI/SceneSizeInformation.h @@ -24,6 +24,7 @@ namespace ramses::internal uint32_t states, uint32_t datalayouts, uint32_t datainstances, + uint32_t uniformBuffers, uint32_t renderGroups, uint32_t renderPasses, uint32_t blitPasses, @@ -42,6 +43,7 @@ namespace ramses::internal , renderStateCount(states) , datalayoutCount(datalayouts) , datainstanceCount(datainstances) + , uniformBufferCount(uniformBuffers) , renderGroupCount(renderGroups) , renderPassCount(renderPasses) , blitPassCount(blitPasses) @@ -67,6 +69,7 @@ namespace ramses::internal && (renderStateCount == other.renderStateCount) && (datalayoutCount == other.datalayoutCount) && (datainstanceCount == other.datainstanceCount) + && (uniformBufferCount == other.uniformBufferCount) && (renderGroupCount == other.renderGroupCount) && (renderPassCount == other.renderPassCount) && (blitPassCount == other.blitPassCount) @@ -89,6 +92,7 @@ namespace ramses::internal || (renderStateCount > other.renderStateCount) || (datalayoutCount > other.datalayoutCount) || (datainstanceCount > other.datainstanceCount) + || (uniformBufferCount > other.uniformBufferCount) || (renderGroupCount > other.renderGroupCount) || (renderPassCount > other.renderPassCount) || (blitPassCount > other.blitPassCount) @@ -110,6 +114,7 @@ namespace ramses::internal uint32_t renderStateCount = 0u; uint32_t datalayoutCount = 0u; uint32_t datainstanceCount = 0u; + uint32_t uniformBufferCount = 0u; uint32_t renderGroupCount = 0u; uint32_t renderPassCount = 0u; uint32_t blitPassCount = 0u; @@ -131,7 +136,7 @@ struct fmt::formatter : public ramses::i constexpr auto format(const ramses::internal::SceneSizeInformation& si, FormatContext& ctx) { return fmt::format_to(ctx.out(), - "[node={} camera={} transform={} renderable={} state={} datalayout={} datainstance={} renderGroup={} renderPass={} blitPass={} " + "[node={} camera={} transform={} renderable={} state={} datalayout={} datainstance={} uniformBuffer={} renderGroup={} renderPass={} blitPass={} " "renderTarget={} renderBuffer={} textureSampler={} dataSlot={} dataBuffer={} textureBuffer={} " "pickableObjectCount={} sceneReferenceCount={}]", si.nodeCount, @@ -141,6 +146,7 @@ struct fmt::formatter : public ramses::i si.renderStateCount, si.datalayoutCount, si.datainstanceCount, + si.uniformBufferCount, si.renderGroupCount, si.renderPassCount, si.blitPassCount, diff --git a/src/framework/internal/SceneGraph/SceneAPI/SceneTypes.h b/src/framework/internal/SceneGraph/SceneAPI/SceneTypes.h index 0590a5b48..8bba6630c 100644 --- a/src/framework/internal/SceneGraph/SceneAPI/SceneTypes.h +++ b/src/framework/internal/SceneGraph/SceneAPI/SceneTypes.h @@ -38,8 +38,18 @@ namespace ramses::internal using DataBufferHandleVector = std::vector; using TextureBufferHandleVector = std::vector; using TextureSamplerHandleVector = std::vector; + using UniformBufferHandleVector = std::vector; + using DataFieldHandleVector = std::vector; + using CameraHandleVector = std::vector; struct PickableObjectIdTag {}; using PickableObjectId = StronglyTypedValue::max(), PickableObjectIdTag>; using PickableObjectIds = std::vector; + + struct UniformBufferBindingTag {}; + using UniformBufferBinding = StronglyTypedValue::max(), UniformBufferBindingTag>; + struct UniformBufferElementSizeTag {}; + using UniformBufferElementSize = StronglyTypedValue::max(), UniformBufferElementSizeTag>; + struct UniformBufferFieldOffsetTag {}; + using UniformBufferFieldOffset = StronglyTypedValue::max(), UniformBufferFieldOffsetTag>; } diff --git a/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.cpp b/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.cpp index 788700d5c..507e18fe3 100644 --- a/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.cpp +++ b/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.cpp @@ -12,16 +12,47 @@ namespace ramses::internal { - DataLayoutHandle DataLayoutCreationHelper::CreateUniformDataLayoutMatchingEffectInputs(IScene& scene, const EffectInputInformationVector& uniformsInputInfo, InputIndexVector& referencedInputs, const ResourceContentHash& effectHash, DataLayoutHandle handle) + void DataLayoutCreationHelper::SetDataFieldMappingForUniformInputs(EffectInputInformationVector& uniformsInputInfo) { - assert(referencedInputs.empty()); + int lastDataFieldIdx = -1; + for (auto& input : uniformsInputInfo) + { + // Uniform buffer and all its fields are stored/represented in data layout/instance as single data instance field for the whole UBO. + // This checks if input is UBO's field and makes sure that it will point to the same data instance field as the UBO (assuming UBO input comes before its fields). + if (!EffectInputInformation::IsUniformBufferField(input)) + lastDataFieldIdx++; + + // UBO's field can never be first input + assert(lastDataFieldIdx >= 0); + input.dataFieldHandle.asMemoryHandleReference() = lastDataFieldIdx; + } + } + void DataLayoutCreationHelper::SetDataFieldMappingForAttributeInputs(EffectInputInformationVector& attributeInputInfo) + { + // data field Zero is always reserved for index arrays + uint32_t lastDataFieldIdx = 0u; + for (auto& input : attributeInputInfo) + input.dataFieldHandle.asMemoryHandleReference() = ++lastDataFieldIdx; + } + + std::tuple DataLayoutCreationHelper::GetDataFieldsFromEffectInputs(const EffectInputInformationVector& uniformsInputInfo) + { const size_t inputCount = uniformsInputInfo.size(); + + InputIndexVector referencedInputs; DataFieldInfoVector dataFields; dataFields.reserve(inputCount); + for (uint32_t i = 0u; i < inputCount; ++i) { const EffectInputInformation& inputInformation = uniformsInputInfo[i]; + + // Uniform buffer and all its fields are stored/represented in data layout/instance as single data instance field for the whole UBO. + // This skips inputs for UBO's fields as they do not produce individual data instance fields. + if (EffectInputInformation::IsUniformBufferField(inputInformation)) + continue; + if (IsBindableInput(inputInformation)) { dataFields.push_back(DataFieldInfo(EDataType::DataReference)); @@ -29,11 +60,22 @@ namespace ramses::internal } else { - dataFields.push_back(DataFieldInfo{ inputInformation.dataType, inputInformation.elementCount, inputInformation.semantics }); + dataFields.push_back(DataFieldInfo{ + inputInformation.dataType, + inputInformation.elementCount, + inputInformation.semantics + }); } } - return scene.allocateDataLayout(dataFields, effectHash, handle); + return { dataFields, referencedInputs }; + } + + std::tuple DataLayoutCreationHelper::CreateUniformDataLayoutMatchingEffectInputs(IScene& scene, const EffectInputInformationVector& uniformsInputInfo, const ResourceContentHash& effectHash, DataLayoutHandle handle) + { + auto [dataFields, referencedInputs] = GetDataFieldsFromEffectInputs(uniformsInputInfo); + + return { scene.allocateDataLayout(dataFields, effectHash, handle), referencedInputs }; } DataInstanceHandle DataLayoutCreationHelper::CreateAndBindDataReference(IScene& scene, DataInstanceHandle dataInstance, DataFieldHandle dataField, EDataType dataType, DataLayoutHandle dataRefLayout, DataInstanceHandle dataRefInstance) @@ -53,6 +95,7 @@ namespace ramses::internal return (inputInfo.semantics == EFixedSemantics::Invalid) && !IsTextureSamplerType(inputInfo.dataType) && !IsBufferDataType(inputInfo.dataType) - && (inputInfo.elementCount == 1u); + && (inputInfo.elementCount == 1u) + && inputInfo.dataType != EDataType::UniformBuffer; } } diff --git a/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.h b/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.h index e97cfaf39..6c610008d 100644 --- a/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.h +++ b/src/framework/internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.h @@ -10,8 +10,9 @@ #include "internal/SceneGraph/SceneAPI/Handles.h" #include "internal/SceneGraph/SceneAPI/EDataType.h" -#include "internal/PlatformAbstraction/Collections/Vector.h" +#include "internal/SceneGraph/SceneAPI/DataFieldInfo.h" #include "internal/SceneGraph/Resource/EffectInputInformation.h" +#include "internal/PlatformAbstraction/Collections/Vector.h" namespace ramses::internal { @@ -22,7 +23,10 @@ namespace ramses::internal class DataLayoutCreationHelper { public: - static DataLayoutHandle CreateUniformDataLayoutMatchingEffectInputs(IScene& scene, const EffectInputInformationVector& uniformsInputInfo, InputIndexVector& referencedInputs, const ResourceContentHash& effectHash, DataLayoutHandle handle = DataLayoutHandle::Invalid()); + static void SetDataFieldMappingForUniformInputs(EffectInputInformationVector& uniformsInputInfo); + static void SetDataFieldMappingForAttributeInputs(EffectInputInformationVector& attributeInputInfo); + static std::tuple GetDataFieldsFromEffectInputs(const EffectInputInformationVector& uniformsInputInfo); + static std::tuple CreateUniformDataLayoutMatchingEffectInputs(IScene& scene, const EffectInputInformationVector& uniformsInputInfo, const ResourceContentHash& effectHash, DataLayoutHandle handle = DataLayoutHandle::Invalid()); static DataInstanceHandle CreateAndBindDataReference(IScene& scene, DataInstanceHandle dataInstance, DataFieldHandle dataField, EDataType dataType, DataLayoutHandle dataRefLayout = DataLayoutHandle::Invalid(), DataInstanceHandle dataRefInstance = DataInstanceHandle::Invalid()); private: diff --git a/src/framework/internal/SceneGraph/SceneUtils/ResourceUtils.h b/src/framework/internal/SceneGraph/SceneUtils/ResourceUtils.h index 549d98ef0..487de3e46 100644 --- a/src/framework/internal/SceneGraph/SceneUtils/ResourceUtils.h +++ b/src/framework/internal/SceneGraph/SceneUtils/ResourceUtils.h @@ -83,8 +83,9 @@ namespace ramses::internal const uint32_t numRenderTargets = scene.getRenderTargetCount(); const uint32_t numBlitPasses = scene.getBlitPassCount(); const uint32_t numDataBuffers = scene.getDataBufferCount(); + const uint32_t numUniformBuffers = scene.getUniformBufferCount(); const uint32_t numTextureBuffers = scene.getTextureBufferCount(); - const uint32_t numSceneResources = numRenderTargets + numRenderBuffers + numBlitPasses + numDataBuffers * 2u + numTextureBuffers * 2u; + const uint32_t numSceneResources = numRenderTargets + numRenderBuffers + numBlitPasses + numDataBuffers * 2u + numTextureBuffers * 2u + numUniformBuffers * 2u; actions.reserve(numSceneResources); usedDataByteSize = 0u; @@ -124,6 +125,16 @@ namespace ramses::internal usedDataByteSize += TextureBuffer::GetMipMapDataSizeInBytes(scene.getTextureBuffer(tbHandle)); } } + + for (UniformBufferHandle ubHandle(0u); ubHandle < numUniformBuffers; ++ubHandle) + { + if (scene.isUniformBufferAllocated(ubHandle)) + { + actions.push_back({ ubHandle.asMemoryHandle(), ESceneResourceAction_CreateUniformBuffer }); + actions.push_back({ ubHandle.asMemoryHandle(), ESceneResourceAction_UpdateUniformBuffer }); + usedDataByteSize += uint32_t(scene.getUniformBuffer(ubHandle).data.size()); + } + } } void DiffResources(ResourceContentHashVector const& old, ResourceContentHashVector const& curr, ResourceChanges& changes); diff --git a/src/framework/internal/SceneGraph/SceneUtils/UniformBufferUtils.h b/src/framework/internal/SceneGraph/SceneUtils/UniformBufferUtils.h new file mode 100644 index 000000000..d19433e93 --- /dev/null +++ b/src/framework/internal/SceneGraph/SceneUtils/UniformBufferUtils.h @@ -0,0 +1,216 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "ramses/framework/DataTypes.h" + +namespace ramses::internal +{ + // General notes: + // std140 guarantees that uniform buffer data is aligned in memory in a way that facilitates GPU performance. + // For that purpose std140 chooses sometimes to space data sparsely, sometimes unexpectedly too much. + // The rules are also a bit tricky and there is just no way around respecting them while storing and reading + // buffer data + // + // Some of the "recognized" tricks: + // 1. arrays end up having vec4 alignment (per element) regardless of element type (most general and most disturbing rule) + // 2. If not in arrays, vec2 keeps its vec2 alignment (no change), while vec3 has vec4 alignment (vec3 always has extra padding of 1 float) + // 3. mat22 is stored as mat42 (2x vec4), and mat33 is stored as mat43 (3x vec4) + // 4. bool is just a mess as always + // + // References: + // https://www.oreilly.com/library/view/opengl-programming-guide/9780132748445/app09lev1sec2.html + // https://registry.khronos.org/OpenGL/specs/gl/glspec45.core.pdf#page=159 + + namespace UniformBufferUtils + { + enum + { + Always, + InArraysOnly, + Never + }; + + template + struct std140_padding_info + { + }; + + // std140 states that some types, e.g., float, bool, vec3i, might have an alignment of vec4 + // depending "on the circumstances". For that GLSLang calculates most offsets and alignment requirements for + // all fields of a uniform buffer, except for two cases which are covered in this util: + // 1. Some types always have special alignment requirements, e.g., vec3f and vec3i always have same + // alignment as vec4f, mat33 always has alignment of mat43 (3x vec4). + // 2. Scalar and vector types have vec4f alignment when they are in arrays. + // + // The approach taken in this implementation is to rely on glm types' ability to + // create/cast one type from another "correctly enough" even if they dont have same type or size. + // For example vec3f can be created from vec4f by eliminating the "w" component, and vec4f + // can be created from vec3f by adding a dummy value to the "w" component. This is considered + // acceptable behavior because "the padding" values are not used on GPU, i.e., they act + // as discardable or "dont care" values. + // + // Additional point: + // To "facilitate" creation of padded values from unpadded scalars/vector, vec4i is used instead of vec4f + // for bool and integer types even though std140 states "vec4f" as the formal alignment. + // This is done to avoid float conversion when creating vec4f from bool/int. + static_assert(sizeof(vec4f) == sizeof(vec4i), "Vec4f and Vec4i do not have same size!"); + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = InArraysOnly; + using padding_type_t = vec4i; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = InArraysOnly; + using padding_type_t = vec4i; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = InArraysOnly; + using padding_type_t = vec4f; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = InArraysOnly; + using padding_type_t = vec4i; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = Always; + using padding_type_t = vec4i; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = Never; + using padding_type_t = vec4i; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = InArraysOnly; + using padding_type_t = vec4f; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = Always; + using padding_type_t = vec4f; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = Never; + using padding_type_t = vec4f; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = Always; + using padding_type_t = glm::mat2x4; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = Always; + using padding_type_t = glm::mat3x4; + }; + + template<> + struct std140_padding_info + { + static constexpr auto is_needed = Never; + using padding_type_t = matrix44f; + }; + + // Query if padding is needed + template + inline bool IsDataTightlyPacked(std::size_t elementCount) + { + const auto isSingleElement = (elementCount == 1u); + return std140_padding_info::is_needed == Never || + (isSingleElement && std140_padding_info::is_needed == InArraysOnly); + } + + // Adding padding + template + inline glm::vec<4, T, Q> Pad(const glm::vec& v) + { + static_assert(std::is_same_v, typename std140_padding_info>::padding_type_t>, "Wrong padding type"); + return glm::make_vec4(v); + } + + template + inline glm::mat Pad(const glm::mat& v) + { + static_assert(std::is_same_v, typename std140_padding_info>::padding_type_t>, "Wrong padding type"); + return glm::mat(v); + } + + inline vec4i Pad(bool v) + { + return vec4i{ v ? 1 : 0 }; + } + + inline vec4i Pad(int32_t v) + { + return vec4i{ v }; + } + + inline vec4f Pad(float v) + { + return vec4f{ v }; + } + + // Remove padding + template + inline void RemovePadding(const glm::vec<4, T, Q>& v, glm::vec& valueOut) + { + valueOut = glm::vec{ v }; + } + + template + inline void RemovePadding(const glm::mat& v, glm::mat& valueOut) + { + valueOut = glm::mat{ v }; + } + + inline void RemovePadding(const vec4i& v, bool& valueOut) + { + valueOut = (v.x != 0); + } + + inline void RemovePadding(const vec4i& v, int32_t& valueOut) + { + valueOut = v.x; + } + + inline void RemovePadding(const vec4f& v, float& valueOut) + { + valueOut = v.x; + } + } +} diff --git a/src/framework/internal/Watchdog/PlatformWatchdog.cpp b/src/framework/internal/Watchdog/PlatformWatchdog.cpp index bf40f7a06..c114320f0 100644 --- a/src/framework/internal/Watchdog/PlatformWatchdog.cpp +++ b/src/framework/internal/Watchdog/PlatformWatchdog.cpp @@ -15,7 +15,7 @@ namespace ramses::internal { PlatformWatchdog::PlatformWatchdog(std::chrono::milliseconds notificationInterval, ERamsesThreadIdentifier thread, IThreadWatchdogNotification* callback) - : m_interval(notificationInterval / 2) + : m_interval{ std::max(notificationInterval / 2, 1ms) } , m_thread(thread) , m_watchdogCallback(callback) , m_lastNotificationTime(0ms) @@ -56,6 +56,8 @@ namespace ramses::internal { timeToNext += m_interval; } + if (timeToNext > m_interval) + timeToNext = m_interval; // protection against non-steady clock values (should never happen) return timeToNext; } } diff --git a/src/ramses-cli/include/ramses-cli.h b/src/ramses-cli/include/ramses-cli.h index 050f8f5cc..5231efd37 100644 --- a/src/ramses-cli/include/ramses-cli.h +++ b/src/ramses-cli/include/ramses-cli.h @@ -23,9 +23,18 @@ namespace ramses */ inline void registerOptions(CLI::App& cli, ramses::RendererConfig& config) { +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + auto* grp = cli.add_option_group("Renderer Options"); grp->add_flag_function( - "--ivi-control", [&](auto /*unused*/) { config.enableSystemCompositorControl(); }, "enable system compositor IVI controller"); + "--ivi-control", [&](auto /*unused*/) { config.enableSystemCompositorControl(); }, "enable system compositor IVI controller [DEPRECATED]"); + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif } /** @@ -57,6 +66,7 @@ namespace ramses {"gles30" , EDeviceType::GLES_3_0}, {"gl42" , EDeviceType::GL_4_2}, {"gl45" , EDeviceType::GL_4_5}, + {"vulkan" , EDeviceType::Vulkan}, }; grp->add_option_function( diff --git a/src/renderer/CMakeLists.txt b/src/renderer/CMakeLists.txt index 8b7b79933..f0535dcc4 100644 --- a/src/renderer/CMakeLists.txt +++ b/src/renderer/CMakeLists.txt @@ -9,14 +9,28 @@ add_subdirectory(internal/RendererLib) add_subdirectory(internal/Platform) +# This object library solves the problem of ramses-renderer +# dependency on Platform, while still allowing unit testing +# of ramses-renderer without that depdendency on Platform +# Since this is an object library it does not need to link to Platform. +# Only ramses-renderer has to link to Platform +# A fake platform factory lib is added to unit tests, which provides a fake implementation +# of PlatformFactory, that basically does nothing, but allows +# the tests to link to ramses-renderer-impl without linker error createModule( - NAME ramses-renderer - TYPE STATIC_LIBRARY + NAME ramses-renderer-impl + TYPE OBJECT ENABLE_INSTALL OFF - SRC_FILES impl/*.h impl/*.cpp + DEPENDENCIES ramses-renderer-internal + ramses-framework +) +createModule( + NAME ramses-renderer + TYPE STATIC_LIBRARY + ENABLE_INSTALL OFF DEPENDENCIES Platform - ramses-framework + ramses-renderer-impl ) diff --git a/src/renderer/impl/DisplayConfig.cpp b/src/renderer/impl/DisplayConfig.cpp index 14970ecb2..c92c56845 100644 --- a/src/renderer/impl/DisplayConfig.cpp +++ b/src/renderer/impl/DisplayConfig.cpp @@ -59,6 +59,11 @@ namespace ramses return m_impl->getWindowType(); } + bool DisplayConfig::setWindowTitle(std::string_view title) + { + return m_impl->setWindowTitle(title); + } + bool DisplayConfig::setWindowRectangle(int32_t x, int32_t y, uint32_t width, uint32_t height) { const auto status = m_impl->setWindowRectangle(x, y, width, height); diff --git a/src/renderer/impl/DisplayConfigImpl.cpp b/src/renderer/impl/DisplayConfigImpl.cpp index 8623bb68c..1d5d53fe0 100644 --- a/src/renderer/impl/DisplayConfigImpl.cpp +++ b/src/renderer/impl/DisplayConfigImpl.cpp @@ -36,6 +36,17 @@ namespace ramses::internal return m_internalConfig.getWindowType(); } + bool DisplayConfigImpl::setWindowTitle(std::string_view windowTitle) + { + m_internalConfig.setWindowTitle(windowTitle); + return true; + } + + std::string_view DisplayConfigImpl::getWindowTitle() const + { + return m_internalConfig.getWindowTitle(); + } + bool DisplayConfigImpl::setWindowRectangle(int32_t x, int32_t y, uint32_t width, uint32_t height) { if (width == 0u || height == 0u) @@ -72,7 +83,7 @@ namespace ramses::internal return m_internalConfig.getFullscreenState(); } - const ramses::internal::DisplayConfig& DisplayConfigImpl::getInternalDisplayConfig() const + const ramses::internal::DisplayConfigData& DisplayConfigImpl::getInternalDisplayConfig() const { return m_internalConfig; } @@ -316,8 +327,22 @@ namespace ramses::internal report.add(EIssueType::Warning, "Competing settings for EmbeddedCompositor are set (file descriptor and file name). File descriptor setting will be preferred.", nullptr); } - if (m_internalConfig.getWindowType() != EWindowType::Windows && m_internalConfig.getDeviceType() != EDeviceType::GLES_3_0) - report.add(EIssueType::Error, "Selected window type supports only GL ES 3.0 device type", nullptr); + const auto requestedWindow = m_internalConfig.getWindowType(); + const auto requestedDevice = m_internalConfig.getDeviceType(); + + const std::vector> supportedDeviceWindowCombinations {{ + {EWindowType::Windows, EDeviceType::GLES_3_0} , {EWindowType::Windows, EDeviceType::GL_4_2}, {EWindowType::Windows, EDeviceType::GL_4_5}, {EWindowType::Windows, EDeviceType::Vulkan}, + {EWindowType::X11, EDeviceType::GLES_3_0}, {EWindowType::X11, EDeviceType::Vulkan}, + {EWindowType::Wayland_IVI, EDeviceType::GLES_3_0}, + {EWindowType::Wayland_Shell, EDeviceType::GLES_3_0}, + {EWindowType::Android, EDeviceType::GLES_3_0}, + {EWindowType::iOS, EDeviceType::GLES_3_0}, + }}; + + const bool supported = std::any_of(supportedDeviceWindowCombinations.cbegin(), supportedDeviceWindowCombinations.cend(), + [requestedWindow, requestedDevice](const auto& e){ return e.first == requestedWindow && e.second == requestedDevice; }); + if (!supported) + report.add(EIssueType::Error, "Selected window type does not support device type", nullptr); if(m_internalConfig.getWindowsWindowHandle().isValid() && m_internalConfig.getWindowType() != EWindowType::Windows) report.add(EIssueType::Error, "External Windows window handle is set and selected window type is not Windows", nullptr); @@ -330,5 +355,8 @@ namespace ramses::internal if (m_internalConfig.getIOSNativeWindow().isValid() && m_internalConfig.getWindowType() != EWindowType::iOS) report.add(EIssueType::Error, "External iOS window handle is set and selected window type is not iOS", nullptr); + + if(requestedDevice == EDeviceType::Vulkan && m_internalConfig.isAsyncEffectUploadEnabled()) + report.add(EIssueType::Error, "Vulkan does not support async shader upload", nullptr); } } diff --git a/src/renderer/impl/DisplayConfigImpl.h b/src/renderer/impl/DisplayConfigImpl.h index 90187005b..5de5f9830 100644 --- a/src/renderer/impl/DisplayConfigImpl.h +++ b/src/renderer/impl/DisplayConfigImpl.h @@ -9,7 +9,7 @@ #pragma once #include "ramses/renderer/Types.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "impl/DataTypesImpl.h" namespace CLI @@ -30,10 +30,12 @@ namespace ramses::internal [[nodiscard]] EDeviceType getDeviceType() const; [[nodiscard]] bool setWindowType(EWindowType windowType); [[nodiscard]] EWindowType getWindowType() const; + [[nodiscard]] bool setWindowTitle(std::string_view windowTitle); + [[nodiscard]] std::string_view getWindowTitle() const; [[nodiscard]] bool setWindowRectangle(int32_t x, int32_t y, uint32_t width, uint32_t height); [[nodiscard]] bool getWindowRectangle(int32_t& x, int32_t& y, uint32_t& width, uint32_t& height) const; [[nodiscard]] bool setFullscreen(bool fullscreen); - [[nodiscard]] bool isFullscreen() const; + [[nodiscard]] bool isFullscreen() const; [[nodiscard]] bool setMultiSampling(uint32_t numSamples); [[nodiscard]] bool getMultiSamplingSamples(uint32_t& numSamples) const; [[nodiscard]] bool setWaylandIviSurfaceID(waylandIviSurfaceId_t waylandIviSurfaceID); @@ -84,9 +86,9 @@ namespace ramses::internal void validate(ValidationReportImpl& report) const; //impl methods - [[nodiscard]] const ramses::internal::DisplayConfig& getInternalDisplayConfig() const; + [[nodiscard]] const ramses::internal::DisplayConfigData& getInternalDisplayConfig() const; private: - ramses::internal::DisplayConfig m_internalConfig; + ramses::internal::DisplayConfigData m_internalConfig; }; } diff --git a/src/renderer/impl/RamsesRendererImpl.cpp b/src/renderer/impl/RamsesRendererImpl.cpp index 3a2757343..e5971c8b4 100644 --- a/src/renderer/impl/RamsesRendererImpl.cpp +++ b/src/renderer/impl/RamsesRendererImpl.cpp @@ -40,7 +40,7 @@ namespace ramses::internal , m_binaryShaderCache(config.impl().getBinaryShaderCache() ? new BinaryShaderCacheProxy(*(config.impl().getBinaryShaderCache())) : nullptr) , m_rendererFrameworkLogic(framework.getScenegraphComponent(), m_rendererCommandBuffer, framework.getFrameworkLock()) , m_threadWatchdog(framework.getThreadWatchdogConfig(), ERamsesThreadIdentifier::Renderer) - , m_displayDispatcher{ std::make_unique(std::make_unique(), config.impl().getInternalRendererConfig(), m_rendererFrameworkLogic, m_threadWatchdog) } + , m_displayDispatcher{ std::make_unique(std::make_unique(), config.impl().getInternalRendererConfig(), m_rendererFrameworkLogic, m_threadWatchdog, m_framework.getFeatureLevel()) } , m_systemCompositorEnabled(config.impl().getInternalRendererConfig().getSystemCompositorControlEnabled()) , m_loopMode(ELoopMode::UpdateAndRender) , m_rendererLoopThreadType(ERendererLoopThreadType_Undefined) diff --git a/src/renderer/impl/RendererConfigImpl.cpp b/src/renderer/impl/RendererConfigImpl.cpp index c64f2f684..32fa0292d 100644 --- a/src/renderer/impl/RendererConfigImpl.cpp +++ b/src/renderer/impl/RendererConfigImpl.cpp @@ -57,7 +57,7 @@ namespace ramses::internal return m_internalConfig.getRenderThreadLoopTimingReportingPeriod(); } - const ramses::internal::RendererConfig& RendererConfigImpl::getInternalRendererConfig() const + const ramses::internal::RendererConfigData& RendererConfigImpl::getInternalRendererConfig() const { return m_internalConfig; } diff --git a/src/renderer/impl/RendererConfigImpl.h b/src/renderer/impl/RendererConfigImpl.h index 7d5dff636..e066ce304 100644 --- a/src/renderer/impl/RendererConfigImpl.h +++ b/src/renderer/impl/RendererConfigImpl.h @@ -8,7 +8,7 @@ #pragma once -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" namespace ramses { @@ -36,10 +36,10 @@ namespace ramses::internal [[nodiscard]] std::chrono::milliseconds getRenderThreadLoopTimingReportingPeriod() const; //impl methods - [[nodiscard]] const ramses::internal::RendererConfig& getInternalRendererConfig() const; + [[nodiscard]] const ramses::internal::RendererConfigData& getInternalRendererConfig() const; private: - ramses::internal::RendererConfig m_internalConfig; + ramses::internal::RendererConfigData m_internalConfig; IBinaryShaderCache* m_binaryShaderCache{nullptr}; }; } diff --git a/src/renderer/impl/RendererFactory.cpp b/src/renderer/impl/RendererFactory.cpp index 7b1c7aab2..b6612e814 100644 --- a/src/renderer/impl/RendererFactory.cpp +++ b/src/renderer/impl/RendererFactory.cpp @@ -12,8 +12,14 @@ namespace ramses::internal { - RendererUniquePtr RendererFactory::createRenderer(RamsesFrameworkImpl& framework, const ramses::RendererConfig& config) const + RendererUniquePtr RendererFactory::createRenderer(RamsesFrameworkImpl& framework, const ramses::RendererConfig& config, std::string_view loggingInstanceName) const { + // Some platforms manage thread local storage in shared library as copy which is initialized with program default + // instead of what was set in runtime, this is a workaround to make sure logging prefix stored as thread local + // will be set to current framework value if renderer loaded from shared library. + // Renderer instantiation will already generate logs so this should be done before, ideally as first code executed from renderer library. + RamsesLoggerPrefixes::SetRamsesLoggerPrefixes(loggingInstanceName, "main"); + auto impl = std::make_unique(framework, config); RendererUniquePtr renderer{ new RamsesRenderer{ std::move(impl) }, [](RamsesRenderer* renderer_) { delete renderer_; } }; diff --git a/src/renderer/impl/RendererFactory.h b/src/renderer/impl/RendererFactory.h index 69e4374d3..654b7bb80 100644 --- a/src/renderer/impl/RendererFactory.h +++ b/src/renderer/impl/RendererFactory.h @@ -18,7 +18,10 @@ namespace ramses::internal public: static bool RegisterRendererFactory(); - RendererUniquePtr createRenderer(RamsesFrameworkImpl& framework, const ramses::RendererConfig& config) const override; + RendererUniquePtr createRenderer( + RamsesFrameworkImpl& framework, + const ramses::RendererConfig& config, + std::string_view loggingInstanceName) const override; }; } diff --git a/src/renderer/internal/Platform/Android/Platform_Android_EGL.cpp b/src/renderer/internal/Platform/Android/Platform_Android_EGL.cpp index 2a2b27307..ecc7c9e05 100644 --- a/src/renderer/internal/Platform/Android/Platform_Android_EGL.cpp +++ b/src/renderer/internal/Platform/Android/Platform_Android_EGL.cpp @@ -7,18 +7,18 @@ // ------------------------------------------------------------------------- #include "internal/Platform/Android/Platform_Android_EGL.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/Platform/EGL/Context_EGL.h" #include "internal/RendererLib/PlatformBase/EmbeddedCompositor_Dummy.h" namespace ramses::internal { - Platform_Android_EGL::Platform_Android_EGL(const RendererConfig& rendererConfig) + Platform_Android_EGL::Platform_Android_EGL(const RendererConfigData& rendererConfig) : Platform_EGL(rendererConfig) { } - bool Platform_Android_EGL::createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) + bool Platform_Android_EGL::createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) { auto window = std::make_unique(displayConfig, windowEventHandler, 0u); if (window->init()) diff --git a/src/renderer/internal/Platform/Android/Platform_Android_EGL.h b/src/renderer/internal/Platform/Android/Platform_Android_EGL.h index 12ef30733..8c3c15a1f 100644 --- a/src/renderer/internal/Platform/Android/Platform_Android_EGL.h +++ b/src/renderer/internal/Platform/Android/Platform_Android_EGL.h @@ -18,10 +18,10 @@ namespace ramses::internal class Platform_Android_EGL : public Platform_EGL { public: - explicit Platform_Android_EGL(const RendererConfig& rendererConfig); + explicit Platform_Android_EGL(const RendererConfigData& rendererConfig); protected: - virtual bool createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) override; + virtual bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) override; virtual uint32_t getSwapInterval() const override; }; } diff --git a/src/renderer/internal/Platform/Android/Window_Android.cpp b/src/renderer/internal/Platform/Android/Window_Android.cpp index 3d0bc9aab..ae8e4fc93 100644 --- a/src/renderer/internal/Platform/Android/Window_Android.cpp +++ b/src/renderer/internal/Platform/Android/Window_Android.cpp @@ -6,7 +6,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Core/Utils/Warnings.h" @@ -15,7 +15,7 @@ namespace ramses::internal { - Window_Android::Window_Android(const DisplayConfig& displayConfig, IWindowEventHandler &windowEventHandler, uint32_t id) + Window_Android::Window_Android(const DisplayConfigData& displayConfig, IWindowEventHandler &windowEventHandler, uint32_t id) : Window_Base(displayConfig, windowEventHandler, id) , m_nativeWindow(static_cast(displayConfig.getAndroidNativeWindow().getValue())) { diff --git a/src/renderer/internal/Platform/Android/Window_Android.h b/src/renderer/internal/Platform/Android/Window_Android.h index f28e72997..b2c4a8194 100644 --- a/src/renderer/internal/Platform/Android/Window_Android.h +++ b/src/renderer/internal/Platform/Android/Window_Android.h @@ -18,7 +18,7 @@ namespace ramses::internal class Window_Android : public Window_Base { public: - Window_Android(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); + Window_Android(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); ~Window_Android() override; bool init() override; diff --git a/src/renderer/internal/Platform/CMakeLists.txt b/src/renderer/internal/Platform/CMakeLists.txt index 056c23611..675b92d11 100644 --- a/src/renderer/internal/Platform/CMakeLists.txt +++ b/src/renderer/internal/Platform/CMakeLists.txt @@ -9,7 +9,9 @@ if(ramses-sdk_ENABLE_WINDOW_TYPE_WINDOWS) list(APPEND PLATFORM_SOURCES Windows/*.h Windows/*.cpp) - message("+ Windows Window") + list(APPEND VULKAN_SOURCES Vulkan/Windows/*.h + Vulkan/Windows/*.cpp) + message(STATUS "+ Window Type: Windows Window") endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_IVI OR ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL OR ramses-sdk_ENABLE_WINDOW_TYPE_X11 OR ramses-sdk_ENABLE_WINDOW_TYPE_ANDROID OR ramses-sdk_ENABLE_WINDOW_TYPE_IOS) @@ -21,15 +23,17 @@ endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_X11) list(APPEND PLATFORM_SOURCES X11/*.h X11/*.cpp) + list(APPEND VULKAN_SOURCES Vulkan/X11/*.h + Vulkan/X11/*.cpp) list(APPEND PLATFORM_LIBS X11) - message("+ X11 Window") + message(STATUS "+ Window Type: X11 Window") endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_ANDROID) list(APPEND PLATFORM_SOURCES Android/*.h Android/*.cpp) list(APPEND PLATFORM_LIBS AndroidSDK) - message("+ Android Window") + message(STATUS "+ Window Type: Android Window") endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_IOS) @@ -37,7 +41,7 @@ if(ramses-sdk_ENABLE_WINDOW_TYPE_IOS) iOS/*.cpp iOS/*.mm) list(APPEND PLATFORM_LIBS QuartzCore) - message("+ iOS Window") + message(STATUS "+ Window Type: iOS Window") endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_IVI OR ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL) @@ -65,7 +69,7 @@ endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL) list(APPEND PLATFORM_SOURCES Wayland/WlShell/*.h Wayland/WlShell/*.cpp) - message("+ Wayland wl_shell Window") + message(STATUS "+ Window Type: Wayland wl_shell Window") endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_IVI) @@ -75,7 +79,15 @@ if(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_IVI) Wayland/IVI/SystemCompositorController/*.cpp) list(APPEND PLATFORM_LIBS libdrm wayland-ivi-extension) - message("+ Wayland ivi Window") + message(STATUS "+ Window Type: Wayland ivi Window") +endif() + +if(ramses-sdk_ENABLE_DEVICE_TYPE_VULKAN) + list(APPEND PLATFORM_SOURCES Vulkan/*.h + Vulkan/*.cpp + ${VULKAN_SOURCES}) + list(APPEND PLATFORM_LIBS ramses-vulkan) + message(STATUS "+ Device Type: Vulkan") endif() createModule( @@ -88,7 +100,7 @@ createModule( OpenGL/*.cpp ${PLATFORM_SOURCES} DEPENDENCIES ramses-renderer-internal - OpenGL + ramses-glad ${PLATFORM_LIBS} # TODO move this to the OpenGL target where it belongs diff --git a/src/renderer/internal/Platform/EGL/Context_EGL.cpp b/src/renderer/internal/Platform/EGL/Context_EGL.cpp index a560934f9..b6b98c0e6 100644 --- a/src/renderer/internal/Platform/EGL/Context_EGL.cpp +++ b/src/renderer/internal/Platform/EGL/Context_EGL.cpp @@ -218,9 +218,9 @@ namespace ramses::internal return true; } - void* Context_EGL::getProcAddress(const char* name) const + IContext::GlProcLoadFunc Context_EGL::getGlProcLoadFunc() const { - return reinterpret_cast(eglGetProcAddress(name)); + return eglGetProcAddress; } EGLDisplay Context_EGL::getEglDisplay() const diff --git a/src/renderer/internal/Platform/EGL/Context_EGL.h b/src/renderer/internal/Platform/EGL/Context_EGL.h index 0cd41c8b5..f2ed234e4 100644 --- a/src/renderer/internal/Platform/EGL/Context_EGL.h +++ b/src/renderer/internal/Platform/EGL/Context_EGL.h @@ -53,7 +53,7 @@ namespace ramses::internal bool enable() override; bool disable() override; - void* getProcAddress(const char* name) const override; + [[nodiscard]] GlProcLoadFunc getGlProcLoadFunc() const override; [[nodiscard]] EGLDisplay getEglDisplay() const; diff --git a/src/renderer/internal/Platform/EGL/Platform_EGL.h b/src/renderer/internal/Platform/EGL/Platform_EGL.h index 773fdf4ed..bde3c1041 100644 --- a/src/renderer/internal/Platform/EGL/Platform_EGL.h +++ b/src/renderer/internal/Platform/EGL/Platform_EGL.h @@ -9,8 +9,8 @@ #pragma once #include "internal/RendererLib/PlatformBase/Platform_Base.h" -#include "internal/RendererLib/RendererConfig.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/RendererConfigData.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Platform/EGL/Context_EGL.h" #include "internal/Platform/OpenGL/Device_GL.h" #include "internal/Core/Utils/LogMacros.h" @@ -28,12 +28,12 @@ namespace ramses::internal class Platform_EGL : public Platform_Base { protected: - explicit Platform_EGL(const RendererConfig& rendererConfig) + explicit Platform_EGL(const RendererConfigData& rendererConfig) : Platform_Base(rendererConfig) { } - bool createContext(const DisplayConfig& displayConfig) override + bool createContext(const DisplayConfigData& displayConfig) override { if (m_glesMinorVersion.has_value()) { @@ -62,7 +62,7 @@ namespace ramses::internal { assert(m_context); assert(m_glesMinorVersion.has_value()); - m_contextUploading = createContextInternal(DisplayConfig{}, static_cast(m_context.get()), *m_glesMinorVersion); + m_contextUploading = createContextInternal(DisplayConfigData{}, static_cast(m_context.get()), *m_glesMinorVersion); return m_contextUploading != nullptr; } @@ -80,7 +80,7 @@ namespace ramses::internal return m_deviceUploading != nullptr; } - bool createDeviceExtension(const DisplayConfig& displayConfig) override + bool createDeviceExtension(const DisplayConfigData& displayConfig) override { const auto platformRenderNode = displayConfig.getPlatformRenderNode(); if (platformRenderNode.empty()) @@ -102,7 +102,7 @@ namespace ramses::internal [[nodiscard]] virtual uint32_t getSwapInterval() const = 0; private: - std::unique_ptr createContextInternal(const DisplayConfig& displayConfig, Context_EGL* sharedContext, EGLint minorVersion) + std::unique_ptr createContextInternal(const DisplayConfigData& displayConfig, Context_EGL* sharedContext, EGLint minorVersion) { if(displayConfig.getDeviceType() != EDeviceType::GLES_3_0) { diff --git a/src/renderer/internal/Platform/OpenGL/DebugOutput.cpp b/src/renderer/internal/Platform/OpenGL/DebugOutput.cpp index c5cab772b..607f179e3 100644 --- a/src/renderer/internal/Platform/OpenGL/DebugOutput.cpp +++ b/src/renderer/internal/Platform/OpenGL/DebugOutput.cpp @@ -8,34 +8,13 @@ #include "internal/Platform/OpenGL/DebugOutput.h" -#include "internal/RendererLib/PlatformInterface/IContext.h" - #include "internal/Core/Utils/LogMacros.h" #include #include namespace ramses::internal { -#if defined(__linux__) || defined(__APPLE__) - #define GL_DEBUG_TYPE_ERROR GL_DEBUG_TYPE_ERROR_KHR - #define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR - #define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR - #define GL_DEBUG_TYPE_PORTABILITY GL_DEBUG_TYPE_PORTABILITY_KHR - #define GL_DEBUG_TYPE_PERFORMANCE GL_DEBUG_TYPE_PERFORMANCE_KHR - #define GL_DEBUG_TYPE_MARKER GL_DEBUG_TYPE_MARKER_KHR - #define GL_DEBUG_TYPE_PUSH_GROUP GL_DEBUG_TYPE_PUSH_GROUP_KHR - #define GL_DEBUG_TYPE_POP_GROUP GL_DEBUG_TYPE_POP_GROUP_KHR - #define GL_DEBUG_TYPE_OTHER GL_DEBUG_TYPE_OTHER_KHR - - #define GL_DEBUG_SOURCE_API GL_DEBUG_SOURCE_API_KHR - #define GL_DEBUG_TYPE_PERFORMANCE GL_DEBUG_TYPE_PERFORMANCE_KHR - #define GL_DEBUG_OUTPUT GL_DEBUG_OUTPUT_KHR - #define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR - - #define APIENTRY GL_APIENTRY -#endif - - static void APIENTRY debugCallback(GLenum /*source*/, + static void GLAPIENTRY debugCallback(GLenum /*source*/, GLenum type, GLuint /*id*/, GLenum /*severity*/, @@ -66,29 +45,12 @@ namespace ramses::internal } } - bool DebugOutput::loadExtensionFunctionPointer(const IContext& context) + void DebugOutput::enable() { -#if defined(__linux__) || defined(__APPLE__) - glDebugMessageCallback = - reinterpret_cast(context.getProcAddress("glDebugMessageCallbackKHR")); - glDebugMessageControl = - reinterpret_cast(context.getProcAddress("glDebugMessageControlKHR")); -#else - glDebugMessageCallback = - reinterpret_cast(context.getProcAddress("glDebugMessageCallback")); - glDebugMessageControl = - reinterpret_cast(context.getProcAddress("glDebugMessageControl")); -#endif - - return isAvailable(); - } - - bool DebugOutput::enable(const IContext& context) - { - if (!loadExtensionFunctionPointer(context)) + if (!IsAvailable()) { - LOG_INFO(CONTEXT_RENDERER, "Could not found OpenGL debug output extension"); - return false; + LOG_INFO(CONTEXT_RENDERER, "Could not find OpenGL debug output extension"); + return; } glEnable(GL_DEBUG_OUTPUT); @@ -103,11 +65,9 @@ namespace ramses::internal // ... except redundant state change warnings on nvidia cards const std::array messageIds{{8}}; glDebugMessageControl(GL_DEBUG_SOURCE_API, GL_DEBUG_TYPE_PERFORMANCE, GL_DONT_CARE, static_cast(messageIds.size()), messageIds.data(), GL_FALSE); - - return true; } - bool DebugOutput::isAvailable() const + bool DebugOutput::IsAvailable() { return (glDebugMessageCallback != nullptr && glDebugMessageControl != nullptr); } diff --git a/src/renderer/internal/Platform/OpenGL/DebugOutput.h b/src/renderer/internal/Platform/OpenGL/DebugOutput.h index 9ae7b091d..6048910aa 100644 --- a/src/renderer/internal/Platform/OpenGL/DebugOutput.h +++ b/src/renderer/internal/Platform/OpenGL/DebugOutput.h @@ -19,20 +19,11 @@ namespace ramses::internal class DebugOutput final { public: - bool enable(const IContext& context); - bool isAvailable() const; - bool checkAndResetError() const; + void enable(); + [[nodiscard]] static bool IsAvailable(); + [[nodiscard]] bool checkAndResetError() const; private: - bool loadExtensionFunctionPointer(const IContext& context); - -#if defined(__linux__) || defined(__APPLE__) - PFNGLDEBUGMESSAGECALLBACKKHRPROC glDebugMessageCallback = nullptr; - PFNGLDEBUGMESSAGECONTROLKHRPROC glDebugMessageControl = nullptr; -#else - PFNGLDEBUGMESSAGECALLBACKPROC glDebugMessageCallback = 0; - PFNGLDEBUGMESSAGECONTROLPROC glDebugMessageControl = 0; -#endif mutable bool m_errorOccured = false; }; } diff --git a/src/renderer/internal/Platform/OpenGL/Device_GL.cpp b/src/renderer/internal/Platform/OpenGL/Device_GL.cpp index 59dd7602f..0bc45944d 100644 --- a/src/renderer/internal/Platform/OpenGL/Device_GL.cpp +++ b/src/renderer/internal/Platform/OpenGL/Device_GL.cpp @@ -34,6 +34,8 @@ namespace ramses::internal { + std::mutex Device_GL::s_gladMutex; + static constexpr GLboolean ToGLboolean(bool b) { return b ? GL_TRUE : GL_FALSE; @@ -69,8 +71,16 @@ namespace ramses::internal , m_deviceExtension(deviceExtension) , m_emptyExternalTextureResource(m_resourceMapper.registerResource(std::make_unique(0u, 0u))) { + { + std::lock_guard lock{s_gladMutex}; + // initialize GLES3.2 API + extensions + if (GLAD_GL_ES_VERSION_2_0 == 0) + { + gladLoadGLES2(m_context.getGlProcLoadFunc()); + } + } #if defined _DEBUG - m_debugOutput.enable(context); + m_debugOutput.enable(); #endif m_limits.addTextureFormat(EPixelStorageFormat::Depth16); @@ -110,8 +120,6 @@ namespace ramses::internal bool Device_GL::init() { - LOAD_ALL_API_PROCS(m_context); - const char* tmp = nullptr; tmp = reinterpret_cast(glGetString(GL_VENDOR)); @@ -126,7 +134,7 @@ namespace ramses::internal tmp = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); LOG_INFO(CONTEXT_RENDERER, " GLSL version {}", tmp); - loadOpenGLExtensions(); + PrintOpenGLExtensions(); queryDeviceDependentFeatures(); m_framebufferRenderTarget = m_resourceMapper.registerResource(std::make_unique(0)); @@ -1108,6 +1116,38 @@ namespace ramses::internal return texID; } + DeviceResourceHandle Device_GL::allocateUniformBuffer(uint32_t totalSizeInBytes) + { + GLHandle glAddress = InvalidGLHandle; + glGenBuffers(1, &glAddress); + assert(glAddress != InvalidGLHandle); + + return m_resourceMapper.registerResource(std::make_unique(glAddress, totalSizeInBytes)); + } + + void Device_GL::uploadUniformBufferData(DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) + { + const auto& uniformBuffer = m_resourceMapper.getResource(handle); + assert(dataSize <= uniformBuffer.getTotalSizeInBytes()); + + glBindBuffer(GL_UNIFORM_BUFFER, uniformBuffer.getGPUAddress()); + glBufferData(GL_UNIFORM_BUFFER, dataSize, data, GL_DYNAMIC_DRAW); + } + + void Device_GL::activateUniformBuffer(DeviceResourceHandle handle, DataFieldHandle field) + { + const auto& uniformBufferResource = m_resourceMapper.getResourceAs(handle); + const auto uniformBufferBinding = m_activeShader->getUniformBufferBinding(field); + glBindBufferBase(GL_UNIFORM_BUFFER, uniformBufferBinding.getValue(), uniformBufferResource.getGPUAddress()); + } + + void Device_GL::deleteUniformBuffer(DeviceResourceHandle handle) + { + const GLHandle resourceAddress = m_resourceMapper.getResource(handle).getGPUAddress(); + glDeleteBuffers(1, &resourceAddress); + m_resourceMapper.deleteResource(handle); + } + DeviceResourceHandle Device_GL::allocateVertexBuffer(uint32_t totalSizeInBytes) { GLHandle glAddress = InvalidGLHandle; @@ -1378,31 +1418,22 @@ namespace ramses::internal GL_NEAREST); } - bool Device_GL::isApiExtensionAvailable(const std::string& extensionName) const - { - return m_apiExtensions.contains(extensionName); - } - void Device_GL::loadOpenGLExtensions() + void Device_GL::PrintOpenGLExtensions() { GLint numExtensions = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &numExtensions); if (numExtensions > 0) { - m_apiExtensions.reserve(numExtensions); - size_t sumExtensionStringLength = 0; - for (auto i = 0; i < numExtensions; i++) - { - const auto tmp = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); - sumExtensionStringLength += std::strlen(tmp); - m_apiExtensions.put(tmp); - } - LOG_INFO_F(CONTEXT_RENDERER, ([&](StringOutputStream& sos) { sos << "Device_GL::init: OpenGL extensions: "; - sos.reserve(sos.capacity() + sumExtensionStringLength + numExtensions); - for (const auto& extensionString : m_apiExtensions) - sos << extensionString << " "; + constexpr std::size_t estimatedLength = 30; + sos.reserve(sos.size() + numExtensions * estimatedLength); + for (auto i = 0; i < numExtensions; i++) + { + const auto tmp = reinterpret_cast(glGetStringi(GL_EXTENSIONS, i)); + sos << tmp << " "; + } })); } else @@ -1471,7 +1502,7 @@ namespace ramses::internal })); } - if (isApiExtensionAvailable("GL_EXT_texture_filter_anisotropic")) + if (GLAD_GL_EXT_texture_filter_anisotropic != 0) { GLint anisotropy = 0; glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &anisotropy); @@ -1488,7 +1519,7 @@ namespace ramses::internal // There are 2 extensions for external texture, one for using external texture sampler in ES2 shader and one for using it in ES3+ shader. // Either of them can be used on client side and therefore we require both. - const bool externalTexturesSupported = isApiExtensionAvailable("GL_OES_EGL_image_external") && isApiExtensionAvailable("GL_OES_EGL_image_external_essl3"); + const bool externalTexturesSupported = (GLAD_GL_OES_EGL_image_external != 0) && (GLAD_GL_OES_EGL_image_external_essl3 != 0); LOG_INFO(CONTEXT_RENDERER, fmt::format("Device_GL::queryDeviceDependentFeatures: External textures support = {}", externalTexturesSupported)); m_limits.setExternalTextureExtensionSupported(externalTexturesSupported); @@ -1506,7 +1537,7 @@ namespace ramses::internal bool Device_GL::isDeviceStatusHealthy() const { - if (m_debugOutput.isAvailable()) + if (DebugOutput::IsAvailable()) { return !m_debugOutput.checkAndResetError(); } diff --git a/src/renderer/internal/Platform/OpenGL/Device_GL.h b/src/renderer/internal/Platform/OpenGL/Device_GL.h index 9588ed83e..ce0bd3a01 100644 --- a/src/renderer/internal/Platform/OpenGL/Device_GL.h +++ b/src/renderer/internal/Platform/OpenGL/Device_GL.h @@ -16,6 +16,7 @@ #include #include +#include namespace ramses::internal { @@ -67,6 +68,11 @@ namespace ramses::internal void readPixels(uint8_t* buffer, uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + DeviceResourceHandle allocateUniformBuffer (uint32_t totalSizeInBytes) override; + void uploadUniformBufferData (DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) override; + void activateUniformBuffer (DeviceResourceHandle handle, DataFieldHandle field) override; + void deleteUniformBuffer (DeviceResourceHandle handle) override; + DeviceResourceHandle allocateVertexBuffer (uint32_t totalSizeInBytes) override; void uploadVertexBufferData(DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) override; void deleteVertexBuffer (DeviceResourceHandle handle) override; @@ -151,7 +157,6 @@ namespace ramses::internal uint32_t m_activeIndexArraySizeBytes = 0u; DebugOutput m_debugOutput; - HashSet m_apiExtensions; std::vector m_supportedBinaryProgramFormats; IDeviceExtension* m_deviceExtension = nullptr; const DeviceResourceHandle m_emptyExternalTextureResource; @@ -159,6 +164,8 @@ namespace ramses::internal std::unordered_map m_textureSamplerObjectsCache; + static std::mutex s_gladMutex; + bool allBuffersHaveTheSameSize(const DeviceHandleVector& renderBuffers) const; static void BindRenderBufferToRenderTarget(const RenderBufferGPUResource& renderBufferGpuResource, size_t colorBufferSlot); static void BindReadWriteRenderBufferToRenderTarget(EPixelStorageFormat bufferFormat, size_t colorBufferSlot, GLHandle bufferGLHandle, bool multiSample); @@ -178,8 +185,7 @@ namespace ramses::internal static void AllocateTextureStorage(const GLTextureInfo& texInfo, uint32_t mipLevels, uint32_t sampleCount = 0); static void UploadTextureMipMapData(uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t z, uint32_t width, uint32_t height, uint32_t depth, const GLTextureInfo& texInfo, const std::byte *pData, uint32_t dataSize, uint32_t stride); - bool isApiExtensionAvailable(const std::string& extensionName) const; void queryDeviceDependentFeatures(); - void loadOpenGLExtensions(); + static void PrintOpenGLExtensions(); }; } diff --git a/src/renderer/internal/Platform/OpenGL/Device_GL_platform.h b/src/renderer/internal/Platform/OpenGL/Device_GL_platform.h index 20d8b28fd..8fe166848 100644 --- a/src/renderer/internal/Platform/OpenGL/Device_GL_platform.h +++ b/src/renderer/internal/Platform/OpenGL/Device_GL_platform.h @@ -8,49 +8,14 @@ #pragma once -#ifdef _WIN32 -#include "internal/PlatformAbstraction/MinimalWindowsH.h" -#include -#include +/* + * glad/gles2.h provides the OpenGLES 3.2 API including the extensions that RAMSES uses. + * The file is generated - see inline documentation for configuration parameters. + * gladLoadGLES2() needs to be called after context creation to initialize the function pointers + * + * This is also expected to work if the context is a GL context >= 3.2 (instead of a GLES context) + * However, this won't make the context GLES3 compatible by itself. It still requires an extension + * to support GLES3 shaders (e.g. GL_ARB_ES3_2_compatibility) + */ +#include -#elif defined(__linux__) -#include -#include -// deprecated -#include -// should always include that file as well, since gl3ext doesn't define ANY extensions, see http://www.khronos.org/registry/gles/#headers -#include - -#elif defined(__APPLE__) -#include -#include -// should always include that file as well, since gl3ext doesn't define ANY extensions, see http://www.khronos.org/registry/gles/#headers -#include - -#endif - -#if defined(__linux__) - #include "internal/Platform/OpenGL/Device_GL_platform_linux.h" -#endif // LINUX - -#if defined(__APPLE__) - #include "internal/Platform/OpenGL/Device_GL_platform_apple.h" -#endif // APPLE - -#ifdef _WIN32 - #include "internal/Platform/OpenGL/Device_GL_platform_windows.h" -#endif // WIN32 - -namespace ramses::internal -{ - // OpenGL API - DECLARE_ALL_API_PROCS -} - -// TODO Violin fix OpenGL headers properly... -// This is so that the external texture sampler (not texture) can be used in scene also on platforms not actually supporting external texture -// (e.g. desktop windows when creating assets to be used with external texture). -#if !defined(GL_OES_EGL_image_external) -#define GL_OES_EGL_image_external -#define GL_TEXTURE_EXTERNAL_OES 0x8D65 -#endif diff --git a/src/renderer/internal/Platform/OpenGL/Device_GL_platform_apple.h b/src/renderer/internal/Platform/OpenGL/Device_GL_platform_apple.h deleted file mode 100644 index 42fa8a10a..000000000 --- a/src/renderer/internal/Platform/OpenGL/Device_GL_platform_apple.h +++ /dev/null @@ -1,17 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (C) 2023 BMW AG -// ------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// ------------------------------------------------------------------------- - -#pragma once - -#define LOAD_ALL_API_PROCS(CONTEXT) (void)CONTEXT // does nothing for apple - api procs are already defined in the GL library -#define DECLARE_ALL_API_PROCS // does nothing for apple - api procs are already declared in the GL headers -#define DEFINE_ALL_API_PROCS // does nothing for apple - api procs are already defined in the GL headers - -// extension procs, however, need to be declared and defined -#define DECLARE_EXTENSION_PROC(TYPE, NAME) extern TYPE NAME; -#define DEFINE_EXTENSION_PROC(TYPE, NAME) TYPE NAME = 0; diff --git a/src/renderer/internal/Platform/OpenGL/Device_GL_platform_linux.h b/src/renderer/internal/Platform/OpenGL/Device_GL_platform_linux.h deleted file mode 100644 index e12eb0026..000000000 --- a/src/renderer/internal/Platform/OpenGL/Device_GL_platform_linux.h +++ /dev/null @@ -1,17 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (C) 2014 BMW Car IT GmbH -// ------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// ------------------------------------------------------------------------- - -#pragma once - -#define LOAD_ALL_API_PROCS(CONTEXT) (void)CONTEXT // does nothing for linux - api procs are already defined in the GL library -#define DECLARE_ALL_API_PROCS // does nothing for linux - api procs are already declared in the GL headers -#define DEFINE_ALL_API_PROCS // does nothing for linux - api procs are already defined in the GL headers - -// extension procs, however, need to be declared and defined -#define DECLARE_EXTENSION_PROC(TYPE, NAME) extern TYPE NAME; -#define DEFINE_EXTENSION_PROC(TYPE, NAME) TYPE NAME = 0; diff --git a/src/renderer/internal/Platform/OpenGL/Device_GL_platform_windows.h b/src/renderer/internal/Platform/OpenGL/Device_GL_platform_windows.h deleted file mode 100644 index 9cd7f6eaf..000000000 --- a/src/renderer/internal/Platform/OpenGL/Device_GL_platform_windows.h +++ /dev/null @@ -1,380 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (C) 2014 BMW Car IT GmbH -// ------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// ------------------------------------------------------------------------- - -#pragma once - -// Required workaround for WGL, because it defines all extension procs -// and leaves no possibility to check if an extension is available in the headers -// or not -#define GL_NV_draw_buffers 1 -#define PFNGLDRAWBUFFERSNVPROC PFNGLDRAWBUFFERSPROC - -#define LOAD_API_PROC(CONTEXT, TYPE, NAME) \ - NAME##Native = reinterpret_cast(CONTEXT.getProcAddress(#NAME)); \ - if(0 == NAME##Native) \ - { \ - LOG_DEBUG(CONTEXT_RENDERER, "---> loading address of proc "#NAME" failed!"); \ - } - -#define DECLARE_API_PROC(TYPE, NAME) extern TYPE NAME##Native; -#define DECLARE_EXTENSION_PROC(TYPE, NAME) extern TYPE NAME; - -#define DEFINE_API_PROC(TYPE, NAME) TYPE NAME##Native = 0; -#define DEFINE_EXTENSION_PROC(TYPE, NAME) TYPE NAME = 0; - -#define glGetStringi(...) glGetStringiNative(__VA_ARGS__) -#define glCreateProgram(...) glCreateProgramNative(__VA_ARGS__) -#define glDeleteProgram(...) glDeleteProgramNative(__VA_ARGS__) -#define glUseProgram(...) glUseProgramNative(__VA_ARGS__) -#define glProgramBinary(...) glProgramBinaryNative(__VA_ARGS__) -#define glGetProgramBinary(...) glGetProgramBinaryNative(__VA_ARGS__) -#define glAttachShader(...) glAttachShaderNative(__VA_ARGS__) -#define glDetachShader(...) glDetachShaderNative(__VA_ARGS__) -#define glLinkProgram(...) glLinkProgramNative(__VA_ARGS__) -#define glGetProgramiv(...) glGetProgramivNative(__VA_ARGS__) -#define glGetShaderInfoLog(...) glGetShaderInfoLogNative(__VA_ARGS__) -#define glGetUniformLocation(...) glGetUniformLocationNative(__VA_ARGS__) -#define glUniform1i(...) glUniform1iNative(__VA_ARGS__) -#define glUniform1iv(...) glUniform1ivNative(__VA_ARGS__) -#define glUniform2iv(...) glUniform2ivNative(__VA_ARGS__) -#define glUniform3iv(...) glUniform3ivNative(__VA_ARGS__) -#define glUniform4iv(...) glUniform4ivNative(__VA_ARGS__) -#define glUniform1f(...) glUniform1fNative(__VA_ARGS__) -#define glUniform1fv(...) glUniform1fvNative(__VA_ARGS__) -#define glUniform2fv(...) glUniform2fvNative(__VA_ARGS__) -#define glUniform3fv(...) glUniform3fvNative(__VA_ARGS__) -#define glUniform4fv(...) glUniform4fvNative(__VA_ARGS__) -#define glUniformMatrix2fv(...) glUniformMatrix2fvNative(__VA_ARGS__) -#define glUniformMatrix3fv(...) glUniformMatrix3fvNative(__VA_ARGS__) -#define glUniformMatrix4fv(...) glUniformMatrix4fvNative(__VA_ARGS__) -#define glGetAttribLocation(...) glGetAttribLocationNative(__VA_ARGS__) -#define glVertexAttrib1f(...) glVertexAttrib1fNative(__VA_ARGS__) -#define glVertexAttrib1fv(...) glVertexAttrib1fvNative(__VA_ARGS__) -#define glVertexAttrib2fv(...) glVertexAttrib2fvNative(__VA_ARGS__) -#define glVertexAttrib3fv(...) glVertexAttrib3fvNative(__VA_ARGS__) -#define glVertexAttrib4fv(...) glVertexAttrib4fvNative(__VA_ARGS__) -#define glEnableVertexAttribArray(...) glEnableVertexAttribArrayNative(__VA_ARGS__) -#define glBindAttribLocation(...) glBindAttribLocationNative(__VA_ARGS__) -#define glGetActiveUniform(...) glGetActiveUniformNative(__VA_ARGS__) -#define glGetActiveAttrib(...) glGetActiveAttribNative(__VA_ARGS__) -#define glGetProgramInfoLog(...) glGetProgramInfoLogNative(__VA_ARGS__) -#define glCreateShader(...) glCreateShaderNative(__VA_ARGS__) -#define glDeleteShader(...) glDeleteShaderNative(__VA_ARGS__) -#define glShaderSource(...) glShaderSourceNative(__VA_ARGS__) -#define glCompileShader(...) glCompileShaderNative(__VA_ARGS__) -#define glGetShaderiv(...) glGetShaderivNative(__VA_ARGS__) -#define glGenVertexArrays(...) glGenVertexArraysNative(__VA_ARGS__) -#define glBindVertexArray(...) glBindVertexArrayNative(__VA_ARGS__) -#define glDeleteVertexArrays(...) glDeleteVertexArraysNative(__VA_ARGS__) -#define glGenBuffers(...) glGenBuffersNative(__VA_ARGS__) -#define glBindBuffer(...) glBindBufferNative(__VA_ARGS__) -#define glBufferData(...) glBufferDataNative(__VA_ARGS__) -#define glVertexAttribPointer(...) glVertexAttribPointerNative(__VA_ARGS__) -#define glGenFramebuffers(...) glGenFramebuffersNative(__VA_ARGS__) -#define glBindFramebuffer(...) glBindFramebufferNative(__VA_ARGS__) -#define glBlitFramebuffer(...) glBlitFramebufferNative(__VA_ARGS__) -#define glDeleteFramebuffers(...) glDeleteFramebuffersNative(__VA_ARGS__) -#define glFramebufferTexture2D(...) glFramebufferTexture2DNative(__VA_ARGS__) -#define glDeleteBuffers(...) glDeleteBuffersNative(__VA_ARGS__) -#define glCheckFramebufferStatus(...) glCheckFramebufferStatusNative(__VA_ARGS__) -#define glGenRenderbuffers(...) glGenRenderbuffersNative(__VA_ARGS__) -#define glBindRenderbuffer(...) glBindRenderbufferNative(__VA_ARGS__) -#define glRenderbufferStorage(...) glRenderbufferStorageNative(__VA_ARGS__) -#define glRenderbufferStorageMultisample(...) glRenderbufferStorageMultisampleNative(__VA_ARGS__) -#define glFramebufferRenderbuffer(...) glFramebufferRenderbufferNative(__VA_ARGS__) -#define glDrawBuffers(...) glDrawBuffersNative(__VA_ARGS__) -#define glDeleteRenderbuffers(...) glDeleteRenderbuffersNative(__VA_ARGS__) -#define glActiveTexture(...) glActiveTextureNative(__VA_ARGS__) -#define glBlendEquation(...) glBlendEquationNative(__VA_ARGS__) -#define glBlendEquationSeparate(...) glBlendEquationSeparateNative(__VA_ARGS__) -#define glBlendFuncSeparate(...) glBlendFuncSeparateNative(__VA_ARGS__) -#define glBlendColor(...) glBlendColorNative(__VA_ARGS__) -#define glGenerateMipmap(...) glGenerateMipmapNative(__VA_ARGS__) -#define glCompressedTexImage2D(...) glCompressedTexImage2DNative(__VA_ARGS__) -#define glGenSamplers(...) glGenSamplersNative(__VA_ARGS__) -#define glDeleteSamplers(...) glDeleteSamplersNative(__VA_ARGS__) -#define glBindSampler(...) glBindSamplerNative(__VA_ARGS__) -#define glSamplerParameteri(...) glSamplerParameteriNative(__VA_ARGS__) -#define glShaderBinary(...) glShaderBinaryNative(__VA_ARGS__) -#define glClearDepthf(...) glClearDepthfNative(__VA_ARGS__) -#define glDrawElementsInstanced(...) glDrawElementsInstancedNative(__VA_ARGS__) -#define glDrawArraysInstanced(...) glDrawArraysInstancedNative(__VA_ARGS__) -#define glVertexAttribDivisor(...) glVertexAttribDivisorNative(__VA_ARGS__) -#define glTexStorage2D(...) glTexStorage2DNative(__VA_ARGS__) -#define glTexStorage2DMultisample(...) glTexStorage2DMultisampleNative(__VA_ARGS__) -#define glTexStorage3D(...) glTexStorage3DNative(__VA_ARGS__) -#define glTexSubImage3D(...) glTexSubImage3DNative(__VA_ARGS__) -#define glCompressedTexSubImage2D(...) glCompressedTexSubImage2DNative(__VA_ARGS__) -#define glCompressedTexSubImage3D(...) glCompressedTexSubImage3DNative(__VA_ARGS__) -#define glGetInternalformativ(...) glGetInternalformativNative(__VA_ARGS__) -#define glInvalidateFramebuffer(...) glInvalidateFramebufferNative(__VA_ARGS__) - -#define DECLARE_ALL_API_PROCS \ -DECLARE_API_PROC(PFNGLGETSTRINGIPROC, glGetStringi); \ -DECLARE_API_PROC(PFNGLCREATEPROGRAMPROC, glCreateProgram); \ -DECLARE_API_PROC(PFNGLDELETEPROGRAMPROC, glDeleteProgram); \ -DECLARE_API_PROC(PFNGLUSEPROGRAMPROC, glUseProgram); \ -DECLARE_API_PROC(PFNGLPROGRAMBINARYPROC, glProgramBinary); \ -DECLARE_API_PROC(PFNGLGETPROGRAMBINARYPROC, glGetProgramBinary); \ -DECLARE_API_PROC(PFNGLATTACHSHADERPROC, glAttachShader); \ -DECLARE_API_PROC(PFNGLDETACHSHADERPROC, glDetachShader); \ -DECLARE_API_PROC(PFNGLLINKPROGRAMPROC, glLinkProgram); \ -DECLARE_API_PROC(PFNGLGETPROGRAMIVPROC, glGetProgramiv); \ -DECLARE_API_PROC(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); \ -DECLARE_API_PROC(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation); \ -DECLARE_API_PROC(PFNGLUNIFORM1IPROC, glUniform1i); \ -DECLARE_API_PROC(PFNGLUNIFORM1IVPROC, glUniform1iv); \ -DECLARE_API_PROC(PFNGLUNIFORM2IVPROC, glUniform2iv); \ -DECLARE_API_PROC(PFNGLUNIFORM3IVPROC, glUniform3iv); \ -DECLARE_API_PROC(PFNGLUNIFORM4IVPROC, glUniform4iv); \ -DECLARE_API_PROC(PFNGLUNIFORM1FPROC, glUniform1f); \ -DECLARE_API_PROC(PFNGLUNIFORM1FVPROC, glUniform1fv); \ -DECLARE_API_PROC(PFNGLUNIFORM2FVPROC, glUniform2fv); \ -DECLARE_API_PROC(PFNGLUNIFORM3FVPROC, glUniform3fv); \ -DECLARE_API_PROC(PFNGLUNIFORM4FVPROC, glUniform4fv); \ -DECLARE_API_PROC(PFNGLUNIFORMMATRIX2FVPROC, glUniformMatrix2fv); \ -DECLARE_API_PROC(PFNGLUNIFORMMATRIX3FVPROC, glUniformMatrix3fv); \ -DECLARE_API_PROC(PFNGLUNIFORMMATRIX4FVPROC, glUniformMatrix4fv); \ -DECLARE_API_PROC(PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation); \ -DECLARE_API_PROC(PFNGLVERTEXATTRIB1FPROC, glVertexAttrib1f); \ -DECLARE_API_PROC(PFNGLVERTEXATTRIB1FVPROC, glVertexAttrib1fv); \ -DECLARE_API_PROC(PFNGLVERTEXATTRIB2FVPROC, glVertexAttrib2fv); \ -DECLARE_API_PROC(PFNGLVERTEXATTRIB3FVPROC, glVertexAttrib3fv); \ -DECLARE_API_PROC(PFNGLVERTEXATTRIB4FVPROC, glVertexAttrib4fv); \ -DECLARE_API_PROC(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); \ -DECLARE_API_PROC(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation); \ -DECLARE_API_PROC(PFNGLGETACTIVEUNIFORMPROC, glGetActiveUniform); \ -DECLARE_API_PROC(PFNGLGETACTIVEATTRIBPROC, glGetActiveAttrib); \ -DECLARE_API_PROC(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog); \ -DECLARE_API_PROC(PFNGLCREATESHADERPROC, glCreateShader); \ -DECLARE_API_PROC(PFNGLDELETESHADERPROC, glDeleteShader); \ -DECLARE_API_PROC(PFNGLSHADERSOURCEPROC, glShaderSource); \ -DECLARE_API_PROC(PFNGLCOMPILESHADERPROC, glCompileShader); \ -DECLARE_API_PROC(PFNGLGETSHADERIVPROC, glGetShaderiv); \ -DECLARE_API_PROC(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); \ -DECLARE_API_PROC(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); \ -DECLARE_API_PROC(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays); \ -DECLARE_API_PROC(PFNGLGENBUFFERSPROC, glGenBuffers); \ -DECLARE_API_PROC(PFNGLBINDBUFFERPROC, glBindBuffer); \ -DECLARE_API_PROC(PFNGLBUFFERDATAPROC, glBufferData); \ -DECLARE_API_PROC(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); \ -DECLARE_API_PROC(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers); \ -DECLARE_API_PROC(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer); \ -DECLARE_API_PROC(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer); \ -DECLARE_API_PROC(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers); \ -DECLARE_API_PROC(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D); \ -DECLARE_API_PROC(PFNGLDELETEBUFFERSPROC, glDeleteBuffers); \ -DECLARE_API_PROC(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus); \ -DECLARE_API_PROC(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers); \ -DECLARE_API_PROC(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer); \ -DECLARE_API_PROC(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage); \ -DECLARE_API_PROC(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample); \ -DECLARE_API_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer); \ -DECLARE_API_PROC(PFNGLDRAWBUFFERSPROC, glDrawBuffers); \ -DECLARE_API_PROC(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers); \ -DECLARE_API_PROC(PFNGLACTIVETEXTUREPROC, glActiveTexture); \ -DECLARE_API_PROC(PFNGLBLENDEQUATIONPROC, glBlendEquation); \ -DECLARE_API_PROC(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate); \ -DECLARE_API_PROC(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate); \ -DECLARE_API_PROC(PFNGLBLENDCOLORPROC, glBlendColor); \ -DECLARE_API_PROC(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap); \ -DECLARE_API_PROC(PFNGLCLEARDEPTHFPROC, glClearDepthf); \ -DECLARE_API_PROC(PFNGLCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2D); \ -DECLARE_API_PROC(PFNGLGENSAMPLERSPROC, glGenSamplers); \ -DECLARE_API_PROC(PFNGLDELETESAMPLERSPROC, glDeleteSamplers); \ -DECLARE_API_PROC(PFNGLBINDSAMPLERPROC, glBindSampler); \ -DECLARE_API_PROC(PFNGLSAMPLERPARAMETERIPROC, glSamplerParameteri); \ -DECLARE_API_PROC(PFNGLSHADERBINARYPROC, glShaderBinary); \ -DECLARE_API_PROC(PFNGLDRAWELEMENTSINSTANCEDPROC, glDrawElementsInstanced); \ -DECLARE_API_PROC(PFNGLDRAWARRAYSINSTANCEDPROC, glDrawArraysInstanced); \ -DECLARE_API_PROC(PFNGLVERTEXATTRIBDIVISORPROC, glVertexAttribDivisor); \ -DECLARE_API_PROC(PFNGLTEXSTORAGE2DPROC, glTexStorage2D); \ -DECLARE_API_PROC(PFNGLTEXSTORAGE2DMULTISAMPLEPROC, glTexStorage2DMultisample); \ -DECLARE_API_PROC(PFNGLTEXSTORAGE3DPROC, glTexStorage3D); \ -DECLARE_API_PROC(PFNGLTEXSUBIMAGE3DPROC, glTexSubImage3D); \ -DECLARE_API_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D); \ -DECLARE_API_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D); \ -DECLARE_API_PROC(PFNGLGETINTERNALFORMATIVPROC, glGetInternalformativ); \ -DECLARE_API_PROC(PFNGLINVALIDATEFRAMEBUFFERPROC, glInvalidateFramebuffer); \ - -#define LOAD_ALL_API_PROCS(CONTEXT) \ -LOAD_API_PROC(CONTEXT, PFNGLGETSTRINGIPROC, glGetStringi); \ -LOAD_API_PROC(CONTEXT, PFNGLCREATEPROGRAMPROC, glCreateProgram); \ -LOAD_API_PROC(CONTEXT, PFNGLDELETEPROGRAMPROC, glDeleteProgram); \ -LOAD_API_PROC(CONTEXT, PFNGLUSEPROGRAMPROC, glUseProgram); \ -LOAD_API_PROC(CONTEXT, PFNGLPROGRAMBINARYPROC, glProgramBinary); \ -LOAD_API_PROC(CONTEXT, PFNGLGETPROGRAMBINARYPROC, glGetProgramBinary); \ -LOAD_API_PROC(CONTEXT, PFNGLATTACHSHADERPROC, glAttachShader); \ -LOAD_API_PROC(CONTEXT, PFNGLDETACHSHADERPROC, glDetachShader); \ -LOAD_API_PROC(CONTEXT, PFNGLLINKPROGRAMPROC, glLinkProgram); \ -LOAD_API_PROC(CONTEXT, PFNGLGETPROGRAMIVPROC, glGetProgramiv); \ -LOAD_API_PROC(CONTEXT, PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); \ -LOAD_API_PROC(CONTEXT, PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM1IPROC, glUniform1i); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM1IVPROC, glUniform1iv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM2IVPROC, glUniform2iv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM3IVPROC, glUniform3iv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM4IVPROC, glUniform4iv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM1FPROC, glUniform1f); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM1FVPROC, glUniform1fv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM2FVPROC, glUniform2fv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM3FVPROC, glUniform3fv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORM4FVPROC, glUniform4fv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORMMATRIX2FVPROC, glUniformMatrix2fv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORMMATRIX3FVPROC, glUniformMatrix3fv); \ -LOAD_API_PROC(CONTEXT, PFNGLUNIFORMMATRIX4FVPROC, glUniformMatrix4fv); \ -LOAD_API_PROC(CONTEXT, PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation); \ -LOAD_API_PROC(CONTEXT, PFNGLVERTEXATTRIB1FPROC, glVertexAttrib1f); \ -LOAD_API_PROC(CONTEXT, PFNGLVERTEXATTRIB1FVPROC, glVertexAttrib1fv); \ -LOAD_API_PROC(CONTEXT, PFNGLVERTEXATTRIB2FVPROC, glVertexAttrib2fv); \ -LOAD_API_PROC(CONTEXT, PFNGLVERTEXATTRIB3FVPROC, glVertexAttrib3fv); \ -LOAD_API_PROC(CONTEXT, PFNGLVERTEXATTRIB4FVPROC, glVertexAttrib4fv); \ -LOAD_API_PROC(CONTEXT, PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); \ -LOAD_API_PROC(CONTEXT, PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation); \ -LOAD_API_PROC(CONTEXT, PFNGLGETACTIVEUNIFORMPROC, glGetActiveUniform); \ -LOAD_API_PROC(CONTEXT, PFNGLGETACTIVEATTRIBPROC, glGetActiveAttrib); \ -LOAD_API_PROC(CONTEXT, PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog); \ -LOAD_API_PROC(CONTEXT, PFNGLCREATESHADERPROC, glCreateShader); \ -LOAD_API_PROC(CONTEXT, PFNGLDELETESHADERPROC, glDeleteShader); \ -LOAD_API_PROC(CONTEXT, PFNGLSHADERSOURCEPROC, glShaderSource); \ -LOAD_API_PROC(CONTEXT, PFNGLCOMPILESHADERPROC, glCompileShader); \ -LOAD_API_PROC(CONTEXT, PFNGLGETSHADERIVPROC, glGetShaderiv); \ -LOAD_API_PROC(CONTEXT, PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); \ -LOAD_API_PROC(CONTEXT, PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); \ -LOAD_API_PROC(CONTEXT, PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays); \ -LOAD_API_PROC(CONTEXT, PFNGLGENBUFFERSPROC, glGenBuffers); \ -LOAD_API_PROC(CONTEXT, PFNGLBINDBUFFERPROC, glBindBuffer); \ -LOAD_API_PROC(CONTEXT, PFNGLBUFFERDATAPROC, glBufferData); \ -LOAD_API_PROC(CONTEXT, PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); \ -LOAD_API_PROC(CONTEXT, PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers); \ -LOAD_API_PROC(CONTEXT, PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer); \ -LOAD_API_PROC(CONTEXT, PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer); \ -LOAD_API_PROC(CONTEXT, PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers); \ -LOAD_API_PROC(CONTEXT, PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D); \ -LOAD_API_PROC(CONTEXT, PFNGLDELETEBUFFERSPROC, glDeleteBuffers); \ -LOAD_API_PROC(CONTEXT, PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus); \ -LOAD_API_PROC(CONTEXT, PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers); \ -LOAD_API_PROC(CONTEXT, PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer); \ -LOAD_API_PROC(CONTEXT, PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage); \ -LOAD_API_PROC(CONTEXT, PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample);\ -LOAD_API_PROC(CONTEXT, PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer); \ -LOAD_API_PROC(CONTEXT, PFNGLDRAWBUFFERSPROC, glDrawBuffers); \ -LOAD_API_PROC(CONTEXT, PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers); \ -LOAD_API_PROC(CONTEXT, PFNGLACTIVETEXTUREPROC, glActiveTexture); \ -LOAD_API_PROC(CONTEXT, PFNGLBLENDEQUATIONPROC, glBlendEquation); \ -LOAD_API_PROC(CONTEXT, PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate); \ -LOAD_API_PROC(CONTEXT, PFNGLBLENDCOLORPROC, glBlendColor); \ -LOAD_API_PROC(CONTEXT, PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate); \ -LOAD_API_PROC(CONTEXT, PFNGLGENERATEMIPMAPPROC, glGenerateMipmap); \ -LOAD_API_PROC(CONTEXT, PFNGLCLEARDEPTHFPROC, glClearDepthf); \ -LOAD_API_PROC(CONTEXT, PFNGLCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2D); \ -LOAD_API_PROC(CONTEXT, PFNGLGENSAMPLERSPROC, glGenSamplers); \ -LOAD_API_PROC(CONTEXT, PFNGLDELETESAMPLERSPROC, glDeleteSamplers); \ -LOAD_API_PROC(CONTEXT, PFNGLBINDSAMPLERPROC, glBindSampler); \ -LOAD_API_PROC(CONTEXT, PFNGLSAMPLERPARAMETERIPROC, glSamplerParameteri); \ -LOAD_API_PROC(CONTEXT, PFNGLSHADERBINARYPROC, glShaderBinary); \ -LOAD_API_PROC(CONTEXT, PFNGLDRAWELEMENTSINSTANCEDPROC, glDrawElementsInstanced); \ -LOAD_API_PROC(CONTEXT, PFNGLDRAWARRAYSINSTANCEDPROC, glDrawArraysInstanced); \ -LOAD_API_PROC(CONTEXT, PFNGLVERTEXATTRIBDIVISORPROC, glVertexAttribDivisor); \ -LOAD_API_PROC(CONTEXT, PFNGLTEXSTORAGE2DPROC, glTexStorage2D); \ -LOAD_API_PROC(CONTEXT, PFNGLTEXSTORAGE2DMULTISAMPLEPROC, glTexStorage2DMultisample); \ -LOAD_API_PROC(CONTEXT, PFNGLTEXSTORAGE3DPROC, glTexStorage3D); \ -LOAD_API_PROC(CONTEXT, PFNGLTEXSUBIMAGE3DPROC, glTexSubImage3D); \ -LOAD_API_PROC(CONTEXT, PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D); \ -LOAD_API_PROC(CONTEXT, PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D); \ -LOAD_API_PROC(CONTEXT, PFNGLGETINTERNALFORMATIVPROC, glGetInternalformativ); \ -LOAD_API_PROC(CONTEXT, PFNGLINVALIDATEFRAMEBUFFERPROC, glInvalidateFramebuffer); \ - -//In WGL (Windows), all api procs are static and need explicit definition in a source file -#define DEFINE_ALL_API_PROCS \ -DEFINE_API_PROC(PFNGLGETSTRINGIPROC, glGetStringi); \ -DEFINE_API_PROC(PFNGLCREATEPROGRAMPROC, glCreateProgram); \ -DEFINE_API_PROC(PFNGLDELETEPROGRAMPROC, glDeleteProgram); \ -DEFINE_API_PROC(PFNGLUSEPROGRAMPROC, glUseProgram); \ -DEFINE_API_PROC(PFNGLPROGRAMBINARYPROC, glProgramBinary); \ -DEFINE_API_PROC(PFNGLGETPROGRAMBINARYPROC, glGetProgramBinary); \ -DEFINE_API_PROC(PFNGLATTACHSHADERPROC, glAttachShader); \ -DEFINE_API_PROC(PFNGLDETACHSHADERPROC, glDetachShader); \ -DEFINE_API_PROC(PFNGLLINKPROGRAMPROC, glLinkProgram); \ -DEFINE_API_PROC(PFNGLGETPROGRAMIVPROC, glGetProgramiv); \ -DEFINE_API_PROC(PFNGLGETSHADERINFOLOGPROC, glGetShaderInfoLog); \ -DEFINE_API_PROC(PFNGLGETUNIFORMLOCATIONPROC, glGetUniformLocation); \ -DEFINE_API_PROC(PFNGLUNIFORM1IPROC, glUniform1i); \ -DEFINE_API_PROC(PFNGLUNIFORM1IVPROC, glUniform1iv); \ -DEFINE_API_PROC(PFNGLUNIFORM2IVPROC, glUniform2iv); \ -DEFINE_API_PROC(PFNGLUNIFORM3IVPROC, glUniform3iv); \ -DEFINE_API_PROC(PFNGLUNIFORM4IVPROC, glUniform4iv); \ -DEFINE_API_PROC(PFNGLUNIFORM1FPROC, glUniform1f); \ -DEFINE_API_PROC(PFNGLUNIFORM1FVPROC, glUniform1fv); \ -DEFINE_API_PROC(PFNGLUNIFORM2FVPROC, glUniform2fv); \ -DEFINE_API_PROC(PFNGLUNIFORM3FVPROC, glUniform3fv); \ -DEFINE_API_PROC(PFNGLUNIFORM4FVPROC, glUniform4fv); \ -DEFINE_API_PROC(PFNGLUNIFORMMATRIX2FVPROC, glUniformMatrix2fv); \ -DEFINE_API_PROC(PFNGLUNIFORMMATRIX3FVPROC, glUniformMatrix3fv); \ -DEFINE_API_PROC(PFNGLUNIFORMMATRIX4FVPROC, glUniformMatrix4fv); \ -DEFINE_API_PROC(PFNGLGETATTRIBLOCATIONPROC, glGetAttribLocation); \ -DEFINE_API_PROC(PFNGLVERTEXATTRIB1FPROC, glVertexAttrib1f); \ -DEFINE_API_PROC(PFNGLVERTEXATTRIB1FVPROC, glVertexAttrib1fv); \ -DEFINE_API_PROC(PFNGLVERTEXATTRIB2FVPROC, glVertexAttrib2fv); \ -DEFINE_API_PROC(PFNGLVERTEXATTRIB3FVPROC, glVertexAttrib3fv); \ -DEFINE_API_PROC(PFNGLVERTEXATTRIB4FVPROC, glVertexAttrib4fv); \ -DEFINE_API_PROC(PFNGLENABLEVERTEXATTRIBARRAYPROC, glEnableVertexAttribArray); \ -DEFINE_API_PROC(PFNGLBINDATTRIBLOCATIONPROC, glBindAttribLocation); \ -DEFINE_API_PROC(PFNGLGETACTIVEUNIFORMPROC, glGetActiveUniform); \ -DEFINE_API_PROC(PFNGLGETACTIVEATTRIBPROC, glGetActiveAttrib); \ -DEFINE_API_PROC(PFNGLGETPROGRAMINFOLOGPROC, glGetProgramInfoLog); \ -DEFINE_API_PROC(PFNGLCREATESHADERPROC, glCreateShader); \ -DEFINE_API_PROC(PFNGLDELETESHADERPROC, glDeleteShader); \ -DEFINE_API_PROC(PFNGLSHADERSOURCEPROC, glShaderSource); \ -DEFINE_API_PROC(PFNGLCOMPILESHADERPROC, glCompileShader); \ -DEFINE_API_PROC(PFNGLGETSHADERIVPROC, glGetShaderiv); \ -DEFINE_API_PROC(PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays); \ -DEFINE_API_PROC(PFNGLBINDVERTEXARRAYPROC, glBindVertexArray); \ -DEFINE_API_PROC(PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays); \ -DEFINE_API_PROC(PFNGLGENBUFFERSPROC, glGenBuffers); \ -DEFINE_API_PROC(PFNGLBINDBUFFERPROC, glBindBuffer); \ -DEFINE_API_PROC(PFNGLBUFFERDATAPROC, glBufferData); \ -DEFINE_API_PROC(PFNGLVERTEXATTRIBPOINTERPROC, glVertexAttribPointer); \ -DEFINE_API_PROC(PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers); \ -DEFINE_API_PROC(PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer); \ -DEFINE_API_PROC(PFNGLBLITFRAMEBUFFERPROC, glBlitFramebuffer); \ -DEFINE_API_PROC(PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers); \ -DEFINE_API_PROC(PFNGLFRAMEBUFFERTEXTURE2DPROC, glFramebufferTexture2D); \ -DEFINE_API_PROC(PFNGLDELETEBUFFERSPROC, glDeleteBuffers); \ -DEFINE_API_PROC(PFNGLCHECKFRAMEBUFFERSTATUSPROC, glCheckFramebufferStatus); \ -DEFINE_API_PROC(PFNGLGENRENDERBUFFERSPROC, glGenRenderbuffers); \ -DEFINE_API_PROC(PFNGLBINDRENDERBUFFERPROC, glBindRenderbuffer); \ -DEFINE_API_PROC(PFNGLRENDERBUFFERSTORAGEPROC, glRenderbufferStorage); \ -DEFINE_API_PROC(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample); \ -DEFINE_API_PROC(PFNGLFRAMEBUFFERRENDERBUFFERPROC, glFramebufferRenderbuffer); \ -DEFINE_API_PROC(PFNGLDRAWBUFFERSPROC, glDrawBuffers); \ -DEFINE_API_PROC(PFNGLDELETERENDERBUFFERSPROC, glDeleteRenderbuffers); \ -DEFINE_API_PROC(PFNGLACTIVETEXTUREPROC, glActiveTexture); \ -DEFINE_API_PROC(PFNGLBLENDEQUATIONPROC, glBlendEquation); \ -DEFINE_API_PROC(PFNGLBLENDEQUATIONSEPARATEPROC, glBlendEquationSeparate); \ -DEFINE_API_PROC(PFNGLBLENDCOLORPROC, glBlendColor); \ -DEFINE_API_PROC(PFNGLBLENDFUNCSEPARATEPROC, glBlendFuncSeparate); \ -DEFINE_API_PROC(PFNGLGENERATEMIPMAPPROC, glGenerateMipmap); \ -DEFINE_API_PROC(PFNGLCLEARDEPTHFPROC, glClearDepthf); \ -DEFINE_API_PROC(PFNGLCOMPRESSEDTEXIMAGE2DPROC, glCompressedTexImage2D); \ -DEFINE_API_PROC(PFNGLGENSAMPLERSPROC, glGenSamplers); \ -DEFINE_API_PROC(PFNGLDELETESAMPLERSPROC, glDeleteSamplers); \ -DEFINE_API_PROC(PFNGLBINDSAMPLERPROC, glBindSampler); \ -DEFINE_API_PROC(PFNGLSAMPLERPARAMETERIPROC, glSamplerParameteri); \ -DEFINE_API_PROC(PFNGLSHADERBINARYPROC, glShaderBinary); \ -DEFINE_API_PROC(PFNGLDRAWELEMENTSINSTANCEDPROC, glDrawElementsInstanced); \ -DEFINE_API_PROC(PFNGLDRAWARRAYSINSTANCEDPROC, glDrawArraysInstanced); \ -DEFINE_API_PROC(PFNGLVERTEXATTRIBDIVISORPROC, glVertexAttribDivisor); \ -DEFINE_API_PROC(PFNGLTEXSTORAGE2DPROC, glTexStorage2D); \ -DEFINE_API_PROC(PFNGLTEXSTORAGE2DMULTISAMPLEPROC, glTexStorage2DMultisample); \ -DEFINE_API_PROC(PFNGLTEXSTORAGE3DPROC, glTexStorage3D); \ -DEFINE_API_PROC(PFNGLTEXSUBIMAGE3DPROC, glTexSubImage3D); \ -DEFINE_API_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC, glCompressedTexSubImage2D); \ -DEFINE_API_PROC(PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC, glCompressedTexSubImage3D); \ -DEFINE_API_PROC(PFNGLGETINTERNALFORMATIVPROC, glGetInternalformativ); \ -DEFINE_API_PROC(PFNGLINVALIDATEFRAMEBUFFERPROC, glInvalidateFramebuffer); \ diff --git a/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.cpp b/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.cpp index 23f34cd54..d8af78dfc 100644 --- a/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.cpp +++ b/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.cpp @@ -17,7 +17,7 @@ namespace ramses::internal : ShaderGPUResource(shaderProgramInfo.shaderProgramHandle) , m_shaderProgramInfo(std::move(shaderProgramInfo)) { - preloadVariableLocations(effect); + init(effect); } ShaderGPUResource_GL::~ShaderGPUResource_GL() @@ -62,37 +62,51 @@ namespace ramses::internal return slot; } - void ShaderGPUResource_GL::preloadVariableLocations(const EffectResource& effect) + UniformBufferBinding ShaderGPUResource_GL::getUniformBufferBinding(DataFieldHandle field) const + { + assert(field.asMemoryHandle() < m_uniformBufferBindings.size()); + const auto uboBinding = m_uniformBufferBindings[field.asMemoryHandle()]; + assert(uboBinding.isValid()); + + return uboBinding; + } + + void ShaderGPUResource_GL::init(const EffectResource& effect) { const EffectInputInformationVector& uniformInputs = effect.getUniformInputs(); const EffectInputInformationVector& attributeInputs = effect.getAttributeInputs(); const size_t vertexInputCount = attributeInputs.size(); - const size_t globalInputCount = uniformInputs.size(); + const size_t uniformInputWithoutUBOFieldsCount = std::count_if(uniformInputs.begin(), uniformInputs.end(), [](const auto& i) { return !EffectInputInformation::IsUniformBufferField(i); }); - m_attributeLocationMap.resize(vertexInputCount); - m_uniformLocationMap.resize(globalInputCount); + m_attributeLocationMap.reserve(vertexInputCount); + m_uniformLocationMap.reserve(uniformInputWithoutUBOFieldsCount); + m_uniformBufferBindings.reserve(uniformInputWithoutUBOFieldsCount); for (uint32_t i = 0u; i < vertexInputCount; ++i) - { - const GLInputLocation location = loadAttributeLocation(effect, attributeInputs[i]); - m_attributeLocationMap[i] = location; - } + m_attributeLocationMap.push_back(loadAttributeLocation(effect, attributeInputs[i])); TextureSlot slotCounter = 0; // texture unit 0 - for (uint32_t i = 0; i < globalInputCount; ++i) + for (const auto& input : uniformInputs) { - const EffectInputInformation& input = uniformInputs[i]; if (IsTextureSamplerType(input.dataType)) { TextureSlotInfo bufferSlot; bufferSlot.slot = slotCounter++; bufferSlot.textureType = GetTextureTypeFromDataType(input.dataType); - m_bufferSlots.put(DataFieldHandle(i), bufferSlot); + m_bufferSlots.put(input.dataFieldHandle, bufferSlot); } - const GLInputLocation location = loadUniformLocation(effect, input); - m_uniformLocationMap[i] = location; + if (EffectInputInformation::IsUniformBuffer(input)) + { + m_uniformLocationMap.emplace_back(GLInputLocation{}); + m_uniformBufferBindings.push_back(input.uniformBufferBinding); + } + else if (!EffectInputInformation::IsUniformBufferField(input)) + { + m_uniformLocationMap.push_back(loadUniformLocation(effect, input)); + m_uniformBufferBindings.emplace_back(UniformBufferBinding{}); + } } } diff --git a/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.h b/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.h index 122f3e076..1eaae5a54 100644 --- a/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.h +++ b/src/renderer/internal/Platform/OpenGL/ShaderGPUResource_GL.h @@ -36,11 +36,12 @@ namespace ramses::internal [[nodiscard]] GLInputLocation getUniformLocation(DataFieldHandle field) const; [[nodiscard]] GLInputLocation getAttributeLocation(DataFieldHandle field) const; [[nodiscard]] TextureSlotInfo getTextureSlot(DataFieldHandle field) const; + [[nodiscard]] UniformBufferBinding getUniformBufferBinding(DataFieldHandle field) const; - bool getBinaryInfo(std::vector& binaryShader, BinaryShaderFormatID& binaryShaderFormat) const; + [[nodiscard]] bool getBinaryInfo(std::vector& binaryShader, BinaryShaderFormatID& binaryShaderFormat) const; private: - void preloadVariableLocations(const EffectResource& effect); + void init(const EffectResource& effect); [[nodiscard]] GLInputLocation loadUniformLocation(const EffectResource& effect, const EffectInputInformation& input) const; [[nodiscard]] GLInputLocation loadAttributeLocation(const EffectResource& effect, const EffectInputInformation& input) const; @@ -52,5 +53,6 @@ namespace ramses::internal BufferSlotMap m_bufferSlots; InputLocationMap m_uniformLocationMap; InputLocationMap m_attributeLocationMap; + std::vector m_uniformBufferBindings; }; } diff --git a/src/renderer/internal/Platform/OpenGL/ShaderUploader_GL.cpp b/src/renderer/internal/Platform/OpenGL/ShaderUploader_GL.cpp index 8e0e8a2f0..4d3900728 100644 --- a/src/renderer/internal/Platform/OpenGL/ShaderUploader_GL.cpp +++ b/src/renderer/internal/Platform/OpenGL/ShaderUploader_GL.cpp @@ -41,7 +41,7 @@ namespace ramses::internal bool ShaderUploader_GL::UploadShaderProgramFromSource(const EffectResource& effect, ShaderProgramInfo& programShaderInfoOut, std::string& debugErrorLog) { - LOG_DEBUG(CONTEXT_RENDERER, "ShaderUploader_GL::UploadShaderProgramFromSource: compiling shaders for effect {}", effect.getName()); + LOG_INFO(CONTEXT_RENDERER, "ShaderUploader_GL::UploadShaderProgramFromSource: compiling shaders for effect {}", effect.getName()); const GLHandle vertexShaderHandle = CompileShaderStage(effect.getVertexShader(), GL_VERTEX_SHADER, debugErrorLog); diff --git a/src/renderer/internal/Platform/OpenGL/TypesConversion_GL.cpp b/src/renderer/internal/Platform/OpenGL/TypesConversion_GL.cpp index 46898999c..b2f729ea8 100644 --- a/src/renderer/internal/Platform/OpenGL/TypesConversion_GL.cpp +++ b/src/renderer/internal/Platform/OpenGL/TypesConversion_GL.cpp @@ -574,8 +574,6 @@ namespace ramses::internal case GL_COMPRESSED_RGBA8_ETC2_EAC: return EPixelStorageFormat::ETC2RGBA; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: // not supported by ramses default: return EPixelStorageFormat::Invalid; diff --git a/src/renderer/internal/Platform/PlatformFactory.cpp b/src/renderer/internal/Platform/PlatformFactory.cpp index 8b53c163d..0d8b02154 100644 --- a/src/renderer/internal/Platform/PlatformFactory.cpp +++ b/src/renderer/internal/Platform/PlatformFactory.cpp @@ -7,8 +7,8 @@ // ------------------------------------------------------------------------- #include "internal/Platform/PlatformFactory.h" -#include "internal/RendererLib/DisplayConfig.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/Core/Utils/LogMacros.h" #if defined(ramses_sdk_ENABLE_WINDOW_TYPE_WINDOWS) @@ -33,9 +33,28 @@ #include "internal/Platform/iOS/Platform_iOS_EGL.h" #endif +#if defined(ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) +#include "internal/Platform/Vulkan/Platform_Vulkan.h" +#endif + namespace ramses::internal { - std::unique_ptr PlatformFactory::createPlatform(const RendererConfig& rendererConfig, const DisplayConfig& displayConfig) + std::unique_ptr PlatformFactory::createPlatform(const RendererConfigData& rendererConfig, const DisplayConfigData& displayConfig) + { + switch (displayConfig.getDeviceType()) + { + case EDeviceType::GLES_3_0: + case EDeviceType::GL_4_2: + case EDeviceType::GL_4_5: + return CreatePlatformWithOpenGL(rendererConfig, displayConfig); + case EDeviceType::Vulkan: + return CreatePlatformWithVulkan(rendererConfig, displayConfig); + } + + return {}; + } + + std::unique_ptr PlatformFactory::CreatePlatformWithOpenGL(const RendererConfigData& rendererConfig, const DisplayConfigData& displayConfig) { switch(displayConfig.getWindowType()) { @@ -53,6 +72,7 @@ namespace ramses::internal #if defined(ramses_sdk_ENABLE_WINDOW_TYPE_ANDROID) return std::make_unique(rendererConfig); #endif + break; case ramses::EWindowType::iOS: #if defined(ramses_sdk_ENABLE_WINDOW_TYPE_IOS) return std::make_unique(rendererConfig); @@ -70,7 +90,43 @@ namespace ramses::internal break; } - LOG_ERROR(CONTEXT_RENDERER, "PlatformFactory::createPlatform: trying to create an unsupported platform"); + LOG_ERROR(CONTEXT_RENDERER, "PlatformFactory::createPlatformWithOpenGL: trying to create an unsupported platform"); + return {}; + } + + std::unique_ptr PlatformFactory::CreatePlatformWithVulkan([[maybe_unused]] const RendererConfigData& rendererConfig, [[maybe_unused]] const DisplayConfigData& displayConfig) + { + switch (displayConfig.getWindowType()) + { + case EWindowType::Windows: +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_WINDOWS) && defined(ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) + return std::make_unique>(rendererConfig); +#endif + break; + case EWindowType::X11: +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_X11) && defined(ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) + return std::make_unique>(rendererConfig); +#endif + break; + case EWindowType::Android: +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_ANDROID) && defined(ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) +#endif + break; + case ramses::EWindowType::iOS: +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_IOS) && defined(ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) +#endif + break; + case EWindowType::Wayland_IVI: +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_WAYLAND_IVI) && defined(ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) +#endif + break; + case EWindowType::Wayland_Shell: +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL) && defined(ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) +#endif + break; + } + + LOG_ERROR(CONTEXT_RENDERER, "PlatformFactory::createPlatformWithVulkan: trying to create an unsupported platform"); return {}; } } diff --git a/src/renderer/internal/Platform/PlatformFactory.h b/src/renderer/internal/Platform/PlatformFactory.h index 85d8ac910..ff7bbaf5c 100644 --- a/src/renderer/internal/Platform/PlatformFactory.h +++ b/src/renderer/internal/Platform/PlatformFactory.h @@ -15,6 +15,10 @@ namespace ramses::internal class PlatformFactory : public IPlatformFactory { public: - std::unique_ptr createPlatform(const RendererConfig& rendererConfig, const DisplayConfig& displayConfig) override; + std::unique_ptr createPlatform(const RendererConfigData& rendererConfig, const DisplayConfigData& displayConfig) override; + + private: + static std::unique_ptr CreatePlatformWithOpenGL(const RendererConfigData& rendererConfig, const DisplayConfigData& displayConfig); + static std::unique_ptr CreatePlatformWithVulkan(const RendererConfigData& rendererConfig, const DisplayConfigData& displayConfig); }; } diff --git a/src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.cpp b/src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.cpp new file mode 100644 index 000000000..66d2bff44 --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.cpp @@ -0,0 +1,238 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "Context_Vulkan_Base.h" + +namespace ramses::internal +{ + Context_Vulkan_Base::Context_Vulkan_Base(std::string platformSurfaceTypeExtensionName, bool enableDebuggingInfo, std::vector platformValidationLayers) + : m_enableDebuggingInfo(enableDebuggingInfo) + , m_requiredValidationLayers(std::move(platformValidationLayers)) + { + assert(!platformSurfaceTypeExtensionName.empty()); + m_requiredExtensionsNames.emplace_back(VK_KHR_SURFACE_EXTENSION_NAME); + m_requiredExtensionsNames.emplace_back(std::move(platformSurfaceTypeExtensionName)); + + if (m_enableDebuggingInfo) + { + m_requiredExtensionsNames.emplace_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + m_requiredExtensionsNames.emplace_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + } + } + + bool Context_Vulkan_Base::init() + { + LOG_INFO(CONTEXT_RENDERER, "Context_Vulkan_Base::init(): Create vulkan context"); + + loadAvailableExtensions(); + loadAvailableValidationLayers(); + if (!checkRequiredExtensionsSupported()) + return false; + if (!checkRequiredValidationLayersSupported()) + return false; + + if (!createInstance()) + return false; + + if (!createDebugMessenger()) + return false; + + if (!createSurface()) + return false; + + LOG_INFO(CONTEXT_RENDERER, "Context_Vulkan_Base::init(): Create vulkan context successful"); + return true; + } + + Context_Vulkan_Base::~Context_Vulkan_Base() + { + LOG_INFO(CONTEXT_RENDERER, "Context_Vulkan_Base::~Context_Vulkan_Base(): destroy vulkan context"); + + if (m_surface != VK_NULL_HANDLE) + vkDestroySurfaceKHR(m_instance, m_surface, nullptr); + if (m_debugMessenger != VK_NULL_HANDLE) + { + auto vkDestroyDebugUtilsMessengerEXT = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkDestroyDebugUtilsMessengerEXT")); + if (vkDestroyDebugUtilsMessengerEXT == nullptr) + { + LOG_ERROR(CONTEXT_RENDERER, "Context_Vulkan_Base::~Context_Vulkan_Base(): Failed loading proc address for vkDestroyDebugUtilsMessengerEXT"); + } + else + { + vkDestroyDebugUtilsMessengerEXT(m_instance, m_debugMessenger, nullptr); + } + } + + if(m_instance != VK_NULL_HANDLE) + vkDestroyInstance(m_instance, nullptr); + } + + bool Context_Vulkan_Base::swapBuffers() + { + // not needed for vulkan context + return true; + } + + bool Context_Vulkan_Base::enable() + { + // not needed for vulkan context + return true; + } + + bool Context_Vulkan_Base::disable() + { + // not needed for vulkan context + return true; + } + + IContext::GlProcLoadFunc Context_Vulkan_Base::getGlProcLoadFunc() const + { + // not needed for vulkan context + return nullptr; + } + + + VKAPI_ATTR VkBool32 VKAPI_CALL Context_Vulkan_Base::ValidationMessageCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, [[maybe_unused]] void* userData) + { + switch (messageSeverity) + { + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT: + LOG_DEBUG(CONTEXT_RENDERER, "Context_Vulkan_Base::ValidationMessageCallback : {}: {}", messageType, callbackData->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT: + LOG_INFO(CONTEXT_RENDERER, "Context_Vulkan_Base::ValidationMessageCallback : {}: {}", messageType, callbackData->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT: + LOG_WARN(CONTEXT_RENDERER, "Context_Vulkan_Base::ValidationMessageCallback : {}: {}", messageType, callbackData->pMessage); + break; + case VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT: + LOG_ERROR(CONTEXT_RENDERER, "Context_Vulkan_Base::ValidationMessageCallback : {}: {}", messageType, callbackData->pMessage); + assert(false); + break; + default: + assert(false); + } + + return VK_FALSE; + } + + void Context_Vulkan_Base::loadAvailableExtensions() + { + m_availableExtensions = VulkanEnumrate(std::bind(vkEnumerateInstanceExtensionProperties, nullptr, _1, _2)); + + LOG_INFO_F(CONTEXT_RENDERER, ([&](StringOutputStream& sos) { + sos << "Context_Vulkan_Base::loadAvailableExtensions(): available extensions (" << m_availableExtensions.size() << (m_availableExtensions.empty() ? ") " : "):"); + for (const auto& extension: m_availableExtensions) + sos << extension.extensionName << " "; + })); + } + + void Context_Vulkan_Base::loadAvailableValidationLayers() + { + m_availableValidationLayers = VulkanEnumrate(std::bind(vkEnumerateInstanceLayerProperties, _1, _2)); + + LOG_INFO_F(CONTEXT_RENDERER, ([&](StringOutputStream& sos) { + sos << "Context_Vulkan_Base::loadAvailableValidationLayers(): available validation layers (" << m_availableValidationLayers.size() << (m_availableValidationLayers.empty() ? ") " : "):"); + for (const auto& layer : m_availableValidationLayers) + sos << layer.layerName << " (" << layer.description << "), "; + })); + } + + bool Context_Vulkan_Base::checkRequiredExtensionsSupported() + { + for (const auto& requiredExtension : m_requiredExtensionsNames) + { + const bool found = std::any_of(m_availableExtensions.cbegin(), m_availableExtensions.cend(), [&requiredExtension](const auto& extension) { return extension.extensionName == requiredExtension; }); + if (!found) + { + LOG_ERROR(CONTEXT_RENDERER, "Context_Vulkan_Base::checkRequiredExtensionsSupported(): Requested extension not found :{} ", requiredExtension); + return false; + } + } + + return true; + } + + bool Context_Vulkan_Base::checkRequiredValidationLayersSupported() + { + if(!m_enableDebuggingInfo) + return true; + + for (const auto& requiredLayer : m_requiredValidationLayers) + { + const bool found = std::any_of(m_availableValidationLayers.cbegin(), m_availableValidationLayers.cend(), [&requiredLayer](const auto& layer) { return layer.layerName == requiredLayer; }); + if (!found) + { + LOG_ERROR(CONTEXT_RENDERER, "Context_Vulkan_Base::checkRequiredValidationLayersSupported(): Requested validation layer not found :{} ", requiredLayer); + return false; + } + } + + return true; + } + + bool Context_Vulkan_Base::createInstance() + { + VkApplicationInfo applicationInfo{}; + applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + applicationInfo.pApplicationName = "RAMSES renderer"; + applicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + applicationInfo.pEngineName = "RAMSES"; + applicationInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + applicationInfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo instanceCreationInfo{}; + instanceCreationInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + instanceCreationInfo.pApplicationInfo = &applicationInfo; + + const VkDebugUtilsMessengerCreateInfoEXT debugMessengerCreationInfo = CreateDebugMessengerCreationInfo(); + instanceCreationInfo.pNext = &debugMessengerCreationInfo; + + std::vector layersCStyle; + std::transform(m_requiredValidationLayers.cbegin(), m_requiredValidationLayers.cend(), std::back_inserter(layersCStyle), [](const auto& s) { return s.c_str(); }); + instanceCreationInfo.enabledLayerCount = static_cast(m_requiredValidationLayers.size()); + instanceCreationInfo.ppEnabledLayerNames = layersCStyle.data(); + + std::vector extensionsCStyle; + std::transform(m_requiredExtensionsNames.cbegin(), m_requiredExtensionsNames.cend(), std::back_inserter(extensionsCStyle), [](const auto& s) { return s.c_str(); }); + instanceCreationInfo.enabledExtensionCount = static_cast(m_requiredExtensionsNames.size()); + instanceCreationInfo.ppEnabledExtensionNames = extensionsCStyle.data(); + + VK_CHECK_RETURN_ERR(vkCreateInstance(&instanceCreationInfo, nullptr, &m_instance)); + + return true; + } + + VkDebugUtilsMessengerCreateInfoEXT Context_Vulkan_Base::CreateDebugMessengerCreationInfo() + { + VkDebugUtilsMessengerCreateInfoEXT debugMessengerCreationInfo{}; + debugMessengerCreationInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + debugMessengerCreationInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + debugMessengerCreationInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + debugMessengerCreationInfo.pfnUserCallback = &ValidationMessageCallback; + debugMessengerCreationInfo.pUserData = nullptr; + + return debugMessengerCreationInfo; + } + + bool Context_Vulkan_Base::createDebugMessenger() + { + assert(m_debugMessenger == VK_NULL_HANDLE); + const VkDebugUtilsMessengerCreateInfoEXT debugMessengerCreationInfo = CreateDebugMessengerCreationInfo(); + + auto vkCreateDebugUtilsMessengerEXT = reinterpret_cast(vkGetInstanceProcAddr(m_instance, "vkCreateDebugUtilsMessengerEXT")); + if (vkCreateDebugUtilsMessengerEXT == nullptr) + { + LOG_ERROR(CONTEXT_RENDERER, "Context_Vulkan_Base::createDebugMessenger(): Failed loading proc address for vkCreateDebugUtilsMessengerEXT"); + return false; + } + + VK_CHECK_RETURN_ERR(vkCreateDebugUtilsMessengerEXT(m_instance, &debugMessengerCreationInfo, nullptr, &m_debugMessenger)); + return true; + } +} diff --git a/src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.h b/src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.h new file mode 100644 index 000000000..80db2bc98 --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/Context_Vulkan_Base.h @@ -0,0 +1,58 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "internal/RendererLib/PlatformBase/Context_Base.h" +#include "VulkanCommon.h" +#include + +namespace ramses::internal +{ + class Context_Vulkan_Base : public Context_Base + { + public: + Context_Vulkan_Base(std::string platformSurfaceTypeExtensionName, bool enableDebuggingInfo, std::vector platformValidationLayers); + ~Context_Vulkan_Base() override; + + bool init(); + + bool swapBuffers() override final; + bool enable() override final; + bool disable() override final; + + [[nodiscard]] GlProcLoadFunc getGlProcLoadFunc() const override; + + VkInstance m_instance = VK_NULL_HANDLE; + VkSurfaceKHR m_surface = VK_NULL_HANDLE; + + protected: + virtual bool createSurface() = 0; + + private: + static VKAPI_ATTR VkBool32 VKAPI_CALL ValidationMessageCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageType, + const VkDebugUtilsMessengerCallbackDataEXT* callbackData, + void* userData); + void loadAvailableExtensions(); + void loadAvailableValidationLayers(); + bool checkRequiredExtensionsSupported(); + bool checkRequiredValidationLayersSupported(); + bool createInstance(); + static VkDebugUtilsMessengerCreateInfoEXT CreateDebugMessengerCreationInfo(); + bool createDebugMessenger(); + + VkDebugUtilsMessengerEXT m_debugMessenger = VK_NULL_HANDLE; + bool m_enableDebuggingInfo = true; + std::vector m_requiredExtensionsNames; + std::vector m_requiredValidationLayers; + + std::vector m_availableExtensions; + std::vector m_availableValidationLayers; + }; +} diff --git a/src/renderer/internal/Platform/Vulkan/Device_Vulkan.cpp b/src/renderer/internal/Platform/Vulkan/Device_Vulkan.cpp new file mode 100644 index 000000000..f55615d57 --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/Device_Vulkan.cpp @@ -0,0 +1,452 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "Device_Vulkan.h" + + +namespace ramses::internal +{ + Device_Vulkan::Device_Vulkan(IContext& context, VkInstance instance, VkSurfaceKHR surface) + : Device_Base(context) + , m_instance(instance) + , m_surface(surface) + { + } + + bool Device_Vulkan::init() + { + (void) m_instance; + (void) m_surface; + + return true; + } + + void Device_Vulkan::drawIndexedTriangles([[maybe_unused]] int32_t startOffset, [[maybe_unused]] int32_t elementCount, [[maybe_unused]] uint32_t instanceCount) + { + + } + + void Device_Vulkan::drawTriangles([[maybe_unused]] int32_t startOffset, [[maybe_unused]] int32_t elementCount, [[maybe_unused]] uint32_t instanceCount) + { + + } + + void Device_Vulkan::clear([[maybe_unused]] ClearFlags clearFlags) + { + + } + + void Device_Vulkan::colorMask([[maybe_unused]] bool r, [[maybe_unused]] bool g, [[maybe_unused]] bool b, [[maybe_unused]] bool a) + { + + } + + void Device_Vulkan::clearColor([[maybe_unused]] const glm::vec4& clearColor) + { + + } + + void Device_Vulkan::clearDepth([[maybe_unused]] float d) + { + + } + + void Device_Vulkan::clearStencil([[maybe_unused]] int32_t s) + { + + } + + void Device_Vulkan::depthFunc([[maybe_unused]] EDepthFunc func) + { + + } + + void Device_Vulkan::depthWrite([[maybe_unused]] EDepthWrite flag) + { + + } + + void Device_Vulkan::scissorTest([[maybe_unused]] EScissorTest state, [[maybe_unused]] const RenderState::ScissorRegion& region) + { + + } + + void Device_Vulkan::blendFactors([[maybe_unused]] EBlendFactor sourceColor, [[maybe_unused]] EBlendFactor destinationColor, [[maybe_unused]] EBlendFactor sourceAlpha, [[maybe_unused]] EBlendFactor destinationAlpha) + { + + } + + void Device_Vulkan::blendColor([[maybe_unused]] const glm::vec4& color) + { + + } + + void Device_Vulkan::blendOperations([[maybe_unused]] EBlendOperation operationColor, [[maybe_unused]] EBlendOperation operationAlpha) + { + + } + + void Device_Vulkan::cullMode([[maybe_unused]] ECullMode mode) + { + + } + + void Device_Vulkan::stencilFunc([[maybe_unused]] EStencilFunc func, [[maybe_unused]] uint8_t ref, [[maybe_unused]] uint8_t mask) + { + + } + + void Device_Vulkan::stencilOp([[maybe_unused]] EStencilOp sfail, [[maybe_unused]] EStencilOp dpfail, [[maybe_unused]] EStencilOp dppass) + { + + } + + void Device_Vulkan::drawMode([[maybe_unused]] EDrawMode mode) + { + + } + + void Device_Vulkan::setViewport([[maybe_unused]] int32_t x, [[maybe_unused]] int32_t y, [[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) + { + + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const float* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::vec2* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::vec3* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::vec4* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const bool* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const int32_t* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::ivec2* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::ivec3* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::ivec4* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::mat2* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::mat3* value) + { + return {}; + } + + bool Device_Vulkan::setConstant([[maybe_unused]] DataFieldHandle field, [[maybe_unused]] uint32_t count, [[maybe_unused]] const glm::mat4* value) + { + return {}; + } + + void Device_Vulkan::readPixels([[maybe_unused]] uint8_t* buffer, [[maybe_unused]] uint32_t x, [[maybe_unused]] uint32_t y, [[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height) + { + + } + + DeviceResourceHandle Device_Vulkan::allocateUniformBuffer([[maybe_unused]] uint32_t totalSizeInBytes) + { + return {}; + } + + void Device_Vulkan::uploadUniformBufferData([[maybe_unused]] DeviceResourceHandle handle, [[maybe_unused]] const std::byte* data, [[maybe_unused]] uint32_t dataSize) + { + + } + + void Device_Vulkan::activateUniformBuffer([[maybe_unused]] DeviceResourceHandle handle, [[maybe_unused]] DataFieldHandle field) + { + + } + + void Device_Vulkan::deleteUniformBuffer([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + DeviceResourceHandle Device_Vulkan::allocateVertexBuffer([[maybe_unused]] uint32_t totalSizeInBytes) + { + return {}; + } + + void Device_Vulkan::uploadVertexBufferData([[maybe_unused]] DeviceResourceHandle handle, [[maybe_unused]] const std::byte* data, [[maybe_unused]] uint32_t dataSize) + { + + } + + void Device_Vulkan::deleteVertexBuffer([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + DeviceResourceHandle Device_Vulkan::allocateVertexArray([[maybe_unused]] const VertexArrayInfo& vertexArrayInfo) + { + return {}; + } + + void Device_Vulkan::activateVertexArray([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::deleteVertexArray([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + DeviceResourceHandle Device_Vulkan::allocateIndexBuffer([[maybe_unused]] EDataType dataType, [[maybe_unused]] uint32_t sizeInBytes) + { + return {}; + } + + void Device_Vulkan::uploadIndexBufferData([[maybe_unused]] DeviceResourceHandle handle, [[maybe_unused]] const std::byte* data, [[maybe_unused]] uint32_t dataSize) + { + + } + + void Device_Vulkan::deleteIndexBuffer([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + std::unique_ptr Device_Vulkan::uploadShader([[maybe_unused]] const EffectResource& shader) + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::registerShader([[maybe_unused]] std::unique_ptr shaderResource) + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::uploadBinaryShader([[maybe_unused]] const EffectResource& shader, [[maybe_unused]] const std::byte* binaryShaderData, [[maybe_unused]] uint32_t binaryShaderDataSize, [[maybe_unused]] BinaryShaderFormatID binaryShaderFormat) + { + return {}; + } + + bool Device_Vulkan::getBinaryShader([[maybe_unused]] DeviceResourceHandle handleconst, [[maybe_unused]] std::vector& binaryShader, [[maybe_unused]] BinaryShaderFormatID& binaryShaderFormat) + { + return {}; + } + + void Device_Vulkan::deleteShader([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::activateShader([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + DeviceResourceHandle Device_Vulkan::allocateTexture2D([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height, [[maybe_unused]] EPixelStorageFormat textureFormat, [[maybe_unused]] const TextureSwizzleArray& swizzle, [[maybe_unused]] uint32_t mipLevelCount, [[maybe_unused]] uint32_t totalSizeInBytes) + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::allocateTexture3D([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height, [[maybe_unused]] uint32_t depth, [[maybe_unused]] EPixelStorageFormat textureFormat, [[maybe_unused]] uint32_t mipLevelCount, [[maybe_unused]] uint32_t totalSizeInBytes) + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::allocateTextureCube([[maybe_unused]] uint32_t faceSize, [[maybe_unused]] EPixelStorageFormat textureFormat, [[maybe_unused]] const TextureSwizzleArray& swizzle, [[maybe_unused]] uint32_t mipLevelCount, [[maybe_unused]] uint32_t totalSizeInBytes) + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::allocateExternalTexture() + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::getEmptyExternalTexture() const + { + return {}; + } + + void Device_Vulkan::bindTexture([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::generateMipmaps([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::uploadTextureData([[maybe_unused]] DeviceResourceHandle handle, + [[maybe_unused]] uint32_t mipLevel, + [[maybe_unused]] uint32_t x, [[maybe_unused]] uint32_t y, [[maybe_unused]] uint32_t z, + [[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height, [[maybe_unused]] uint32_t depth, + [[maybe_unused]] const std::byte* data, [[maybe_unused]] uint32_t dataSize, [[maybe_unused]] uint32_t stride) + { + + } + + DeviceResourceHandle Device_Vulkan::uploadStreamTexture2D([[maybe_unused]] DeviceResourceHandle handle, [[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height, [[maybe_unused]] EPixelStorageFormat format, [[maybe_unused]] const std::byte* data, [[maybe_unused]] const TextureSwizzleArray& swizzle) + { + return {}; + } + + void Device_Vulkan::deleteTexture([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::activateTexture([[maybe_unused]] DeviceResourceHandle handle, [[maybe_unused]] DataFieldHandle field) + { + + } + + uint32_t Device_Vulkan::getTextureAddress([[maybe_unused]] DeviceResourceHandle handle) const + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::uploadRenderBuffer([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height, [[maybe_unused]] EPixelStorageFormat format, [[maybe_unused]] ERenderBufferAccessMode accessMode, [[maybe_unused]] uint32_t sampleCount) + { + return {}; + } + + void Device_Vulkan::deleteRenderBuffer([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + DeviceResourceHandle Device_Vulkan::uploadDmaRenderBuffer([[maybe_unused]] uint32_t width, [[maybe_unused]] uint32_t height, [[maybe_unused]] DmaBufferFourccFormat fourccFormat, [[maybe_unused]] DmaBufferUsageFlags usageFlags, [[maybe_unused]] DmaBufferModifiers modifiers) + { + return {}; + } + + int Device_Vulkan::getDmaRenderBufferFD([[maybe_unused]] DeviceResourceHandle handle) + { + return -1; + } + + uint32_t Device_Vulkan::getDmaRenderBufferStride([[maybe_unused]] DeviceResourceHandle handle) + { + return std::numeric_limits::max(); + } + + void Device_Vulkan::destroyDmaRenderBuffer([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::activateTextureSamplerObject([[maybe_unused]] const TextureSamplerStates& samplerStates, [[maybe_unused]] DataFieldHandle field) + { + + } + + DeviceResourceHandle Device_Vulkan::getFramebufferRenderTarget() const + { + return {}; + } + + DeviceResourceHandle Device_Vulkan::uploadRenderTarget([[maybe_unused]] const DeviceHandleVector& renderBuffers) + { + return {}; + } + + void Device_Vulkan::activateRenderTarget([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::deleteRenderTarget([[maybe_unused]] DeviceResourceHandle handle) + { + + } + + void Device_Vulkan::discardDepthStencil() + { + + } + + void Device_Vulkan::pairRenderTargetsForDoubleBuffering([[maybe_unused]] const std::array& renderTargets, [[maybe_unused]] const std::array& colorBuffers) + { + + } + + void Device_Vulkan::unpairRenderTargets([[maybe_unused]] DeviceResourceHandle renderTarget) + { + + } + + void Device_Vulkan::swapDoubleBufferedRenderTarget([[maybe_unused]] DeviceResourceHandle renderTarget) + { + + } + + void Device_Vulkan::blitRenderTargets([[maybe_unused]] DeviceResourceHandle rtSrc, [[maybe_unused]] DeviceResourceHandle rtDst, [[maybe_unused]] const PixelRectangle& srcRect, [[maybe_unused]] const PixelRectangle& dstRect, [[maybe_unused]] bool colorOnly) + { + + } + + void Device_Vulkan::validateDeviceStatusHealthy() const + { + + } + + bool Device_Vulkan::isDeviceStatusHealthy() const + { + return true; + } + + void Device_Vulkan::getSupportedBinaryProgramFormats([[maybe_unused]] std::vector& formats) const + { + + } + + bool Device_Vulkan::isExternalTextureExtensionSupported() const + { + return {}; + } + + uint32_t Device_Vulkan::getTotalGpuMemoryUsageInKB() const + { + return 0u; + } + + void Device_Vulkan::flush() + { + + } +} diff --git a/src/renderer/internal/Platform/Vulkan/Device_Vulkan.h b/src/renderer/internal/Platform/Vulkan/Device_Vulkan.h new file mode 100644 index 000000000..cda34ab05 --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/Device_Vulkan.h @@ -0,0 +1,135 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "internal/RendererLib/PlatformBase/Device_Base.h" +#include "vulkan/vulkan.h" + +namespace ramses::internal +{ + class IContext; + + class Device_Vulkan final : public Device_Base + { + public: + explicit Device_Vulkan(IContext& context, VkInstance instance, VkSurfaceKHR surface); + ~Device_Vulkan() override = default; + + bool init(); + + void drawIndexedTriangles(int32_t startOffset, int32_t elementCount, uint32_t instanceCount) override; + void drawTriangles(int32_t startOffset, int32_t elementCount, uint32_t instanceCount) override; + + void clear(ClearFlags clearFlags) override; + void colorMask(bool r, bool g, bool b, bool a) override; + void clearColor(const glm::vec4& clearColor) override; + void clearDepth(float d) override; + void clearStencil(int32_t s) override; + void depthFunc(EDepthFunc func) override; + void depthWrite(EDepthWrite flag) override; + void scissorTest(EScissorTest state, const RenderState::ScissorRegion& region) override; + void blendFactors(EBlendFactor sourceColor, EBlendFactor destinationColor, EBlendFactor sourceAlpha, EBlendFactor destinationAlpha) override; + void blendColor(const glm::vec4& color) override; + void blendOperations(EBlendOperation operationColor, EBlendOperation operationAlpha) override; + void cullMode(ECullMode mode) override; + void stencilFunc(EStencilFunc func, uint8_t ref, uint8_t mask) override; + void stencilOp(EStencilOp sfail, EStencilOp dpfail, EStencilOp dppass) override; + void drawMode(EDrawMode mode) override; + void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height) override; + + bool setConstant(DataFieldHandle field, uint32_t count, const float* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::vec2* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::vec3* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::vec4* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const bool* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const int32_t* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::ivec2* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::ivec3* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::ivec4* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::mat2* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::mat3* value) override; + bool setConstant(DataFieldHandle field, uint32_t count, const glm::mat4* value) override; + + void readPixels(uint8_t* buffer, uint32_t x, uint32_t y, uint32_t width, uint32_t height) override; + + DeviceResourceHandle allocateUniformBuffer(uint32_t totalSizeInBytes) override; + void uploadUniformBufferData(DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) override; + void activateUniformBuffer(DeviceResourceHandle handle, DataFieldHandle field) override; + void deleteUniformBuffer(DeviceResourceHandle handle) override; + + DeviceResourceHandle allocateVertexBuffer(uint32_t totalSizeInBytes) override; + void uploadVertexBufferData(DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) override; + void deleteVertexBuffer(DeviceResourceHandle handle) override; + + DeviceResourceHandle allocateVertexArray(const VertexArrayInfo& vertexArrayInfo) override; + void activateVertexArray(DeviceResourceHandle handle) override; + void deleteVertexArray(DeviceResourceHandle handle) override; + + DeviceResourceHandle allocateIndexBuffer(EDataType dataType, uint32_t sizeInBytes) override; + void uploadIndexBufferData(DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) override; + void deleteIndexBuffer(DeviceResourceHandle handle) override; + + std::unique_ptr uploadShader(const EffectResource& shader) override; + DeviceResourceHandle registerShader(std::unique_ptr shaderResource) override; + DeviceResourceHandle uploadBinaryShader(const EffectResource& shader, const std::byte* binaryShaderData, uint32_t binaryShaderDataSize, BinaryShaderFormatID binaryShaderFormat) override; + bool getBinaryShader(DeviceResourceHandle handleconst, std::vector& binaryShader, BinaryShaderFormatID& binaryShaderFormat) override; + void deleteShader(DeviceResourceHandle handle) override; + void activateShader(DeviceResourceHandle handle) override; + + DeviceResourceHandle allocateTexture2D(uint32_t width, uint32_t height, EPixelStorageFormat textureFormat, const TextureSwizzleArray& swizzle, uint32_t mipLevelCount, uint32_t totalSizeInBytes) override; + DeviceResourceHandle allocateTexture3D(uint32_t width, uint32_t height, uint32_t depth, EPixelStorageFormat textureFormat, uint32_t mipLevelCount, uint32_t totalSizeInBytes) override; + DeviceResourceHandle allocateTextureCube(uint32_t faceSize, EPixelStorageFormat textureFormat, const TextureSwizzleArray& swizzle, uint32_t mipLevelCount, uint32_t totalSizeInBytes) override; + DeviceResourceHandle allocateExternalTexture() override; + [[nodiscard]] DeviceResourceHandle getEmptyExternalTexture() const override; + + void bindTexture(DeviceResourceHandle handle) override; + void generateMipmaps(DeviceResourceHandle handle) override; + void uploadTextureData(DeviceResourceHandle handle, uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t z, uint32_t width, uint32_t height, uint32_t depth, const std::byte* data, uint32_t dataSize, uint32_t stride) override; + DeviceResourceHandle uploadStreamTexture2D(DeviceResourceHandle handle, uint32_t width, uint32_t height, EPixelStorageFormat format, const std::byte* data, const TextureSwizzleArray& swizzle) override; + void deleteTexture(DeviceResourceHandle handle) override; + void activateTexture(DeviceResourceHandle handle, DataFieldHandle field) override; + [[nodiscard]] uint32_t getTextureAddress(DeviceResourceHandle handle) const override; + + DeviceResourceHandle uploadRenderBuffer(uint32_t width, uint32_t height, EPixelStorageFormat format, ERenderBufferAccessMode accessMode, uint32_t sampleCount) override; + void deleteRenderBuffer(DeviceResourceHandle handle) override; + + DeviceResourceHandle uploadDmaRenderBuffer(uint32_t width, uint32_t height, DmaBufferFourccFormat fourccFormat, DmaBufferUsageFlags usageFlags, DmaBufferModifiers modifiers) override; + int getDmaRenderBufferFD(DeviceResourceHandle handle) override; + uint32_t getDmaRenderBufferStride(DeviceResourceHandle handle) override; + void destroyDmaRenderBuffer(DeviceResourceHandle handle) override; + + void activateTextureSamplerObject(const TextureSamplerStates& samplerStates, DataFieldHandle field) override; + + [[nodiscard]] DeviceResourceHandle getFramebufferRenderTarget() const override; + DeviceResourceHandle uploadRenderTarget(const DeviceHandleVector& renderBuffers) override; + void activateRenderTarget(DeviceResourceHandle handle) override; + void deleteRenderTarget(DeviceResourceHandle handle) override; + void discardDepthStencil() override; + + void pairRenderTargetsForDoubleBuffering(const std::array& renderTargets, const std::array& colorBuffers) override; + void unpairRenderTargets(DeviceResourceHandle renderTarget) override; + void swapDoubleBufferedRenderTarget(DeviceResourceHandle renderTarget) override; + + void blitRenderTargets(DeviceResourceHandle rtSrc, DeviceResourceHandle rtDst, const PixelRectangle& srcRect, const PixelRectangle& dstRect, bool colorOnly) override; + + void validateDeviceStatusHealthy() const override; + [[nodiscard]] bool isDeviceStatusHealthy() const override; + void getSupportedBinaryProgramFormats(std::vector& formats) const override; + [[nodiscard]] bool isExternalTextureExtensionSupported() const override; + + + [[nodiscard]] uint32_t getTotalGpuMemoryUsageInKB() const override; + + void flush() override; + + private: + VkInstance m_instance; + VkSurfaceKHR m_surface; + }; +} diff --git a/src/renderer/internal/Platform/Vulkan/Platform_Vulkan.h b/src/renderer/internal/Platform/Vulkan/Platform_Vulkan.h new file mode 100644 index 000000000..f7beaede9 --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/Platform_Vulkan.h @@ -0,0 +1,111 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_WINDOWS) +#include "internal/Platform/Windows/Window_Windows.h" +#include "internal/Platform/Vulkan/Windows/Context_Vulkan_Windows.h" +#endif +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_X11) +#include "internal/Platform/X11/Window_X11.h" +#include "internal/Platform/Vulkan/X11/Context_Vulkan_X11.h" +#endif + +#include "internal/RendererLib/PlatformBase/Platform_Base.h" +#include "internal/Platform/Vulkan/Device_Vulkan.h" + +namespace ramses::internal +{ + template + struct Platform_Vulkan_Type_Traits + { + }; + +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_WINDOWS) + template<> struct Platform_Vulkan_Type_Traits + { + using ContextT = Context_Vulkan_Windows; + }; +#endif +#if defined(ramses_sdk_ENABLE_WINDOW_TYPE_X11) + template<> struct Platform_Vulkan_Type_Traits + { + using ContextT = Context_Vulkan_X11; + }; +#endif + + + template + class Platform_Vulkan : public Platform_Base + { + using ContextT = typename Platform_Vulkan_Type_Traits::ContextT; + + public: + explicit Platform_Vulkan(const RendererConfigData& rendererConfig) + : Platform_Base(rendererConfig) + { + } + + bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) override + { + auto window = std::make_unique(displayConfig, windowEventHandler, 0u); + if (window->init()) + { + m_window = std::move(window); + return true; + } + + return false; + } + + bool createContext([[maybe_unused]] const DisplayConfigData& displayConfig) override + { + assert(m_window); + auto* platformWindow = static_cast(m_window.get()); + + auto context = std::make_unique(*platformWindow); + + if (context->init()) + { + m_context = std::move(context); + return true; + } + + return false; + } + + bool createContextUploading() override + { + LOG_ERROR(CONTEXT_RENDERER, "createContextUploading(): Platform_Vulkan does not support async shader upload"); + return false; + } + + bool createDevice() override + { + assert(m_context); + auto* platformContext = static_cast(m_context.get()); + + auto device = std::make_unique(*platformContext, platformContext->m_instance, platformContext->m_surface); + + if (device->init()) + { + m_device = std::move(device); + return true; + } + + return false; + } + + bool createDeviceUploading() override + { + LOG_ERROR(CONTEXT_RENDERER, "createDeviceUploading(): Platform_Vulkan does not support async shader upload"); + return false; + } + }; +} diff --git a/src/renderer/internal/Platform/Vulkan/VulkanCommon.h b/src/renderer/internal/Platform/Vulkan/VulkanCommon.h new file mode 100644 index 000000000..f74694539 --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/VulkanCommon.h @@ -0,0 +1,53 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "internal/Core/Utils/LogMacros.h" +#include "vulkan/vulkan.h" +#include "fmt/format.h" +#include +#include + +#define VK_CALLING_FUNCTION_NAME __func__ + +#define VK_CHECK_RETURN_ERR(expr) \ + VkResult errorCode ## __COUNTER__ = (expr); \ + if(errorCode ## __COUNTER__ != VK_SUCCESS) \ + { \ + LOG_ERROR(CONTEXT_RENDERER, "VK_CHECK_RETURN_ERR: {}(): " #expr ": Failed! Error code (VkResult): {}", VK_CALLING_FUNCTION_NAME, errorCode ## __COUNTER__); \ + return {}; \ + } + +template <> struct fmt::formatter +{ + template constexpr auto parse(ParseContext& ctx) + { + return ctx.begin(); + } + + template constexpr auto format(VkResult value, FormatContext& ctx) + { + return fmt::format_to(ctx.out(), "0x{0:x}", static_cast(value)); + } +}; + +namespace ramses::internal +{ + using namespace std::placeholders; + template + static std::vector VulkanEnumrate(std::function vkFunction) + { + uint32_t count = 0u; + vkFunction(&count, nullptr); + std::vector result(count); + vkFunction(&count, result.data()); + + return result; + } +} diff --git a/src/renderer/internal/Platform/Vulkan/Windows/Context_Vulkan_Windows.cpp b/src/renderer/internal/Platform/Vulkan/Windows/Context_Vulkan_Windows.cpp new file mode 100644 index 000000000..4db366e3f --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/Windows/Context_Vulkan_Windows.cpp @@ -0,0 +1,30 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "Context_Vulkan_Windows.h" +#include "internal/Platform/Windows/Window_Windows.h" + +namespace ramses::internal +{ + Context_Vulkan_Windows::Context_Vulkan_Windows(Window_Windows& window) + : Context_Vulkan_Base(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, true, { "VK_LAYER_KHRONOS_validation" }) + , m_window(window) + { + } + + bool Context_Vulkan_Windows::createSurface() + { + VkWin32SurfaceCreateInfoKHR surfaceCreationInfo = {}; + surfaceCreationInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR; + surfaceCreationInfo.pNext = nullptr; + surfaceCreationInfo.hinstance = m_window.getModuleHandle(); + surfaceCreationInfo.hwnd = m_window.getNativeWindowHandle(); + VK_CHECK_RETURN_ERR(vkCreateWin32SurfaceKHR(m_instance, &surfaceCreationInfo, nullptr, &m_surface)); + return true; + } +} diff --git a/src/renderer/internal/Platform/Vulkan/Windows/Context_Vulkan_Windows.h b/src/renderer/internal/Platform/Vulkan/Windows/Context_Vulkan_Windows.h new file mode 100644 index 000000000..fe1ff326c --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/Windows/Context_Vulkan_Windows.h @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#define VK_USE_PLATFORM_WIN32_KHR +#include "internal/Platform/Vulkan/Context_Vulkan_Base.h" + +namespace ramses::internal +{ + class Window_Windows; + + class Context_Vulkan_Windows : public Context_Vulkan_Base + { + public: + explicit Context_Vulkan_Windows(Window_Windows& window); + + protected: + bool createSurface() override; + + private: + Window_Windows& m_window; + }; +} diff --git a/src/renderer/internal/Platform/Vulkan/X11/Context_Vulkan_X11.cpp b/src/renderer/internal/Platform/Vulkan/X11/Context_Vulkan_X11.cpp new file mode 100644 index 000000000..36a15f593 --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/X11/Context_Vulkan_X11.cpp @@ -0,0 +1,36 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + + +#include "internal/Platform/X11/Window_X11.h" +#undef Status +#undef Bool +#undef None +#undef Always + +#include "Context_Vulkan_X11.h" + +namespace ramses::internal +{ + Context_Vulkan_X11::Context_Vulkan_X11(Window_X11& window) + : Context_Vulkan_Base(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, true, { "VK_LAYER_MESA_device_select" }) + , m_window(window) + { + } + + bool Context_Vulkan_X11::createSurface() + { + VkXlibSurfaceCreateInfoKHR surfaceCreationInfo = {}; + surfaceCreationInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR; + surfaceCreationInfo.pNext = nullptr; + surfaceCreationInfo.window = m_window.getNativeWindowHandle(); + surfaceCreationInfo.dpy = m_window.getNativeDisplayHandle(); + VK_CHECK_RETURN_ERR(vkCreateXlibSurfaceKHR(m_instance, &surfaceCreationInfo, nullptr, &m_surface)); + return true; + } +} diff --git a/src/renderer/internal/Platform/Vulkan/X11/Context_Vulkan_X11.h b/src/renderer/internal/Platform/Vulkan/X11/Context_Vulkan_X11.h new file mode 100644 index 000000000..ab5079d9c --- /dev/null +++ b/src/renderer/internal/Platform/Vulkan/X11/Context_Vulkan_X11.h @@ -0,0 +1,29 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#define VK_USE_PLATFORM_XLIB_KHR +#include "internal/Platform/Vulkan/Context_Vulkan_Base.h" + +namespace ramses::internal +{ + class Window_X11; + + class Context_Vulkan_X11 : public Context_Vulkan_Base + { + public: + explicit Context_Vulkan_X11(Window_X11 &window); + + protected: + bool createSurface() override; + + private: + Window_X11& m_window; + }; +} diff --git a/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.cpp b/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.cpp index 31a5a3bc7..c85e713b3 100644 --- a/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.cpp +++ b/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.cpp @@ -17,7 +17,7 @@ #include "internal/Platform/Wayland/EmbeddedCompositor/LinuxDmabuf.h" #include "internal/Platform/Wayland/EmbeddedCompositor/WaylandOutputParams.h" #include "internal/Platform/EGL/Context_EGL.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/RendererLogContext.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Core/Utils/Warnings.h" @@ -27,7 +27,7 @@ namespace ramses::internal { - EmbeddedCompositor_Wayland::EmbeddedCompositor_Wayland(const DisplayConfig& displayConfig, Context_EGL &context) + EmbeddedCompositor_Wayland::EmbeddedCompositor_Wayland(const DisplayConfigData& displayConfig, Context_EGL &context) : m_waylandEmbeddedSocketName(displayConfig.getWaylandSocketEmbedded()) , m_waylandEmbeddedSocketGroup(displayConfig.getWaylandSocketEmbeddedGroup()) , m_waylandEmbeddedSocketPermissions(displayConfig.getWaylandSocketEmbeddedPermissions()) diff --git a/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.h b/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.h index 1bfb5466d..96453f882 100644 --- a/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.h +++ b/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.h @@ -23,7 +23,7 @@ namespace ramses::internal { - class DisplayConfig; + class DisplayConfigData; class Context_EGL; class IWaylandCompositorConnection; class IWaylandSurface; @@ -34,7 +34,7 @@ namespace ramses::internal class EmbeddedCompositor_Wayland: public IEmbeddedCompositor, public IEmbeddedCompositor_Wayland { public: - EmbeddedCompositor_Wayland(const DisplayConfig& displayConfig, Context_EGL& context); + EmbeddedCompositor_Wayland(const DisplayConfigData& displayConfig, Context_EGL& context); ~EmbeddedCompositor_Wayland() override; bool init(); diff --git a/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/WaylandDisplay.cpp b/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/WaylandDisplay.cpp index 774c94bf9..7bbdefcf4 100644 --- a/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/WaylandDisplay.cpp +++ b/src/renderer/internal/Platform/Wayland/EmbeddedCompositor/WaylandDisplay.cpp @@ -96,7 +96,7 @@ namespace ramses::internal } LOG_ERROR(CONTEXT_RENDERER, "WaylandDisplay::addSocketToDisplayWithFD(): Failed to add wayland display on embedded compositor socket " - "provided by RendererConfig::setWaylandEmbeddedCompositingSocketFD()"); + "provided by RendererConfigData::setWaylandEmbeddedCompositingSocketFD()"); return false; } diff --git a/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.cpp b/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.cpp index a6f3dd23e..bf799a1bb 100644 --- a/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.cpp +++ b/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.cpp @@ -9,14 +9,14 @@ #include "internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.h" #include "internal/Platform/Wayland/IVI/Window_Wayland_IVI.h" #include "internal/Platform/Wayland/IVI/SystemCompositorController/SystemCompositorController_Wayland_IVI.h" -#include "internal/RendererLib/RendererConfig.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/RendererConfigData.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" namespace ramses::internal { - Platform_Wayland_IVI_EGL_ES_3_0::Platform_Wayland_IVI_EGL_ES_3_0(const RendererConfig& rendererConfig) + Platform_Wayland_IVI_EGL_ES_3_0::Platform_Wayland_IVI_EGL_ES_3_0(const RendererConfigData& rendererConfig) : Platform_Wayland_EGL(rendererConfig) { } @@ -38,11 +38,11 @@ namespace ramses::internal } - bool Platform_Wayland_IVI_EGL_ES_3_0::createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) + bool Platform_Wayland_IVI_EGL_ES_3_0::createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) { - if(!displayConfig.getWaylandIviLayerID().isValid()) + if(m_systemCompositorController && !displayConfig.getWaylandIviLayerID().isValid()) { - LOG_ERROR(CONTEXT_RENDERER, "Can not create Wayland IVI window because IVI layer ID was not set in display config!"); + LOG_ERROR(CONTEXT_RENDERER, "Can not create Wayland IVI window because System compositor controller enabled while IVI layer ID was not set in display config!"); return false; } diff --git a/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.h b/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.h index 3ad89dd95..1909515b1 100644 --- a/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.h +++ b/src/renderer/internal/Platform/Wayland/IVI/Platform_Wayland_IVI_EGL_ES_3_0.h @@ -15,11 +15,11 @@ namespace ramses::internal class Platform_Wayland_IVI_EGL_ES_3_0 : public Platform_Wayland_EGL { public: - explicit Platform_Wayland_IVI_EGL_ES_3_0(const RendererConfig& rendererConfig); + explicit Platform_Wayland_IVI_EGL_ES_3_0(const RendererConfigData& rendererConfig); protected: bool createSystemCompositorController() override; - bool createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) override; + bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) override; }; } diff --git a/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.cpp b/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.cpp index cb186a9e6..0dd7be9fc 100644 --- a/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.cpp +++ b/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.cpp @@ -12,7 +12,7 @@ namespace ramses::internal { - Window_Wayland_IVI::Window_Wayland_IVI(const DisplayConfig& displayConfig, + Window_Wayland_IVI::Window_Wayland_IVI(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime) diff --git a/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.h b/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.h index ead0afd18..ec26db8d4 100644 --- a/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.h +++ b/src/renderer/internal/Platform/Wayland/IVI/Window_Wayland_IVI.h @@ -19,7 +19,7 @@ namespace ramses::internal class Window_Wayland_IVI : public Window_Wayland { public: - Window_Wayland_IVI(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime); + Window_Wayland_IVI(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime); ~Window_Wayland_IVI() override; private: diff --git a/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.cpp b/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.cpp index c4ff05d27..fb4ca63ac 100644 --- a/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.cpp +++ b/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.cpp @@ -8,8 +8,8 @@ #include "internal/Platform/Wayland/Platform_Wayland_EGL.h" #include "internal/Platform/Wayland/Logger_Wayland.h" -#include "internal/RendererLib/DisplayConfig.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/RendererLib/PlatformBase/EmbeddedCompositor_Dummy.h" #include "internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.h" #include "internal/Platform/Wayland/EmbeddedCompositor/TextureUploadingAdapter_Wayland.h" @@ -17,7 +17,7 @@ namespace ramses::internal { - Platform_Wayland_EGL::Platform_Wayland_EGL(const RendererConfig& rendererConfig) + Platform_Wayland_EGL::Platform_Wayland_EGL(const RendererConfigData& rendererConfig) : Platform_EGL(rendererConfig) , m_frameCallbackMaxPollTime(m_rendererConfig.getFrameCallbackMaxPollTime()) { @@ -26,7 +26,7 @@ namespace ramses::internal Platform_Wayland_EGL::~Platform_Wayland_EGL() = default; - bool Platform_Wayland_EGL::IsCreatingWaylandEmbeddedCompositorRequired(const DisplayConfig& displayConfig) + bool Platform_Wayland_EGL::IsCreatingWaylandEmbeddedCompositorRequired(const DisplayConfigData& displayConfig) { //EC should be created if (any of) display config params are set const bool areConfigParametersForEmbeddedCompositorSet = !displayConfig.getWaylandSocketEmbedded().empty() @@ -35,12 +35,12 @@ namespace ramses::internal return areConfigParametersForEmbeddedCompositorSet; } - bool Platform_Wayland_EGL::createEmbeddedCompositor(const DisplayConfig& displayConfig) + bool Platform_Wayland_EGL::createEmbeddedCompositor(const DisplayConfigData& displayConfig) { //TODO Mohamed: remove use of EC dummy as soon as it is possible to create multiple displays on wayland if (!IsCreatingWaylandEmbeddedCompositorRequired(displayConfig)) { - LOG_INFO(CONTEXT_RENDERER, "Embedded compositor not created because RendererConfig parameters were not set"); + LOG_INFO(CONTEXT_RENDERER, "Embedded compositor not created because RendererConfigData parameters were not set"); return Platform_EGL::createEmbeddedCompositor(displayConfig); } auto compositor = std::make_unique(displayConfig, static_cast(*m_context)); @@ -50,7 +50,7 @@ namespace ramses::internal return m_embeddedCompositor != nullptr; } - void Platform_Wayland_EGL::createTextureUploadingAdapter(const DisplayConfig& displayConfig) + void Platform_Wayland_EGL::createTextureUploadingAdapter(const DisplayConfigData& displayConfig) { assert(m_device); //TODO Mohamed: remove use of EC dummy as soon as it is possible to create multiple displays on wayland diff --git a/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.h b/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.h index 5381d2af2..7b4ab6d97 100644 --- a/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.h +++ b/src/renderer/internal/Platform/Wayland/Platform_Wayland_EGL.h @@ -16,16 +16,16 @@ namespace ramses::internal class Platform_Wayland_EGL : public Platform_EGL { protected: - explicit Platform_Wayland_EGL(const RendererConfig& rendererConfig); + explicit Platform_Wayland_EGL(const RendererConfigData& rendererConfig); ~Platform_Wayland_EGL() override; - bool createEmbeddedCompositor(const DisplayConfig& displayConfig) override; - void createTextureUploadingAdapter(const DisplayConfig& displayConfig) override; + bool createEmbeddedCompositor(const DisplayConfigData& displayConfig) override; + void createTextureUploadingAdapter(const DisplayConfigData& displayConfig) override; [[nodiscard]] uint32_t getSwapInterval() const override; //TODO Mohamed: remove use of EC dummy as soon as it is possible to create multiple displays on wayland - [[nodiscard]] static bool IsCreatingWaylandEmbeddedCompositorRequired(const DisplayConfig& displayConfig); + [[nodiscard]] static bool IsCreatingWaylandEmbeddedCompositorRequired(const DisplayConfigData& displayConfig); const std::chrono::microseconds m_frameCallbackMaxPollTime; }; diff --git a/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.cpp b/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.cpp index 9aee8ca13..1ba47c99a 100644 --- a/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.cpp +++ b/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.cpp @@ -23,7 +23,6 @@ namespace ramses::internal : m_eglDisplay(eglGetDisplay(waylandWindowDisplay)) , m_eglCreateImageKHR(nullptr) , m_eglDestroyImageKHR(nullptr) - , m_glEGLImageTargetTexture2DOES(nullptr) , m_eglBindWaylandDisplayWL(nullptr) , m_eglUnbindWaylandDisplayWL(nullptr) , m_eglQueryWaylandBufferWL(nullptr) @@ -37,7 +36,6 @@ namespace ramses::internal : m_eglDisplay(eglDisplay) , m_eglCreateImageKHR(nullptr) , m_eglDestroyImageKHR(nullptr) - , m_glEGLImageTargetTexture2DOES(nullptr) , m_eglBindWaylandDisplayWL(nullptr) , m_eglUnbindWaylandDisplayWL(nullptr) , m_eglQueryWaylandBufferWL(nullptr) @@ -53,39 +51,47 @@ namespace ramses::internal { LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::Init EGL_NO_DISPLAY"); } + if (!glGetString) + { + LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::Init glGetString is not available (context not initialized)"); + return; + } + const auto eglExtensionsString = getString(eglQueryString(m_eglDisplay, EGL_EXTENSIONS)); const auto glExtensionsString = getString(reinterpret_cast(glGetString(GL_EXTENSIONS))); const auto eglExtensions = StringUtils::TokenizeToSet(eglExtensionsString); const auto glExtensions = StringUtils::TokenizeToSet(glExtensionsString); - if (CheckExtensionAvailable(glExtensions, "GL_OES_EGL_image") && - CheckExtensionAvailable(eglExtensions, "EGL_KHR_image_base") && - CheckExtensionAvailable(eglExtensions, "EGL_WL_bind_wayland_display")) + if (CheckExtensionAvailable(eglExtensions, "EGL_WL_bind_wayland_display")) { - m_glEGLImageTargetTexture2DOES = reinterpret_cast(eglGetProcAddress("glEGLImageTargetTexture2DOES")); - assert(m_glEGLImageTargetTexture2DOES != nullptr); + m_eglBindWaylandDisplayWL = reinterpret_cast(eglGetProcAddress("eglBindWaylandDisplayWL")); + LOG_INFO(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::Init: loaded proc eglBindWaylandDisplayWL :{}", reinterpret_cast(m_eglBindWaylandDisplayWL)); + assert(m_eglBindWaylandDisplayWL != nullptr); + + m_eglUnbindWaylandDisplayWL = reinterpret_cast(eglGetProcAddress("eglUnbindWaylandDisplayWL")); + LOG_INFO(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::Init: loaded proc eglUnbindWaylandDisplayWL :{}", reinterpret_cast(m_eglUnbindWaylandDisplayWL)); + assert(m_eglUnbindWaylandDisplayWL != nullptr); + } + if (CheckExtensionAvailable(eglExtensions, "EGL_KHR_image_base")) + { m_eglCreateImageKHR = reinterpret_cast(eglGetProcAddress("eglCreateImageKHR")); + LOG_INFO(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::Init: loaded proc eglCreateImageKHR :{}", reinterpret_cast(m_eglCreateImageKHR)); assert(m_eglCreateImageKHR != nullptr); m_eglDestroyImageKHR = reinterpret_cast(eglGetProcAddress("eglDestroyImageKHR")); + LOG_INFO(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::Init: loaded proc eglDestroyImageKHR :{}", reinterpret_cast(m_eglDestroyImageKHR)); assert(m_eglDestroyImageKHR != nullptr); - m_eglBindWaylandDisplayWL = reinterpret_cast(eglGetProcAddress("eglBindWaylandDisplayWL")); - assert(m_eglBindWaylandDisplayWL != nullptr); - - m_eglUnbindWaylandDisplayWL = reinterpret_cast(eglGetProcAddress("eglUnbindWaylandDisplayWL")); - assert(m_eglUnbindWaylandDisplayWL != nullptr); - m_eglQueryWaylandBufferWL = reinterpret_cast(eglGetProcAddress("eglQueryWaylandBufferWL")); + LOG_INFO(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::Init: loaded proc eglQueryWaylandBufferWL :{}", reinterpret_cast(m_eglQueryWaylandBufferWL)); assert(m_eglQueryWaylandBufferWL != nullptr); m_extensionsSupported = true; } - if (CheckExtensionAvailable(glExtensions, "GL_OES_EGL_image") && - CheckExtensionAvailable(eglExtensions, "EGL_KHR_image_base") && + if (CheckExtensionAvailable(eglExtensions, "EGL_KHR_image_base") && CheckExtensionAvailable(eglExtensions, "EGL_EXT_image_dma_buf_import")) { m_dmabufExtensionsSupported = true; @@ -96,9 +102,10 @@ namespace ramses::internal { if (eglExtensions.contains(extensionName)) { + LOG_INFO(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::CheckExtensionAvailable Extension {} is supported!", extensionName); return true; } - LOG_INFO(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::CheckExtensionAvailable Extension {} not supported!", extensionName); + LOG_WARN(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::CheckExtensionAvailable Extension {} not supported!", extensionName); return false; } @@ -109,7 +116,6 @@ namespace ramses::internal return m_eglCreateImageKHR(m_eglDisplay, context, target, buffer, attributeList); } LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::eglCreateImageKHR Extension not bound!"); - assert(false); return EGL_NO_IMAGE; } @@ -120,18 +126,17 @@ namespace ramses::internal return m_eglDestroyImageKHR(m_eglDisplay, image); } LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::eglDestroyImageKHR Extension not bound!"); - assert(false); return EGL_FALSE; } + // NOLINTNEXTLINE(readability-convert-member-functions-to-static) void WaylandEGLExtensionProcs::glEGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) const { - if (m_glEGLImageTargetTexture2DOES) + if (::glEGLImageTargetTexture2DOES) { - return m_glEGLImageTargetTexture2DOES(target, image); + return ::glEGLImageTargetTexture2DOES(target, image); } LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::glEGLImageTargetTexture2DOES Extension not bound!"); - assert(false); } EGLBoolean WaylandEGLExtensionProcs::eglBindWaylandDisplayWL(wl_display* waylandDisplay) const @@ -141,7 +146,6 @@ namespace ramses::internal return m_eglBindWaylandDisplayWL(m_eglDisplay, waylandDisplay); } LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::eglBindWaylandDisplayWL Extension not bound!"); - assert(false); return EGL_FALSE; } @@ -152,7 +156,6 @@ namespace ramses::internal return m_eglUnbindWaylandDisplayWL(m_eglDisplay, waylandDisplay); } LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::eglUnbindWaylandDisplayWL Extension not bound!"); - assert(false); return EGL_FALSE; } @@ -163,7 +166,6 @@ namespace ramses::internal return m_eglQueryWaylandBufferWL(m_eglDisplay, buffer, attribute, value); } LOG_ERROR(CONTEXT_RENDERER, "WaylandEGLExtensionProcs::eglQueryWaylandBufferWL Extension not bound!"); - assert(false); return EGL_FALSE; } diff --git a/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.h b/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.h index 30ce04960..d7c0c9478 100644 --- a/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.h +++ b/src/renderer/internal/Platform/Wayland/WaylandEGLExtensionProcs.h @@ -16,8 +16,7 @@ WARNING_DISABLE_LINUX(-Wdeprecated-declarations) #include "wayland-egl.h" WARNINGS_POP -#include "GLES2/gl2.h" -#include "GLES2/gl2ext.h" +#include "internal/Platform/OpenGL/Device_GL_platform.h" #include "EGL/egl.h" #include "EGL/eglext.h" #ifdef RAMSES_HAS_EGLMESAEXT @@ -56,7 +55,6 @@ namespace ramses::internal PFNEGLCREATEIMAGEKHRPROC m_eglCreateImageKHR; PFNEGLDESTROYIMAGEKHRPROC m_eglDestroyImageKHR; - PFNGLEGLIMAGETARGETTEXTURE2DOESPROC m_glEGLImageTargetTexture2DOES; PFNEGLBINDWAYLANDDISPLAYWL m_eglBindWaylandDisplayWL; PFNEGLUNBINDWAYLANDDISPLAYWL m_eglUnbindWaylandDisplayWL; PFNEGLQUERYWAYLANDBUFFERWL m_eglQueryWaylandBufferWL; diff --git a/src/renderer/internal/Platform/Wayland/Window_Wayland.cpp b/src/renderer/internal/Platform/Wayland/Window_Wayland.cpp index 121c18b4a..b06399f26 100644 --- a/src/renderer/internal/Platform/Wayland/Window_Wayland.cpp +++ b/src/renderer/internal/Platform/Wayland/Window_Wayland.cpp @@ -9,12 +9,12 @@ #include "internal/Platform/Wayland/Window_Wayland.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Platform/Wayland/WaylandEnvironmentUtils.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include namespace ramses::internal { - Window_Wayland::Window_Wayland(const DisplayConfig& displayConfig, + Window_Wayland::Window_Wayland(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime) diff --git a/src/renderer/internal/Platform/Wayland/Window_Wayland.h b/src/renderer/internal/Platform/Wayland/Window_Wayland.h index 899867a87..95e123b0d 100644 --- a/src/renderer/internal/Platform/Wayland/Window_Wayland.h +++ b/src/renderer/internal/Platform/Wayland/Window_Wayland.h @@ -20,7 +20,7 @@ namespace ramses::internal class Window_Wayland : public Window_Base { public: - Window_Wayland(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime); + Window_Wayland(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime); ~Window_Wayland() override; bool init() override; diff --git a/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.cpp b/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.cpp index ac12c9220..f1d1a3ace 100644 --- a/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.cpp +++ b/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.cpp @@ -8,17 +8,17 @@ #include "internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.h" #include "internal/Platform/Wayland/WlShell/Window_Wayland_Shell.h" -#include "internal/RendererLib/RendererConfig.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/RendererConfigData.h" +#include "internal/RendererLib/DisplayConfigData.h" namespace ramses::internal { - Platform_Wayland_Shell_EGL_ES_3_0::Platform_Wayland_Shell_EGL_ES_3_0(const RendererConfig& rendererConfig) + Platform_Wayland_Shell_EGL_ES_3_0::Platform_Wayland_Shell_EGL_ES_3_0(const RendererConfigData& rendererConfig) : Platform_Wayland_EGL(rendererConfig) { } - bool Platform_Wayland_Shell_EGL_ES_3_0::createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) + bool Platform_Wayland_Shell_EGL_ES_3_0::createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) { auto window = std::make_unique(displayConfig, windowEventHandler, 0u, m_frameCallbackMaxPollTime); if (window->init()) diff --git a/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.h b/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.h index 0b1628244..e6f7ea5c5 100644 --- a/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.h +++ b/src/renderer/internal/Platform/Wayland/WlShell/Platform_Wayland_Shell_EGL_ES_3_0.h @@ -15,10 +15,10 @@ namespace ramses::internal class Platform_Wayland_Shell_EGL_ES_3_0 : public Platform_Wayland_EGL { public: - explicit Platform_Wayland_Shell_EGL_ES_3_0(const RendererConfig& rendererConfig); + explicit Platform_Wayland_Shell_EGL_ES_3_0(const RendererConfigData& rendererConfig); protected: - bool createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) override; + bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) override; }; } diff --git a/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.cpp b/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.cpp index bd7b7888b..cd30458a9 100644 --- a/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.cpp +++ b/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.cpp @@ -11,7 +11,7 @@ namespace ramses::internal { - Window_Wayland_Shell::Window_Wayland_Shell(const DisplayConfig& displayConfig, + Window_Wayland_Shell::Window_Wayland_Shell(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime) diff --git a/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.h b/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.h index a41afc5d5..248856664 100644 --- a/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.h +++ b/src/renderer/internal/Platform/Wayland/WlShell/Window_Wayland_Shell.h @@ -15,7 +15,7 @@ namespace ramses::internal class Window_Wayland_Shell : public Window_Wayland { public: - Window_Wayland_Shell(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime); + Window_Wayland_Shell(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id, std::chrono::microseconds frameCallbackMaxPollTime); ~Window_Wayland_Shell() override; void setTitle(std::string_view title) override; diff --git a/src/renderer/internal/Platform/Windows/Context_WGL.cpp b/src/renderer/internal/Platform/Windows/Context_WGL.cpp index 327697378..94c8434db 100644 --- a/src/renderer/internal/Platform/Windows/Context_WGL.cpp +++ b/src/renderer/internal/Platform/Windows/Context_WGL.cpp @@ -13,7 +13,17 @@ namespace ramses::internal { - Context_WGL::Context_WGL(EDepthBufferType depthStencilBufferType, HDC displayHandle, WglExtensions wglExtensions, const Config& config, uint32_t msaaSampleCount) + static IContext::ApiProc getGLProcAddress(const char* name) + { + // wglGetProcAddress only loads extensions - not the OpenGL 1 functions + auto proc = wglGetProcAddress(name); + if (proc) + return reinterpret_cast(proc); + + return reinterpret_cast(GetProcAddress(GetModuleHandle(TEXT("opengl32.dll")), name)); + } + + Context_WGL::Context_WGL(EDepthBufferType depthStencilBufferType, HDC displayHandle, WglExtensions& wglExtensions, const Config& config, uint32_t msaaSampleCount) : m_displayHandle(displayHandle) , m_ext(wglExtensions) , m_contextAttributes(createContextAttributes(config)) @@ -22,7 +32,7 @@ namespace ramses::internal { } - Context_WGL::Context_WGL(Context_WGL& sharedContext, HDC displayHandle, WglExtensions wglExtensions, uint32_t msaaSampleCount) + Context_WGL::Context_WGL(Context_WGL& sharedContext, HDC displayHandle, WglExtensions& wglExtensions, uint32_t msaaSampleCount) : m_displayHandle(displayHandle) , m_ext(wglExtensions) , m_contextAttributes(sharedContext.m_contextAttributes) @@ -186,7 +196,7 @@ namespace ramses::internal return false; } - LOG_INFO(CONTEXT_RENDERER, "Context_WGL::initCustomPixelFormat: OpenGL pixel format: COLOR_BITS:{}, ALPHA_BITS :{}, DEPTH_BITS : {}, STENCIL_BITS :{}, SAMPLE_COUNT : ", + LOG_INFO(CONTEXT_RENDERER, "Context_WGL::initCustomPixelFormat: OpenGL pixel format: COLOR_BITS:{}, ALPHA_BITS:{}, DEPTH_BITS:{}, STENCIL_BITS:{}, SAMPLE_COUNT:{}", resultAttribs[0], resultAttribs[1], resultAttribs[2], resultAttribs[3], resultAttribs[4]); if (resultAttribs[0] != colorBits) @@ -267,9 +277,9 @@ namespace ramses::internal return {}; } - void* Context_WGL::getProcAddress(const char* name) const + IContext::GlProcLoadFunc Context_WGL::getGlProcLoadFunc() const { - return reinterpret_cast(wglGetProcAddress(name)); + return getGLProcAddress; } HGLRC Context_WGL::getNativeContextHandle() const diff --git a/src/renderer/internal/Platform/Windows/Context_WGL.h b/src/renderer/internal/Platform/Windows/Context_WGL.h index 8eeba2582..3224a7d5d 100644 --- a/src/renderer/internal/Platform/Windows/Context_WGL.h +++ b/src/renderer/internal/Platform/Windows/Context_WGL.h @@ -28,13 +28,13 @@ namespace ramses::internal bool gles = false; }; - Context_WGL(EDepthBufferType depthStencilBufferType, HDC displayHandle, WglExtensions procs, const Config& config, uint32_t msaaSampleCount); - Context_WGL(Context_WGL& sharedContext, HDC displayHandle, WglExtensions procs, uint32_t msaaSampleCount); + Context_WGL(EDepthBufferType depthStencilBufferType, HDC displayHandle, WglExtensions& procs, const Config& config, uint32_t msaaSampleCount); + Context_WGL(Context_WGL& sharedContext, HDC displayHandle, WglExtensions& procs, uint32_t msaaSampleCount); ~Context_WGL() override; bool init(); - void* getProcAddress(const char* name) const override; + [[nodiscard]] GlProcLoadFunc getGlProcLoadFunc() const override; // Platform stuff used by other platform modules HGLRC getNativeContextHandle() const; @@ -48,7 +48,7 @@ namespace ramses::internal std::vector createContextAttributes(const Config& config); HDC m_displayHandle; - WglExtensions m_ext; + const WglExtensions& m_ext; // Type is broken in WGL - it has no type abstraction const std::vector m_contextAttributes; uint32_t m_msaaSampleCount; diff --git a/src/renderer/internal/Platform/Windows/HiddenWindow.cpp b/src/renderer/internal/Platform/Windows/HiddenWindow.cpp index 31571975d..2725380e5 100644 --- a/src/renderer/internal/Platform/Windows/HiddenWindow.cpp +++ b/src/renderer/internal/Platform/Windows/HiddenWindow.cpp @@ -30,7 +30,8 @@ namespace ramses::internal const ATOM atom = RegisterClassA(&windowClass); if (0 == atom) { - GetLastError(); + const auto err = GetLastError(); + LOG_ERROR(CONTEXT_RENDERER, "HiddenWindow: Failed to register window class (error {})", err); return; } @@ -57,6 +58,8 @@ namespace ramses::internal if (0 == windowHandle) { + const auto err = GetLastError(); + LOG_ERROR(CONTEXT_RENDERER, "HiddenWindow: Failed to create window (error {})", err); return; } @@ -66,6 +69,7 @@ namespace ramses::internal if (0 == displayHandle) { + LOG_ERROR(CONTEXT_RENDERER, "HiddenWindow: Failed to get window handle"); return; } diff --git a/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.cpp b/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.cpp index 34cb87ed6..6ce40c454 100644 --- a/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.cpp +++ b/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.cpp @@ -11,18 +11,18 @@ #include "internal/Platform/OpenGL/Device_GL.h" #include "internal/Platform/Windows/Window_Windows.h" #include "internal/RendererLib/PlatformBase/EmbeddedCompositor_Dummy.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" namespace ramses::internal { - Platform_Windows_WGL::Platform_Windows_WGL(const RendererConfig& rendererConfig) + Platform_Windows_WGL::Platform_Windows_WGL(const RendererConfigData& rendererConfig) : Platform_Base(rendererConfig) , m_wglExtensions() { } - bool Platform_Windows_WGL::createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) + bool Platform_Windows_WGL::createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) { auto window = std::make_unique(displayConfig, windowEventHandler, 0u); if (window->init()) @@ -34,7 +34,7 @@ namespace ramses::internal return false; } - bool Platform_Windows_WGL::createContext(const DisplayConfig& displayConfig) + bool Platform_Windows_WGL::createContext(const DisplayConfigData& displayConfig) { if (m_contextConfig.has_value()) { @@ -118,7 +118,7 @@ namespace ramses::internal return m_deviceUploading.get() != nullptr; } - std::unique_ptr Platform_Windows_WGL::createContextInternal(const DisplayConfig& displayConfig, const Context_WGL::Config& contextConfig) + std::unique_ptr Platform_Windows_WGL::createContextInternal(const DisplayConfigData& displayConfig, const Context_WGL::Config& contextConfig) { assert(m_window); Window_Windows* platformWindow = static_cast(m_window.get()); diff --git a/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.h b/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.h index 1d7c8407c..99b76410e 100644 --- a/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.h +++ b/src/renderer/internal/Platform/Windows/Platform_Windows_WGL.h @@ -19,16 +19,16 @@ namespace ramses::internal class Platform_Windows_WGL final : public Platform_Base { public: - explicit Platform_Windows_WGL(const RendererConfig& rendererConfig); + explicit Platform_Windows_WGL(const RendererConfigData& rendererConfig); private: - virtual bool createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) override; - virtual bool createContext(const DisplayConfig& displayConfig) override; + virtual bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) override; + virtual bool createContext(const DisplayConfigData& displayConfig) override; virtual bool createContextUploading() override; virtual bool createDevice() override; virtual bool createDeviceUploading() override; - std::unique_ptr createContextInternal(const DisplayConfig& displayConfig, const Context_WGL::Config& contextConfig); + std::unique_ptr createContextInternal(const DisplayConfigData& displayConfig, const Context_WGL::Config& contextConfig); static std::string GetVersionString(const Context_WGL::Config& config); diff --git a/src/renderer/internal/Platform/Windows/WglExtensions.cpp b/src/renderer/internal/Platform/Windows/WglExtensions.cpp index cdc66af51..7ab11fdb6 100644 --- a/src/renderer/internal/Platform/Windows/WglExtensions.cpp +++ b/src/renderer/internal/Platform/Windows/WglExtensions.cpp @@ -13,6 +13,8 @@ namespace ramses::internal { + std::mutex WglExtensions::wglMutex; + Procs::Procs() : wglChoosePixelFormatARB(0) , wglGetPixelFormatAttribivARB(0) @@ -25,6 +27,11 @@ namespace ramses::internal WglExtensions::WglExtensions() : m_loaded(false) { + // Following process of creating dummy window to get extensions seems to cause race if it happens to be executed in parallel, + // this is workaround making the whole extensions init a critical section but could possibly be narrowed down to HiddenWindow init, + // also a solution with non-static mutex would be better. However this is WGL specific and not performance critical code. + std::lock_guard lock{ wglMutex }; + HiddenWindow hiddenWindow; // Create a temporary hidden window to query extensions - setPixelFormat can't be called more than once on same HDC @@ -112,13 +119,13 @@ namespace ramses::internal return m_loaded; } - bool WglExtensions::isExtensionAvailable(const std::string& extensionName) + bool WglExtensions::isExtensionAvailable(const std::string& extensionName) const { // try out various prefixes; add more if required std::string nameEXT = "WGL_EXT_" + extensionName; std::string nameARB = "WGL_ARB_" + extensionName; - return m_extensionNames.contains(nameEXT) || + return m_extensionNames.contains(nameEXT) || m_extensionNames.contains(nameARB); } diff --git a/src/renderer/internal/Platform/Windows/WglExtensions.h b/src/renderer/internal/Platform/Windows/WglExtensions.h index 029f64136..e41e4a186 100644 --- a/src/renderer/internal/Platform/Windows/WglExtensions.h +++ b/src/renderer/internal/Platform/Windows/WglExtensions.h @@ -16,6 +16,7 @@ #include "GL/wgl.h" #include +#include namespace ramses::internal { @@ -36,12 +37,14 @@ namespace ramses::internal WglExtensions(); bool areLoaded() const; - bool isExtensionAvailable(const std::string& extensionName); + bool isExtensionAvailable(const std::string& extensionName) const; Procs procs; private: HashSet m_extensionNames; bool m_loaded; + + static std::mutex wglMutex; }; } diff --git a/src/renderer/internal/Platform/Windows/Window_Windows.cpp b/src/renderer/internal/Platform/Windows/Window_Windows.cpp index b820d0866..037b39f54 100644 --- a/src/renderer/internal/Platform/Windows/Window_Windows.cpp +++ b/src/renderer/internal/Platform/Windows/Window_Windows.cpp @@ -8,7 +8,7 @@ #include "internal/Platform/Windows/Window_Windows.h" #include "internal/RendererLib/PlatformInterface/IWindowEventHandler.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/Enums/EKeyModifier.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/PlatformAbstraction/Collections/Guid.h" @@ -145,7 +145,7 @@ namespace ramses::internal return (TrackMouseEvent(&tme) == TRUE); } - Window_Windows::Window_Windows(const DisplayConfig& displayConfig, IWindowEventHandler& eventHandler, uint32_t id) + Window_Windows::Window_Windows(const DisplayConfigData& displayConfig, IWindowEventHandler& eventHandler, uint32_t id) : Window_Base(displayConfig, eventHandler, id) , m_displayHandle(0) , m_windowHandle(WindowsWindowHandleToHWND(displayConfig.getWindowsWindowHandle())) @@ -235,7 +235,7 @@ namespace ramses::internal { m_windowHandle = CreateWindowExA(m_windowEXStyle, m_windowClass.lpszClassName, - m_classname.c_str(), + getTitle().c_str(), m_windowStyle, windowRect.left, windowRect.top, @@ -320,6 +320,11 @@ namespace ramses::internal return m_windowHandle; } + HINSTANCE Window_Windows::getModuleHandle() + { + return m_windowClass.hInstance; + } + bool Window_Windows::setFullscreen(bool fullscreen) { assert(0 != m_windowHandle); diff --git a/src/renderer/internal/Platform/Windows/Window_Windows.h b/src/renderer/internal/Platform/Windows/Window_Windows.h index 5ab60ecf2..6f4239dc9 100644 --- a/src/renderer/internal/Platform/Windows/Window_Windows.h +++ b/src/renderer/internal/Platform/Windows/Window_Windows.h @@ -22,7 +22,7 @@ namespace ramses::internal class Window_Windows : public Window_Base { public: - Window_Windows(const DisplayConfig& displayConfig, IWindowEventHandler& eventHandler, uint32_t id); + Window_Windows(const DisplayConfigData& displayConfig, IWindowEventHandler& eventHandler, uint32_t id); ~Window_Windows() override; virtual bool init() override; @@ -40,6 +40,7 @@ namespace ramses::internal // Platform specific stuff, used by other platform specific classes HDC getNativeDisplayHandle(); HWND getNativeWindowHandle(); + HINSTANCE getModuleHandle(); // public as it is used by tests static EKeyCode convertVirtualKeyCodeIntoRamsesKeyCode(WPARAM virtualKeyCode, LPARAM lParam); diff --git a/src/renderer/internal/Platform/X11/Platform_X11_EGL.cpp b/src/renderer/internal/Platform/X11/Platform_X11_EGL.cpp index 744adb082..c7679bf0a 100644 --- a/src/renderer/internal/Platform/X11/Platform_X11_EGL.cpp +++ b/src/renderer/internal/Platform/X11/Platform_X11_EGL.cpp @@ -7,17 +7,17 @@ // ------------------------------------------------------------------------- #include "internal/Platform/X11/Platform_X11_EGL.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/RendererLib/PlatformBase/EmbeddedCompositor_Dummy.h" namespace ramses::internal { - Platform_X11_EGL::Platform_X11_EGL(const RendererConfig& rendererConfig) + Platform_X11_EGL::Platform_X11_EGL(const RendererConfigData& rendererConfig) : Platform_EGL(rendererConfig) { } - bool Platform_X11_EGL::createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) + bool Platform_X11_EGL::createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) { auto window = std::make_unique(displayConfig, windowEventHandler, 0u); if (window->init()) diff --git a/src/renderer/internal/Platform/X11/Platform_X11_EGL.h b/src/renderer/internal/Platform/X11/Platform_X11_EGL.h index b7954ec62..f0dd5dec7 100644 --- a/src/renderer/internal/Platform/X11/Platform_X11_EGL.h +++ b/src/renderer/internal/Platform/X11/Platform_X11_EGL.h @@ -16,10 +16,10 @@ namespace ramses::internal class Platform_X11_EGL : public Platform_EGL { public: - explicit Platform_X11_EGL(const RendererConfig& rendererConfig); + explicit Platform_X11_EGL(const RendererConfigData& rendererConfig); protected: - bool createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) override; + bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) override; [[nodiscard]] uint32_t getSwapInterval() const override; }; } diff --git a/src/renderer/internal/Platform/X11/Window_X11.cpp b/src/renderer/internal/Platform/X11/Window_X11.cpp index 69330ed8a..ca69376fd 100644 --- a/src/renderer/internal/Platform/X11/Window_X11.cpp +++ b/src/renderer/internal/Platform/X11/Window_X11.cpp @@ -7,7 +7,7 @@ // ------------------------------------------------------------------------- #include "internal/Platform/X11/Window_X11.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Core/Utils/Warnings.h" #include @@ -166,7 +166,7 @@ namespace ramses::internal } } - Window_X11::Window_X11(const DisplayConfig& displayConfig, IWindowEventHandler &windowEventHandler, uint32_t id) + Window_X11::Window_X11(const DisplayConfigData& displayConfig, IWindowEventHandler &windowEventHandler, uint32_t id) : Window_Base(displayConfig, windowEventHandler, id) , m_keyModifiers(0) , m_bLButtonDown(false) diff --git a/src/renderer/internal/Platform/X11/Window_X11.h b/src/renderer/internal/Platform/X11/Window_X11.h index f0f0b5584..ec4ecf74a 100644 --- a/src/renderer/internal/Platform/X11/Window_X11.h +++ b/src/renderer/internal/Platform/X11/Window_X11.h @@ -39,7 +39,7 @@ namespace ramses::internal class Window_X11 : public Window_Base { public: - Window_X11(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); + Window_X11(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); ~Window_X11() override; bool init() override; diff --git a/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.h b/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.h index 59ab8f039..d701940af 100644 --- a/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.h +++ b/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.h @@ -16,10 +16,10 @@ namespace ramses::internal class Platform_iOS_EGL : public Platform_EGL { public: - explicit Platform_iOS_EGL(const RendererConfig& rendererConfig); + explicit Platform_iOS_EGL(const RendererConfigData& rendererConfig); protected: - virtual bool createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) override; + virtual bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) override; virtual uint32_t getSwapInterval() const override; }; } diff --git a/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.mm b/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.mm index 870c1ead4..cd3c4c847 100644 --- a/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.mm +++ b/src/renderer/internal/Platform/iOS/Platform_iOS_EGL.mm @@ -10,12 +10,12 @@ namespace ramses::internal { - Platform_iOS_EGL::Platform_iOS_EGL(const RendererConfig& rendererConfig) + Platform_iOS_EGL::Platform_iOS_EGL(const RendererConfigData& rendererConfig) : Platform_EGL(rendererConfig) { } - bool Platform_iOS_EGL::createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) + bool Platform_iOS_EGL::createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) { auto window = std::make_unique(displayConfig, windowEventHandler, 0u); if (window->init()) diff --git a/src/renderer/internal/Platform/iOS/Window_iOS.h b/src/renderer/internal/Platform/iOS/Window_iOS.h index d79478eb2..73840c710 100644 --- a/src/renderer/internal/Platform/iOS/Window_iOS.h +++ b/src/renderer/internal/Platform/iOS/Window_iOS.h @@ -15,7 +15,7 @@ namespace ramses::internal class Window_iOS : public Window_Base { public: - Window_iOS(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); + Window_iOS(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); ~Window_iOS() override; bool init() override; diff --git a/src/renderer/internal/Platform/iOS/Window_iOS.mm b/src/renderer/internal/Platform/iOS/Window_iOS.mm index fd57cb798..1cae3307b 100644 --- a/src/renderer/internal/Platform/iOS/Window_iOS.mm +++ b/src/renderer/internal/Platform/iOS/Window_iOS.mm @@ -7,7 +7,7 @@ // ------------------------------------------------------------------------- #include "internal/Platform/iOS/Window_iOS.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Core/Utils/Warnings.h" @@ -16,7 +16,7 @@ namespace ramses::internal { - Window_iOS::Window_iOS(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, UInt32 id) + Window_iOS::Window_iOS(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, UInt32 id) : Window_Base(displayConfig, windowEventHandler, id) , m_metalLayer(static_cast(displayConfig.getIOSNativeWindow().getValue())) { diff --git a/src/renderer/internal/RendererLib/CMakeLists.txt b/src/renderer/internal/RendererLib/CMakeLists.txt index fbb628d02..464345517 100644 --- a/src/renderer/internal/RendererLib/CMakeLists.txt +++ b/src/renderer/internal/RendererLib/CMakeLists.txt @@ -45,3 +45,7 @@ endif() if(ramses-sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL) target_compile_definitions(ramses-renderer-internal PUBLIC ramses_sdk_ENABLE_WINDOW_TYPE_WAYLAND_WL_SHELL) endif() + +if(ramses-sdk_ENABLE_DEVICE_TYPE_VULKAN) + target_compile_definitions(ramses-renderer-internal PUBLIC ramses_sdk_ENABLE_DEVICE_TYPE_VULKAN) +endif() diff --git a/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.cpp b/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.cpp index dee97c7e8..cfa92dcdd 100644 --- a/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.cpp +++ b/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.cpp @@ -12,13 +12,13 @@ namespace ramses::internal { DataReferenceLinkCachedScene::DataReferenceLinkCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo) - : TransformationLinkCachedScene(sceneLinksManager, sceneInfo) + : BaseT(sceneLinksManager, sceneInfo) { } DataSlotHandle DataReferenceLinkCachedScene::allocateDataSlot(const DataSlot& dataSlot, DataSlotHandle handle) { - const DataSlotHandle actualHandle = TransformationLinkCachedScene::allocateDataSlot(dataSlot, handle); + const DataSlotHandle actualHandle = BaseT::allocateDataSlot(dataSlot, handle); if (dataSlot.type == EDataSlotType::DataConsumer) { @@ -33,7 +33,7 @@ namespace ramses::internal void DataReferenceLinkCachedScene::releaseDataSlot(DataSlotHandle handle) { const DataInstanceHandle dataRef = getDataSlot(handle).attachedDataReference; - TransformationLinkCachedScene::releaseDataSlot(handle); + BaseT::releaseDataSlot(handle); if (m_fallbackValues.isAllocated(dataRef)) { m_fallbackValues.release(dataRef); @@ -42,73 +42,73 @@ namespace ramses::internal void DataReferenceLinkCachedScene::setDataFloatArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const float* data) { - TransformationLinkCachedScene::setDataFloatArray(containerHandle, field, elementCount, data); + BaseT::setDataFloatArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataVector2fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec2* data) { - TransformationLinkCachedScene::setDataVector2fArray(containerHandle, field, elementCount, data); + BaseT::setDataVector2fArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataVector3fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec3* data) { - TransformationLinkCachedScene::setDataVector3fArray(containerHandle, field, elementCount, data); + BaseT::setDataVector3fArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataVector4fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec4* data) { - TransformationLinkCachedScene::setDataVector4fArray(containerHandle, field, elementCount, data); + BaseT::setDataVector4fArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataBooleanArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const bool* data) { - TransformationLinkCachedScene::setDataBooleanArray(containerHandle, field, elementCount, data); + BaseT::setDataBooleanArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataIntegerArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const int32_t* data) { - TransformationLinkCachedScene::setDataIntegerArray(containerHandle, field, elementCount, data); + BaseT::setDataIntegerArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataVector2iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec2* data) { - TransformationLinkCachedScene::setDataVector2iArray(containerHandle, field, elementCount, data); + BaseT::setDataVector2iArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataVector3iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec3* data) { - TransformationLinkCachedScene::setDataVector3iArray(containerHandle, field, elementCount, data); + BaseT::setDataVector3iArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataVector4iArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::ivec4* data) { - TransformationLinkCachedScene::setDataVector4iArray(containerHandle, field, elementCount, data); + BaseT::setDataVector4iArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataMatrix22fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat2* data) { - TransformationLinkCachedScene::setDataMatrix22fArray(containerHandle, field, elementCount, data); + BaseT::setDataMatrix22fArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataMatrix33fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat3* data) { - TransformationLinkCachedScene::setDataMatrix33fArray(containerHandle, field, elementCount, data); + BaseT::setDataMatrix33fArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } void DataReferenceLinkCachedScene::setDataMatrix44fArray(DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::mat4* data) { - TransformationLinkCachedScene::setDataMatrix44fArray(containerHandle, field, elementCount, data); + BaseT::setDataMatrix44fArray(containerHandle, field, elementCount, data); updateFallbackValue(containerHandle, data); } diff --git a/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.h b/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.h index 260a62dfd..fc747180f 100644 --- a/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.h +++ b/src/renderer/internal/RendererLib/DataReferenceLinkCachedScene.h @@ -15,6 +15,8 @@ namespace ramses::internal { class DataReferenceLinkCachedScene : public TransformationLinkCachedScene { + using BaseT = TransformationLinkCachedScene; + public: explicit DataReferenceLinkCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo = SceneInfo()); diff --git a/src/renderer/internal/RendererLib/DisplayBundle.cpp b/src/renderer/internal/RendererLib/DisplayBundle.cpp index bc0f5e557..fcac9d619 100644 --- a/src/renderer/internal/RendererLib/DisplayBundle.cpp +++ b/src/renderer/internal/RendererLib/DisplayBundle.cpp @@ -20,13 +20,14 @@ namespace ramses::internal IRendererSceneEventSender& rendererSceneSender, IPlatform& platform, IThreadAliveNotifier& notifier, - std::chrono::milliseconds timingReportingPeriod) + std::chrono::milliseconds timingReportingPeriod, + EFeatureLevel featureLevel) : m_display(display) , m_rendererScenes(m_rendererEventCollector) , m_expirationMonitor(m_rendererScenes, m_rendererEventCollector, m_rendererStatistics) , m_renderer(display, platform, m_rendererScenes, m_rendererEventCollector, m_frameTimer, m_expirationMonitor, m_rendererStatistics) , m_sceneStateExecutor(m_renderer, rendererSceneSender, m_rendererEventCollector) - , m_rendererSceneUpdater(display, platform, m_renderer, m_rendererScenes, m_sceneStateExecutor, m_rendererEventCollector, m_frameTimer, m_expirationMonitor, notifier) + , m_rendererSceneUpdater(display, platform, m_renderer, m_rendererScenes, m_sceneStateExecutor, m_rendererEventCollector, m_frameTimer, m_expirationMonitor, notifier, featureLevel) , m_sceneControlLogic(m_rendererSceneUpdater) , m_rendererCommandExecutor(m_renderer, m_pendingCommands, m_rendererSceneUpdater, m_sceneControlLogic, m_rendererEventCollector, m_frameTimer) , m_sceneReferenceLogic(m_rendererScenes, m_sceneControlLogic, m_rendererSceneUpdater, rendererSceneSender, m_sceneReferenceOwnership) diff --git a/src/renderer/internal/RendererLib/DisplayBundle.h b/src/renderer/internal/RendererLib/DisplayBundle.h index 32bc17854..7ea8a6654 100644 --- a/src/renderer/internal/RendererLib/DisplayBundle.h +++ b/src/renderer/internal/RendererLib/DisplayBundle.h @@ -57,7 +57,8 @@ namespace ramses::internal IRendererSceneEventSender& rendererSceneSender, IPlatform& platform, IThreadAliveNotifier& notifier, - std::chrono::milliseconds timingReportingPeriod); + std::chrono::milliseconds timingReportingPeriod, + EFeatureLevel featureLevel); void doOneLoop(ELoopMode loopMode, std::chrono::microseconds sleepTime) override; diff --git a/src/renderer/internal/RendererLib/DisplayConfig.cpp b/src/renderer/internal/RendererLib/DisplayConfigData.cpp similarity index 56% rename from src/renderer/internal/RendererLib/DisplayConfig.cpp rename to src/renderer/internal/RendererLib/DisplayConfigData.cpp index 2e037e269..8d628bfd5 100644 --- a/src/renderer/internal/RendererLib/DisplayConfig.cpp +++ b/src/renderer/internal/RendererLib/DisplayConfigData.cpp @@ -6,254 +6,264 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include namespace ramses::internal { - EDeviceType DisplayConfig::getDeviceType() const + EDeviceType DisplayConfigData::getDeviceType() const { return m_deviceType; } - void DisplayConfig::setDeviceType(EDeviceType deviceType) + void DisplayConfigData::setDeviceType(EDeviceType deviceType) { m_deviceType = deviceType; } - EWindowType DisplayConfig::getWindowType() const + EWindowType DisplayConfigData::getWindowType() const { return m_windowType; } - void DisplayConfig::setWindowType(EWindowType windowType) + void DisplayConfigData::setWindowType(EWindowType windowType) { m_windowType = windowType; } - void DisplayConfig::setAntialiasingSampleCount(uint32_t samples) + const std::string& DisplayConfigData::getWindowTitle() const + { + return m_windowTitle; + } + + void DisplayConfigData::setWindowTitle(std::string_view title) + { + m_windowTitle = title; + } + + void DisplayConfigData::setAntialiasingSampleCount(uint32_t samples) { assert(contains_c({ 1u, 2u, 4u, 8u }, samples)); m_antiAliasingSamples = samples; } - WaylandIviLayerId DisplayConfig::getWaylandIviLayerID() const + WaylandIviLayerId DisplayConfigData::getWaylandIviLayerID() const { return m_waylandIviLayerID; } - void DisplayConfig::setWaylandIviLayerID(WaylandIviLayerId waylandIviLayerID) + void DisplayConfigData::setWaylandIviLayerID(WaylandIviLayerId waylandIviLayerID) { m_waylandIviLayerID = waylandIviLayerID; } - WaylandIviSurfaceId DisplayConfig::getWaylandIviSurfaceID() const + WaylandIviSurfaceId DisplayConfigData::getWaylandIviSurfaceID() const { return m_waylandIviSurfaceID; } - void DisplayConfig::setWaylandIviSurfaceID(WaylandIviSurfaceId waylandIviSurfaceID) + void DisplayConfigData::setWaylandIviSurfaceID(WaylandIviSurfaceId waylandIviSurfaceID) { m_waylandIviSurfaceID = waylandIviSurfaceID; } - AndroidNativeWindowPtr DisplayConfig::getAndroidNativeWindow() const + AndroidNativeWindowPtr DisplayConfigData::getAndroidNativeWindow() const { return m_androidNativeWindowPtr; } - void DisplayConfig::setAndroidNativeWindow(AndroidNativeWindowPtr nativeWindowPtr) + void DisplayConfigData::setAndroidNativeWindow(AndroidNativeWindowPtr nativeWindowPtr) { m_androidNativeWindowPtr = nativeWindowPtr; } - IOSNativeWindowPtr DisplayConfig::getIOSNativeWindow() const + IOSNativeWindowPtr DisplayConfigData::getIOSNativeWindow() const { return m_iOSNativeWindowPtr; } - void DisplayConfig::setIOSNativeWindow(IOSNativeWindowPtr nativeWindowPtr) + void DisplayConfigData::setIOSNativeWindow(IOSNativeWindowPtr nativeWindowPtr) { m_iOSNativeWindowPtr = nativeWindowPtr; } - bool DisplayConfig::getStartVisibleIvi() const + bool DisplayConfigData::getStartVisibleIvi() const { return m_startVisibleIvi; } - void DisplayConfig::setStartVisibleIvi(bool startVisible) + void DisplayConfigData::setStartVisibleIvi(bool startVisible) { m_startVisibleIvi = startVisible; } - bool DisplayConfig::getFullscreenState() const + bool DisplayConfigData::getFullscreenState() const { return m_fullscreen; } - void DisplayConfig::setFullscreenState(bool state) + void DisplayConfigData::setFullscreenState(bool state) { m_fullscreen = state; } - uint32_t DisplayConfig::getAntialiasingSampleCount() const + uint32_t DisplayConfigData::getAntialiasingSampleCount() const { return m_antiAliasingSamples; } - uint32_t DisplayConfig::getDesiredWindowWidth() const + uint32_t DisplayConfigData::getDesiredWindowWidth() const { return m_desiredWindowWidth; } - void DisplayConfig::setDesiredWindowWidth(uint32_t width) + void DisplayConfigData::setDesiredWindowWidth(uint32_t width) { assert(width != 0u); m_desiredWindowWidth = width; } - uint32_t DisplayConfig::getDesiredWindowHeight() const + uint32_t DisplayConfigData::getDesiredWindowHeight() const { return m_desiredWindowHeight; } - void DisplayConfig::setDesiredWindowHeight(uint32_t height) + void DisplayConfigData::setDesiredWindowHeight(uint32_t height) { assert(height != 0u); m_desiredWindowHeight = height; } - int32_t DisplayConfig::getWindowPositionX() const + int32_t DisplayConfigData::getWindowPositionX() const { return m_windowPositionX; } - void DisplayConfig::setWindowPositionX(int32_t posx) + void DisplayConfigData::setWindowPositionX(int32_t posx) { m_windowPositionX = posx; } - int32_t DisplayConfig::getWindowPositionY() const + int32_t DisplayConfigData::getWindowPositionY() const { return m_windowPositionY; } - void DisplayConfig::setWindowPositionY(int32_t posy) + void DisplayConfigData::setWindowPositionY(int32_t posy) { m_windowPositionY = posy; } - bool DisplayConfig::isResizable() const + bool DisplayConfigData::isResizable() const { return m_resizable; } - void DisplayConfig::setResizable(bool resizable) + void DisplayConfigData::setResizable(bool resizable) { m_resizable = resizable; } - uint64_t DisplayConfig::getGPUMemoryCacheSize() const + uint64_t DisplayConfigData::getGPUMemoryCacheSize() const { return m_gpuMemoryCacheSize; } - void DisplayConfig::setGPUMemoryCacheSize(uint64_t size) + void DisplayConfigData::setGPUMemoryCacheSize(uint64_t size) { m_gpuMemoryCacheSize = size; } - void DisplayConfig::setClearColor(const glm::vec4& clearColor) + void DisplayConfigData::setClearColor(const glm::vec4& clearColor) { m_clearColor = clearColor; } - const glm::vec4& DisplayConfig::getClearColor() const + const glm::vec4& DisplayConfigData::getClearColor() const { return m_clearColor; } - void DisplayConfig::setDepthStencilBufferType(EDepthBufferType depthStencilBufferType) + void DisplayConfigData::setDepthStencilBufferType(EDepthBufferType depthStencilBufferType) { m_depthStencilBufferType = depthStencilBufferType; } - EDepthBufferType DisplayConfig::getDepthStencilBufferType() const + EDepthBufferType DisplayConfigData::getDepthStencilBufferType() const { return m_depthStencilBufferType; } - void DisplayConfig::setWaylandDisplay(std::string_view waylandDisplay) + void DisplayConfigData::setWaylandDisplay(std::string_view waylandDisplay) { m_waylandDisplay.assign(waylandDisplay); } - std::string_view DisplayConfig::getWaylandDisplay() const + std::string_view DisplayConfigData::getWaylandDisplay() const { return m_waylandDisplay; } - void DisplayConfig::setWindowsWindowHandle(WindowsWindowHandle hwnd) + void DisplayConfigData::setWindowsWindowHandle(WindowsWindowHandle hwnd) { m_windowsWindowHandle = hwnd; } - WindowsWindowHandle DisplayConfig::getWindowsWindowHandle() const + WindowsWindowHandle DisplayConfigData::getWindowsWindowHandle() const { return m_windowsWindowHandle; } - void DisplayConfig::setX11WindowHandle(X11WindowHandle windowHandle) + void DisplayConfigData::setX11WindowHandle(X11WindowHandle windowHandle) { m_x11WindowHandle = windowHandle; } - X11WindowHandle DisplayConfig::getX11WindowHandle() const + X11WindowHandle DisplayConfigData::getX11WindowHandle() const { return m_x11WindowHandle; } - void DisplayConfig::setAsyncEffectUploadEnabled(bool enabled) + void DisplayConfigData::setAsyncEffectUploadEnabled(bool enabled) { m_asyncEffectUploadEnabled = enabled; } - bool DisplayConfig::isAsyncEffectUploadEnabled() const + bool DisplayConfigData::isAsyncEffectUploadEnabled() const { return m_asyncEffectUploadEnabled; } - void DisplayConfig::setWaylandEmbeddedCompositingSocketName(std::string_view socket) + void DisplayConfigData::setWaylandEmbeddedCompositingSocketName(std::string_view socket) { m_waylandSocketEmbedded = socket; } - void DisplayConfig::setWaylandEmbeddedCompositingSocketFD(int fd) + void DisplayConfigData::setWaylandEmbeddedCompositingSocketFD(int fd) { m_waylandSocketEmbeddedFD = fd; } - std::string_view DisplayConfig::getWaylandSocketEmbedded() const + std::string_view DisplayConfigData::getWaylandSocketEmbedded() const { return m_waylandSocketEmbedded; } - std::string_view DisplayConfig::getWaylandSocketEmbeddedGroup() const + std::string_view DisplayConfigData::getWaylandSocketEmbeddedGroup() const { return m_waylandSocketEmbeddedGroupName; } - int DisplayConfig::getWaylandSocketEmbeddedFD() const + int DisplayConfigData::getWaylandSocketEmbeddedFD() const { return m_waylandSocketEmbeddedFD; } - void DisplayConfig::setWaylandEmbeddedCompositingSocketGroup(std::string_view groupNameForSocketPermissions) + void DisplayConfigData::setWaylandEmbeddedCompositingSocketGroup(std::string_view groupNameForSocketPermissions) { m_waylandSocketEmbeddedGroupName = groupNameForSocketPermissions; } - bool DisplayConfig::setWaylandEmbeddedCompositingSocketPermissions(uint32_t permissions) + bool DisplayConfigData::setWaylandEmbeddedCompositingSocketPermissions(uint32_t permissions) { if (permissions == 0) return false; @@ -261,37 +271,37 @@ namespace ramses::internal return true; } - uint32_t DisplayConfig::getWaylandSocketEmbeddedPermissions() const + uint32_t DisplayConfigData::getWaylandSocketEmbeddedPermissions() const { return m_waylandSocketEmbeddedPermissions; } - void DisplayConfig::setPlatformRenderNode(std::string_view renderNode) + void DisplayConfigData::setPlatformRenderNode(std::string_view renderNode) { m_platformRenderNode = renderNode; } - std::string_view DisplayConfig::getPlatformRenderNode() const + std::string_view DisplayConfigData::getPlatformRenderNode() const { return m_platformRenderNode; } - void DisplayConfig::setSwapInterval(int32_t interval) + void DisplayConfigData::setSwapInterval(int32_t interval) { m_swapInterval = interval; } - int32_t DisplayConfig::getSwapInterval() const + int32_t DisplayConfigData::getSwapInterval() const { return m_swapInterval; } - void DisplayConfig::setScenePriority(SceneId sceneId, int32_t priority) + void DisplayConfigData::setScenePriority(SceneId sceneId, int32_t priority) { m_scenePriorities[sceneId] = priority; } - int32_t DisplayConfig::getScenePriority(SceneId sceneId) const + int32_t DisplayConfigData::getScenePriority(SceneId sceneId) const { const auto it = m_scenePriorities.find(sceneId); if (it != m_scenePriorities.end()) @@ -301,26 +311,27 @@ namespace ramses::internal return 0; } - const std::unordered_map& DisplayConfig::getScenePriorities() const + const std::unordered_map& DisplayConfigData::getScenePriorities() const { return m_scenePriorities; } - void DisplayConfig::setResourceUploadBatchSize(uint32_t batchSize) + void DisplayConfigData::setResourceUploadBatchSize(uint32_t batchSize) { m_resourceUploadBatchSize = batchSize; } - uint32_t DisplayConfig::getResourceUploadBatchSize() const + uint32_t DisplayConfigData::getResourceUploadBatchSize() const { return m_resourceUploadBatchSize; } - bool DisplayConfig::operator == (const DisplayConfig& other) const + bool DisplayConfigData::operator == (const DisplayConfigData& other) const { return m_deviceType == other.m_deviceType && m_windowType == other.m_windowType && + m_windowTitle == other.m_windowTitle && m_fullscreen == other.m_fullscreen && m_antiAliasingSamples == other.m_antiAliasingSamples && m_desiredWindowWidth == other.m_desiredWindowWidth && @@ -347,7 +358,7 @@ namespace ramses::internal m_resourceUploadBatchSize == other.m_resourceUploadBatchSize; } - bool DisplayConfig::operator != (const DisplayConfig& other) const + bool DisplayConfigData::operator != (const DisplayConfigData& other) const { return !operator==(other); } diff --git a/src/renderer/internal/RendererLib/DisplayConfig.h b/src/renderer/internal/RendererLib/DisplayConfigData.h similarity index 95% rename from src/renderer/internal/RendererLib/DisplayConfig.h rename to src/renderer/internal/RendererLib/DisplayConfigData.h index d8556d091..f43852d38 100644 --- a/src/renderer/internal/RendererLib/DisplayConfig.h +++ b/src/renderer/internal/RendererLib/DisplayConfigData.h @@ -20,10 +20,10 @@ namespace ramses::internal { - class DisplayConfig + class DisplayConfigData { public: - DisplayConfig() = default; + DisplayConfigData() = default; [[nodiscard]] EDeviceType getDeviceType() const; void setDeviceType(EDeviceType deviceType); @@ -31,6 +31,9 @@ namespace ramses::internal [[nodiscard]] EWindowType getWindowType() const; void setWindowType(EWindowType windowType); + [[nodiscard]] const std::string& getWindowTitle() const; + void setWindowTitle(std::string_view title); + [[nodiscard]] bool getFullscreenState() const; void setFullscreenState(bool state); @@ -113,8 +116,8 @@ namespace ramses::internal void setResourceUploadBatchSize(uint32_t batchSize); [[nodiscard]] uint32_t getResourceUploadBatchSize() const; - bool operator==(const DisplayConfig& other) const; - bool operator!=(const DisplayConfig& other) const; + bool operator==(const DisplayConfigData& other) const; + bool operator!=(const DisplayConfigData& other) const; private: EDeviceType m_deviceType = EDeviceType::GLES_3_0; @@ -142,6 +145,8 @@ namespace ramses::internal static_assert(!SupportedWindowTypes.empty(), "No window types supported for build configuration"); EWindowType m_windowType = *SupportedWindowTypes.begin(); + std::string m_windowTitle; + bool m_fullscreen = false; bool m_resizable = false; diff --git a/src/renderer/internal/RendererLib/DisplayController.cpp b/src/renderer/internal/RendererLib/DisplayController.cpp index b020b3c62..9fac1b51a 100644 --- a/src/renderer/internal/RendererLib/DisplayController.cpp +++ b/src/renderer/internal/RendererLib/DisplayController.cpp @@ -11,7 +11,7 @@ #include "internal/RendererLib/PlatformInterface/IDevice.h" #include "internal/RendererLib/PlatformInterface/IWindow.h" #include "internal/RendererLib/PlatformInterface/IContext.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/RendererLib/RendererLogContext.h" #include "internal/RendererLib/LoggingDevice.h" #include "internal/RendererLib/RendererCachedScene.h" diff --git a/src/renderer/internal/RendererLib/DisplayController.h b/src/renderer/internal/RendererLib/DisplayController.h index 06df50957..14111fe6e 100644 --- a/src/renderer/internal/RendererLib/DisplayController.h +++ b/src/renderer/internal/RendererLib/DisplayController.h @@ -16,7 +16,7 @@ namespace ramses::internal { - class RendererConfig; + class RendererConfigData; class IRenderBackend; class RendererCachedScene; class VirtualUpdateScene; diff --git a/src/renderer/internal/RendererLib/DisplayDispatcher.cpp b/src/renderer/internal/RendererLib/DisplayDispatcher.cpp index 74dcd2981..02c4b0c81 100644 --- a/src/renderer/internal/RendererLib/DisplayDispatcher.cpp +++ b/src/renderer/internal/RendererLib/DisplayDispatcher.cpp @@ -15,13 +15,15 @@ namespace ramses::internal { DisplayDispatcher::DisplayDispatcher( std::unique_ptr platformFactory, - RendererConfig config, + RendererConfigData config, IRendererSceneEventSender& rendererSceneSender, - IThreadAliveNotifier& notifier) + IThreadAliveNotifier& notifier, + EFeatureLevel featureLevel) : m_platformFactory(std::move(platformFactory)) , m_rendererConfig{ std::move(config) } , m_rendererSceneSender{ rendererSceneSender } , m_notifier{ notifier } + , m_featureLevel{ featureLevel } { } @@ -89,7 +91,7 @@ namespace ramses::internal for (auto& display : m_displays) { // in non-threaded mode use additional log prefix for each display update - RamsesLogger::SetPrefixAdditional(fmt::format("Display{}", display.first)); + RamsesLoggerPrefixes::SetRamsesLoggerPrefixAdditional(fmt::format("Display{}", display.first)); // avoid unnecessary context switch if running only single display if (m_displays.size() > 1u || m_forceContextEnableNextLoop) @@ -97,7 +99,7 @@ namespace ramses::internal display.second.displayBundle->doOneLoop(m_loopMode, sleepTime); } - RamsesLogger::SetPrefixAdditional({}); + RamsesLoggerPrefixes::SetRamsesLoggerPrefixAdditional({}); m_forceContextEnableNextLoop = false; } @@ -182,7 +184,7 @@ namespace ramses::internal } } - DisplayDispatcher::Display DisplayDispatcher::createDisplayBundle(DisplayHandle displayHandle, const DisplayConfig& dispConfig) + DisplayDispatcher::Display DisplayDispatcher::createDisplayBundle(DisplayHandle displayHandle, const DisplayConfigData& dispConfig) { Display bundle; LOG_INFO(CONTEXT_RENDERER, "DisplayDispatcher: creating platform for display {}", displayHandle); @@ -194,7 +196,8 @@ namespace ramses::internal m_rendererSceneSender, *bundle.platform, m_notifier, - m_rendererConfig.getRenderThreadLoopTimingReportingPeriod()) + m_rendererConfig.getRenderThreadLoopTimingReportingPeriod(), + m_featureLevel) }; if (m_threadedDisplays) { @@ -445,7 +448,7 @@ namespace ramses::internal return displayBundle.hasSystemCompositorController(); } - const RendererConfig& DisplayDispatcher::getRendererConfig() const + const RendererConfigData& DisplayDispatcher::getRendererConfig() const { return m_rendererConfig; } diff --git a/src/renderer/internal/RendererLib/DisplayDispatcher.h b/src/renderer/internal/RendererLib/DisplayDispatcher.h index 20a10fadd..d07e9d89b 100644 --- a/src/renderer/internal/RendererLib/DisplayDispatcher.h +++ b/src/renderer/internal/RendererLib/DisplayDispatcher.h @@ -9,7 +9,7 @@ #pragma once #include "internal/RendererLib/DisplayBundle.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/RendererLib/SceneDisplayTracker.h" #include "internal/RendererLib/DisplayThread.h" #include "internal/RendererLib/Enums/ELoopMode.h" @@ -24,16 +24,17 @@ namespace ramses::internal class Ramsh; class IEmbeddedCompositingManager; class IEmbeddedCompositor; - class DisplayConfig; + class DisplayConfigData; class DisplayDispatcher { public: DisplayDispatcher( std::unique_ptr platformFactory, - RendererConfig config, + RendererConfigData config, IRendererSceneEventSender& rendererSceneSender, - IThreadAliveNotifier& notifier); + IThreadAliveNotifier& notifier, + EFeatureLevel featureLevel); virtual ~DisplayDispatcher() = default; void dispatchCommands(RendererCommandBuffer& cmds); @@ -52,7 +53,7 @@ namespace ramses::internal void setMinFrameDuration(std::chrono::microseconds minFrameDuration, DisplayHandle display); [[nodiscard]] std::chrono::microseconds getMinFrameDuration(DisplayHandle display) const; - [[nodiscard]] const RendererConfig& getRendererConfig() const; + [[nodiscard]] const RendererConfigData& getRendererConfig() const; // needed for EC tests... IEmbeddedCompositingManager& getECManager(DisplayHandle display); @@ -76,10 +77,10 @@ namespace ramses::internal uint32_t lastFrameCounter = 0; }; // virtual to allow mock of display thread - virtual Display createDisplayBundle(DisplayHandle displayHandle, const DisplayConfig& dispConfig); + virtual Display createDisplayBundle(DisplayHandle displayHandle, const DisplayConfigData& dispConfig); std::unique_ptr m_platformFactory; - const RendererConfig m_rendererConfig; + const RendererConfigData m_rendererConfig; IRendererSceneEventSender& m_rendererSceneSender; SceneDisplayTracker m_sceneDisplayTrackerForCommands; @@ -105,6 +106,8 @@ namespace ramses::internal IThreadAliveNotifier& m_notifier; + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; + // flag to force context enable for next doOneLoop (relevant only for non-threaded mode) bool m_forceContextEnableNextLoop = false; diff --git a/src/renderer/internal/RendererLib/DisplaySetup.cpp b/src/renderer/internal/RendererLib/DisplaySetup.cpp index 067eb1c80..3d22ca557 100644 --- a/src/renderer/internal/RendererLib/DisplaySetup.cpp +++ b/src/renderer/internal/RendererLib/DisplaySetup.cpp @@ -11,12 +11,12 @@ namespace ramses::internal { - void DisplaySetup::registerDisplayBuffer(DeviceResourceHandle displayBuffer, const Viewport& viewport, const glm::vec4& clearColor, bool isOffscreenBuffer, bool isInterruptible) + void DisplaySetup::registerDisplayBuffer(DeviceResourceHandle displayBuffer, const Viewport& viewport, const glm::vec4& clearColor, bool isOffscreenBuffer, uint32_t sampleCount, bool isInterruptible) { assert(!isInterruptible || isOffscreenBuffer); assert(m_displayBuffers.find(displayBuffer) == m_displayBuffers.cend()); - DisplayBufferInfo bufferInfo{ isOffscreenBuffer, isInterruptible, viewport, EClearFlag::All, clearColor, {}, true }; + DisplayBufferInfo bufferInfo{ isOffscreenBuffer, isInterruptible, sampleCount, viewport, EClearFlag::All, clearColor, {}, true }; m_displayBuffers.emplace(displayBuffer, std::move(bufferInfo)); } diff --git a/src/renderer/internal/RendererLib/DisplaySetup.h b/src/renderer/internal/RendererLib/DisplaySetup.h index 84d270371..d2519c0da 100644 --- a/src/renderer/internal/RendererLib/DisplaySetup.h +++ b/src/renderer/internal/RendererLib/DisplaySetup.h @@ -30,6 +30,7 @@ namespace ramses::internal { bool isOffscreenBuffer{false}; bool isInterruptible{false}; + uint32_t sampleCount{0u}; Viewport viewport; ClearFlags clearFlags; glm::vec4 clearColor; @@ -41,7 +42,7 @@ namespace ramses::internal class DisplaySetup { public: - void registerDisplayBuffer(DeviceResourceHandle displayBuffer, const Viewport& viewport, const glm::vec4& clearColor, bool isOffscreenBuffer, bool isInterruptible); + void registerDisplayBuffer(DeviceResourceHandle displayBuffer, const Viewport& viewport, const glm::vec4& clearColor, bool isOffscreenBuffer, uint32_t sampleCount, bool isInterruptible); void unregisterDisplayBuffer(DeviceResourceHandle displayBuffer); [[nodiscard]] const DisplayBufferInfo& getDisplayBuffer(DeviceResourceHandle displayBuffer) const; diff --git a/src/renderer/internal/RendererLib/DisplayThread.cpp b/src/renderer/internal/RendererLib/DisplayThread.cpp index fd30cb8fe..349830d15 100644 --- a/src/renderer/internal/RendererLib/DisplayThread.cpp +++ b/src/renderer/internal/RendererLib/DisplayThread.cpp @@ -130,6 +130,11 @@ namespace ramses::internal std::chrono::milliseconds DisplayThread::SleepToControlFramerate(std::chrono::microseconds loopDuration, std::chrono::microseconds minimumFrameDuration) { std::chrono::milliseconds sleepTime{ 0 }; + if (loopDuration < std::chrono::microseconds(0)) + { + LOG_ERROR(CONTEXT_RENDERER, "DisplayThread bad loopDuration: {}us", loopDuration.count()); + return sleepTime; + } if (loopDuration < minimumFrameDuration) { // we use millisecond sleep precision, this will cast microseconds to whole milliseconds (floor) diff --git a/src/renderer/internal/RendererLib/FrameProfilerStatistics.h b/src/renderer/internal/RendererLib/FrameProfilerStatistics.h index 9e64d31fa..679898e0f 100644 --- a/src/renderer/internal/RendererLib/FrameProfilerStatistics.h +++ b/src/renderer/internal/RendererLib/FrameProfilerStatistics.h @@ -26,8 +26,9 @@ namespace ramses::internal "UpdateStreamTextures", "UpdateScenesToBeMapped", "UpdateResourceCache", - "UpdateAnimations", + "UpdateTransformations", "UpdateDataLinks", + "UpdateSemanticUniformBuffers", "HandleDisplayEvents", "DrawScenes", "SwapBuffersNotifyClients", @@ -49,6 +50,7 @@ namespace ramses::internal UpdateResourceCache, UpdateTransformations, UpdateDataLinks, + UpdateSemanticUniformBuffers, HandleDisplayEvents, DrawScenes, SwapBuffersAndNotifyClients, diff --git a/src/renderer/internal/RendererLib/IRendererResourceManager.h b/src/renderer/internal/RendererLib/IRendererResourceManager.h index 9ec1c56c1..116655e0d 100644 --- a/src/renderer/internal/RendererLib/IRendererResourceManager.h +++ b/src/renderer/internal/RendererLib/IRendererResourceManager.h @@ -13,7 +13,6 @@ #include "internal/SceneGraph/SceneAPI/RenderBuffer.h" #include "internal/SceneGraph/SceneAPI/SceneTypes.h" #include "internal/SceneGraph/SceneAPI/TextureSamplerStates.h" -#include "internal/SceneGraph/SceneAPI/EDataType.h" #include "internal/SceneGraph/Resource/ResourceTypes.h" #include "internal/Components/ManagedResource.h" #include "ramses/renderer/Types.h" @@ -62,6 +61,14 @@ namespace ramses::internal virtual void uploadVertexArray(RenderableHandle renderableHandle, const VertexArrayInfo& vertexArrayInfo, SceneId sceneId) = 0; virtual void unloadVertexArray(RenderableHandle renderableHandle, SceneId sceneId) = 0; + virtual void uploadUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t size, SceneId sceneId) = 0; + virtual void unloadUniformBuffer(UniformBufferHandle uniformBufferHandle, SceneId sceneId) = 0; + virtual void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t size, const std::byte* data, SceneId sceneId) = 0; + + virtual DeviceResourceHandle uploadUniformBuffer(SemanticUniformBufferHandle handle, uint32_t size, SceneId sceneId) = 0; + virtual void unloadUniformBuffer(SemanticUniformBufferHandle handle, SceneId sceneId) = 0; + virtual void updateUniformBuffer(SemanticUniformBufferHandle handle, uint32_t size, const std::byte* data, SceneId sceneId) = 0; + virtual void unloadAllSceneResourcesForScene(SceneId sceneId) = 0; virtual void unreferenceAllResourcesForScene(SceneId sceneId) = 0; [[nodiscard]] virtual const ResourceContentHashVector* getResourcesInUseByScene(SceneId sceneId) const = 0; diff --git a/src/renderer/internal/RendererLib/IRendererSceneUpdater.h b/src/renderer/internal/RendererLib/IRendererSceneUpdater.h index d0d57f793..ffae38700 100644 --- a/src/renderer/internal/RendererLib/IRendererSceneUpdater.h +++ b/src/renderer/internal/RendererLib/IRendererSceneUpdater.h @@ -20,14 +20,14 @@ namespace ramses::internal { struct SceneUpdate; - class DisplayConfig; + class DisplayConfigData; class IBinaryShaderCache; class IRendererSceneUpdater { public: virtual void handleSceneUpdate(SceneId sceneId, SceneUpdate&& sceneUpdate) = 0; - virtual void createDisplayContext(const DisplayConfig& displayConfig, IBinaryShaderCache* binaryShaderCache) = 0; + virtual void createDisplayContext(const DisplayConfigData& displayConfig, IBinaryShaderCache* binaryShaderCache) = 0; virtual void destroyDisplayContext() = 0; virtual void handleScenePublished(SceneId sceneId, EScenePublicationMode mode) = 0; virtual void handleSceneUnpublished(SceneId sceneId) = 0; diff --git a/src/renderer/internal/RendererLib/IResourceDeviceHandleAccessor.h b/src/renderer/internal/RendererLib/IResourceDeviceHandleAccessor.h index 57cefae7e..962ccc16c 100644 --- a/src/renderer/internal/RendererLib/IResourceDeviceHandleAccessor.h +++ b/src/renderer/internal/RendererLib/IResourceDeviceHandleAccessor.h @@ -12,6 +12,7 @@ #include "internal/SceneGraph/SceneAPI/Handles.h" #include "internal/SceneGraph/SceneAPI/SceneId.h" #include "internal/RendererLib/Types.h" +#include "internal/RendererLib/SemanticUniformBufferHandle.h" namespace ramses::internal { @@ -27,7 +28,7 @@ namespace ramses::internal [[nodiscard]] virtual DeviceResourceHandle getOffscreenBufferDeviceHandle(OffscreenBufferHandle bufferHandle) const = 0; [[nodiscard]] virtual DeviceResourceHandle getOffscreenBufferColorBufferDeviceHandle(OffscreenBufferHandle bufferHandle) const = 0; [[nodiscard]] virtual int getDmaOffscreenBufferFD(OffscreenBufferHandle bufferHandle) const = 0; - [[nodiscard]] virtual uint32_t getDmaOffscreenBufferStride(OffscreenBufferHandle bufferHandle) const = 0; + [[nodiscard]] virtual uint32_t getDmaOffscreenBufferStride(OffscreenBufferHandle bufferHandle) const = 0; [[nodiscard]] virtual OffscreenBufferHandle getOffscreenBufferHandle(DeviceResourceHandle bufferDeviceHandle) const = 0; [[nodiscard]] virtual DeviceResourceHandle getStreamBufferDeviceHandle(StreamBufferHandle bufferHandle) const = 0; [[nodiscard]] virtual DeviceResourceHandle getExternalBufferDeviceHandle(ExternalBufferHandle bufferHandle) const = 0; @@ -36,6 +37,8 @@ namespace ramses::internal [[nodiscard]] virtual DeviceResourceHandle getDataBufferDeviceHandle(DataBufferHandle dataBufferHandle, SceneId sceneId) const = 0; [[nodiscard]] virtual DeviceResourceHandle getTextureBufferDeviceHandle(TextureBufferHandle textureBufferHandle, SceneId sceneId) const = 0; [[nodiscard]] virtual DeviceResourceHandle getVertexArrayDeviceHandle(RenderableHandle renderableHandle, SceneId sceneId) const = 0; + [[nodiscard]] virtual DeviceResourceHandle getUniformBufferDeviceHandle(UniformBufferHandle uniformBufferHandle, SceneId sceneId) const = 0; + [[nodiscard]] virtual DeviceResourceHandle getUniformBufferDeviceHandle(SemanticUniformBufferHandle handle, SceneId sceneId) const = 0; }; } diff --git a/src/renderer/internal/RendererLib/LoggingDevice.cpp b/src/renderer/internal/RendererLib/LoggingDevice.cpp index 82c03816e..fbd1fbb9c 100644 --- a/src/renderer/internal/RendererLib/LoggingDevice.cpp +++ b/src/renderer/internal/RendererLib/LoggingDevice.cpp @@ -193,6 +193,28 @@ namespace ramses::internal m_logContext << "set draw mode: " << EnumToString(mode) << RendererLogContext::NewLine; } + + DeviceResourceHandle LoggingDevice::allocateUniformBuffer(uint32_t totalSizeInBytes) + { + m_logContext << "allocate uniform buffer [total size: " << totalSizeInBytes << "]" << RendererLogContext::NewLine; + return {}; + } + + void LoggingDevice::uploadUniformBufferData(DeviceResourceHandle handle, [[maybe_unused]] const std::byte* data, uint32_t dataSize) + { + m_logContext << "upload uniform buffer data [device handle: " << handle << " size: " << dataSize << "]" << RendererLogContext::NewLine; + } + + void LoggingDevice::activateUniformBuffer(DeviceResourceHandle handle, DataFieldHandle field) + { + m_logContext << "activate uniform buffer [device handle: " << handle << " field: " << field << "]" << RendererLogContext::NewLine; + } + + void LoggingDevice::deleteUniformBuffer(DeviceResourceHandle handle) + { + m_logContext << "delete uniform buffer [handle: " << handle << "]" << RendererLogContext::NewLine; + } + DeviceResourceHandle LoggingDevice::allocateVertexBuffer(uint32_t totalSizeInBytes) { m_logContext << "allocate vertex buffer [total size: " << totalSizeInBytes << "]" << RendererLogContext::NewLine; diff --git a/src/renderer/internal/RendererLib/LoggingDevice.h b/src/renderer/internal/RendererLib/LoggingDevice.h index 1ba3119b2..3571ea450 100644 --- a/src/renderer/internal/RendererLib/LoggingDevice.h +++ b/src/renderer/internal/RendererLib/LoggingDevice.h @@ -48,6 +48,11 @@ namespace ramses::internal void drawMode(EDrawMode mode) override; void setViewport(int32_t x, int32_t y, uint32_t width, uint32_t height) override; + DeviceResourceHandle allocateUniformBuffer(uint32_t totalSizeInBytes) override; + void uploadUniformBufferData(DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) override; + void activateUniformBuffer(DeviceResourceHandle handle, DataFieldHandle field) override; + void deleteUniformBuffer(DeviceResourceHandle handle) override; + DeviceResourceHandle allocateVertexBuffer(uint32_t totalSizeInBytes) override; void uploadVertexBufferData(DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) override; void deleteVertexBuffer(DeviceResourceHandle handle) override; diff --git a/src/renderer/internal/RendererLib/PendingSceneResourcesUtils.cpp b/src/renderer/internal/RendererLib/PendingSceneResourcesUtils.cpp index 9f04e0db7..a6ffc14c2 100644 --- a/src/renderer/internal/RendererLib/PendingSceneResourcesUtils.cpp +++ b/src/renderer/internal/RendererLib/PendingSceneResourcesUtils.cpp @@ -68,6 +68,18 @@ namespace ramses::internal //add update action iff update action does not already exist wasCanceledOut = ContainsSceneResourceAction(currentActionsInOut, sceneResourceAction.handle, ESceneResourceAction_UpdateTextureBuffer); break; + case ESceneResourceAction_UpdateUniformBuffer: + //add update action iff update action does not already exist + wasCanceledOut = ContainsSceneResourceAction(currentActionsInOut, sceneResourceAction.handle, ESceneResourceAction_UpdateUniformBuffer); + break; + case ESceneResourceAction_DestroyUniformBuffer: + //remove all update actions first + while (RemoveSceneResourceActionIfContained(currentActionsInOut, sceneResourceAction.handle, ESceneResourceAction_UpdateUniformBuffer)) + { + } + wasCanceledOut = RemoveSceneResourceActionIfContained(currentActionsInOut, sceneResourceAction.handle, ESceneResourceAction_CreateUniformBuffer); + break; + default: break; } @@ -138,6 +150,21 @@ namespace ramses::internal case ESceneResourceAction_DestroyTextureBuffer: resourceManager.unloadTextureBuffer(TextureBufferHandle(handle), scene.getSceneId()); break; + case ESceneResourceAction_CreateUniformBuffer: + { + const auto& uniformBuffer = scene.getUniformBuffer(UniformBufferHandle{ handle }); + resourceManager.uploadUniformBuffer(UniformBufferHandle{ handle }, uint32_t(uniformBuffer.data.size()), scene.getSceneId()); + break; + } + case ESceneResourceAction_DestroyUniformBuffer: + resourceManager.unloadUniformBuffer(UniformBufferHandle{ handle }, scene.getSceneId()); + break; + case ESceneResourceAction_UpdateUniformBuffer: + { + const auto& uniformBuffer = scene.getUniformBuffer(UniformBufferHandle{ handle }); + resourceManager.updateUniformBuffer(UniformBufferHandle{ handle }, uint32_t(uniformBuffer.data.size()), uniformBuffer.data.data(), scene.getSceneId()); + break; + } default: assert(false && "unknown scene resource action"); break; diff --git a/src/renderer/internal/RendererLib/PlatformBase/Context_Base.h b/src/renderer/internal/RendererLib/PlatformBase/Context_Base.h index cba2def82..8f47c502d 100644 --- a/src/renderer/internal/RendererLib/PlatformBase/Context_Base.h +++ b/src/renderer/internal/RendererLib/PlatformBase/Context_Base.h @@ -17,7 +17,7 @@ namespace ramses::internal { - class DisplayConfig; + class DisplayConfigData; class Context_Base : public IContext { diff --git a/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.cpp b/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.cpp index fecf52f4f..9ad808948 100644 --- a/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.cpp +++ b/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.cpp @@ -15,15 +15,15 @@ #include "internal/RendererLib/PlatformInterface/ISystemCompositorController.h" #include "internal/RendererLib/RenderBackend.h" #include "internal/RendererLib/ResourceUploadRenderBackend.h" -#include "internal/RendererLib/RendererConfig.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/RendererConfigData.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/PlatformBase/TextureUploadingAdapter_Base.h" #include "internal/RendererLib/PlatformBase/EmbeddedCompositor_Dummy.h" #include "internal/Core/Utils/LogMacros.h" namespace ramses::internal { - Platform_Base::Platform_Base(RendererConfig rendererConfig) + Platform_Base::Platform_Base(RendererConfigData rendererConfig) : m_rendererConfig(std::move(rendererConfig)) { } @@ -38,7 +38,7 @@ namespace ramses::internal assert(!m_textureUploadingAdapter); } - bool Platform_Base::createDeviceExtension(const DisplayConfig& displayConfig) + bool Platform_Base::createDeviceExtension(const DisplayConfigData& displayConfig) { if(displayConfig.getPlatformRenderNode() != "") { @@ -48,7 +48,7 @@ namespace ramses::internal return true; } - IRenderBackend* Platform_Base::createRenderBackend(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) + IRenderBackend* Platform_Base::createRenderBackend(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) { if (m_rendererConfig.getSystemCompositorControlEnabled() && !createSystemCompositorController()) { @@ -177,13 +177,13 @@ namespace ramses::internal return m_systemCompositorController.get(); } - void Platform_Base::createTextureUploadingAdapter(const DisplayConfig& /*unused*/) + void Platform_Base::createTextureUploadingAdapter(const DisplayConfigData& /*unused*/) { assert(!m_textureUploadingAdapter); m_textureUploadingAdapter = std::make_unique(*m_device); } - bool Platform_Base::createEmbeddedCompositor(const DisplayConfig& /*unused*/) + bool Platform_Base::createEmbeddedCompositor(const DisplayConfigData& /*unused*/) { m_embeddedCompositor = std::make_unique(); return m_embeddedCompositor != nullptr; diff --git a/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.h b/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.h index 173053709..a48e1da52 100644 --- a/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.h +++ b/src/renderer/internal/RendererLib/PlatformBase/Platform_Base.h @@ -9,7 +9,7 @@ #pragma once #include "internal/RendererLib/PlatformInterface/IPlatform.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/PlatformAbstraction/Collections/Vector.h" #include #include @@ -26,7 +26,7 @@ namespace ramses::internal class Platform_Base : public IPlatform { public: - IRenderBackend* createRenderBackend(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) final override; + IRenderBackend* createRenderBackend(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) final override; void destroyRenderBackend() final override; IResourceUploadRenderBackend* createResourceUploadRenderBackend() final override; @@ -35,20 +35,20 @@ namespace ramses::internal ISystemCompositorController* getSystemCompositorController() override; protected: - explicit Platform_Base(RendererConfig rendererConfig); + explicit Platform_Base(RendererConfigData rendererConfig); ~Platform_Base() override; - virtual bool createWindow(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) = 0; - virtual bool createContext(const DisplayConfig& displayConfig) = 0; + virtual bool createWindow(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) = 0; + virtual bool createContext(const DisplayConfigData& displayConfig) = 0; virtual bool createContextUploading() = 0; - virtual bool createDeviceExtension(const DisplayConfig& displayConfig); + virtual bool createDeviceExtension(const DisplayConfigData& displayConfig); virtual bool createDevice() = 0; virtual bool createDeviceUploading() = 0; - virtual bool createEmbeddedCompositor(const DisplayConfig& displayConfig); - virtual void createTextureUploadingAdapter(const DisplayConfig& displayConfig); + virtual bool createEmbeddedCompositor(const DisplayConfigData& displayConfig); + virtual void createTextureUploadingAdapter(const DisplayConfigData& displayConfig); virtual bool createSystemCompositorController(); - RendererConfig m_rendererConfig; + RendererConfigData m_rendererConfig; std::unique_ptr m_renderBackend; std::unique_ptr m_resourceUploadRenderBackend; diff --git a/src/renderer/internal/RendererLib/PlatformBase/Window_Base.cpp b/src/renderer/internal/RendererLib/PlatformBase/Window_Base.cpp index b2fc92330..12fd377cd 100644 --- a/src/renderer/internal/RendererLib/PlatformBase/Window_Base.cpp +++ b/src/renderer/internal/RendererLib/PlatformBase/Window_Base.cpp @@ -8,15 +8,15 @@ #include "internal/RendererLib/PlatformBase/Window_Base.h" #include "internal/PlatformAbstraction/Collections/StringOutputStream.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/PlatformInterface/IWindowEventHandler.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Core/Utils/LogMacros.h" namespace ramses::internal { - Window_Base::Window_Base(const DisplayConfig& displayConfig, IWindowEventHandler& eventHandler, uint32_t id) - : m_windowName((StringOutputStream() << "RAMSES Renderer " << id).release()) + Window_Base::Window_Base(const DisplayConfigData& displayConfig, IWindowEventHandler& eventHandler, uint32_t id) + : m_windowName(displayConfig.getWindowTitle().empty() ? fmt::format("RAMSES Renderer {}", id) : displayConfig.getWindowTitle()) , m_eventHandler(eventHandler) , m_fullscreen(displayConfig.getFullscreenState()) , m_msaaSampleCount(1) diff --git a/src/renderer/internal/RendererLib/PlatformBase/Window_Base.h b/src/renderer/internal/RendererLib/PlatformBase/Window_Base.h index 2858a2d16..04cbac9ab 100644 --- a/src/renderer/internal/RendererLib/PlatformBase/Window_Base.h +++ b/src/renderer/internal/RendererLib/PlatformBase/Window_Base.h @@ -12,13 +12,13 @@ namespace ramses::internal { - class DisplayConfig; + class DisplayConfigData; class IWindowEventHandler; class Window_Base : public IWindow { public: - Window_Base(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); + Window_Base(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler, uint32_t id); [[nodiscard]] bool canRenderNewFrame() const override; void frameRendered() override; diff --git a/src/renderer/internal/RendererLib/PlatformInterface/IContext.h b/src/renderer/internal/RendererLib/PlatformInterface/IContext.h index 0e8ef22ec..5b0c61c81 100644 --- a/src/renderer/internal/RendererLib/PlatformInterface/IContext.h +++ b/src/renderer/internal/RendererLib/PlatformInterface/IContext.h @@ -24,7 +24,9 @@ namespace ramses::internal virtual bool disable() = 0; virtual DeviceResourceMapper& getResources() = 0; - // TODO Violin this should be removed - provides access to platform-specific data - virtual void* getProcAddress(const char* name) const = 0; + using ApiProc = void (*)(); + using GlProcLoadFunc = ApiProc (*)(const char*); + + [[nodiscard]] virtual GlProcLoadFunc getGlProcLoadFunc() const = 0; }; } diff --git a/src/renderer/internal/RendererLib/PlatformInterface/IDevice.h b/src/renderer/internal/RendererLib/PlatformInterface/IDevice.h index e2c5cc1d8..b927a312e 100644 --- a/src/renderer/internal/RendererLib/PlatformInterface/IDevice.h +++ b/src/renderer/internal/RendererLib/PlatformInterface/IDevice.h @@ -11,8 +11,8 @@ #include "internal/RendererLib/Types.h" #include "internal/SceneGraph/SceneAPI/TextureEnums.h" #include "internal/SceneGraph/SceneAPI/RenderState.h" -#include "internal/SceneGraph/SceneAPI/EDataType.h" #include "internal/SceneGraph/Resource/TextureMetaInfo.h" +#include "internal/SceneGraph/SceneAPI/SceneTypes.h" #include "internal/RendererLib/PlatformBase/GpuResource.h" #include #include @@ -67,6 +67,11 @@ namespace ramses::internal virtual void setViewport (int32_t x, int32_t y, uint32_t width, uint32_t height) = 0; // resources + virtual DeviceResourceHandle allocateUniformBuffer (uint32_t totalSizeInBytes) = 0; + virtual void uploadUniformBufferData (DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) = 0; + virtual void activateUniformBuffer (DeviceResourceHandle handle, DataFieldHandle field) = 0; + virtual void deleteUniformBuffer (DeviceResourceHandle handle) = 0; + virtual DeviceResourceHandle allocateVertexBuffer (uint32_t totalSizeInBytes) = 0; virtual void uploadVertexBufferData (DeviceResourceHandle handle, const std::byte* data, uint32_t dataSize) = 0; virtual void deleteVertexBuffer (DeviceResourceHandle handle) = 0; diff --git a/src/renderer/internal/RendererLib/PlatformInterface/IPlatform.h b/src/renderer/internal/RendererLib/PlatformInterface/IPlatform.h index c3574c925..cf0fa14c5 100644 --- a/src/renderer/internal/RendererLib/PlatformInterface/IPlatform.h +++ b/src/renderer/internal/RendererLib/PlatformInterface/IPlatform.h @@ -11,7 +11,7 @@ namespace ramses::internal { class IRenderBackend; - class DisplayConfig; + class DisplayConfigData; class IWindowEventHandler; class IResourceUploadRenderBackend; class ISystemCompositorController; @@ -19,7 +19,7 @@ namespace ramses::internal class IPlatform { public: - virtual IRenderBackend* createRenderBackend(const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler) = 0; + virtual IRenderBackend* createRenderBackend(const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler) = 0; virtual void destroyRenderBackend() = 0; virtual IResourceUploadRenderBackend* createResourceUploadRenderBackend() = 0; virtual void destroyResourceUploadRenderBackend() = 0; diff --git a/src/renderer/internal/RendererLib/PlatformInterface/IPlatformFactory.h b/src/renderer/internal/RendererLib/PlatformInterface/IPlatformFactory.h index 803f410d1..fad1d3bda 100644 --- a/src/renderer/internal/RendererLib/PlatformInterface/IPlatformFactory.h +++ b/src/renderer/internal/RendererLib/PlatformInterface/IPlatformFactory.h @@ -13,13 +13,13 @@ namespace ramses::internal { - class RendererConfig; - class DisplayConfig; + class RendererConfigData; + class DisplayConfigData; class IPlatformFactory { public: virtual ~IPlatformFactory() = default; - virtual std::unique_ptr createPlatform(const RendererConfig& rendererConfig, const DisplayConfig& displayConfig) = 0; + virtual std::unique_ptr createPlatform(const RendererConfigData& rendererConfig, const DisplayConfigData& displayConfig) = 0; }; } diff --git a/src/renderer/internal/RendererLib/RenderExecutor.cpp b/src/renderer/internal/RendererLib/RenderExecutor.cpp index 5e7e72630..11a380240 100644 --- a/src/renderer/internal/RendererLib/RenderExecutor.cpp +++ b/src/renderer/internal/RendererLib/RenderExecutor.cpp @@ -234,103 +234,103 @@ namespace ramses::internal DataInstanceHandle dataRef = renderScene.getDataReference(uniformData, constantField); const DataLayoutHandle dataRefLayout = renderScene.getLayoutOfDataInstance(dataRef); const EDataType dataTypeRef = renderScene.getDataLayout(dataRefLayout).getField(DataFieldHandle(0u)).dataType; - executeConstant(dataTypeRef, 1u, dataRef, DataFieldHandle(0u), constantField); + executeConstant(DataFieldInfo{ dataTypeRef, 1u }, dataRef, DataFieldHandle(0u), constantField); } else { - executeConstant(field.dataType, field.elementCount, uniformData, constantField, constantField); + executeConstant(field, uniformData, constantField, constantField); } } } - void RenderExecutor::executeConstant(EDataType dataType, uint32_t elementCount, DataInstanceHandle dataInstance, DataFieldHandle dataInstancefield, DataFieldHandle uniformInputField) const + void RenderExecutor::executeConstant(const DataFieldInfo& field, DataInstanceHandle dataInstance, DataFieldHandle dataInstancefield, DataFieldHandle uniformInputField) const { IDevice& device = m_state.getDevice(); const ResourceCachedScene& renderScene = m_state.getScene(); - switch (dataType) + switch (field.dataType) { case EDataType::Float: { const float* value = renderScene.getDataFloatArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Vector2F: { const auto* value = renderScene.getDataVector2fArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Vector3F: { const auto* value = renderScene.getDataVector3fArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Vector4F: { const auto* value = renderScene.getDataVector4fArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Matrix22F: { const auto* value = renderScene.getDataMatrix22fArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Matrix33F: { const auto* value = renderScene.getDataMatrix33fArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Matrix44F: { const auto* value = renderScene.getDataMatrix44fArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Bool: { const bool* value = renderScene.getDataBooleanArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Int32: { const int32_t* value = renderScene.getDataIntegerArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Vector2I: { const glm::ivec2* value = renderScene.getDataVector2iArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Vector3I: { const auto* value = renderScene.getDataVector3iArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } case EDataType::Vector4I: { const auto* value = renderScene.getDataVector4iArray(dataInstance, dataInstancefield); - device.setConstant(uniformInputField, elementCount, value); + device.setConstant(uniformInputField, field.elementCount, value); break; } @@ -338,6 +338,35 @@ namespace ramses::internal assert(false && "Multiple level data referencing not supported"); break; + case EDataType::UniformBuffer: + { + DeviceResourceHandle deviceHandle{}; + switch (field.semantics) + { + case EFixedSemantics::Invalid: + deviceHandle = renderScene.getCachedHandlesForUniformInstancesBuffers()[m_state.getRenderable().asMemoryHandle()][dataInstancefield.asMemoryHandle()]; + break; + case EFixedSemantics::ModelBlock: + deviceHandle = renderScene.getDeviceHandle(m_state.getRenderable()); + break; + case EFixedSemantics::CameraBlock: + deviceHandle = renderScene.getDeviceHandle(m_state.getCamera()); + break; + case EFixedSemantics::ModelCameraBlock: + deviceHandle = renderScene.getDeviceHandle(m_state.getRenderable(), m_state.getCamera()); + break; + case EFixedSemantics::FramebufferBlock: + case EFixedSemantics::SceneBlock: + return; // TODO _SEMANTICUBO_ + default: + assert(false); + } + + assert(deviceHandle.isValid()); + device.activateUniformBuffer(deviceHandle, dataInstancefield); + break; + } + case EDataType::TextureSampler2D: case EDataType::TextureSampler3D: case EDataType::TextureSamplerCube: @@ -470,6 +499,13 @@ namespace ramses::internal auto& scene = const_cast(m_state.getScene()); switch (semantics) { + case EFixedSemantics::ModelBlock: + case EFixedSemantics::CameraBlock: + case EFixedSemantics::ModelCameraBlock: + case EFixedSemantics::FramebufferBlock: + case EFixedSemantics::SceneBlock: + // do nothing since UBOs were already set/updated within "update loop" + break; case EFixedSemantics::ViewMatrix: { const auto& mat = m_state.getViewMatrix(); diff --git a/src/renderer/internal/RendererLib/RenderExecutor.h b/src/renderer/internal/RendererLib/RenderExecutor.h index 60abbfda5..43ca4b23e 100644 --- a/src/renderer/internal/RendererLib/RenderExecutor.h +++ b/src/renderer/internal/RendererLib/RenderExecutor.h @@ -18,6 +18,7 @@ namespace ramses::internal struct RenderingContext; class FrameTimer; class IScene; + struct DataFieldInfo; class RenderExecutor { @@ -37,7 +38,7 @@ namespace ramses::internal void executeRenderTarget (RenderTargetHandle renderTarget) const; void executeRenderStates () const; void executeEffectAndInputs () const; - void executeConstant (EDataType dataType, uint32_t elementCount, DataInstanceHandle dataInstance, DataFieldHandle dataInstancefield, DataFieldHandle uniformInputField) const; + void executeConstant (const DataFieldInfo& field, DataInstanceHandle dataInstance, DataFieldHandle dataInstancefield, DataFieldHandle uniformInputField) const; void executeDrawCall () const; void setGlobalInternalStates (const RendererCachedScene& scene) const; diff --git a/src/renderer/internal/RendererLib/RenderExecutorInternalState.h b/src/renderer/internal/RendererLib/RenderExecutorInternalState.h index 097dfccf0..5f02a5d3d 100644 --- a/src/renderer/internal/RendererLib/RenderExecutorInternalState.h +++ b/src/renderer/internal/RendererLib/RenderExecutorInternalState.h @@ -80,7 +80,8 @@ namespace ramses::internal [[nodiscard]] const glm::mat4& getModelViewMatrix() const; [[nodiscard]] const glm::mat4& getModelViewProjectionMatrix() const; - void setCamera(CameraHandle camera); + void setCamera(CameraHandle camera); + [[nodiscard]] CameraHandle getCamera() const; void setRenderable(RenderableHandle renderable); [[nodiscard]] RenderableHandle getRenderable() const; @@ -130,6 +131,11 @@ namespace ramses::internal return m_renderable; } + inline CameraHandle RenderExecutorInternalState::getCamera() const + { + return m_camera.getState(); + } + inline IDevice& RenderExecutorInternalState::getDevice() const { return m_device; diff --git a/src/renderer/internal/RendererLib/Renderer.cpp b/src/renderer/internal/RendererLib/Renderer.cpp index 6782507c5..06d99d094 100644 --- a/src/renderer/internal/RendererLib/Renderer.cpp +++ b/src/renderer/internal/RendererLib/Renderer.cpp @@ -17,7 +17,7 @@ #include "internal/RendererLib/RendererCachedScene.h" #include "internal/RendererLib/DisplayController.h" #include "internal/RendererLib/RendererLogContext.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/RendererScenes.h" #include "internal/RendererLib/DisplayEventHandler.h" #include "internal/RendererLib/SceneExpirationMonitor.h" @@ -52,11 +52,11 @@ namespace ramses::internal assert(!hasDisplayController()); } - void Renderer::registerOffscreenBuffer(DeviceResourceHandle bufferDeviceHandle, uint32_t width, uint32_t height, bool isInterruptible) + void Renderer::registerOffscreenBuffer(DeviceResourceHandle bufferDeviceHandle, uint32_t width, uint32_t height, uint32_t sampleCount, bool isInterruptible) { assert(hasDisplayController()); assert(!hasAnyBufferWithInterruptedRendering()); - m_displayBuffersSetup.registerDisplayBuffer(bufferDeviceHandle, { 0, 0, width, height }, DefaultClearColor, true, isInterruptible); + m_displayBuffersSetup.registerDisplayBuffer(bufferDeviceHandle, { 0, 0, width, height }, DefaultClearColor, true, sampleCount, isInterruptible); // no need to re-render OB as long as no scene is assigned to it, OB is cleared at creation time m_displayBuffersSetup.setDisplayBufferToBeRerendered(bufferDeviceHandle, false); } @@ -92,7 +92,7 @@ namespace ramses::internal return m_displayEventHandler; } - void Renderer::createDisplayContext(const DisplayConfig& displayConfig) + void Renderer::createDisplayContext(const DisplayConfigData& displayConfig) { LOG_TRACE(CONTEXT_PROFILING, "Renderer::createDisplayContext start creating display"); @@ -105,7 +105,8 @@ namespace ramses::internal } m_frameBufferDeviceHandle = m_displayController->getDisplayBuffer(); - m_displayBuffersSetup.registerDisplayBuffer(m_frameBufferDeviceHandle, { 0, 0, m_displayController->getDisplayWidth(), m_displayController->getDisplayHeight() }, DefaultClearColor, false, false); + m_displayBuffersSetup.registerDisplayBuffer(m_frameBufferDeviceHandle, { 0, 0, m_displayController->getDisplayWidth(), m_displayController->getDisplayHeight() }, + DefaultClearColor, false, displayConfig.getAntialiasingSampleCount(), false); setClearColor(m_frameBufferDeviceHandle, displayConfig.getClearColor()); LOG_TRACE(CONTEXT_PROFILING, "RamsesRenderer::createDisplayContext finished creating display"); @@ -552,7 +553,7 @@ namespace ramses::internal return m_platform.getSystemCompositorController() != nullptr; } - IDisplayController* Renderer::createDisplayControllerFromConfig(const DisplayConfig& config) + IDisplayController* Renderer::createDisplayControllerFromConfig(const DisplayConfigData& config) { IRenderBackend* renderBackend = m_platform.createRenderBackend(config, m_displayEventHandler); if (nullptr == renderBackend) diff --git a/src/renderer/internal/RendererLib/Renderer.h b/src/renderer/internal/RendererLib/Renderer.h index 2971dc1d4..a43d4aa1c 100644 --- a/src/renderer/internal/RendererLib/Renderer.h +++ b/src/renderer/internal/RendererLib/Renderer.h @@ -27,7 +27,7 @@ namespace ramses::internal class IDisplayController; class RendererCachedScene; class ISystemCompositorController; - class DisplayConfig; + class DisplayConfigData; class IPlatform; class RendererScenes; class RendererEventCollector; @@ -49,7 +49,7 @@ namespace ramses::internal RendererStatistics& rendererStatistics); virtual ~Renderer(); - void registerOffscreenBuffer (DeviceResourceHandle bufferDeviceHandle, uint32_t width, uint32_t height, bool isInterruptible); + void registerOffscreenBuffer (DeviceResourceHandle bufferDeviceHandle, uint32_t width, uint32_t height, uint32_t sampleCount, bool isInterruptible); void unregisterOffscreenBuffer (DeviceResourceHandle bufferDeviceHandle); void doOneRenderLoop(); @@ -67,7 +67,7 @@ namespace ramses::internal IDisplayController& getDisplayController(); [[nodiscard]] bool hasDisplayController() const; [[nodiscard]] const DisplaySetup& getDisplaySetup() const; - void createDisplayContext(const DisplayConfig& displayConfig); + void createDisplayContext(const DisplayConfigData& displayConfig); void destroyDisplayContext(); DisplayEventHandler& getDisplayEventHandler(); @@ -103,7 +103,7 @@ namespace ramses::internal std::atomic_int m_traceId{ 0 }; protected: - virtual IDisplayController* createDisplayControllerFromConfig(const DisplayConfig& config); + virtual IDisplayController* createDisplayControllerFromConfig(const DisplayConfigData& config); private: void handleDisplayEvents(); diff --git a/src/renderer/internal/RendererLib/RendererCachedScene.cpp b/src/renderer/internal/RendererLib/RendererCachedScene.cpp index a72edd54f..9fb6f371b 100644 --- a/src/renderer/internal/RendererLib/RendererCachedScene.cpp +++ b/src/renderer/internal/RendererLib/RendererCachedScene.cpp @@ -14,51 +14,51 @@ namespace ramses::internal { RendererCachedScene::RendererCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo) - : ResourceCachedScene(sceneLinksManager, sceneInfo) + : BaseT(sceneLinksManager, sceneInfo) , m_renderableOrderingDirty(true) { } void RendererCachedScene::setRenderableVisibility(RenderableHandle renderableHandle, EVisibilityMode visible) { - ResourceCachedScene::setRenderableVisibility(renderableHandle, visible); + BaseT::setRenderableVisibility(renderableHandle, visible); m_renderableOrderingDirty = true; } void RendererCachedScene::releaseRenderGroup(RenderGroupHandle groupHandle) { - ResourceCachedScene::releaseRenderGroup(groupHandle); + BaseT::releaseRenderGroup(groupHandle); m_renderableOrderingDirty = true; } void RendererCachedScene::addRenderableToRenderGroup(RenderGroupHandle groupHandle, RenderableHandle renderableHandle, int32_t order) { - ResourceCachedScene::addRenderableToRenderGroup(groupHandle, renderableHandle, order); + BaseT::addRenderableToRenderGroup(groupHandle, renderableHandle, order); m_renderableOrderingDirty = true; } void RendererCachedScene::removeRenderableFromRenderGroup(RenderGroupHandle groupHandle, RenderableHandle renderableHandle) { - ResourceCachedScene::removeRenderableFromRenderGroup(groupHandle, renderableHandle); + BaseT::removeRenderableFromRenderGroup(groupHandle, renderableHandle); m_renderableOrderingDirty = true; } void RendererCachedScene::releaseRenderPass(RenderPassHandle passHandle) { m_renderOncePassesToRender.remove(passHandle); - ResourceCachedScene::releaseRenderPass(passHandle); + BaseT::releaseRenderPass(passHandle); m_renderableOrderingDirty = true; } void RendererCachedScene::setRenderPassRenderOrder(RenderPassHandle passHandle, int32_t renderOrder) { - ResourceCachedScene::setRenderPassRenderOrder(passHandle, renderOrder); + BaseT::setRenderPassRenderOrder(passHandle, renderOrder); m_renderableOrderingDirty = true; } BlitPassHandle RendererCachedScene::allocateBlitPass(RenderBufferHandle sourceRenderBufferHandle, RenderBufferHandle destinationRenderBufferHandle, BlitPassHandle passHandle) { - const BlitPassHandle blitPass = ResourceCachedScene::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); + const BlitPassHandle blitPass = BaseT::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); m_renderableOrderingDirty = true; return blitPass; @@ -66,25 +66,25 @@ namespace ramses::internal void RendererCachedScene::releaseBlitPass(BlitPassHandle passHandle) { - ResourceCachedScene::releaseBlitPass(passHandle); + BaseT::releaseBlitPass(passHandle); m_renderableOrderingDirty = true; } void RendererCachedScene::setBlitPassRenderOrder(BlitPassHandle passHandle, int32_t renderOrder) { - ResourceCachedScene::setBlitPassRenderOrder(passHandle, renderOrder); + BaseT::setBlitPassRenderOrder(passHandle, renderOrder); m_renderableOrderingDirty = true; } void RendererCachedScene::setBlitPassEnabled(BlitPassHandle passHandle, bool isEnabled) { - ResourceCachedScene::setBlitPassEnabled(passHandle, isEnabled); + BaseT::setBlitPassEnabled(passHandle, isEnabled); m_renderableOrderingDirty = true; } TextureBufferHandle RendererCachedScene::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) { - auto resultHandle = TextureLinkCachedScene::allocateTextureBuffer(textureFormat, mipMapDimensions, handle); + auto resultHandle = BaseT::allocateTextureBuffer(textureFormat, mipMapDimensions, handle); m_textureBufferUpdates.resize(getTextureBufferCount()); auto& update = m_textureBufferUpdates[resultHandle.asMemoryHandle()]; update.resize(mipMapDimensions.size()); @@ -99,7 +99,7 @@ namespace ramses::internal void RendererCachedScene::updateTextureBuffer(TextureBufferHandle handle, uint32_t mipLevel, uint32_t x, uint32_t y, uint32_t width, uint32_t height, const std::byte* data) { - TextureLinkCachedScene::updateTextureBuffer(handle, mipLevel, x, y, width, height, data); + BaseT::updateTextureBuffer(handle, mipLevel, x, y, width, height, data); assert(handle.asMemoryHandle() < m_textureBufferUpdates.size()); auto& update = m_textureBufferUpdates[handle.asMemoryHandle()]; assert(mipLevel < update.size()); @@ -109,8 +109,8 @@ namespace ramses::internal void RendererCachedScene::setRenderPassEnabled(RenderPassHandle passHandle, bool isEnabled) { - ResourceCachedScene::setRenderPassEnabled(passHandle, isEnabled); - if (isEnabled && ResourceCachedScene::getRenderPass(passHandle).isRenderOnce) + BaseT::setRenderPassEnabled(passHandle, isEnabled); + if (isEnabled && BaseT::getRenderPass(passHandle).isRenderOnce) { m_renderOncePassesToRender.put(passHandle); } @@ -123,8 +123,8 @@ namespace ramses::internal void RendererCachedScene::setRenderPassRenderOnce(RenderPassHandle passHandle, bool enable) { - ResourceCachedScene::setRenderPassRenderOnce(passHandle, enable); - if (enable && ResourceCachedScene::getRenderPass(passHandle).isEnabled) + BaseT::setRenderPassRenderOnce(passHandle, enable); + if (enable && BaseT::getRenderPass(passHandle).isEnabled) { m_renderOncePassesToRender.put(passHandle); } @@ -137,8 +137,8 @@ namespace ramses::internal void RendererCachedScene::retriggerRenderPassRenderOnce(RenderPassHandle passHandle) { - ResourceCachedScene::retriggerRenderPassRenderOnce(passHandle); - if (ResourceCachedScene::getRenderPass(passHandle).isEnabled) + BaseT::retriggerRenderPassRenderOnce(passHandle); + if (BaseT::getRenderPass(passHandle).isEnabled) { m_renderOncePassesToRender.put(passHandle); m_renderableOrderingDirty = true; @@ -147,25 +147,25 @@ namespace ramses::internal void RendererCachedScene::addRenderGroupToRenderPass(RenderPassHandle passHandle, RenderGroupHandle groupHandle, int32_t order) { - ResourceCachedScene::addRenderGroupToRenderPass(passHandle, groupHandle, order); + BaseT::addRenderGroupToRenderPass(passHandle, groupHandle, order); m_renderableOrderingDirty = true; } void RendererCachedScene::removeRenderGroupFromRenderPass(RenderPassHandle passHandle, RenderGroupHandle groupHandle) { - ResourceCachedScene::removeRenderGroupFromRenderPass(passHandle, groupHandle); + BaseT::removeRenderGroupFromRenderPass(passHandle, groupHandle); m_renderableOrderingDirty = true; } void RendererCachedScene::addRenderGroupToRenderGroup(RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild, int32_t order) { - ResourceCachedScene::addRenderGroupToRenderGroup(groupHandleParent, groupHandleChild, order); + BaseT::addRenderGroupToRenderGroup(groupHandleParent, groupHandleChild, order); m_renderableOrderingDirty = true; } void RendererCachedScene::removeRenderGroupFromRenderGroup(RenderGroupHandle groupHandleParent, RenderGroupHandle groupHandleChild) { - ResourceCachedScene::removeRenderGroupFromRenderGroup(groupHandleParent, groupHandleChild); + BaseT::removeRenderGroupFromRenderGroup(groupHandleParent, groupHandleChild); m_renderableOrderingDirty = true; } @@ -192,8 +192,8 @@ namespace ramses::internal { m_sortedRenderingPasses.clear(); - const uint32_t totalNumberOfRenderPasses = ResourceCachedScene::getRenderPassCount(); - const uint32_t totalNumberOfBlitPasses = ResourceCachedScene::getBlitPassCount(); + const uint32_t totalNumberOfRenderPasses = BaseT::getRenderPassCount(); + const uint32_t totalNumberOfBlitPasses = BaseT::getBlitPassCount(); //add render passes m_passRenderableOrder.resize(totalNumberOfRenderPasses); @@ -207,9 +207,9 @@ namespace ramses::internal //add blit passes for (BlitPassHandle passHandle(0); passHandle < totalNumberOfBlitPasses; ++passHandle) { - if (ResourceCachedScene::isBlitPassAllocated(passHandle)) + if (BaseT::isBlitPassAllocated(passHandle)) { - const BlitPass& blitPass = ResourceCachedScene::getBlitPass(passHandle); + const BlitPass& blitPass = BaseT::getBlitPass(passHandle); if (blitPass.isEnabled) { assert(blitPass.sourceRenderBuffer.isValid()); @@ -309,7 +309,7 @@ namespace ramses::internal void RendererCachedScene::updateRenderableWorldMatrices() { - m_renderableMatrices.resize(ResourceCachedScene::getRenderableCount()); + m_renderableMatrices.resize(BaseT::getRenderableCount()); for (const auto& renderables : m_passRenderableOrder) { for (const auto renderable : renderables) @@ -324,13 +324,13 @@ namespace ramses::internal void RendererCachedScene::updateRenderableWorldMatricesWithLinks() { - m_renderableMatrices.resize(ResourceCachedScene::getRenderableCount()); + m_renderableMatrices.resize(BaseT::getRenderableCount()); for (const auto& renderables : m_passRenderableOrder) { for (const auto renderable : renderables) { assert(renderable.isValid()); - const NodeHandle node = ResourceCachedScene::getRenderable(renderable).node; + const NodeHandle node = BaseT::getRenderable(renderable).node; assert(node.isValid()); m_renderableMatrices[renderable.asMemoryHandle()] = updateMatrixCacheWithLinks(ETransformationMatrixType_World, node); } @@ -339,12 +339,12 @@ namespace ramses::internal bool RendererCachedScene::shouldRenderPassBeRendered(RenderPassHandle handle) const { - if (!ResourceCachedScene::isRenderPassAllocated(handle)) + if (!BaseT::isRenderPassAllocated(handle)) { return false; } - const RenderPass& rp = ResourceCachedScene::getRenderPass(handle); + const RenderPass& rp = BaseT::getRenderPass(handle); if (!rp.camera.isValid() || !rp.isEnabled) { return false; @@ -355,10 +355,10 @@ namespace ramses::internal void RendererCachedScene::retriggerAllRenderOncePasses() { - const uint32_t numRPs = ResourceCachedScene::getRenderPassCount(); + const uint32_t numRPs = BaseT::getRenderPassCount(); for (RenderPassHandle handle(0u); handle < numRPs; ++handle) { - if (ResourceCachedScene::isRenderPassAllocated(handle)) + if (BaseT::isRenderPassAllocated(handle)) { const auto& rp = getRenderPass(handle); if (rp.isEnabled && rp.isRenderOnce) diff --git a/src/renderer/internal/RendererLib/RendererCachedScene.h b/src/renderer/internal/RendererLib/RendererCachedScene.h index 315e46fd1..6feac49d0 100644 --- a/src/renderer/internal/RendererLib/RendererCachedScene.h +++ b/src/renderer/internal/RendererLib/RendererCachedScene.h @@ -9,7 +9,7 @@ #pragma once #include "internal/RendererLib/ResourceCachedScene.h" -#include "RenderingPassInfo.h" +#include "internal/RendererLib/RenderingPassInfo.h" namespace ramses::internal { @@ -17,6 +17,8 @@ namespace ramses::internal class RendererCachedScene final : public ResourceCachedScene { + using BaseT = ResourceCachedScene; + public: explicit RendererCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo = SceneInfo()); diff --git a/src/renderer/internal/RendererLib/RendererCommands.h b/src/renderer/internal/RendererLib/RendererCommands.h index 3d0d335ca..d299a421c 100644 --- a/src/renderer/internal/RendererLib/RendererCommands.h +++ b/src/renderer/internal/RendererLib/RendererCommands.h @@ -13,7 +13,7 @@ #include "internal/RendererLib/Types.h" #include "internal/SceneGraph/Scene/EScenePublicationMode.h" #include "internal/Components/SceneUpdate.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/PlatformAbstraction/VariantWrapper.h" #include "impl/DataTypesImpl.h" @@ -30,6 +30,9 @@ namespace ramses::internal { SceneId scene; EScenePublicationMode publicationMode = EScenePublicationMode::LocalAndRemote; + ERenderBackendCompatibility renderBackendCompatibility = ERenderBackendCompatibility::OpenGL; + EVulkanAPIVersion vulkanAPIVersion = EVulkanAPIVersion::Invalid; + ESPIRVVersion spirvVersion = ESPIRVVersion::Invalid; }; struct SceneUnpublished @@ -111,7 +114,7 @@ namespace ramses::internal struct CreateDisplay { DisplayHandle display; - DisplayConfig config; + DisplayConfigData config; IBinaryShaderCache* binaryShaderCache{nullptr}; }; diff --git a/src/renderer/internal/RendererLib/RendererConfig.cpp b/src/renderer/internal/RendererLib/RendererConfigData.cpp similarity index 59% rename from src/renderer/internal/RendererLib/RendererConfig.cpp rename to src/renderer/internal/RendererLib/RendererConfigData.cpp index d36bd53e2..d43f773f8 100644 --- a/src/renderer/internal/RendererLib/RendererConfig.cpp +++ b/src/renderer/internal/RendererLib/RendererConfigData.cpp @@ -6,47 +6,47 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "internal/PlatformAbstraction/Collections/StringOutputStream.h" namespace ramses::internal { - void RendererConfig::enableSystemCompositorControl() + void RendererConfigData::enableSystemCompositorControl() { m_systemCompositorEnabled = true; } - bool RendererConfig::getSystemCompositorControlEnabled() const + bool RendererConfigData::getSystemCompositorControlEnabled() const { return m_systemCompositorEnabled; } - std::chrono::microseconds RendererConfig::getFrameCallbackMaxPollTime() const + std::chrono::microseconds RendererConfigData::getFrameCallbackMaxPollTime() const { return m_frameCallbackMaxPollTime; } - void RendererConfig::setFrameCallbackMaxPollTime(std::chrono::microseconds pollTime) + void RendererConfigData::setFrameCallbackMaxPollTime(std::chrono::microseconds pollTime) { m_frameCallbackMaxPollTime = pollTime; } - void RendererConfig::setWaylandDisplayForSystemCompositorController(std::string_view wd) + void RendererConfigData::setWaylandDisplayForSystemCompositorController(std::string_view wd) { m_waylandDisplayForSystemCompositorController = wd; } - std::string_view RendererConfig::getWaylandDisplayForSystemCompositorController() const + std::string_view RendererConfigData::getWaylandDisplayForSystemCompositorController() const { return m_waylandDisplayForSystemCompositorController; } - void RendererConfig::setRenderthreadLooptimingReportingPeriod(std::chrono::milliseconds period) + void RendererConfigData::setRenderthreadLooptimingReportingPeriod(std::chrono::milliseconds period) { m_renderThreadLoopTimingReportingPeriod = period; } - std::chrono::milliseconds RendererConfig::getRenderThreadLoopTimingReportingPeriod() const + std::chrono::milliseconds RendererConfigData::getRenderThreadLoopTimingReportingPeriod() const { return m_renderThreadLoopTimingReportingPeriod; } diff --git a/src/renderer/internal/RendererLib/RendererConfig.h b/src/renderer/internal/RendererLib/RendererConfigData.h similarity index 98% rename from src/renderer/internal/RendererLib/RendererConfig.h rename to src/renderer/internal/RendererLib/RendererConfigData.h index 624a91cba..c9b8391dd 100644 --- a/src/renderer/internal/RendererLib/RendererConfig.h +++ b/src/renderer/internal/RendererLib/RendererConfigData.h @@ -15,7 +15,7 @@ namespace ramses::internal { - class RendererConfig + class RendererConfigData { public: void setWaylandDisplayForSystemCompositorController(std::string_view wd); diff --git a/src/renderer/internal/RendererLib/RendererEvent.h b/src/renderer/internal/RendererLib/RendererEvent.h index 023ff110f..748b692d3 100644 --- a/src/renderer/internal/RendererLib/RendererEvent.h +++ b/src/renderer/internal/RendererLib/RendererEvent.h @@ -18,7 +18,7 @@ #include "internal/RendererLib/Enums/EKeyEvent.h" #include "internal/RendererLib/Enums/EKeyCode.h" #include "internal/RendererLib/Enums/EKeyModifier.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LoggingUtils.h" #include @@ -194,7 +194,7 @@ namespace ramses::internal SceneId sceneId; RendererSceneState state = RendererSceneState::Unavailable; DisplayHandle displayHandle; - DisplayConfig displayConfig; + DisplayConfigData displayConfig; std::vector pixelData; SceneId providerSceneId; SceneId consumerSceneId; diff --git a/src/renderer/internal/RendererLib/RendererEventCollector.cpp b/src/renderer/internal/RendererLib/RendererEventCollector.cpp index 0bd39f44b..8686fcd55 100644 --- a/src/renderer/internal/RendererLib/RendererEventCollector.cpp +++ b/src/renderer/internal/RendererLib/RendererEventCollector.cpp @@ -36,7 +36,7 @@ namespace ramses::internal return m_sceneControlEvents; } - void RendererEventCollector::addDisplayEvent(ERendererEventType eventType, DisplayHandle displayHandle, const DisplayConfig& config) + void RendererEventCollector::addDisplayEvent(ERendererEventType eventType, DisplayHandle displayHandle, const DisplayConfigData& config) { LOG_INFO(CONTEXT_RENDERER, "{} display={}", eventType, displayHandle); diff --git a/src/renderer/internal/RendererLib/RendererEventCollector.h b/src/renderer/internal/RendererLib/RendererEventCollector.h index 6b3a4c046..7c3760271 100644 --- a/src/renderer/internal/RendererLib/RendererEventCollector.h +++ b/src/renderer/internal/RendererLib/RendererEventCollector.h @@ -21,7 +21,7 @@ namespace ramses::internal [[nodiscard]] RendererEventVector getRendererEvents() const; [[nodiscard]] RendererEventVector getSceneControlEvents() const; - void addDisplayEvent(ERendererEventType eventType, DisplayHandle displayHandle, const DisplayConfig& config = {}); + void addDisplayEvent(ERendererEventType eventType, DisplayHandle displayHandle, const DisplayConfigData& config = {}); void addReadPixelsEvent(ERendererEventType eventType, DisplayHandle displayHandle, OffscreenBufferHandle offscreenBufferHandle, std::vector&& pixelData); void addInternalSceneEvent(ERendererEventType eventType, SceneId sceneId); void addSceneEvent(ERendererEventType eventType, SceneId sceneId, RendererSceneState state); diff --git a/src/renderer/internal/RendererLib/RendererFrameworkLogic.cpp b/src/renderer/internal/RendererLib/RendererFrameworkLogic.cpp index 6e4694926..2c7f8cb0b 100644 --- a/src/renderer/internal/RendererLib/RendererFrameworkLogic.cpp +++ b/src/renderer/internal/RendererLib/RendererFrameworkLogic.cpp @@ -41,11 +41,11 @@ namespace ramses::internal if (m_sceneClients.contains(newScene.sceneID)) { - LOG_WARN(CONTEXT_RENDERER, "RendererFrameworkLogic::handleNewScenesAvailable: ignore already published scene: {} @ {} name:{} publicationmode: {}", newScene.sceneID, providerID, newScene.friendlyName, EnumToString(newScene.publicationMode)); + LOG_WARN(CONTEXT_RENDERER, "RendererFrameworkLogic::handleNewScenesAvailable: ignore already published scene: {} @ {} name:{} publicationmode: {} renderBackendCompatibility: {}", newScene.sceneID, providerID, newScene.friendlyName, EnumToString(newScene.publicationMode), newScene.renderBackendCompatibility); return; } m_sceneClients.put(newScene.sceneID, std::make_pair(providerID, newScene.friendlyName)); - m_rendererCommands.enqueueCommand(RendererCommand::ScenePublished{ newScene.sceneID, newScene.publicationMode }); + m_rendererCommands.enqueueCommand(RendererCommand::ScenePublished{ newScene.sceneID, newScene.publicationMode, newScene.renderBackendCompatibility, newScene.vulkanAPIVersion, newScene.spirvVersion }); } void RendererFrameworkLogic::handleSceneBecameUnavailable(const SceneId& unavailableScene, const Guid& providerID) diff --git a/src/renderer/internal/RendererLib/RendererLogger.cpp b/src/renderer/internal/RendererLib/RendererLogger.cpp index 7a5bf0117..156609f14 100644 --- a/src/renderer/internal/RendererLib/RendererLogger.cpp +++ b/src/renderer/internal/RendererLib/RendererLogger.cpp @@ -410,13 +410,13 @@ namespace ramses::internal const RenderBuffer& rbDesc = *rb.second; if (context.isLogLevelFlagEnabled(ERendererLogLevelFlag_Details)) { - const auto deviceHandle = resRegistry.getRenderBufferDeviceHandle(rb.first); + const auto deviceHandle = resRegistry.get(rb.first).deviceHandle; context << rb.first << " (deviceHandle=" << deviceHandle << " GPUhandle=" << device.getGPUHandle(deviceHandle) << ") "; context << "[" << rbDesc.width << "x" << rbDesc.height << "; " << EnumToString(rbDesc.format) << "; " << EnumToString(rbDesc.accessMode) << "; " << rbDesc.sampleCount << " samples] "; - context << resRegistry.getRenderBufferByteSize(rb.first) / 1024 << " KB"; + context << resRegistry.get(rb.first).size / 1024 << " KB"; context << RendererLogContext::NewLine; } - size += resRegistry.getRenderBufferByteSize(rb.first); + size += resRegistry.get(rb.first).size; } context << "Total KB: " << size / 1024 << RendererLogContext::NewLine; context.unindent(); @@ -430,7 +430,7 @@ namespace ramses::internal context.indent(); for (const auto& rt : renderTargets) { - const auto deviceHandle = resRegistry.getRenderTargetDeviceHandle(rt.first); + const auto deviceHandle = resRegistry.get(rt.first); context << rt.first << " (deviceHandle=" << deviceHandle << " GPUhandle=" << device.getGPUHandle(deviceHandle) << ") "; context << "renderBuffer handles: [ "; for (uint32_t i = 0u; i < scene.getRenderTargetRenderBufferCount(rt.first); ++i) @@ -468,14 +468,14 @@ namespace ramses::internal const TextureBuffer& tbDesc = *tb.second; if (context.isLogLevelFlagEnabled(ERendererLogLevelFlag_Details)) { - context << tb.first << " (deviceHandle " << resRegistry.getTextureBufferDeviceHandle(tb.first) << ") " << EnumToString(tbDesc.textureFormat); + context << tb.first << " (deviceHandle " << resRegistry.get(tb.first).deviceHandle << ") " << EnumToString(tbDesc.textureFormat); context << " mips: "; for (const auto& mip : tbDesc.mipMaps) context << "[" << mip.width << "x" << mip.height << "] "; - context << resRegistry.getTextureBufferByteSize(tb.first) / 1024 << " KB"; + context << resRegistry.get(tb.first).size / 1024 << " KB"; context << RendererLogContext::NewLine; } - size += resRegistry.getTextureBufferByteSize(tb.first); + size += resRegistry.get(tb.first).size; } context << "Total KB: " << size / 1024 << RendererLogContext::NewLine; context.unindent(); @@ -492,7 +492,7 @@ namespace ramses::internal const GeometryDataBuffer& dbDesc = *db.second; if (context.isLogLevelFlagEnabled(ERendererLogLevelFlag_Details)) { - context << db.first << " (deviceHandle " << resRegistry.getDataBufferDeviceHandle(db.first) << ") "; + context << db.first << " (deviceHandle " << resRegistry.get(db.first).deviceHandle << ") "; context << EnumToString(dbDesc.bufferType) << " " << EnumToString(dbDesc.dataType); context << " size used/allocated in B: " << dbDesc.usedSize << "/" << dbDesc.data.size(); context << RendererLogContext::NewLine; diff --git a/src/renderer/internal/RendererLib/RendererResourceManager.cpp b/src/renderer/internal/RendererLib/RendererResourceManager.cpp index 90db0eceb..75919fe3b 100644 --- a/src/renderer/internal/RendererLib/RendererResourceManager.cpp +++ b/src/renderer/internal/RendererLib/RendererResourceManager.cpp @@ -27,9 +27,9 @@ namespace ramses::internal RendererResourceManager::RendererResourceManager( IRenderBackend& renderBackend, std::unique_ptr resourceUploader, - AsyncEffectUploader& asyncEffectUploader, + AsyncEffectUploader* asyncEffectUploader, IEmbeddedCompositingManager& embeddedCompositingManager, - const DisplayConfig& displayConfig, + const DisplayConfigData& displayConfig, const FrameTimer& frameTimer, RendererStatistics& stats) : m_renderBackend(renderBackend) @@ -113,36 +113,30 @@ namespace ramses::internal { RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - RenderTargetHandleVector renderTargets; - sceneResources.getAllRenderTargets(renderTargets); - for (const auto& rt : renderTargets) + for (const auto& rt : sceneResources.getAll()) unloadRenderTarget(rt, sceneId); - BlitPassHandleVector blitPasses; - sceneResources.getAllBlitPasses(blitPasses); - for (const auto& bp : blitPasses) + for (const auto& bp : sceneResources.getAll()) unloadBlitPassRenderTargets(bp, sceneId); - RenderBufferHandleVector renderBuffers; - sceneResources.getAllRenderBuffers(renderBuffers); - for(const auto& rb : renderBuffers) + for(const auto& rb : sceneResources.getAll()) unloadRenderTargetBuffer(rb, sceneId); - RenderableVector vertexArrayRenderables; - sceneResources.getAllVertexArrayRenderables(vertexArrayRenderables); - for (const auto r : vertexArrayRenderables) + for (const auto r : sceneResources.getAll()) unloadVertexArray(r, sceneId); - DataBufferHandleVector dataBuffers; - sceneResources.getAllDataBuffers(dataBuffers); - for (const auto db : dataBuffers) + for (const auto db : sceneResources.getAll()) unloadDataBuffer(db, sceneId); - TextureBufferHandleVector textureBuffers; - sceneResources.getAllTextureBuffers(textureBuffers); - for (const auto tb : textureBuffers) + for (const auto tb : sceneResources.getAll()) unloadTextureBuffer(tb, sceneId); + for (const auto ub : sceneResources.getAll()) + unloadUniformBuffer(ub, sceneId); + + for (const auto sub : sceneResources.getAll()) + unloadUniformBuffer(sub, sceneId); + m_sceneResourceRegistryMap.remove(sceneId); } } @@ -204,14 +198,14 @@ namespace ramses::internal { assert(m_sceneResourceRegistryMap.contains(sceneId)); const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - return sceneResources.getRenderTargetDeviceHandle(handle); + return sceneResources.get(handle); } DeviceResourceHandle RendererResourceManager::getRenderTargetBufferDeviceHandle(RenderBufferHandle bufferHandle, SceneId sceneId) const { assert(m_sceneResourceRegistryMap.contains(sceneId)); const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - return sceneResources.getRenderBufferDeviceHandle(bufferHandle); + return sceneResources.get(bufferHandle).deviceHandle; } void RendererResourceManager::getBlitPassRenderTargetsDeviceHandle(BlitPassHandle blitPassHandle, SceneId sceneId, DeviceResourceHandle& srcRT, DeviceResourceHandle& dstRT) const @@ -319,7 +313,7 @@ namespace ramses::internal std::ignore = device.isDeviceStatusHealthy(); } - sceneResources.addRenderBuffer(renderBufferHandle, deviceHandle, memSize, renderBuffer); + sceneResources.add(renderBufferHandle, deviceHandle, memSize, renderBuffer); m_stats.sceneResourceUploaded(sceneId, memSize); } @@ -331,8 +325,8 @@ namespace ramses::internal RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); IDevice& device = m_renderBackend.getDevice(); - device.deleteRenderBuffer(sceneResources.getRenderBufferDeviceHandle(renderBufferHandle)); - sceneResources.removeRenderBuffer(renderBufferHandle); + device.deleteRenderBuffer(sceneResources.get(renderBufferHandle).deviceHandle); + sceneResources.remove(renderBufferHandle); } void RendererResourceManager::updateRenderTargetBufferProperties(RenderBufferHandle renderBufferHandle, SceneId sceneId, const RenderBuffer& renderBuffer) @@ -343,7 +337,7 @@ namespace ramses::internal assert(m_sceneResourceRegistryMap.contains(sceneId)); RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - const RenderBuffer& uploadedRenderBufferProperties = sceneResources.getRenderBufferProperties(renderBufferHandle); + const RenderBuffer& uploadedRenderBufferProperties = sceneResources.get(renderBufferHandle).renderBufferProperties; if (renderBuffer.width != uploadedRenderBufferProperties.width || renderBuffer.height != uploadedRenderBufferProperties.height || renderBuffer.sampleCount != uploadedRenderBufferProperties.sampleCount || @@ -370,7 +364,7 @@ namespace ramses::internal rtBufferDeviceHandles.reserve(rtBufferHandles.size()); for(const auto& rb : rtBufferHandles) { - const DeviceResourceHandle rbDeviceHandle = sceneResources.getRenderBufferDeviceHandle(rb); + const DeviceResourceHandle rbDeviceHandle = sceneResources.get(rb).deviceHandle; assert(rbDeviceHandle.isValid()); rtBufferDeviceHandles.push_back(rbDeviceHandle); } @@ -378,7 +372,7 @@ namespace ramses::internal IDevice& device = m_renderBackend.getDevice(); const DeviceResourceHandle rtDeviceHandle = device.uploadRenderTarget(rtBufferDeviceHandles); - sceneResources.addRenderTarget(renderTarget, rtDeviceHandle); + sceneResources.add(renderTarget, rtDeviceHandle); } void RendererResourceManager::unloadRenderTarget(RenderTargetHandle renderTarget, SceneId sceneId) @@ -387,10 +381,10 @@ namespace ramses::internal assert(m_sceneResourceRegistryMap.contains(sceneId)); RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - const DeviceResourceHandle rtDeviceHandle = sceneResources.getRenderTargetDeviceHandle(renderTarget); + const DeviceResourceHandle rtDeviceHandle = sceneResources.get(renderTarget); IDevice& device = m_renderBackend.getDevice(); device.deleteRenderTarget(rtDeviceHandle); - sceneResources.removeRenderTarget(renderTarget); + sceneResources.remove(renderTarget); } void RendererResourceManager::uploadDmaOffscreenBuffer(OffscreenBufferHandle bufferHandle, uint32_t width, uint32_t height, DmaBufferFourccFormat dmaBufferFourccFormat, DmaBufferUsageFlags dmaBufferUsageFlags, DmaBufferModifiers dmaBufferModifiers) @@ -574,8 +568,8 @@ namespace ramses::internal assert(destinationRenderBuffer.isValid()); RendererSceneResourceRegistry& sceneResources = getSceneResourceRegistry(sceneId); - const DeviceResourceHandle sourceRenderBufferDeviceHandle = sceneResources.getRenderBufferDeviceHandle(sourceRenderBuffer); - const DeviceResourceHandle destinationRenderBufferDeviceHandle = sceneResources.getRenderBufferDeviceHandle(destinationRenderBuffer); + const DeviceResourceHandle sourceRenderBufferDeviceHandle = sceneResources.get(sourceRenderBuffer).deviceHandle; + const DeviceResourceHandle destinationRenderBufferDeviceHandle = sceneResources.get(destinationRenderBuffer).deviceHandle; assert(sourceRenderBufferDeviceHandle.isValid() && destinationRenderBufferDeviceHandle.isValid()); IDevice& device = m_renderBackend.getDevice(); @@ -592,7 +586,7 @@ namespace ramses::internal std::ignore = device.isDeviceStatusHealthy(); } - sceneResources.addBlitPass(blitPass, blitRtSource, blitRtDest); + sceneResources.add(blitPass, blitRtSource, blitRtDest); } void RendererResourceManager::unloadBlitPassRenderTargets(BlitPassHandle blitPass, SceneId sceneId) @@ -605,7 +599,7 @@ namespace ramses::internal DeviceResourceHandle srcRTDeviceHandle; DeviceResourceHandle dstRTDeviceHandle; sceneResources.getBlitPassDeviceHandles(blitPass, srcRTDeviceHandle, dstRTDeviceHandle); - sceneResources.removeBlitPass(blitPass); + sceneResources.remove(blitPass); IDevice& device = m_renderBackend.getDevice(); device.deleteRenderTarget(srcRTDeviceHandle); @@ -642,7 +636,7 @@ namespace ramses::internal std::ignore = device.isDeviceStatusHealthy(); } - sceneResources.addDataBuffer(dataBufferHandle, deviceHandle, dataBufferType, dataSizeInBytes); + sceneResources.add(dataBufferHandle, deviceHandle, dataBufferType, dataSizeInBytes); m_stats.sceneResourceUploaded(sceneId, dataSizeInBytes); } @@ -651,9 +645,9 @@ namespace ramses::internal assert(m_sceneResourceRegistryMap.contains(sceneId)); RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - const DeviceResourceHandle deviceHandle = sceneResources.getDataBufferDeviceHandle(dataBufferHandle); + const DeviceResourceHandle deviceHandle = sceneResources.get(dataBufferHandle).deviceHandle; assert(deviceHandle.isValid()); - const EDataBufferType dataBufferType = sceneResources.getDataBufferType(dataBufferHandle); + const EDataBufferType dataBufferType = sceneResources.get(dataBufferHandle).dataBufferType; IDevice& device = m_renderBackend.getDevice(); switch (dataBufferType) @@ -669,7 +663,7 @@ namespace ramses::internal assert(false); } - sceneResources.removeDataBuffer(dataBufferHandle); + sceneResources.remove(dataBufferHandle); } void RendererResourceManager::updateDataBuffer(DataBufferHandle handle, uint32_t dataSizeInBytes, const std::byte* data, SceneId sceneId) @@ -677,9 +671,9 @@ namespace ramses::internal assert(m_sceneResourceRegistryMap.contains(sceneId)); const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - const DeviceResourceHandle deviceHandle = sceneResources.getDataBufferDeviceHandle(handle); + const DeviceResourceHandle deviceHandle = sceneResources.get(handle).deviceHandle; assert(deviceHandle.isValid()); - const EDataBufferType dataBufferType = sceneResources.getDataBufferType(handle); + const EDataBufferType dataBufferType = sceneResources.get(handle).dataBufferType; IDevice& device = m_renderBackend.getDevice(); switch (dataBufferType) @@ -701,7 +695,7 @@ namespace ramses::internal { assert(m_sceneResourceRegistryMap.contains(sceneId)); const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - return sceneResources.getDataBufferDeviceHandle(dataBufferHandle); + return sceneResources.get(dataBufferHandle).deviceHandle; } void RendererResourceManager::uploadTextureBuffer(TextureBufferHandle textureBufferHandle, uint32_t width, uint32_t height, EPixelStorageFormat textureFormat, uint32_t mipLevelCount, SceneId sceneId) @@ -724,7 +718,7 @@ namespace ramses::internal std::ignore = device.isDeviceStatusHealthy(); } - sceneResources.addTextureBuffer(textureBufferHandle, deviceHandle, textureFormat, totalSizeInBytes); + sceneResources.add(textureBufferHandle, deviceHandle, textureFormat, totalSizeInBytes); m_stats.sceneResourceUploaded(sceneId, totalSizeInBytes); } @@ -733,12 +727,12 @@ namespace ramses::internal assert(m_sceneResourceRegistryMap.contains(sceneId)); RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - const DeviceResourceHandle deviceHandle = sceneResources.getTextureBufferDeviceHandle(textureBufferHandle); + const DeviceResourceHandle deviceHandle = sceneResources.get(textureBufferHandle).deviceHandle; assert(deviceHandle.isValid()); IDevice& device = m_renderBackend.getDevice(); device.deleteTexture(deviceHandle); - sceneResources.removeTextureBuffer(textureBufferHandle); + sceneResources.remove(textureBufferHandle); } void RendererResourceManager::updateTextureBuffer(TextureBufferHandle textureBufferHandle, uint32_t mipLevel, const Quad& area, uint32_t stride, const std::byte* data, SceneId sceneId) @@ -746,14 +740,14 @@ namespace ramses::internal assert(m_sceneResourceRegistryMap.contains(sceneId)); const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - const DeviceResourceHandle deviceHandle = sceneResources.getTextureBufferDeviceHandle(textureBufferHandle); + const DeviceResourceHandle deviceHandle = sceneResources.get(textureBufferHandle).deviceHandle; assert(deviceHandle.isValid()); IDevice& device = m_renderBackend.getDevice(); device.bindTexture(deviceHandle); device.uploadTextureData(deviceHandle, mipLevel, area.x, area.y, 0u, area.width, area.height, 1u, data, 0u, stride); - const uint32_t updateDataSizeInBytes = TextureMathUtils::GetTotalMemoryUsedByMipmappedTexture(GetTexelSizeFromFormat(sceneResources.getTextureBufferFormat(textureBufferHandle)), area.width, area.height, 1u, 1u); + const uint32_t updateDataSizeInBytes = TextureMathUtils::GetTotalMemoryUsedByMipmappedTexture(GetTexelSizeFromFormat(sceneResources.get(textureBufferHandle).format), area.width, area.height, 1u, 1u); m_stats.sceneResourceUploaded(sceneId, updateDataSizeInBytes); } @@ -761,7 +755,7 @@ namespace ramses::internal { assert(m_sceneResourceRegistryMap.contains(sceneId)); const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - return sceneResources.getTextureBufferDeviceHandle(textureBufferHandle); + return sceneResources.get(textureBufferHandle).deviceHandle; } void RendererResourceManager::uploadVertexArray(RenderableHandle renderableHandle, const VertexArrayInfo& vertexArrayInfo, SceneId sceneId) @@ -777,22 +771,106 @@ namespace ramses::internal } RendererSceneResourceRegistry& sceneResources = getSceneResourceRegistry(sceneId); - sceneResources.addVertexArray(renderableHandle, deviceHandle); + sceneResources.add(renderableHandle, deviceHandle); } void RendererResourceManager::unloadVertexArray(RenderableHandle renderableHandle, SceneId sceneId) { assert(m_sceneResourceRegistryMap.contains(sceneId)); RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - const auto deviceHandle = sceneResources.getVertexArrayDeviceHandle(renderableHandle); + const auto deviceHandle = sceneResources.get(renderableHandle); m_renderBackend.getDevice().deleteVertexArray(deviceHandle); - sceneResources.removeVertexArray(renderableHandle); + sceneResources.remove(renderableHandle); } DeviceResourceHandle RendererResourceManager::getVertexArrayDeviceHandle(RenderableHandle renderableHandle, SceneId sceneId) const { assert(m_sceneResourceRegistryMap.contains(sceneId)); const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); - return sceneResources.getVertexArrayDeviceHandle(renderableHandle); + return sceneResources.get(renderableHandle); + } + + void RendererResourceManager::uploadUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t size, SceneId sceneId) + { + auto& device = m_renderBackend.getDevice(); + const auto deviceHandle = device.allocateUniformBuffer(size); + if (!deviceHandle.isValid()) + { + LOG_ERROR(CONTEXT_RENDERER, "RendererResourceManager::uploadUniformBuffer sceneId={} uniformBufferHandle={} failed to allocate uniform buffer, this is fatal...", + sceneId, uniformBufferHandle); + std::ignore = device.isDeviceStatusHealthy(); + } + assert(deviceHandle.isValid()); + + RendererSceneResourceRegistry& sceneResources = getSceneResourceRegistry(sceneId); + sceneResources.add(uniformBufferHandle, deviceHandle); + } + + void RendererResourceManager::unloadUniformBuffer(UniformBufferHandle uniformBufferHandle, SceneId sceneId) + { + assert(m_sceneResourceRegistryMap.contains(sceneId)); + RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); + const auto deviceHandle = sceneResources.get(uniformBufferHandle); + m_renderBackend.getDevice().deleteUniformBuffer(deviceHandle); + sceneResources.remove(uniformBufferHandle); + } + + void RendererResourceManager::updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t dataSize, const std::byte* data, SceneId sceneId) + { + assert(m_sceneResourceRegistryMap.contains(sceneId)); + const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); + + const DeviceResourceHandle deviceHandle = sceneResources.get(uniformBufferHandle); + assert(deviceHandle.isValid()); + + IDevice& device = m_renderBackend.getDevice(); + device.uploadUniformBufferData(deviceHandle, data, dataSize); + } + + DeviceResourceHandle RendererResourceManager::getUniformBufferDeviceHandle(UniformBufferHandle uniformBufferHandle, SceneId sceneId) const + { + assert(m_sceneResourceRegistryMap.contains(sceneId)); + const RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); + return sceneResources.get(uniformBufferHandle); + } + + DeviceResourceHandle RendererResourceManager::uploadUniformBuffer(SemanticUniformBufferHandle handle, uint32_t size, SceneId sceneId) + { + auto& device = m_renderBackend.getDevice(); + const auto deviceHandle = device.allocateUniformBuffer(size); + if (!deviceHandle.isValid()) + { + LOG_ERROR(CONTEXT_RENDERER, "RendererResourceManager::uploadUniformBuffer sceneId={} handle={} failed to allocate uniform buffer, this is fatal...", + sceneId, handle); + std::ignore = device.isDeviceStatusHealthy(); + } + assert(deviceHandle.isValid()); + + getSceneResourceRegistry(sceneId).add(handle, deviceHandle); + + return deviceHandle; + } + + void RendererResourceManager::unloadUniformBuffer(SemanticUniformBufferHandle handle, SceneId sceneId) + { + assert(m_sceneResourceRegistryMap.contains(sceneId)); + RendererSceneResourceRegistry& sceneResources = *m_sceneResourceRegistryMap.get(sceneId); + const auto deviceHandle = sceneResources.get(handle); + m_renderBackend.getDevice().deleteUniformBuffer(deviceHandle); + sceneResources.remove(handle); + } + + void RendererResourceManager::updateUniformBuffer(SemanticUniformBufferHandle handle, uint32_t dataSize, const std::byte* data, SceneId sceneId) + { + assert(m_sceneResourceRegistryMap.contains(sceneId)); + const DeviceResourceHandle deviceHandle = m_sceneResourceRegistryMap.get(sceneId)->get(handle); + assert(deviceHandle.isValid()); + m_renderBackend.getDevice().uploadUniformBufferData(deviceHandle, data, dataSize); + } + + DeviceResourceHandle RendererResourceManager::getUniformBufferDeviceHandle(SemanticUniformBufferHandle handle, SceneId sceneId) const + { + assert(m_sceneResourceRegistryMap.contains(sceneId)); + return m_sceneResourceRegistryMap.get(sceneId)->get(handle); } } diff --git a/src/renderer/internal/RendererLib/RendererResourceManager.h b/src/renderer/internal/RendererLib/RendererResourceManager.h index cbbdb9792..fcf7f5c09 100644 --- a/src/renderer/internal/RendererLib/RendererResourceManager.h +++ b/src/renderer/internal/RendererLib/RendererResourceManager.h @@ -12,6 +12,7 @@ #include "internal/RendererLib/RendererResourceRegistry.h" #include "internal/RendererLib/RendererSceneResourceRegistry.h" #include "internal/RendererLib/ResourceUploadingManager.h" +#include "internal/RendererLib/SemanticUniformBufferHandle.h" #include "internal/PlatformAbstraction/Collections/HashMap.h" #include "internal/PlatformAbstraction/Collections/Vector.h" #include "internal/Core/Utils/MemoryPool.h" @@ -26,7 +27,7 @@ namespace ramses::internal class RendererStatistics; class IBinaryShaderCache; class IResourceUploader; - class DisplayConfig; + class DisplayConfigData; class RendererResourceManager final : public IRendererResourceManager { @@ -34,9 +35,9 @@ namespace ramses::internal RendererResourceManager( IRenderBackend& renderBackend, std::unique_ptr resourceUploader, - AsyncEffectUploader& asyncEffectUploader, + AsyncEffectUploader* asyncEffectUploader, IEmbeddedCompositingManager& embeddedCompositingManager, - const DisplayConfig& displayConfig, + const DisplayConfigData& displayConfig, const FrameTimer& frameTimer, RendererStatistics& stats); ~RendererResourceManager() override; @@ -92,6 +93,16 @@ namespace ramses::internal void unloadVertexArray(RenderableHandle renderableHandle, SceneId sceneId) override; [[nodiscard]] DeviceResourceHandle getVertexArrayDeviceHandle(RenderableHandle renderableHandle, SceneId sceneId) const override; + void uploadUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t size, SceneId sceneId) override; + void unloadUniformBuffer(UniformBufferHandle uniformBufferHandle, SceneId sceneId) override; + void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t dataSize, const std::byte* data, SceneId sceneId) override; + [[nodiscard]] DeviceResourceHandle getUniformBufferDeviceHandle(UniformBufferHandle uniformBufferHandle, SceneId sceneId) const override; + + DeviceResourceHandle uploadUniformBuffer(SemanticUniformBufferHandle handle, uint32_t size, SceneId sceneId) override; + void unloadUniformBuffer(SemanticUniformBufferHandle handle, SceneId sceneId) override; + void updateUniformBuffer(SemanticUniformBufferHandle handle, uint32_t size, const std::byte* data, SceneId sceneId) override; + [[nodiscard]] DeviceResourceHandle getUniformBufferDeviceHandle(SemanticUniformBufferHandle handle, SceneId sceneId) const override; + void unloadAllSceneResourcesForScene(SceneId sceneId) override; void unreferenceAllResourcesForScene(SceneId sceneId) override; [[nodiscard]] const ResourceContentHashVector* getResourcesInUseByScene(SceneId sceneId) const override; diff --git a/src/renderer/internal/RendererLib/RendererSceneControlLogic.cpp b/src/renderer/internal/RendererLib/RendererSceneControlLogic.cpp index d917035bc..dcab2ca0a 100644 --- a/src/renderer/internal/RendererLib/RendererSceneControlLogic.cpp +++ b/src/renderer/internal/RendererLib/RendererSceneControlLogic.cpp @@ -77,6 +77,13 @@ namespace ramses::internal const ESceneStateInternal currentSceneState = sceneInfo.currentState; const ESceneStateInternal targetSceneState = sceneInfo.targetState; + if (targetSceneState == ESceneStateInternal::Published && currentSceneState == ESceneStateInternal::Published && sceneInfo.lastCommandWaitigForReply == ESceneStateCommand::Subscribe) + { + LOG_INFO(CONTEXT_RENDERER, "RendererSceneControlLogic initiating exceptional unsubscribe of scene with id: {}", sceneId); + m_sceneStateControl.handleSceneUnsubscriptionRequest(sceneId, false); + sceneInfo.lastCommandWaitigForReply = ESceneStateCommand::Unsubscribe; + } + if (currentSceneState == targetSceneState) return; diff --git a/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.cpp b/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.cpp index 221d9cda2..f20a89bb5 100644 --- a/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.cpp +++ b/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.cpp @@ -20,206 +20,15 @@ namespace ramses::internal assert(m_dataBuffers.size() == 0u); assert(m_textureBuffers.size() == 0u); assert(m_vertexArrays.size() == 0u); - } - - void RendererSceneResourceRegistry::addRenderBuffer(RenderBufferHandle handle, DeviceResourceHandle deviceHandle, uint32_t size, const RenderBuffer& properties) - { - assert(!m_renderBuffers.contains(handle)); - m_renderBuffers.put(handle, { deviceHandle, size, properties }); - } - - void RendererSceneResourceRegistry::removeRenderBuffer(RenderBufferHandle handle) - { - assert(m_renderBuffers.contains(handle)); - m_renderBuffers.remove(handle); - } - - DeviceResourceHandle RendererSceneResourceRegistry::getRenderBufferDeviceHandle(RenderBufferHandle handle) const - { - assert(m_renderBuffers.contains(handle)); - return m_renderBuffers.get(handle)->deviceHandle; - } - - uint32_t RendererSceneResourceRegistry::getRenderBufferByteSize(RenderBufferHandle handle) const - { - assert(m_renderBuffers.contains(handle)); - return m_renderBuffers.get(handle)->size; - } - - const RenderBuffer& RendererSceneResourceRegistry::getRenderBufferProperties(RenderBufferHandle handle) const - { - assert(m_renderBuffers.contains(handle)); - return m_renderBuffers.get(handle)->renderBufferProperties; - } - - void RendererSceneResourceRegistry::getAllRenderBuffers(RenderBufferHandleVector& renderBuffers) const - { - assert(renderBuffers.empty()); - renderBuffers.reserve(m_renderBuffers.size()); - for(const auto& renderBuffer : m_renderBuffers) - { - renderBuffers.push_back(renderBuffer.key); - } - } - - void RendererSceneResourceRegistry::addRenderTarget(RenderTargetHandle handle, DeviceResourceHandle deviceHandle) - { - assert(!m_renderTargets.contains(handle)); - m_renderTargets.put(handle, { deviceHandle }); - } - - void RendererSceneResourceRegistry::removeRenderTarget(RenderTargetHandle handle) - { - assert(m_renderTargets.contains(handle)); - m_renderTargets.remove(handle); - } - - DeviceResourceHandle RendererSceneResourceRegistry::getRenderTargetDeviceHandle(RenderTargetHandle handle) const - { - return *m_renderTargets.get(handle); - } - - void RendererSceneResourceRegistry::getAllRenderTargets(RenderTargetHandleVector& renderTargets) const - { - assert(renderTargets.empty()); - renderTargets.reserve(m_renderTargets.size()); - for(const auto& renderTarget : m_renderTargets) - { - renderTargets.push_back(renderTarget.key); - } - } - - void RendererSceneResourceRegistry::addBlitPass(BlitPassHandle handle, DeviceResourceHandle srcRenderTargetDeviceHandle, DeviceResourceHandle dstRenderTargetDeviceHandle) - { - assert(!m_blitPasses.contains(handle)); - BlitPassEntry bpEntry; - bpEntry.sourceRenderTargetDeviceHandle = srcRenderTargetDeviceHandle; - bpEntry.destinationRenderTargetDeviceHandle = dstRenderTargetDeviceHandle; - m_blitPasses.put(handle, bpEntry); - } - - void RendererSceneResourceRegistry::removeBlitPass(BlitPassHandle handle) - { - assert(m_blitPasses.contains(handle)); - m_blitPasses.remove(handle); + assert(m_uniformBuffers.size() == 0u); + assert(m_semanticUniformBuffers.size() == 0u); } void RendererSceneResourceRegistry::getBlitPassDeviceHandles(BlitPassHandle handle, DeviceResourceHandle& srcRenderTargetDeviceHandle, DeviceResourceHandle& dstRenderTargetDeviceHandle) const { - const BlitPassEntry* const bpEntry = m_blitPasses.get(handle); - assert(bpEntry != nullptr); - srcRenderTargetDeviceHandle = bpEntry->sourceRenderTargetDeviceHandle; - dstRenderTargetDeviceHandle = bpEntry->destinationRenderTargetDeviceHandle; - } - - void RendererSceneResourceRegistry::getAllBlitPasses(BlitPassHandleVector& blitPasses) const - { - assert(blitPasses.empty()); - blitPasses.reserve(m_blitPasses.size()); - for(const auto& blitPass : m_blitPasses) - { - blitPasses.push_back(blitPass.key); - } - } - - void RendererSceneResourceRegistry::addDataBuffer(DataBufferHandle handle, DeviceResourceHandle deviceHandle, EDataBufferType dataBufferType, uint32_t size) - { - assert(!m_dataBuffers.contains(handle)); - m_dataBuffers.put(handle, { deviceHandle, size, dataBufferType }); - } - - void RendererSceneResourceRegistry::removeDataBuffer(DataBufferHandle handle) - { - assert(m_dataBuffers.contains(handle)); - m_dataBuffers.remove(handle); - } - - DeviceResourceHandle RendererSceneResourceRegistry::getDataBufferDeviceHandle(DataBufferHandle handle) const - { - assert(m_dataBuffers.contains(handle)); - return m_dataBuffers.get(handle)->deviceHandle; - } - - EDataBufferType RendererSceneResourceRegistry::getDataBufferType(DataBufferHandle handle) const - { - assert(m_dataBuffers.contains(handle)); - return m_dataBuffers.get(handle)->dataBufferType; - } - - void RendererSceneResourceRegistry::getAllDataBuffers(DataBufferHandleVector& dataBuffers) const - { - assert(dataBuffers.empty()); - dataBuffers.reserve(m_dataBuffers.size()); - for(const auto& db : m_dataBuffers) - { - dataBuffers.push_back(db.key); - } - } - - void RendererSceneResourceRegistry::addTextureBuffer(TextureBufferHandle handle, DeviceResourceHandle deviceHandle, EPixelStorageFormat format, uint32_t size) - { - assert(!m_textureBuffers.contains(handle)); - m_textureBuffers.put(handle, { deviceHandle, size, format }); - } - - void RendererSceneResourceRegistry::removeTextureBuffer(TextureBufferHandle handle) - { - assert(m_textureBuffers.contains(handle)); - m_textureBuffers.remove(handle); - } - - DeviceResourceHandle RendererSceneResourceRegistry::getTextureBufferDeviceHandle(TextureBufferHandle handle) const - { - assert(m_textureBuffers.contains(handle)); - return m_textureBuffers.get(handle)->deviceHandle; - } - - EPixelStorageFormat RendererSceneResourceRegistry::getTextureBufferFormat(TextureBufferHandle handle) const - { - assert(m_textureBuffers.contains(handle)); - return m_textureBuffers.get(handle)->format; - } - - uint32_t RendererSceneResourceRegistry::getTextureBufferByteSize(TextureBufferHandle handle) const - { - assert(m_textureBuffers.contains(handle)); - return m_textureBuffers.get(handle)->size; - } - - void RendererSceneResourceRegistry::getAllTextureBuffers(TextureBufferHandleVector& textureBuffers) const - { - assert(textureBuffers.empty()); - textureBuffers.reserve(m_textureBuffers.size()); - for (const auto& tb : m_textureBuffers) - { - textureBuffers.push_back(tb.key); - } - } - - void RendererSceneResourceRegistry::addVertexArray(RenderableHandle renderableHandle, DeviceResourceHandle deviceHandle) - { - assert(!m_vertexArrays.contains(renderableHandle)); - m_vertexArrays.put(renderableHandle, deviceHandle); - } - - void RendererSceneResourceRegistry::removeVertexArray(RenderableHandle renderableHandle) - { - assert(m_vertexArrays.contains(renderableHandle)); - m_vertexArrays.remove(renderableHandle); - } - - DeviceResourceHandle RendererSceneResourceRegistry::getVertexArrayDeviceHandle(RenderableHandle renderableHandle) const - { - assert(m_vertexArrays.contains(renderableHandle)); - return *m_vertexArrays.get(renderableHandle); - } - - void RendererSceneResourceRegistry::getAllVertexArrayRenderables(RenderableVector& vertexArrayRenderables) const - { - assert(vertexArrayRenderables.empty()); - vertexArrayRenderables.reserve(m_vertexArrays.size()); - for (const auto& va : m_vertexArrays) - vertexArrayRenderables.push_back(va.key); + const auto& bpEntry = get(handle); + srcRenderTargetDeviceHandle = bpEntry.sourceRenderTargetDeviceHandle; + dstRenderTargetDeviceHandle = bpEntry.destinationRenderTargetDeviceHandle; } uint32_t RendererSceneResourceRegistry::getSceneResourceMemoryUsage(ESceneResourceType resourceType) const diff --git a/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.h b/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.h index 7ee8c00c5..f9a53364d 100644 --- a/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.h +++ b/src/renderer/internal/RendererLib/RendererSceneResourceRegistry.h @@ -9,6 +9,7 @@ #pragma once #include "internal/RendererLib/Types.h" +#include "internal/RendererLib/SemanticUniformBufferHandle.h" #include "internal/SceneGraph/SceneAPI/Handles.h" #include "internal/SceneGraph/SceneAPI/SceneTypes.h" #include "internal/SceneGraph/SceneAPI/TextureEnums.h" @@ -33,49 +34,55 @@ namespace ramses::internal RendererSceneResourceRegistry(); ~RendererSceneResourceRegistry(); - void addRenderBuffer (RenderBufferHandle handle, DeviceResourceHandle deviceHandle, uint32_t size, const RenderBuffer& properties); - void removeRenderBuffer (RenderBufferHandle handle); - [[nodiscard]] DeviceResourceHandle getRenderBufferDeviceHandle (RenderBufferHandle handle) const; - [[nodiscard]] uint32_t getRenderBufferByteSize (RenderBufferHandle handle) const; - [[nodiscard]] const RenderBuffer& getRenderBufferProperties (RenderBufferHandle handle) const; - void getAllRenderBuffers (RenderBufferHandleVector& renderBuffers) const; - - void addRenderTarget (RenderTargetHandle handle, DeviceResourceHandle deviceHandle); - void removeRenderTarget (RenderTargetHandle handle); - [[nodiscard]] DeviceResourceHandle getRenderTargetDeviceHandle (RenderTargetHandle handle) const; - void getAllRenderTargets (RenderTargetHandleVector& renderTargets) const; - - void addBlitPass (BlitPassHandle handle, DeviceResourceHandle srcRenderTargetDeviceHandle, DeviceResourceHandle dstRenderTargetDeviceHandle); - void removeBlitPass (BlitPassHandle handle); - void getBlitPassDeviceHandles (BlitPassHandle handle, DeviceResourceHandle& srcRenderTargetDeviceHandle, DeviceResourceHandle& dstRenderTargetDeviceHandle) const; - void getAllBlitPasses (BlitPassHandleVector& blitPasses) const; - - void addDataBuffer (DataBufferHandle handle, DeviceResourceHandle deviceHandle, EDataBufferType dataBufferType, uint32_t size); - void removeDataBuffer (DataBufferHandle handle); - [[nodiscard]] DeviceResourceHandle getDataBufferDeviceHandle (DataBufferHandle handle) const; - [[nodiscard]] EDataBufferType getDataBufferType (DataBufferHandle handle) const; - void getAllDataBuffers (DataBufferHandleVector& dataBuffers) const; - - void addTextureBuffer (TextureBufferHandle handle, DeviceResourceHandle deviceHandle, EPixelStorageFormat format, uint32_t size); - void removeTextureBuffer (TextureBufferHandle handle); - [[nodiscard]] DeviceResourceHandle getTextureBufferDeviceHandle(TextureBufferHandle handle) const; - [[nodiscard]] EPixelStorageFormat getTextureBufferFormat (TextureBufferHandle handle) const; - [[nodiscard]] uint32_t getTextureBufferByteSize (TextureBufferHandle handle) const; - void getAllTextureBuffers (TextureBufferHandleVector& textureBuffers) const; - - void addVertexArray(RenderableHandle renderableHandle, DeviceResourceHandle deviceHandle); - void removeVertexArray(RenderableHandle renderableHandle); - [[nodiscard]] DeviceResourceHandle getVertexArrayDeviceHandle(RenderableHandle renderableHandle) const; - void getAllVertexArrayRenderables(RenderableVector& vertexArrayRenderables) const; - - [[nodiscard]] uint32_t getSceneResourceMemoryUsage(ESceneResourceType resourceType) const; + template + void add(HandleType handle, const ParamsT&... params) + { + auto& infoStorage = getInternalStorage(); + + assert(!infoStorage.contains(handle)); + infoStorage.put(handle, { params... }); + } + + template + void remove(HandleType handle) + { + auto& infoStorage = getInternalStorage(); + + assert(infoStorage.contains(handle)); + infoStorage.remove(handle); + } + + template + [[nodiscard]] const auto& get(HandleType handle) const + { + const auto& internalStorage = getConstInternalStorage(); + assert(internalStorage.contains(handle)); + return *internalStorage.get(handle); + } + + template + [[nodiscard]] std::vector getAll() const + { + const auto& internalStorage = getConstInternalStorage(); + std::vector resultStorage; + resultStorage.reserve(internalStorage.size()); + for (const auto& e : internalStorage) + { + resultStorage.push_back(e.key); + } + + return resultStorage; + } + + void getBlitPassDeviceHandles (BlitPassHandle handle, DeviceResourceHandle& srcRenderTargetDeviceHandle, DeviceResourceHandle& dstRenderTargetDeviceHandle) const; + [[nodiscard]] uint32_t getSceneResourceMemoryUsage (ESceneResourceType resourceType) const; private: struct TextureBufferEntry { DeviceResourceHandle deviceHandle; - uint32_t size = 0u; EPixelStorageFormat format = EPixelStorageFormat::Invalid; + uint32_t size = 0u; }; struct RenderBufferEntry @@ -94,8 +101,8 @@ namespace ramses::internal struct DataBufferEntry { DeviceResourceHandle deviceHandle; - uint32_t size = 0u; EDataBufferType dataBufferType = EDataBufferType::Invalid; + uint32_t size = 0u; }; using RenderBufferMap = HashMap; @@ -103,8 +110,56 @@ namespace ramses::internal using BlitPassMap = HashMap; using DataBufferMap = HashMap; using TextureBufferMap = HashMap; - using TextureSamplerMap = HashMap; using VertexArrayMap = HashMap; + using UniformBufferMap = HashMap; + using SemanticUniformBufferMap = HashMap; + + template>> + RenderBufferMap& getInternalStorage() + { + return m_renderBuffers; + } + template>> + RenderTargetMap& getInternalStorage() + { + return m_renderTargets; + } + template>> + BlitPassMap& getInternalStorage() + { + return m_blitPasses; + } + template>> + DataBufferMap& getInternalStorage() + { + return m_dataBuffers; + } + template>> + TextureBufferMap& getInternalStorage() + { + return m_textureBuffers; + } + template>> + VertexArrayMap& getInternalStorage() + { + return m_vertexArrays; + } + template>> + UniformBufferMap& getInternalStorage() + { + return m_uniformBuffers; + } + template>> + SemanticUniformBufferMap& getInternalStorage() + { + return m_semanticUniformBuffers; + } + + template + [[nodiscard]] const auto& getConstInternalStorage() const// -> const decltype(getInternalStorage())& + { + return const_cast(*this).getInternalStorage(); + } RenderBufferMap m_renderBuffers; RenderTargetMap m_renderTargets; @@ -112,5 +167,7 @@ namespace ramses::internal DataBufferMap m_dataBuffers; TextureBufferMap m_textureBuffers; VertexArrayMap m_vertexArrays; + UniformBufferMap m_uniformBuffers; + SemanticUniformBufferMap m_semanticUniformBuffers; }; } diff --git a/src/renderer/internal/RendererLib/RendererSceneUpdater.cpp b/src/renderer/internal/RendererLib/RendererSceneUpdater.cpp index 10bbcad68..18d6225e7 100644 --- a/src/renderer/internal/RendererLib/RendererSceneUpdater.cpp +++ b/src/renderer/internal/RendererLib/RendererSceneUpdater.cpp @@ -17,7 +17,7 @@ #include "internal/RendererLib/RendererSceneUpdater.h" #include "internal/RendererLib/SceneStateExecutor.h" #include "internal/RendererLib/RendererResourceManager.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/RendererScenes.h" #include "internal/RendererLib/DataLinkUtils.h" #include "internal/RendererLib/FrameTimer.h" @@ -49,7 +49,8 @@ namespace ramses::internal RendererEventCollector& eventCollector, FrameTimer& frameTimer, SceneExpirationMonitor& expirationMonitor, - IThreadAliveNotifier& notifier + IThreadAliveNotifier& notifier, + EFeatureLevel featureLevel ) : m_display{ display } , m_platform(platform) @@ -60,6 +61,7 @@ namespace ramses::internal , m_frameTimer(frameTimer) , m_expirationMonitor(expirationMonitor) , m_notifier(notifier) + , m_featureLevel{ featureLevel } { } @@ -104,7 +106,7 @@ namespace ramses::internal } } - void RendererSceneUpdater::createDisplayContext(const DisplayConfig& displayConfig, IBinaryShaderCache* binaryShaderCache) + void RendererSceneUpdater::createDisplayContext(const DisplayConfigData& displayConfig, IBinaryShaderCache* binaryShaderCache) { assert(!m_displayResourceManager); assert(!m_asyncEffectUploader); @@ -117,12 +119,15 @@ namespace ramses::internal IRenderBackend& renderBackend = displayController.getRenderBackend(); IEmbeddedCompositingManager& embeddedCompositingManager = displayController.getEmbeddedCompositingManager(); - m_asyncEffectUploader = std::make_unique(m_platform, renderBackend, m_notifier, m_display); - if (!m_asyncEffectUploader->createResourceUploadRenderBackendAndStartThread()) + if (displayConfig.isAsyncEffectUploadEnabled()) { - m_renderer.destroyDisplayContext(); - m_rendererEventCollector.addDisplayEvent(ERendererEventType::DisplayCreateFailed, m_display); - return; + m_asyncEffectUploader = std::make_unique(m_platform, renderBackend, m_notifier, m_display); + if (!m_asyncEffectUploader->createResourceUploadRenderBackendAndStartThread()) + { + m_renderer.destroyDisplayContext(); + m_rendererEventCollector.addDisplayEvent(ERendererEventType::DisplayCreateFailed, m_display); + return; + } } // ownership of uploadStrategy is transferred into RendererResourceManager m_displayResourceManager = createResourceManager(renderBackend, @@ -143,13 +148,13 @@ namespace ramses::internal std::unique_ptr RendererSceneUpdater::createResourceManager( IRenderBackend& renderBackend, IEmbeddedCompositingManager& embeddedCompositingManager, - const DisplayConfig& displayConfig, + const DisplayConfigData& displayConfig, IBinaryShaderCache* binaryShaderCache) { return std::make_unique( renderBackend, std::make_unique(displayConfig.isAsyncEffectUploadEnabled(), binaryShaderCache), - *m_asyncEffectUploader, + m_asyncEffectUploader.get(), embeddedCompositingManager, displayConfig, m_frameTimer, @@ -185,8 +190,11 @@ namespace ramses::internal return; } - m_asyncEffectUploader->destroyResourceUploadRenderBackendAndStopThread(); - m_asyncEffectUploader.reset(); + if (m_asyncEffectUploader) + { + m_asyncEffectUploader->destroyResourceUploadRenderBackendAndStopThread(); + m_asyncEffectUploader.reset(); + } m_displayResourceManager.reset(); m_renderer.resetRenderInterruptState(); @@ -264,6 +272,7 @@ namespace ramses::internal m_renderer.m_traceId = 10; LOG_TRACE(CONTEXT_PROFILING, " RendererSceneUpdater::updateScenes update scenes transformation cache and transformation links"); FRAME_PROFILER_REGION(FrameProfilerStatistics::ERegion::UpdateTransformations); + collectDirtySemanticUniformBuffers(); updateScenesTransformationCache(); } @@ -274,6 +283,13 @@ namespace ramses::internal updateScenesDataLinks(); } + { + m_renderer.m_traceId = 13; + LOG_TRACE(CONTEXT_PROFILING, " RendererSceneUpdater::updateScenes update and upload semantic uniform buffers"); + FRAME_PROFILER_REGION(FrameProfilerStatistics::ERegion::UpdateSemanticUniformBuffers); + updateAndUploadSemanticUniformBuffers(); + } + m_renderer.m_traceId = 12; for (const auto scene : m_modifiedScenesToRerender) { @@ -581,7 +597,7 @@ namespace ramses::internal rendererScene.getSceneId()); rendererScene.setEffectTimeSync(pendingFlush.timeInfo.internalTimestamp); } - ApplySceneActions(rendererScene, pendingFlush); + applySceneActions(rendererScene, pendingFlush); if (pendingFlush.versionTag.isValid()) { @@ -615,6 +631,41 @@ namespace ramses::internal } } + void RendererSceneUpdater::collectDirtySemanticUniformBuffers() + { + for (const auto& rendererScene : m_rendererScenes) + { + const SceneId sceneId = rendererScene.key; + if (m_sceneStateExecutor.getSceneState(sceneId) == ESceneState::Rendered) + { + auto& scene = *rendererScene.value.scene; + for (const auto& passInfo : scene.getSortedRenderingPasses()) + { + if (passInfo.getType() == ERenderingPassType::RenderPass) + { + const auto camera = scene.getRenderPass(passInfo.getRenderPassHandle()).camera; + const auto& passRenderables = scene.getOrderedRenderablesForPass(passInfo.getRenderPassHandle()); + scene.collectDirtySemanticUniformBuffers(passRenderables, camera); + } + } + } + } + } + + void RendererSceneUpdater::updateAndUploadSemanticUniformBuffers() + { + for (const auto& rendererScene : m_rendererScenes) + { + const SceneId sceneId = rendererScene.key; + if (m_sceneStateExecutor.getSceneState(sceneId) == ESceneState::Rendered) + { + auto& scene = *rendererScene.value.scene; + scene.updateSemanticUniformBuffers(); + scene.uploadSemanticUniformBuffers(*m_displayResourceManager); + } + } + } + void RendererSceneUpdater::processStagedResourceChangesFromAppliedFlushes() { // process resource changes only if there are no pending flushes @@ -918,13 +969,13 @@ namespace ramses::internal return false; } - void RendererSceneUpdater::ApplySceneActions(RendererCachedScene& scene, PendingFlush& flushInfo) + void RendererSceneUpdater::applySceneActions(RendererCachedScene& scene, PendingFlush& flushInfo) { const SceneActionCollection& actionsForScene = flushInfo.sceneActions; const uint32_t numActions = actionsForScene.numberOfActions(); LOG_TRACE(CONTEXT_PROFILING, " RendererSceneUpdater::applySceneActions start applying scene actions [count:{}] for scene with id {}", numActions, scene.getSceneId()); - SceneActionApplier::ApplyActionsOnScene(scene, actionsForScene); + SceneActionApplier::ApplyActionsOnScene(scene, actionsForScene, m_featureLevel); LOG_TRACE(CONTEXT_PROFILING, " RendererSceneUpdater::applySceneActions finished applying scene actions for scene with id {}", scene.getSceneId()); } @@ -1168,7 +1219,7 @@ namespace ramses::internal resourceManager.uploadOffscreenBuffer(buffer, width, height, sampleCount, isDoubleBuffered, depthStencilBufferType); const DeviceResourceHandle deviceHandle = resourceManager.getOffscreenBufferDeviceHandle(buffer); m_renderer.resetRenderInterruptState(); - m_renderer.registerOffscreenBuffer(deviceHandle, width, height, isDoubleBuffered); + m_renderer.registerOffscreenBuffer(deviceHandle, width, height, sampleCount, isDoubleBuffered); LOG_INFO(CONTEXT_RENDERER, "Created offscreen buffer {} (device handle {}): {}x{} {}", buffer, deviceHandle, width, height, (isDoubleBuffered ? " interruptible" : "")); success = true; @@ -1202,7 +1253,7 @@ namespace ramses::internal resourceManager.uploadDmaOffscreenBuffer(buffer, width, height, dmaBufferFourccFormat, dmaBufferUsageFlags, dmaBufferModifiers); const DeviceResourceHandle deviceHandle = resourceManager.getOffscreenBufferDeviceHandle(buffer); m_renderer.resetRenderInterruptState(); - m_renderer.registerOffscreenBuffer(deviceHandle, width, height, false); + m_renderer.registerOffscreenBuffer(deviceHandle, width, height, 0u, false); LOG_INFO(CONTEXT_RENDERER, "Created DMA offscreen buffer {} (device handle {}): {}x{}", buffer, deviceHandle, width, height); dmaBufferFD = resourceManager.getDmaOffscreenBufferFD(buffer); @@ -1441,7 +1492,8 @@ namespace ramses::internal if (renderTargetHandle.isValid()) { - const auto& bufferViewport = m_renderer.getDisplaySetup().getDisplayBuffer(renderTargetHandle).viewport; + const auto& bufferInfo = m_renderer.getDisplaySetup().getDisplayBuffer(renderTargetHandle); + const auto& bufferViewport = bufferInfo.viewport; if (screenshotInfo.fullScreen) { screenshotInfo.rectangle = { 0u, 0u, bufferViewport.width, bufferViewport.height }; @@ -1452,6 +1504,12 @@ namespace ramses::internal LOG_ERROR(CONTEXT_RENDERER, "RendererSceneUpdater::readPixels failed, requested area is out of offscreen display/buffer size boundaries!"); readPixelsFailed = true; } + + if (bufferInfo.isOffscreenBuffer && bufferInfo.sampleCount > 1u) + { + LOG_ERROR(CONTEXT_RENDERER, "RendererSceneUpdater::readPixels failed, reading pixels from multisampled offscreen buffer is not supported!"); + readPixelsFailed = true; + } } else { diff --git a/src/renderer/internal/RendererLib/RendererSceneUpdater.h b/src/renderer/internal/RendererLib/RendererSceneUpdater.h index 41f46eb7a..01d722aea 100644 --- a/src/renderer/internal/RendererLib/RendererSceneUpdater.h +++ b/src/renderer/internal/RendererLib/RendererSceneUpdater.h @@ -10,15 +10,16 @@ #include "internal/RendererLib/Types.h" #include "internal/RendererLib/PlatformInterface/IEmbeddedCompositingManager.h" -#include "internal/SceneGraph/SceneAPI/SceneId.h" #include "internal/RendererLib/StagingInfo.h" #include "internal/RendererLib/BufferLinks.h" #include "internal/RendererLib/FrameTimer.h" #include "internal/RendererLib/IRendererSceneStateControl.h" #include "internal/RendererLib/IRendererSceneUpdater.h" #include "internal/RendererLib/IRendererResourceManager.h" +#include "internal/RendererLib/AsyncEffectUploader.h" #include "internal/SceneGraph/Scene/EScenePublicationMode.h" -#include "AsyncEffectUploader.h" +#include "internal/SceneGraph/SceneAPI/SceneId.h" +#include "ramses/framework/EFeatureLevel.h" #include namespace ramses::internal @@ -29,7 +30,7 @@ namespace ramses::internal class IBinaryShaderCache; class RendererEventCollector; class RendererScenes; - class DisplayConfig; + class DisplayConfigData; class SceneExpirationMonitor; struct SceneUpdate; class DataReferenceLinkManager; @@ -54,12 +55,13 @@ namespace ramses::internal RendererEventCollector& eventCollector, FrameTimer& frameTimer, SceneExpirationMonitor& expirationMonitor, - IThreadAliveNotifier& notifier); + IThreadAliveNotifier& notifier, + EFeatureLevel featureLevel); ~RendererSceneUpdater() override; // IRendererSceneUpdater void handleSceneUpdate(SceneId sceneId, SceneUpdate&& sceneUpdate) override; - void createDisplayContext(const DisplayConfig& displayConfig, IBinaryShaderCache* binaryShaderCache) override; + void createDisplayContext(const DisplayConfigData& displayConfig, IBinaryShaderCache* binaryShaderCache) override; void destroyDisplayContext() final override; void handleScenePublished(SceneId sceneId, EScenePublicationMode mode) override; void handleSceneUnpublished(SceneId sceneId) override; @@ -105,7 +107,7 @@ namespace ramses::internal virtual std::unique_ptr createResourceManager( IRenderBackend& renderBackend, IEmbeddedCompositingManager& embeddedCompositingManager, - const DisplayConfig& displayConfig, + const DisplayConfigData& displayConfig, IBinaryShaderCache* binaryShaderCache); [[nodiscard]] bool hasResourceManager() const; @@ -118,7 +120,7 @@ namespace ramses::internal bool markClientAndSceneResourcesForReupload(SceneId sceneId); void updateScenePendingFlushes(SceneId sceneID, StagingInfo& stagingInfo); - static void ApplySceneActions(RendererCachedScene& scene, PendingFlush& flushInfo); + void applySceneActions(RendererCachedScene& scene, PendingFlush& flushInfo); void applyPendingFlushes(SceneId sceneID, StagingInfo& stagingInfo); void processStagedResourceChanges(SceneId sceneID, StagingInfo& stagingInfo); @@ -130,6 +132,7 @@ namespace ramses::internal void requestAndUploadAndUnloadResources(); void uploadUpdatedECStreams(); void tryToApplyPendingFlushes(); + void collectDirtySemanticUniformBuffers(); void processStagedResourceChangesFromAppliedFlushes(); void handleECStreamAvailabilityChanges(); void uploadAndUnloadVertexArrays(); @@ -137,6 +140,7 @@ namespace ramses::internal void updateScenesShaderAnimations(); void updateScenesTransformationCache(); void updateScenesDataLinks(); + void updateAndUploadSemanticUniformBuffers(); void updateScenesStates(); void resolveDataLinksForConsumerScenes(const DataReferenceLinkManager& dataRefLinkManager); @@ -184,6 +188,8 @@ namespace ramses::internal IThreadAliveNotifier& m_notifier; + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; + // keep as members to avoid runtime re-allocs StreamSourceUpdates m_streamUpdates; RenderableVector m_tempRenderablesWithUpdatedVertexArrays; diff --git a/src/renderer/internal/RendererLib/ResourceCachedScene.cpp b/src/renderer/internal/RendererLib/ResourceCachedScene.cpp index 16f2b7673..20b4e91aa 100644 --- a/src/renderer/internal/RendererLib/ResourceCachedScene.cpp +++ b/src/renderer/internal/RendererLib/ResourceCachedScene.cpp @@ -8,13 +8,13 @@ #include "internal/RendererLib/ResourceCachedScene.h" #include "internal/RendererLib/IResourceDeviceHandleAccessor.h" -#include "internal/RendererLib/TextureLinkCachedScene.h" #include "internal/Core/Utils/LogMacros.h" +#include "ramses/framework/EFeatureLevel.h" namespace ramses::internal { ResourceCachedScene::ResourceCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo) - : TextureLinkCachedScene(sceneLinksManager, sceneInfo) + : BaseT(sceneLinksManager, sceneInfo) { } @@ -29,7 +29,7 @@ namespace ramses::internal void ResourceCachedScene::preallocateSceneSize(const SceneSizeInformation& sizeInfo) { - TextureLinkCachedScene::preallocateSceneSize(sizeInfo); + BaseT::preallocateSceneSize(sizeInfo); resizeContainerIfSmaller(m_renderableResourcesDirty, sizeInfo.renderableCount); resizeContainerIfSmaller(m_dataInstancesDirty, sizeInfo.datainstanceCount); @@ -40,11 +40,12 @@ namespace ramses::internal resizeContainerIfSmaller(m_deviceHandleCacheForTextures, sizeInfo.textureSamplerCount); resizeContainerIfSmaller(m_renderTargetCache, sizeInfo.renderTargetCount); resizeContainerIfSmaller(m_blitPassCache, sizeInfo.blitPassCount * 2u); + resizeContainerIfSmaller(m_uniformBuffersCache, sizeInfo.renderableCount); } RenderableHandle ResourceCachedScene::allocateRenderable(NodeHandle nodeHandle, RenderableHandle handle) { - const RenderableHandle renderable = TextureLinkCachedScene::allocateRenderable(nodeHandle, handle); + const RenderableHandle renderable = BaseT::allocateRenderable(nodeHandle, handle); const uint32_t indexIntoCache = renderable.asMemoryHandle(); assert(indexIntoCache < m_effectDeviceHandleCache.size()); @@ -56,7 +57,7 @@ namespace ramses::internal void ResourceCachedScene::releaseRenderable(RenderableHandle renderableHandle) { - TextureLinkCachedScene::releaseRenderable(renderableHandle); + BaseT::releaseRenderable(renderableHandle); setRenderableResourcesDirtyFlag(renderableHandle, false); setRenderableVertexArrayDirtyFlag(renderableHandle, true); } @@ -69,18 +70,18 @@ namespace ramses::internal setRenderableResourcesDirtyFlag(renderableHandle, true); setRenderableVertexArrayDirtyFlag(renderableHandle, true); } - TextureLinkCachedScene::setRenderableVisibility(renderableHandle, visibility); + BaseT::setRenderableVisibility(renderableHandle, visibility); } void ResourceCachedScene::setRenderableStartVertex(RenderableHandle renderableHandle, uint32_t startVertex) { - TextureLinkCachedScene::setRenderableStartVertex(renderableHandle, startVertex); + BaseT::setRenderableStartVertex(renderableHandle, startVertex); setRenderableVertexArrayDirtyFlag(renderableHandle, true); } DataInstanceHandle ResourceCachedScene::allocateDataInstance(DataLayoutHandle handle, DataInstanceHandle instanceHandle) { - const DataInstanceHandle dataInstance = TextureLinkCachedScene::allocateDataInstance(handle, instanceHandle); + const DataInstanceHandle dataInstance = BaseT::allocateDataInstance(handle, instanceHandle); setDataInstanceDirtyFlag(dataInstance, true); return dataInstance; @@ -88,13 +89,13 @@ namespace ramses::internal void ResourceCachedScene::releaseDataInstance(DataInstanceHandle dataInstanceHandle) { - TextureLinkCachedScene::releaseDataInstance(dataInstanceHandle); + BaseT::releaseDataInstance(dataInstanceHandle); setDataInstanceDirtyFlag(dataInstanceHandle, true); } TextureSamplerHandle ResourceCachedScene::allocateTextureSampler(const TextureSampler& sampler, TextureSamplerHandle handle) { - const TextureSamplerHandle actualHandle = TextureLinkCachedScene::allocateTextureSampler(sampler, handle); + const TextureSamplerHandle actualHandle = BaseT::allocateTextureSampler(sampler, handle); const uint32_t indexIntoCache = actualHandle.asMemoryHandle(); assert(indexIntoCache < m_deviceHandleCacheForTextures.size()); @@ -107,12 +108,12 @@ namespace ramses::internal void ResourceCachedScene::releaseTextureSampler(TextureSamplerHandle handle) { setTextureSamplerDirtyFlag(handle, true); - TextureLinkCachedScene::releaseTextureSampler(handle); + BaseT::releaseTextureSampler(handle); } void ResourceCachedScene::setRenderableDataInstance(RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) { - TextureLinkCachedScene::setRenderableDataInstance(renderableHandle, slot, newDataInstance); + BaseT::setRenderableDataInstance(renderableHandle, slot, newDataInstance); const uint32_t indexIntoCache = renderableHandle.asMemoryHandle(); assert(indexIntoCache < m_effectDeviceHandleCache.size()); @@ -124,19 +125,19 @@ namespace ramses::internal void ResourceCachedScene::setDataResource(DataInstanceHandle dataInstanceHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) { - TextureLinkCachedScene::setDataResource(dataInstanceHandle, field, hash, dataBuffer, instancingDivisor, offsetWithinElementInBytes, stride); + BaseT::setDataResource(dataInstanceHandle, field, hash, dataBuffer, instancingDivisor, offsetWithinElementInBytes, stride); setDataInstanceDirtyFlag(dataInstanceHandle, true); } void ResourceCachedScene::setDataTextureSamplerHandle(DataInstanceHandle dataInstanceHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) { - TextureLinkCachedScene::setDataTextureSamplerHandle(dataInstanceHandle, field, samplerHandle); + BaseT::setDataTextureSamplerHandle(dataInstanceHandle, field, samplerHandle); setDataInstanceDirtyFlag(dataInstanceHandle, true); } RenderTargetHandle ResourceCachedScene::allocateRenderTarget(RenderTargetHandle targetHandle) { - const RenderTargetHandle rtHandle = TextureLinkCachedScene::allocateRenderTarget(targetHandle); + const RenderTargetHandle rtHandle = BaseT::allocateRenderTarget(targetHandle); const uint32_t indexIntoCache = rtHandle.asMemoryHandle(); assert(indexIntoCache < m_renderTargetCache.size()); @@ -148,7 +149,7 @@ namespace ramses::internal BlitPassHandle ResourceCachedScene::allocateBlitPass(RenderBufferHandle sourceRenderBufferHandle, RenderBufferHandle destinationRenderBufferHandle, BlitPassHandle passHandle) { - const BlitPassHandle blitPassHandle = TextureLinkCachedScene::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); + const BlitPassHandle blitPassHandle = BaseT::allocateBlitPass(sourceRenderBufferHandle, destinationRenderBufferHandle, passHandle); const uint32_t indexIntoCache = blitPassHandle.asMemoryHandle() * 2u; assert(indexIntoCache + 1u < m_blitPassCache.size()); @@ -208,6 +209,11 @@ namespace ramses::internal return m_renderableVertexArrayDirty; } + const UniformBuffersCache& ResourceCachedScene::getCachedHandlesForUniformInstancesBuffers() const + { + return m_uniformBuffersCache; + } + bool ResourceCachedScene::CheckAndUpdateDeviceHandle(const IResourceDeviceHandleAccessor& resourceAccessor, DeviceResourceHandle& deviceHandleInOut, const ResourceContentHash& resourceHash) { deviceHandleInOut = DeviceResourceHandle::Invalid(); @@ -306,6 +312,31 @@ namespace ramses::internal return true; } + bool ResourceCachedScene::checkAndUpdateUniformBuffers(const IResourceDeviceHandleAccessor& resourceAccessor, RenderableHandle renderable) + { + const DataInstanceHandle dataInstance = getRenderable(renderable).dataInstances[ERenderableDataSlotType_Uniforms]; + if (!dataInstance.isValid()) + return false; + + const auto& fields = getDataLayout(getLayoutOfDataInstance(dataInstance)).getDataFields(); + + auto& uniformBuffersEntry = m_uniformBuffersCache[renderable.asMemoryHandle()]; + uniformBuffersEntry.resize(fields.size(), DeviceResourceHandle::Invalid()); + + for (DataFieldHandle fieldHandle{ 0u }; fieldHandle < fields.size(); ++fieldHandle) + { + const auto& field = fields[fieldHandle.asMemoryHandle()]; + if (field.dataType == EDataType::UniformBuffer && field.semantics == EFixedSemantics::Invalid) + { + const auto ubHandle = getDataUniformBuffer(dataInstance, fieldHandle); + const auto deviceHandle = resourceAccessor.getUniformBufferDeviceHandle(ubHandle, getSceneId()); + uniformBuffersEntry[fieldHandle.asMemoryHandle()] = deviceHandle; + } + } + + return true; + } + void ResourceCachedScene::checkAndUpdateRenderTargetResources(const IResourceDeviceHandleAccessor& resourceAccessor) { if (!m_renderTargetsDirty) @@ -459,7 +490,8 @@ namespace ramses::internal { if (checkAndUpdateEffectResource(resourceAccessor, renderable) && checkAndUpdateTextureResources(resourceAccessor, renderable) && - checkGeometryResources(resourceAccessor, renderable)) + checkGeometryResources(resourceAccessor, renderable) && + checkAndUpdateUniformBuffers(resourceAccessor, renderable)) { setRenderableResourcesDirtyFlag(renderable, false); } @@ -677,9 +709,9 @@ namespace ramses::internal std::fill(m_deviceHandleCacheForTextures.begin(), m_deviceHandleCacheForTextures.end(), DeviceResourceHandle::Invalid()); std::fill(m_renderTargetCache.begin(), m_renderTargetCache.end(), DeviceResourceHandle::Invalid()); std::fill(m_blitPassCache.begin(), m_blitPassCache.end(), DeviceResourceHandle::Invalid()); + std::fill(m_uniformBuffersCache.begin(), m_uniformBuffersCache.end(), UniformBuffersCacheEntry{}); m_renderTargetsDirty = !m_renderTargetCache.empty(); m_blitPassesDirty = !m_blitPassCache.empty(); } - } diff --git a/src/renderer/internal/RendererLib/ResourceCachedScene.h b/src/renderer/internal/RendererLib/ResourceCachedScene.h index a65524025..7e5640ebe 100644 --- a/src/renderer/internal/RendererLib/ResourceCachedScene.h +++ b/src/renderer/internal/RendererLib/ResourceCachedScene.h @@ -8,7 +8,7 @@ #pragma once -#include "internal/RendererLib/TextureLinkCachedScene.h" +#include "internal/RendererLib/SemanticUniformBufferScene.h" namespace ramses::internal { @@ -21,8 +21,13 @@ namespace ramses::internal }; using VertexArrayCache = std::vector; - class ResourceCachedScene : public TextureLinkCachedScene + using UniformBuffersCacheEntry = DeviceHandleVector; + using UniformBuffersCache = std::vector; + + class ResourceCachedScene : public SemanticUniformBufferScene { + using BaseT = SemanticUniformBufferScene; + public: explicit ResourceCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo = SceneInfo()); @@ -56,6 +61,7 @@ namespace ramses::internal const DeviceHandleVector& getCachedHandlesForRenderTargets() const; const DeviceHandleVector& getCachedHandlesForBlitPassRenderTargets() const; const BoolVector& getVertexArraysDirtinessFlags() const; + const UniformBuffersCache& getCachedHandlesForUniformInstancesBuffers() const; void updateRenderableResources(const IResourceDeviceHandleAccessor& resourceAccessor); void updateRenderablesResourcesDirtiness(); @@ -85,6 +91,7 @@ namespace ramses::internal bool checkAndUpdateEffectResource(const IResourceDeviceHandleAccessor& resourceAccessor, RenderableHandle renderable); bool checkAndUpdateTextureResources(const IResourceDeviceHandleAccessor& resourceAccessor, RenderableHandle renderable); bool checkGeometryResources(const IResourceDeviceHandleAccessor& resourceAccessor, RenderableHandle renderable); + bool checkAndUpdateUniformBuffers(const IResourceDeviceHandleAccessor& resourceAccessor, RenderableHandle renderable); void checkAndUpdateRenderTargetResources(const IResourceDeviceHandleAccessor& resourceAccessor); void checkAndUpdateBlitPassResources(const IResourceDeviceHandleAccessor& resourceAccessor); @@ -98,6 +105,7 @@ namespace ramses::internal mutable DeviceHandleVector m_deviceHandleCacheForTextures; DeviceHandleVector m_renderTargetCache; DeviceHandleVector m_blitPassCache; + UniformBuffersCache m_uniformBuffersCache; mutable bool m_renderableResourcesDirtinessNeedsUpdate = false; mutable bool m_renderableVertexArraysDirty = false; diff --git a/src/renderer/internal/RendererLib/ResourceUploadingManager.cpp b/src/renderer/internal/RendererLib/ResourceUploadingManager.cpp index 9c1bdc724..7b592b40d 100644 --- a/src/renderer/internal/RendererLib/ResourceUploadingManager.cpp +++ b/src/renderer/internal/RendererLib/ResourceUploadingManager.cpp @@ -11,7 +11,7 @@ #include "internal/RendererLib/IResourceUploader.h" #include "internal/RendererLib/FrameTimer.h" #include "internal/RendererLib/RendererStatistics.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/PlatformInterface/IRenderBackend.h" #include "internal/RendererLib/PlatformInterface/IEmbeddedCompositingManager.h" #include "internal/RendererLib/PlatformInterface/IDevice.h" @@ -27,8 +27,8 @@ namespace ramses::internal RendererResourceRegistry& resources, std::unique_ptr uploader, IRenderBackend& renderBackend, - AsyncEffectUploader& asyncEffectUploader, - const DisplayConfig& displayConfig, + AsyncEffectUploader* asyncEffectUploader, + const DisplayConfigData& displayConfig, const FrameTimer& frameTimer, RendererStatistics& stats) : m_resources(resources) @@ -93,7 +93,10 @@ namespace ramses::internal void ResourceUploadingManager::syncEffects() { - m_asyncEffectUploader.sync(m_effectsToUpload, m_effectsUploadedTemp); + assert(m_asyncEffectUploader || m_effectsToUpload.empty()); + if (!m_asyncEffectUploader) + return; + m_asyncEffectUploader->sync(m_effectsToUpload, m_effectsUploadedTemp); m_effectsToUpload.clear(); for (auto& e : m_effectsUploadedTemp) @@ -188,6 +191,7 @@ namespace ramses::internal uint32_t vramSize = 0; // upload to GPU const auto deviceHandle = m_uploader->uploadResource(m_renderBackend, rd, vramSize); + assert(deviceHandle.has_value() || m_asyncEffectUploader); if (deviceHandle.has_value()) { if (deviceHandle.value().isValid()) diff --git a/src/renderer/internal/RendererLib/ResourceUploadingManager.h b/src/renderer/internal/RendererLib/ResourceUploadingManager.h index 8b8e256b4..915e919cb 100644 --- a/src/renderer/internal/RendererLib/ResourceUploadingManager.h +++ b/src/renderer/internal/RendererLib/ResourceUploadingManager.h @@ -21,7 +21,7 @@ namespace ramses::internal struct RenderBuffer; class FrameTimer; class RendererStatistics; - class DisplayConfig; + class DisplayConfigData; class ResourceUploadingManager { @@ -30,8 +30,8 @@ namespace ramses::internal RendererResourceRegistry& resources, std::unique_ptr uploader, IRenderBackend& renderBackend, - AsyncEffectUploader& asyncEffectUploader, - const DisplayConfig& displayConfig, + AsyncEffectUploader* asyncEffectUploader, + const DisplayConfigData& displayConfig, const FrameTimer& frameTimer, RendererStatistics& stats); ~ResourceUploadingManager(); @@ -60,7 +60,7 @@ namespace ramses::internal RendererResourceRegistry& m_resources; std::unique_ptr m_uploader; IRenderBackend& m_renderBackend; - AsyncEffectUploader& m_asyncEffectUploader; + AsyncEffectUploader* m_asyncEffectUploader; EffectsRawResources m_effectsToUpload; EffectsGpuResources m_effectsUploadedTemp; //to avoid re-allocation each frame diff --git a/src/renderer/internal/RendererLib/SceneLinkScene.cpp b/src/renderer/internal/RendererLib/SceneLinkScene.cpp index 55f96e71d..b86107038 100644 --- a/src/renderer/internal/RendererLib/SceneLinkScene.cpp +++ b/src/renderer/internal/RendererLib/SceneLinkScene.cpp @@ -12,14 +12,14 @@ namespace ramses::internal { SceneLinkScene::SceneLinkScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo) - : TransformationCachedSceneWithExplicitMemory(sceneInfo) + : BaseT(sceneInfo) , m_sceneLinksManager(sceneLinksManager) { } DataSlotHandle SceneLinkScene::allocateDataSlot(const DataSlot& dataSlot, DataSlotHandle handle) { - const DataSlotHandle dataSlotHandle = TransformationCachedSceneWithExplicitMemory::allocateDataSlot(dataSlot, handle); + const DataSlotHandle dataSlotHandle = BaseT::allocateDataSlot(dataSlot, handle); m_sceneLinksManager.handleDataSlotCreated(getSceneId(), dataSlotHandle); return dataSlotHandle; @@ -28,6 +28,6 @@ namespace ramses::internal void SceneLinkScene::releaseDataSlot(DataSlotHandle handle) { m_sceneLinksManager.handleDataSlotDestroyed(getSceneId(), handle); - TransformationCachedSceneWithExplicitMemory::releaseDataSlot(handle); + BaseT::releaseDataSlot(handle); } } diff --git a/src/renderer/internal/RendererLib/SceneLinkScene.h b/src/renderer/internal/RendererLib/SceneLinkScene.h index d3933ecf9..621699ef7 100644 --- a/src/renderer/internal/RendererLib/SceneLinkScene.h +++ b/src/renderer/internal/RendererLib/SceneLinkScene.h @@ -16,6 +16,8 @@ namespace ramses::internal class SceneLinkScene : public TransformationCachedSceneWithExplicitMemory { + using BaseT = TransformationCachedSceneWithExplicitMemory; + public: explicit SceneLinkScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo = SceneInfo()); diff --git a/src/renderer/internal/RendererLib/SemanticUniformBufferHandle.h b/src/renderer/internal/RendererLib/SemanticUniformBufferHandle.h new file mode 100644 index 000000000..1f4e8b862 --- /dev/null +++ b/src/renderer/internal/RendererLib/SemanticUniformBufferHandle.h @@ -0,0 +1,153 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/PlatformAbstraction/Hash.h" +#include "internal/PlatformAbstraction/FmtBase.h" +#include + +namespace ramses::internal +{ + // Handle type for semantic UBOs. + // It is important that handle stays max 64bit (cache performance, hashing function, alignment, etc.). + // It consists of two MemoryHandles and makes use of reserved handles to mark which type of semantic is stored: + // Model = [renderable, InvalidMemoryHandle] + // Camera = [InvalidMemoryHandle, camera] + // ModelCamera = [renderable, camera] + // Framebuffer = [renderTarget, ReservedHandle1] + // SceneInfo = [0, ReservedHandle2] + // Note that SemanticUniformBufferHandle cannot be invalid. + class SemanticUniformBufferHandle + { + public: + enum class Type + { + Model, + Camera, + ModelCamera, + Framebuffer, // not yet implemented + SceneInfo // not yet implemented + }; + + explicit constexpr SemanticUniformBufferHandle(RenderableHandle renderable) + : m_handle1{ renderable.asMemoryHandle() } + , m_handle2{ InvalidMemoryHandle } + { + assert(renderable.isValid()); + assert(getType() == Type::Model); + } + + explicit constexpr SemanticUniformBufferHandle(CameraHandle camera) + : m_handle1{ InvalidMemoryHandle } + , m_handle2{ camera.asMemoryHandle() } + { + assert(camera.isValid()); + assert(getType() == Type::Camera); + } + + explicit constexpr SemanticUniformBufferHandle(RenderableHandle renderable, CameraHandle camera) + : m_handle1{ renderable.asMemoryHandle() } + , m_handle2{ camera.asMemoryHandle() } + { + assert(renderable.isValid()); + assert(camera.isValid()); + assert(getType() == Type::ModelCamera); + } + + [[nodiscard]] constexpr Type getType() const + { + assert(m_handle1 != InvalidMemoryHandle || m_handle2 != InvalidMemoryHandle); + + if (m_handle1 == InvalidMemoryHandle) + return Type::Camera; + if (m_handle2 == InvalidMemoryHandle) + return Type::Model; + + return Type::ModelCamera; + } + + [[nodiscard]] constexpr CameraHandle getCamera() const + { + assert(getType() == Type::Camera || getType() == Type::ModelCamera); + return CameraHandle{ m_handle2 }; + } + + [[nodiscard]] constexpr RenderableHandle getRenderable() const + { + assert(getType() == Type::Model || getType() == Type::ModelCamera); + return RenderableHandle{ m_handle1 }; + } + + [[nodiscard]] constexpr uint64_t getRawHandle() const + { + static_assert(sizeof(::ramses::internal::MemoryHandle) == sizeof(uint32_t)); + return uint64_t(m_handle1) << 32 | m_handle2; + } + + // operators + [[nodiscard]] constexpr inline friend bool operator==(SemanticUniformBufferHandle a, SemanticUniformBufferHandle b) + { + return a.m_handle1 == b.m_handle1 && a.m_handle2 == b.m_handle2; + } + [[nodiscard]] constexpr inline friend bool operator!=(SemanticUniformBufferHandle a, SemanticUniformBufferHandle b) + { + return !(a == b); + } + [[nodiscard]] constexpr inline friend bool operator<(SemanticUniformBufferHandle a, SemanticUniformBufferHandle b) + { + return a.getRawHandle() < b.getRawHandle(); + } + + private: + MemoryHandle m_handle1 = InvalidMemoryHandle; + MemoryHandle m_handle2 = InvalidMemoryHandle; + + static constexpr MemoryHandle ReservedHandle1 = InvalidMemoryHandle - 1; + static constexpr MemoryHandle ReservedHandle2 = InvalidMemoryHandle - 2; + }; +} + +template <> +struct fmt::formatter : public ramses::internal::SimpleFormatterBase +{ + template + constexpr auto format(const ramses::internal::SemanticUniformBufferHandle& str, FormatContext& ctx) + { + switch (str.getType()) + { + case ramses::internal::SemanticUniformBufferHandle::Type::Model: + return fmt::format_to(ctx.out(), "model({})", str.getRenderable()); + case ramses::internal::SemanticUniformBufferHandle::Type::Camera: + return fmt::format_to(ctx.out(), "camera({})", str.getCamera()); + case ramses::internal::SemanticUniformBufferHandle::Type::ModelCamera: + return fmt::format_to(ctx.out(), "modelCamera({}:{})", str.getRenderable(), str.getCamera()); + case ramses::internal::SemanticUniformBufferHandle::Type::Framebuffer: + return fmt::format_to(ctx.out(), "framebuffer({})", str.getRawHandle()); + case ramses::internal::SemanticUniformBufferHandle::Type::SceneInfo: + return fmt::format_to(ctx.out(), "sceneInfo({}:{})", str.getRawHandle()); + } + + assert(false); + return fmt::format_to(ctx.out(), "unknown({})", str.getRawHandle()); + } +}; + +namespace std +{ + template <> + struct hash<::ramses::internal::SemanticUniformBufferHandle> + { + size_t operator()(const ::ramses::internal::SemanticUniformBufferHandle& key) const + { + static_assert(sizeof(::ramses::internal::MemoryHandle) == sizeof(uint32_t)); + return hash()(key.getRawHandle()); + } + }; +} diff --git a/src/renderer/internal/RendererLib/SemanticUniformBufferScene.cpp b/src/renderer/internal/RendererLib/SemanticUniformBufferScene.cpp new file mode 100644 index 000000000..7b7f43e3e --- /dev/null +++ b/src/renderer/internal/RendererLib/SemanticUniformBufferScene.cpp @@ -0,0 +1,160 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "internal/RendererLib/SemanticUniformBufferScene.h" +#include "internal/RendererLib/IRendererResourceManager.h" +#include "internal/Core/Math3d/CameraMatrixHelper.h" +#include "ramses/framework/EFeatureLevel.h" +#include "glm/gtc/type_ptr.hpp" + +namespace ramses::internal +{ + SemanticUniformBufferScene::SemanticUniformBufferScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo) + : BaseT(sceneLinksManager, sceneInfo) + , m_semanticUBOsModel{ sceneInfo.sceneID } + , m_semanticUBOsCamera{ sceneInfo.sceneID } + , m_semanticUBOsModelCamera{ sceneInfo.sceneID } + { + } + + void SemanticUniformBufferScene::preallocateSceneSize(const SceneSizeInformation& sizeInfo) + { + BaseT::preallocateSceneSize(sizeInfo); + m_cameraProjectionParamsCache.preallocateSize(sizeInfo.cameraCount); + } + + void SemanticUniformBufferScene::setRenderableDataInstance(RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) + { + BaseT::setRenderableDataInstance(renderableHandle, slot, newDataInstance); + if (slot == ERenderableDataSlotType::ERenderableDataSlotType_Uniforms) + { + ActiveSemantics activeSemantics{ false, false }; + if (newDataInstance.isValid()) + { + const auto dataLayout = getDataLayout(getLayoutOfDataInstance(newDataInstance)); + for (DataFieldHandle field{ 0u }; field < dataLayout.getFieldCount(); field++) + { + activeSemantics.model |= (dataLayout.getField(field).semantics == EFixedSemantics::ModelBlock); + activeSemantics.modelCamera |= (dataLayout.getField(field).semantics == EFixedSemantics::ModelCameraBlock); + } + } + + m_renderableSemantics[renderableHandle] = activeSemantics; + } + } + + CameraHandle SemanticUniformBufferScene::allocateCamera(ECameraProjectionType type, NodeHandle nodeHandle, DataInstanceHandle dataInstance, CameraHandle handle) + { + const auto newHandle = BaseT::allocateCamera(type, nodeHandle, dataInstance, handle); + m_cameraProjectionParamsCache.allocate(newHandle); + return newHandle; + } + + void SemanticUniformBufferScene::releaseCamera(CameraHandle cameraHandle) + { + m_cameraProjectionParamsCache.release(cameraHandle); + BaseT::releaseCamera(cameraHandle); + } + + const SemanticUniformBufferScene::CameraProjectionParams& SemanticUniformBufferScene::updateCameraProjectionParams(CameraHandle cameraHandle) const + { + // store in cache for next dirtiness check + const auto& camera = getCamera(cameraHandle); + CameraProjectionParams& cachedParams = *m_cameraProjectionParamsCache.getMemory(cameraHandle); + cachedParams = getCameraProjection(camera); + return cachedParams; + } + + DeviceResourceHandle SemanticUniformBufferScene::getDeviceHandle(RenderableHandle renderable) const + { + return m_semanticUBOsModel.getDeviceHandle(SemanticUniformBufferHandle{ renderable }); + } + + DeviceResourceHandle SemanticUniformBufferScene::getDeviceHandle(CameraHandle camera) const + { + return m_semanticUBOsCamera.getDeviceHandle(SemanticUniformBufferHandle{ camera }); + } + + DeviceResourceHandle SemanticUniformBufferScene::getDeviceHandle(RenderableHandle renderable, CameraHandle camera) const + { + return m_semanticUBOsModelCamera.getDeviceHandle(SemanticUniformBufferHandle{ renderable, camera }); + } + + SemanticUniformBufferScene::CameraProjectionParams SemanticUniformBufferScene::getCameraProjection(const Camera& camera) const + { + const auto planesDataInstance = getDataReference(camera.dataInstance, Camera::FrustumPlanesField); + const auto nearFarDataInstance = getDataReference(camera.dataInstance, Camera::FrustumNearFarPlanesField); + return CameraProjectionParams{ getDataSingleVector4f(planesDataInstance, DataFieldHandle{0u}), getDataSingleVector2f(nearFarDataInstance, DataFieldHandle{0u}) }; + } + + bool SemanticUniformBufferScene::checkRenderableDirtiness(const Renderable& renderable) const + { + return renderable.visibilityMode == EVisibilityMode::Visible + && getMatrixCacheEntry(renderable.node).m_matrixDirty[ETransformationMatrixType_World]; + } + + bool SemanticUniformBufferScene::checkCameraDirtiness(CameraHandle cameraHandle) const + { + const auto& camera = getCamera(cameraHandle); + return getMatrixCacheEntry(camera.node).m_matrixDirty[ETransformationMatrixType_Object] + || getCameraProjection(camera) != *m_cameraProjectionParamsCache.getMemory(cameraHandle); + } + + void SemanticUniformBufferScene::collectDirtySemanticUniformBuffers(const RenderableVector& renderableHandles, CameraHandle camera) + { + // here we get all renderables with camera (per render pass) that will be rendered in this frame + if (renderableHandles.empty()) + return; + + const SemanticUniformBufferHandle cameraUboHandle{ camera }; + m_semanticUBOsCamera.markAsUsed(cameraUboHandle); + const bool camDirty = checkCameraDirtiness(camera); + if (camDirty) + m_semanticUBOsCamera.markDirty(cameraUboHandle); + + for (auto renderableHandle : renderableHandles) + { + const auto renderableSemantics = m_renderableSemantics[renderableHandle]; + if (!renderableSemantics.model && !renderableSemantics.modelCamera) + continue; + + const auto& renderable = getRenderable(renderableHandle); + const bool renderableDirty = checkRenderableDirtiness(renderable); + + if (renderableSemantics.model) + { + const SemanticUniformBufferHandle uboHandle{ renderableHandle }; + m_semanticUBOsModel.markAsUsed(uboHandle); + if (renderableDirty) + m_semanticUBOsModel.markDirty(uboHandle); + } + + if (renderableSemantics.modelCamera) + { + const SemanticUniformBufferHandle uboHandle{ renderableHandle, camera }; + m_semanticUBOsModelCamera.markAsUsed(uboHandle); + if (camDirty || renderableDirty) + m_semanticUBOsModelCamera.markDirty(uboHandle); + } + } + } + + void SemanticUniformBufferScene::updateSemanticUniformBuffers() + { + m_semanticUBOsModel.update(*this); + m_semanticUBOsCamera.update(*this); + m_semanticUBOsModelCamera.update(*this); + } + + void SemanticUniformBufferScene::uploadSemanticUniformBuffers(IRendererResourceManager& resourceManager) + { + m_semanticUBOsModel.upload(resourceManager); + m_semanticUBOsCamera.upload(resourceManager); + m_semanticUBOsModelCamera.upload(resourceManager); + } +} diff --git a/src/renderer/internal/RendererLib/SemanticUniformBufferScene.h b/src/renderer/internal/RendererLib/SemanticUniformBufferScene.h new file mode 100644 index 000000000..7a5c2df1a --- /dev/null +++ b/src/renderer/internal/RendererLib/SemanticUniformBufferScene.h @@ -0,0 +1,58 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "internal/RendererLib/TextureLinkCachedScene.h" +#include "internal/RendererLib/SemanticUniformBuffers.h" + +namespace ramses::internal +{ + class IRendererResourceManager; + + class SemanticUniformBufferScene : public TextureLinkCachedScene + { + using BaseT = TextureLinkCachedScene; + + public: + explicit SemanticUniformBufferScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo = SceneInfo()); + + void preallocateSceneSize(const SceneSizeInformation& sizeInfo) override; + void setRenderableDataInstance(RenderableHandle renderableHandle, ERenderableDataSlotType slot, DataInstanceHandle newDataInstance) override; + CameraHandle allocateCamera(ECameraProjectionType type, NodeHandle nodeHandle, DataInstanceHandle dataInstance, CameraHandle handle) override; + void releaseCamera(CameraHandle cameraHandle) override; + + DeviceResourceHandle getDeviceHandle(RenderableHandle renderable) const; + DeviceResourceHandle getDeviceHandle(CameraHandle camera) const; + DeviceResourceHandle getDeviceHandle(RenderableHandle renderable, CameraHandle camera) const; + + void collectDirtySemanticUniformBuffers(const RenderableVector& renderableHandles, CameraHandle camera); + void updateSemanticUniformBuffers(); + void uploadSemanticUniformBuffers(IRendererResourceManager& resourceManager); + + using CameraProjectionParams = std::pair;// frustum planes (vec4), frustum near and far (vec2) + const CameraProjectionParams& updateCameraProjectionParams(CameraHandle camera) const; + + private: + CameraProjectionParams getCameraProjection(const Camera& camera) const; + inline bool checkRenderableDirtiness(const Renderable& renderable) const; + inline bool checkCameraDirtiness(CameraHandle cameraHandle) const; + + struct ActiveSemantics + { + bool model = false; + bool modelCamera = false; + }; + std::unordered_map m_renderableSemantics; + mutable MemoryPoolExplicit m_cameraProjectionParamsCache; + + SemanticUniformBuffers_Model m_semanticUBOsModel; + SemanticUniformBuffers_Camera m_semanticUBOsCamera; + SemanticUniformBuffers_ModelCamera m_semanticUBOsModelCamera; + }; +} diff --git a/src/renderer/internal/RendererLib/SemanticUniformBuffers.cpp b/src/renderer/internal/RendererLib/SemanticUniformBuffers.cpp new file mode 100644 index 000000000..30119ae1f --- /dev/null +++ b/src/renderer/internal/RendererLib/SemanticUniformBuffers.cpp @@ -0,0 +1,205 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "internal/RendererLib/SemanticUniformBuffers.h" +#include "internal/RendererLib/IRendererResourceManager.h" +#include "internal/RendererLib/SemanticUniformBufferScene.h" +#include "internal/Core/Math3d/CameraMatrixHelper.h" +#include "glm/gtc/type_ptr.hpp" + +namespace ramses::internal +{ + template + SemanticUniformBuffers::SemanticUniformBuffers(SceneId sceneId) + : m_sceneId{ sceneId } + { + } + + template + void SemanticUniformBuffers::markAsUsed(SemanticUniformBufferHandle uboHandle) + { + auto it = m_decays.find(uboHandle); + if (it != m_decays.cend()) + { + it->second = 0u; + } + else + { + m_decays.emplace(uboHandle, 0u); + m_dirtyUBOs.push_back(uboHandle); // make sure newly added UBO will be updated + } + } + + template + void SemanticUniformBuffers::markDirty(SemanticUniformBufferHandle uboHandle) + { + assert(m_decays.count(uboHandle) != 0u); + m_dirtyUBOs.push_back(uboHandle); + } + + template + DeviceResourceHandle SemanticUniformBuffers::getDeviceHandle(SemanticUniformBufferHandle uboHandle) const + { + const auto it = m_deviceHandles.find(uboHandle); + assert(it != m_deviceHandles.cend()); + assert(it->second.isValid()); + return it->second; + } + + template + void SemanticUniformBuffers::update(const SemanticUniformBufferScene& scene) + { + // early out + if (m_dirtyUBOs.empty()) + return; + + // remove any duplicates + std::sort(m_dirtyUBOs.begin(), m_dirtyUBOs.end()); + m_dirtyUBOs.erase(std::unique(m_dirtyUBOs.begin(), m_dirtyUBOs.end()), m_dirtyUBOs.end()); + + // update matrices for all UBOs to be updated + assert(m_newUBOs.empty()); + for (const auto uboHandle : m_dirtyUBOs) + { + assert(m_decays.count(uboHandle) != 0u); + UBOData uboData; + SemanticUniformBuffersInstances::CalculateUBOData(uboHandle, scene, uboData); + + auto it = m_uboData.find(uboHandle); + if (it == m_uboData.cend()) + { + m_newUBOs.push_back(uboHandle); + m_uboData.emplace(uboHandle, std::move(uboData)); + assert(m_deviceHandles.count(uboHandle) == 0u); + } + else + { + it->second = std::move(uboData); + } + } + } + + template + void SemanticUniformBuffers::uploadNewUBOs(IRendererResourceManager& resourceManager) + { + for (const auto uboHandle : m_newUBOs) + { + assert(uboHandle.getType() == SemanticUniformBuffersInstances::GetMatchingSemanticType()); + m_deviceHandles[uboHandle] = resourceManager.uploadUniformBuffer(uboHandle, UBOSize, m_sceneId); + } + m_newUBOs.clear(); + } + + template + void SemanticUniformBuffers::decayAndUnloadUnusedUBOs(IRendererResourceManager& resourceManager) + { + auto& toDelete = m_newUBOs; // just reusing container to avoid allocating any memory + assert(toDelete.empty()); + for (auto& decay : m_decays) + { + if (++decay.second > DecayCountToDeallocate) + toDelete.push_back(decay.first); + } + for (const auto uboHandle : toDelete) + { + assert(uboHandle.getType() == SemanticUniformBuffersInstances::GetMatchingSemanticType()); + assert(std::find(m_dirtyUBOs.cbegin(), m_dirtyUBOs.cend(), uboHandle) == m_dirtyUBOs.cend()); + resourceManager.unloadUniformBuffer(uboHandle, m_sceneId); + m_decays.erase(uboHandle); + m_uboData.erase(uboHandle); + m_deviceHandles.erase(uboHandle); + } + toDelete.clear(); + } + + template + void SemanticUniformBuffers::uploadUpdatedUBOs(IRendererResourceManager& resourceManager) + { + for (const auto uboHandle : m_dirtyUBOs) + { + assert(uboHandle.getType() == SemanticUniformBuffersInstances::GetMatchingSemanticType()); + resourceManager.updateUniformBuffer(uboHandle, UBOSize, SemanticUniformBuffersInstances::GetUBODataPtr(m_uboData.find(uboHandle)->second), m_sceneId); + } + m_dirtyUBOs.clear(); + } + + template + void SemanticUniformBuffers::upload(IRendererResourceManager& resourceManager) + { + // early out (decayed UBOs will be evaluated only on next change) + if (m_dirtyUBOs.empty()) + return; + + uploadNewUBOs(resourceManager); + decayAndUnloadUnusedUBOs(resourceManager); + uploadUpdatedUBOs(resourceManager); + } + + void SemanticUniformBuffersInstances::CalculateUBOData(SemanticUniformBufferHandle uboHandle, const SemanticUniformBufferScene& scene, ModelData& uboData) + { + assert(uboHandle.getType() == SemanticUniformBufferHandle::Type::Model); + const auto& renderable = scene.getRenderable(uboHandle.getRenderable()); + const auto mMat = scene.updateMatrixCacheWithLinks(ETransformationMatrixType_World, renderable.node); + + std::memcpy(uboData.data(), glm::value_ptr(mMat), 16u * sizeof(float)); + } + + const std::byte* SemanticUniformBuffersInstances::GetUBODataPtr(const ModelData& uboData) + { + return uboData.data(); + } + + void SemanticUniformBuffersInstances::CalculateUBOData(SemanticUniformBufferHandle uboHandle, const SemanticUniformBufferScene& scene, CameraData& uboData) + { + assert(uboHandle.getType() == SemanticUniformBufferHandle::Type::Camera); + const auto pMat = SemanticUniformBuffersInstances::CalculateProjectionMatrix(uboHandle.getCamera(), scene); + const auto vMat = scene.updateMatrixCacheWithLinks(ETransformationMatrixType_Object, scene.getCamera(uboHandle.getCamera()).node); + const auto position = glm::inverse(vMat) * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f); + + std::memcpy(uboData.pMat.data(), glm::value_ptr(pMat), 16u * sizeof(float)); + std::memcpy(uboData.vMat.data(), glm::value_ptr(vMat), 16u * sizeof(float)); + std::memcpy(uboData.position.data(), glm::value_ptr(position), 3u * sizeof(float)); + } + + const std::byte* SemanticUniformBuffersInstances::GetUBODataPtr(const CameraData& uboData) + { + return uboData.pMat.data(); + } + + void SemanticUniformBuffersInstances::CalculateUBOData(SemanticUniformBufferHandle uboHandle, const SemanticUniformBufferScene& scene, ModelCameraData& uboData) + { + assert(uboHandle.getType() == SemanticUniformBufferHandle::Type::ModelCamera); + const auto& renderable = scene.getRenderable(uboHandle.getRenderable()); + const auto mMat = scene.updateMatrixCacheWithLinks(ETransformationMatrixType_World, renderable.node); + const auto vMat = scene.updateMatrixCacheWithLinks(ETransformationMatrixType_Object, scene.getCamera(uboHandle.getCamera()).node); + const auto pMat = SemanticUniformBuffersInstances::CalculateProjectionMatrix(uboHandle.getCamera(), scene); + const auto mvMat = vMat * mMat; + const auto mvpMat = pMat * mvMat; + const auto normalMat = glm::transpose(glm::inverse(mvMat)); + + std::memcpy(uboData.mvpMat.data(), glm::value_ptr(mvpMat), 16u * sizeof(float)); + std::memcpy(uboData.mvMat.data(), glm::value_ptr(mvMat), 16u * sizeof(float)); + std::memcpy(uboData.normalMat.data(), glm::value_ptr(normalMat), 16u * sizeof(float)); + } + + const std::byte* SemanticUniformBuffersInstances::GetUBODataPtr(const ModelCameraData& uboData) + { + return uboData.mvpMat.data(); + } + + glm::mat4 SemanticUniformBuffersInstances::CalculateProjectionMatrix(CameraHandle camera, const SemanticUniformBufferScene& scene) + { + const auto& projParams = scene.updateCameraProjectionParams(camera); + return CameraMatrixHelper::ProjectionMatrix(ProjectionParams::Frustum( + scene.getCamera(camera).projectionType, projParams.first.x, projParams.first.y, projParams.first.z, projParams.first.w, projParams.second.x, projParams.second.y)); + } + + template class SemanticUniformBuffers; + template class SemanticUniformBuffers; + template class SemanticUniformBuffers; +} diff --git a/src/renderer/internal/RendererLib/SemanticUniformBuffers.h b/src/renderer/internal/RendererLib/SemanticUniformBuffers.h new file mode 100644 index 000000000..d4cb89046 --- /dev/null +++ b/src/renderer/internal/RendererLib/SemanticUniformBuffers.h @@ -0,0 +1,106 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "ramses/framework/DataTypes.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/SceneGraph/SceneAPI/SceneId.h" +#include "internal/RendererLib/SemanticUniformBufferHandle.h" +#include "internal/RendererLib/Types.h" +#include +#include + +namespace ramses::internal +{ + class IRendererResourceManager; + class SemanticUniformBufferScene; + + template + class SemanticUniformBuffers + { + public: + explicit SemanticUniformBuffers(SceneId sceneId); + + void markAsUsed(SemanticUniformBufferHandle uboHandle); + void markDirty(SemanticUniformBufferHandle uboHandle); + + DeviceResourceHandle getDeviceHandle(SemanticUniformBufferHandle uboHandle) const; + + void update(const SemanticUniformBufferScene& scene); + void upload(IRendererResourceManager& resourceManager); + + // number of decays to reach before deallocating a UBO from memory (in practice this is number of frames with some update where UBO was not used) + static constexpr uint32_t DecayCountToDeallocate = 500; + + private: + void uploadNewUBOs(IRendererResourceManager& resourceManager); + void decayAndUnloadUnusedUBOs(IRendererResourceManager& resourceManager); + void uploadUpdatedUBOs(IRendererResourceManager& resourceManager); + + SceneId m_sceneId; + + std::unordered_map m_decays; // in practice this is number of frames with some update since last time UBO was used (not necessarily updated, just used) + std::unordered_map m_deviceHandles; + + std::unordered_map m_uboData; + std::vector m_dirtyUBOs; + std::vector m_updatedUBOs; + std::vector m_newUBOs; + + static constexpr size_t UBOSize = sizeof(UBOData); + }; + + namespace SemanticUniformBuffersInstances + { + using Mat44Bytes = std::array; + using Vec3Bytes = std::array; + + // Model instance specific data/logic + using ModelData = Mat44Bytes; + void CalculateUBOData(SemanticUniformBufferHandle uboHandle, const SemanticUniformBufferScene& scene, ModelData& uboData); + const std::byte* GetUBODataPtr(const ModelData& uboData); + + // Camera instance specific data/logic + struct CameraData + { + Mat44Bytes pMat; + Mat44Bytes vMat; + Vec3Bytes position; + }; + void CalculateUBOData(SemanticUniformBufferHandle uboHandle, const SemanticUniformBufferScene& scene, CameraData& uboData); + const std::byte* GetUBODataPtr(const CameraData& uboData); + + // ModelCamera instance specific data/logic + struct ModelCameraData + { + Mat44Bytes mvpMat; + Mat44Bytes mvMat; + Mat44Bytes normalMat; + }; + void CalculateUBOData(SemanticUniformBufferHandle uboHandle, const SemanticUniformBufferScene& scene, ModelCameraData& uboData); + const std::byte* GetUBODataPtr(const ModelCameraData& uboData); + + glm::mat4 CalculateProjectionMatrix(CameraHandle camera, const SemanticUniformBufferScene& scene); + + template + SemanticUniformBufferHandle::Type GetMatchingSemanticType() + { + if constexpr (std::is_same_v) + return SemanticUniformBufferHandle::Type::Model; + if constexpr (std::is_same_v) + return SemanticUniformBufferHandle::Type::ModelCamera; + if constexpr (std::is_same_v) + return SemanticUniformBufferHandle::Type::Camera; + } + }; + + using SemanticUniformBuffers_Model = SemanticUniformBuffers; + using SemanticUniformBuffers_Camera = SemanticUniformBuffers; + using SemanticUniformBuffers_ModelCamera = SemanticUniformBuffers; +} diff --git a/src/renderer/internal/RendererLib/TextureLinkCachedScene.cpp b/src/renderer/internal/RendererLib/TextureLinkCachedScene.cpp index e826956e5..2ebd26d89 100644 --- a/src/renderer/internal/RendererLib/TextureLinkCachedScene.cpp +++ b/src/renderer/internal/RendererLib/TextureLinkCachedScene.cpp @@ -14,19 +14,19 @@ namespace ramses::internal { TextureLinkCachedScene::TextureLinkCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo) - : DataReferenceLinkCachedScene(sceneLinksManager, sceneInfo) + : BaseT(sceneLinksManager, sceneInfo) { } DataSlotHandle TextureLinkCachedScene::allocateDataSlot(const DataSlot& dataSlot, DataSlotHandle handle) { - const DataSlotHandle actualHandle = DataReferenceLinkCachedScene::allocateDataSlot(dataSlot, handle); + const DataSlotHandle actualHandle = BaseT::allocateDataSlot(dataSlot, handle); if (dataSlot.type == EDataSlotType::TextureConsumer) { const auto sampler = dataSlot.attachedTextureSampler; assert(sampler.isValid() && isTextureSamplerAllocated(sampler)); - m_fallbackTextureSamplers[sampler] = DataReferenceLinkCachedScene::getTextureSampler(sampler); + m_fallbackTextureSamplers[sampler] = BaseT::getTextureSampler(sampler); } return actualHandle; @@ -35,7 +35,7 @@ namespace ramses::internal void TextureLinkCachedScene::releaseDataSlot(DataSlotHandle handle) { const TextureSamplerHandle sampler = getDataSlot(handle).attachedTextureSampler; - DataReferenceLinkCachedScene::releaseDataSlot(handle); + BaseT::releaseDataSlot(handle); auto it = m_fallbackTextureSamplers.find(sampler); if (it != m_fallbackTextureSamplers.end()) @@ -44,7 +44,7 @@ namespace ramses::internal void TextureLinkCachedScene::setDataSlotTexture(DataSlotHandle handle, const ResourceContentHash& texture) { - DataReferenceLinkCachedScene::setDataSlotTexture(handle, texture); + BaseT::setDataSlotTexture(handle, texture); m_sceneLinksManager.getTextureLinkManager().setTextureToConsumers(getSceneId(), handle, texture); } diff --git a/src/renderer/internal/RendererLib/TextureLinkCachedScene.h b/src/renderer/internal/RendererLib/TextureLinkCachedScene.h index 36fbebb97..714480e3d 100644 --- a/src/renderer/internal/RendererLib/TextureLinkCachedScene.h +++ b/src/renderer/internal/RendererLib/TextureLinkCachedScene.h @@ -15,6 +15,8 @@ namespace ramses::internal { class TextureLinkCachedScene : public DataReferenceLinkCachedScene { + using BaseT = DataReferenceLinkCachedScene; + public: explicit TextureLinkCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo = SceneInfo()); diff --git a/src/renderer/internal/RendererLib/TransformationLinkCachedScene.cpp b/src/renderer/internal/RendererLib/TransformationLinkCachedScene.cpp index e19dd0c6e..10b01ef7b 100644 --- a/src/renderer/internal/RendererLib/TransformationLinkCachedScene.cpp +++ b/src/renderer/internal/RendererLib/TransformationLinkCachedScene.cpp @@ -12,20 +12,20 @@ namespace ramses::internal { TransformationLinkCachedScene::TransformationLinkCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo) - : SceneLinkScene(sceneLinksManager, sceneInfo) + : BaseT(sceneLinksManager, sceneInfo) { } void TransformationLinkCachedScene::removeChildFromNode(NodeHandle parent, NodeHandle child) { propagateDirtyToConsumers(child); - SceneLinkScene::removeChildFromNode(parent, child); + BaseT::removeChildFromNode(parent, child); } void TransformationLinkCachedScene::addChildToNode(NodeHandle parent, NodeHandle child) { propagateDirtyToConsumers(child); - SceneLinkScene::addChildToNode(parent, child); + BaseT::addChildToNode(parent, child); } void TransformationLinkCachedScene::setRotation(TransformHandle transform, const glm::vec4& rotation, ERotationType rotationType) @@ -33,7 +33,7 @@ namespace ramses::internal const NodeHandle nodeTransformIsConnectedTo = getTransformNode(transform); assert(nodeTransformIsConnectedTo.isValid()); propagateDirtyToConsumers(nodeTransformIsConnectedTo); - SceneLinkScene::setRotation(transform, rotation, rotationType); + BaseT::setRotation(transform, rotation, rotationType); } void TransformationLinkCachedScene::setScaling(TransformHandle transform, const glm::vec3& scaling) @@ -41,7 +41,7 @@ namespace ramses::internal const NodeHandle nodeTransformIsConnectedTo = getTransformNode(transform); assert(nodeTransformIsConnectedTo.isValid()); propagateDirtyToConsumers(nodeTransformIsConnectedTo); - SceneLinkScene::setScaling(transform, scaling); + BaseT::setScaling(transform, scaling); } void TransformationLinkCachedScene::setTranslation(TransformHandle transform, const glm::vec3& translation) @@ -49,7 +49,7 @@ namespace ramses::internal const NodeHandle nodeTransformIsConnectedTo = getTransformNode(transform); assert(nodeTransformIsConnectedTo.isValid()); propagateDirtyToConsumers(nodeTransformIsConnectedTo); - SceneLinkScene::setTranslation(transform, translation); + BaseT::setTranslation(transform, translation); } void TransformationLinkCachedScene::releaseDataSlot(DataSlotHandle handle) @@ -60,7 +60,7 @@ namespace ramses::internal propagateDirtyToConsumers(dataSlot.attachedNode); } - SceneLinkScene::releaseDataSlot(handle); + BaseT::releaseDataSlot(handle); } void TransformationLinkCachedScene::propagateDirtyToConsumers(NodeHandle startNode) const @@ -89,10 +89,10 @@ namespace ramses::internal if (!m_sceneLinksManager.getTransformationLinkManager().getDependencyChecker().hasDependencyAsConsumer(getSceneId())) { // early out, if no links need to be resolved fall back to standard transformation scene - return SceneLinkScene::updateMatrixCache(matrixType, node); + return BaseT::updateMatrixCache(matrixType, node); } - glm::mat4 chainMatrix = SceneLinkScene::findCleanAncestorMatrixAndCollectDirtyNodesOnTheWay(matrixType, node, m_dirtyNodes); + glm::mat4 chainMatrix = BaseT::findCleanAncestorMatrixAndCollectDirtyNodesOnTheWay(matrixType, node, m_dirtyNodes); // update cache for all transforms for the nodes we collected for (int32_t i = static_cast(m_dirtyNodes.size()) - 1; i >= 0; --i) diff --git a/src/renderer/internal/RendererLib/TransformationLinkCachedScene.h b/src/renderer/internal/RendererLib/TransformationLinkCachedScene.h index 42e854b2b..55538bb54 100644 --- a/src/renderer/internal/RendererLib/TransformationLinkCachedScene.h +++ b/src/renderer/internal/RendererLib/TransformationLinkCachedScene.h @@ -14,6 +14,8 @@ namespace ramses::internal { class TransformationLinkCachedScene : public SceneLinkScene { + using BaseT = SceneLinkScene; + public: explicit TransformationLinkCachedScene(SceneLinksManager& sceneLinksManager, const SceneInfo& sceneInfo = SceneInfo()); diff --git a/src/shared-lib/CMakeLists.txt b/src/shared-lib/CMakeLists.txt index 662b6b589..8ff5bb219 100644 --- a/src/shared-lib/CMakeLists.txt +++ b/src/shared-lib/CMakeLists.txt @@ -31,14 +31,11 @@ endif() # Collect impl.cpp for framework and client depending on configured cmake options list(APPEND HEADLESS_SOURCES ${PROJECT_SOURCE_DIR}/src/framework/impl/*.cpp) list(APPEND HEADLESS_SOURCES ${PROJECT_SOURCE_DIR}/src/client/impl/*.cpp) +list(APPEND HEADLESS_SOURCES ${PROJECT_SOURCE_DIR}/src/client/impl/logic/*.cpp) if(ramses-sdk_TEXT_SUPPORT) list(APPEND HEADLESS_SOURCES ${PROJECT_SOURCE_DIR}/src/client/impl/text/*.cpp) endif() -if(ramses-sdk_ENABLE_LOGIC) - list(APPEND HEADLESS_SOURCES ${PROJECT_SOURCE_DIR}/src/client/impl/logic/*.cpp) -endif() - set(RENDERER_SOURCES ${PROJECT_SOURCE_DIR}/src/renderer/impl/*.cpp) # build shared library without renderer diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b2b6f19b0..bf4cbc1ba 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,6 +12,4 @@ if(ANY_WINDOW_TYPE_ENABLED) add_subdirectory(integration) endif() -if(ramses-sdk_ENABLE_LOGIC) - add_subdirectory(benchmarks) -endif() +add_subdirectory(benchmarks) diff --git a/tests/integration/CMakeLists.txt b/tests/integration/CMakeLists.txt index e1a7d5c88..c43ab3f2d 100644 --- a/tests/integration/CMakeLists.txt +++ b/tests/integration/CMakeLists.txt @@ -16,6 +16,6 @@ if(ramses-sdk_BUILD_FULL_SHARED_LIB) add_subdirectory(shared-lib-tests) endif() -if(ramses-sdk_ENABLE_LOGIC AND ramses-sdk_USE_IMAGEMAGICK) +if(ramses-sdk_USE_IMAGEMAGICK) add_subdirectory(viewer-tests) endif() diff --git a/tests/integration/render-backend-tests/CMakeLists.txt b/tests/integration/render-backend-tests/CMakeLists.txt index 27dc8b758..74bbe1454 100644 --- a/tests/integration/render-backend-tests/CMakeLists.txt +++ b/tests/integration/render-backend-tests/CMakeLists.txt @@ -12,7 +12,9 @@ createModuleWithRenderer( ENABLE_INSTALL ON SRC_FILES *.h *.cpp - DEPENDENCIES RendererTestUtils ramses-cli + DEPENDENCIES RendererTestUtils + ramses-cli + glslang-init-gtest-env ) # Tests which are supposed to be run in the gate build job @@ -37,4 +39,23 @@ IF (ramses-sdk_BUILD_TESTS) EXTRA_ARGS --gtest_filter=${GATE_FILTER} --ivi-layer 3 WINDOW_TYPE_FILTER ${GATE_WINDOW_PLATFORMS} ) + + # Vulkan tests + if(ramses-sdk_ENABLE_DEVICE_TYPE_VULKAN) + set(VULKAN_FILTER "${GATE_FILTER}") + + if(ramses-sdk_ENABLE_WINDOW_TYPE_X11) + makeTestFromTarget(TARGET render-backend-tests + SUFFIX x11-vulkan_RNDSANDWICHTEST_SWRAST + EXTRA_ARGS --gtest_filter=${VULKAN_FILTER} --device-type vulkan --window-type x11 + ) + endif() + + if(ramses-sdk_ENABLE_WINDOW_TYPE_WINDOWS) + makeTestFromTarget(TARGET render-backend-tests + SUFFIX windows-vulkan_RNDSANDWICHTEST + EXTRA_ARGS --gtest_filter=${VULKAN_FILTER} --device-type vulkan --window-type windows + ) + endif() + endif() ENDIF() diff --git a/tests/integration/render-backend-tests/PlatformTest.cpp b/tests/integration/render-backend-tests/PlatformTest.cpp index 2d699e2e4..a314f3d04 100644 --- a/tests/integration/render-backend-tests/PlatformTest.cpp +++ b/tests/integration/render-backend-tests/PlatformTest.cpp @@ -7,9 +7,9 @@ // ------------------------------------------------------------------------- #include "gmock/gmock.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "WindowEventHandlerMock.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/RenderBackend.h" #include "internal/RendererLib/ResourceUploadRenderBackend.h" #include "internal/RendererLib/PlatformInterface/IContext.h" @@ -42,7 +42,7 @@ namespace ramses::internal APlatform() { PlatformFactory platformFactory; - auto dispConfig = RendererTestUtils::CreateTestDisplayConfig(0u); + dispConfig = RendererTestUtils::CreateTestDisplayConfig(0u); platform = platformFactory.createPlatform(rendererConfig, dispConfig.impl().getInternalDisplayConfig()); assert(platform); } @@ -53,7 +53,7 @@ namespace ramses::internal EXPECT_CALL(eventHandlerMock, onResize(_, _)).Times(AnyNumber()); EXPECT_CALL(eventHandlerMock, onWindowMove(_, _)).Times(AnyNumber()); - DisplayConfig displayConfig; + DisplayConfigData displayConfig; if (multisampling) displayConfig.setAntialiasingSampleCount(4); @@ -89,7 +89,7 @@ namespace ramses::internal } )SHADER"; - EffectResource effect(vertexShader, fragmentShader, "", {}, {}, {}, ""); + EffectResource effect(vertexShader, fragmentShader, "", SPIRVShaders{}, {}, {}, {}, "", EFeatureLevel_Latest); EXPECT_TRUE(device.isDeviceStatusHealthy()); auto resource = device.uploadShader(effect); EXPECT_NE(nullptr, resource); @@ -104,7 +104,8 @@ namespace ramses::internal EXPECT_TRUE(device.isDeviceStatusHealthy()); } - RendererConfig rendererConfig; + RendererConfigData rendererConfig; + ramses::DisplayConfig dispConfig; std::unique_ptr platform; StrictMock eventHandlerMock; }; @@ -167,6 +168,9 @@ namespace ramses::internal TEST_F(APlatform, CanCreateAndInitializeResourceUploadRenderBackend) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* mainRenderBackend = createRenderBackend(); ASSERT_NE(nullptr, mainRenderBackend); IResourceUploadRenderBackend* resourceUploadRenderBackend = createResourceUploadRenderBackend(); @@ -175,8 +179,23 @@ namespace ramses::internal platform->destroyRenderBackend(); } + TEST_F(APlatform, CanNotCreateAndInitializeResourceUploadRenderBackend) + { + if (dispConfig.getDeviceType() != EDeviceType::Vulkan) + GTEST_SKIP() << "Test supports only device type vulkan"; + + IRenderBackend* mainRenderBackend = createRenderBackend(); + ASSERT_NE(nullptr, mainRenderBackend); + IResourceUploadRenderBackend* resourceUploadRenderBackend = createResourceUploadRenderBackend(); + ASSERT_EQ(nullptr, resourceUploadRenderBackend); + platform->destroyRenderBackend(); + } + TEST_F(APlatform, CanRecreateRenderBackendsWithResourceUploadRenderBackends) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + { IRenderBackend* renderBackend = createRenderBackend(); ASSERT_NE(nullptr, renderBackend); @@ -201,6 +220,9 @@ namespace ramses::internal TEST_F(APlatform, ResourceUploadRenderBackendsCanBeEnabledMultipleTimes) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* renderBackend = createRenderBackend(); ASSERT_NE(nullptr, renderBackend); @@ -220,6 +242,9 @@ namespace ramses::internal TEST_F(APlatform, ResourceUploadRenderBackendCanBeDisabled) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* renderBackend = createRenderBackend(); ASSERT_NE(nullptr, renderBackend); @@ -234,6 +259,8 @@ namespace ramses::internal TEST_F(APlatform, ResourceUploadRenderBackendCanBeEnabledAndDisabledMultipleTimes) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; IRenderBackend* renderBackend = createRenderBackend(); ASSERT_NE(nullptr, renderBackend); @@ -251,6 +278,9 @@ namespace ramses::internal TEST_F(APlatform, CanCreateAndInitializeResourceUploadRenderBackendInOtherThreads) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* mainRenderBackend = createRenderBackend(); ASSERT_NE(nullptr, mainRenderBackend); EXPECT_TRUE(mainRenderBackend->getContext().disable()); @@ -278,6 +308,9 @@ namespace ramses::internal TEST_F(APlatform, CanEnableRenderBackendsInSameTimeInDifferentThreads) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* mainRenderBackend = createRenderBackend(); ASSERT_NE(nullptr, mainRenderBackend); EXPECT_TRUE(mainRenderBackend->getContext().disable()); @@ -315,6 +348,9 @@ namespace ramses::internal TEST_F(APlatform, CanUploadResourcesToRenderBackendsInDifferentThreads) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* mainRenderBackend = createRenderBackend(); ASSERT_NE(nullptr, mainRenderBackend); EXPECT_TRUE(mainRenderBackend->getContext().disable()); @@ -347,6 +383,9 @@ namespace ramses::internal TEST_F(APlatform, EnableContextInMainThreadDoesNotBlockResourceUploadInOtherThread) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* mainRenderBackend = createRenderBackend(); ASSERT_NE(nullptr, mainRenderBackend); EXPECT_TRUE(mainRenderBackend->getContext().disable()); @@ -391,6 +430,9 @@ namespace ramses::internal TEST_F(APlatform, CanUploadResourceInOneRenderBackendAndUseItInDifferentOneInDifferentThreads) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* mainRenderBackend = createRenderBackend(); ASSERT_NE(nullptr, mainRenderBackend); EXPECT_TRUE(mainRenderBackend->getContext().disable()); @@ -435,6 +477,9 @@ namespace ramses::internal TEST_F(APlatform, CanUploadResourceInOneRenderBackendAndUseItInDifferentOneInDifferentThreads_AfterResourceUploadRenderBackendDestroyed) { + if (dispConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Test does not support device type vulkan"; + IRenderBackend* mainRenderBackend = createRenderBackend(); ASSERT_NE(nullptr, mainRenderBackend); EXPECT_TRUE(mainRenderBackend->getContext().disable()); diff --git a/tests/integration/render-backend-tests/ShaderUploadTest.cpp b/tests/integration/render-backend-tests/ShaderUploadTest.cpp index 00b95ea3e..4a289ac78 100644 --- a/tests/integration/render-backend-tests/ShaderUploadTest.cpp +++ b/tests/integration/render-backend-tests/ShaderUploadTest.cpp @@ -18,7 +18,10 @@ #include "internal/SceneGraph/Resource/ResourceTypes.h" #include "internal/RendererLib/PlatformInterface/IRenderBackend.h" #include "internal/RendererLib/PlatformBase/Device_Base.h" +#include "internal/RendererLib/PlatformInterface/IContext.h" +#include "internal/RendererLib/PlatformBase/DeviceResourceMapper.h" #include "internal/Platform/PlatformFactory.h" +#include "internal/Platform/OpenGL/ShaderGPUResource_GL.h" #include #include @@ -29,8 +32,11 @@ namespace ramses::internal class ADevice : public Test { public: - ADevice() + void SetUp() override { + if (displayConfig.getDeviceType() == EDeviceType::Vulkan) + GTEST_SKIP() << "Shader upload tests do not support device type vulkan"; + // Need to "read" the error state in Device_GL once, in order to reset the error state to NO_ERROR // This is needed because all tests share the same device to save time std::ignore = testDevice->isDeviceStatusHealthy(); @@ -72,7 +78,7 @@ namespace ramses::internal EffectInputInformationVector attributeInputs; attributeInputs.push_back(EffectInputInformation("a_position", 1, EDataType::Vector3F, EFixedSemantics::Invalid)); - return new EffectResource(vertexShader, fragmentShader, "", {}, uniformInputs, attributeInputs, "test effect"); + return new EffectResource(vertexShader, fragmentShader, "", SPIRVShaders{}, {}, uniformInputs, attributeInputs, "test effect", EFeatureLevel_Latest); } static void SetUpTestSuite() @@ -80,15 +86,16 @@ namespace ramses::internal assert(nullptr == platform); ramses::RendererConfig rendererConfig = RendererTestUtils::CreateTestRendererConfig(); - ramses::DisplayConfig dispConfig = RendererTestUtils::CreateTestDisplayConfig(0u); + displayConfig = RendererTestUtils::CreateTestDisplayConfig(0u); + if (displayConfig.getDeviceType() == EDeviceType::Vulkan) + return; PlatformFactory platformFactory; - platform = platformFactory.createPlatform(rendererConfig.impl().getInternalRendererConfig(), dispConfig.impl().getInternalDisplayConfig()); + platform = platformFactory.createPlatform(rendererConfig.impl().getInternalRendererConfig(), displayConfig.impl().getInternalDisplayConfig()); assert(nullptr != platform); - eventHandler = new NiceMock(); + eventHandler = std::make_unique>(); - ramses::DisplayConfig displayConfig = RendererTestUtils::CreateTestDisplayConfig(0); displayConfig.setWindowRectangle(0, 0, 16u, 16u); renderBackend = platform->createRenderBackend(displayConfig.impl().getInternalDisplayConfig(), *eventHandler); assert(nullptr != renderBackend); @@ -98,30 +105,33 @@ namespace ramses::internal static void TearDownTestSuite() { - testDevice = nullptr; - - platform->destroyRenderBackend(); - renderBackend = nullptr; + if (platform) + { + testDevice = nullptr; - platform.reset(); + platform->destroyRenderBackend(); + renderBackend = nullptr; - delete eventHandler; - eventHandler = nullptr; + platform.reset(); + eventHandler.reset(); + } } protected: static IDevice* testDevice; + static IRenderBackend* renderBackend; private: static std::unique_ptr platform; - static IRenderBackend* renderBackend; - static NiceMock* eventHandler; + static std::unique_ptr> eventHandler; + static ramses::DisplayConfig displayConfig; }; std::unique_ptr ADevice::platform ; IDevice* ADevice::testDevice = nullptr; IRenderBackend* ADevice::renderBackend = nullptr; - NiceMock* ADevice::eventHandler = nullptr; + std::unique_ptr> ADevice::eventHandler = nullptr; + ramses::DisplayConfig ADevice::displayConfig; // Needed so that these tests can be blacklisted on drivers which don't support binary shaders @@ -189,7 +199,7 @@ namespace ramses::internal EffectInputInformationVector attributeInputs; attributeInputs.push_back(EffectInputInformation("a_position", 1, EDataType::Vector3F, EFixedSemantics::Invalid)); - return new EffectResource(vertexShader, fragmentShader, geometryShader, EDrawMode::Points, uniformInputs, attributeInputs, "test effect"); + return new EffectResource(vertexShader, fragmentShader, geometryShader, SPIRVShaders{}, EDrawMode::Points, uniformInputs, attributeInputs, "test effect", EFeatureLevel_Latest); } }; @@ -211,10 +221,10 @@ namespace ramses::internal const EffectResource invalidEffect( "--this is some invalid shader source code--", templateEffect->getFragmentShader(), - "", {}, + "", {}, {}, templateEffect->getUniformInputs(), templateEffect->getAttributeInputs(), - "invalid effect"); + "invalid effect", EFeatureLevel_Latest); const auto shaderGpuResource = testDevice->uploadShader(invalidEffect); EXPECT_EQ(nullptr, shaderGpuResource); } @@ -225,10 +235,10 @@ namespace ramses::internal const EffectResource invalidEffect( templateEffect->getVertexShader(), "--this is some invalid shader source code--", - "", {}, + "", SPIRVShaders{}, {}, templateEffect->getUniformInputs(), templateEffect->getAttributeInputs(), - "invalid effect"); + "invalid effect", EFeatureLevel_Latest); const auto shaderGpuResource = testDevice->uploadShader(invalidEffect); EXPECT_EQ(nullptr, shaderGpuResource); } @@ -252,10 +262,10 @@ namespace ramses::internal const EffectResource invalidEffect( templateEffect->getVertexShader(), fragmentShader, - "", {}, + "", SPIRVShaders{}, {}, templateEffect->getUniformInputs(), templateEffect->getAttributeInputs(), - "invalid effect"); + "invalid effect", EFeatureLevel_Latest); const auto shaderGpuResource = testDevice->uploadShader(invalidEffect); EXPECT_EQ(nullptr, shaderGpuResource); } @@ -310,10 +320,10 @@ namespace ramses::internal const EffectResource testEffect( templateEffect->getVertexShader(), fragmentShader, - "", {}, + "", SPIRVShaders{}, {}, uniformInputs, templateEffect->getAttributeInputs(), - "uniform test effect"); + "uniform test effect", EFeatureLevel_Latest); auto shaderGpuResource = testDevice->uploadShader(testEffect); ASSERT_NE(nullptr, shaderGpuResource); const DeviceResourceHandle handle = testDevice->registerShader(std::move(shaderGpuResource)); @@ -376,10 +386,10 @@ namespace ramses::internal const EffectResource testEffect( templateEffect->getVertexShader(), templateEffect->getFragmentShader(), - "", {}, + "", SPIRVShaders{}, {}, uniformInputs, templateEffect->getAttributeInputs(), - "test effect"); + "test effect", EFeatureLevel_Latest); auto shaderGpuResource = testDevice->uploadShader(testEffect); ASSERT_NE(nullptr, shaderGpuResource); @@ -500,10 +510,11 @@ namespace ramses::internal templateEffect->getVertexShader(), templateEffect->getFragmentShader(), "--this is some invalid shader source code--", + SPIRVShaders{}, EDrawMode::Lines, templateEffect->getUniformInputs(), templateEffect->getAttributeInputs(), - "invalid effect"); + "invalid effect", EFeatureLevel_Latest); const auto shaderGpuResource = testDevice->uploadShader(invalidEffect); EXPECT_EQ(nullptr, shaderGpuResource); } @@ -532,10 +543,11 @@ namespace ramses::internal templateEffect->getVertexShader(), templateEffect->getFragmentShader(), geometryShader, + SPIRVShaders{}, EDrawMode::Points, templateEffect->getUniformInputs(), templateEffect->getAttributeInputs(), - "invalid effect"); + "invalid effect", EFeatureLevel_Latest); const auto shaderGpuResource = testDevice->uploadShader(invalidEffect); EXPECT_EQ(nullptr, shaderGpuResource); } @@ -576,16 +588,17 @@ namespace ramses::internal const EffectResource invalidEffect(invalidShader, templateEffect->getFragmentShader(), templateEffect->getGeometryShader(), + SPIRVShaders{}, std::nullopt, templateEffect->getUniformInputs(), templateEffect->getAttributeInputs(), - "invalid effect"); + "invalid effect", EFeatureLevel_Latest); (void)testDevice->uploadShader(invalidEffect); - EXPECT_THAT(collectedErrors, ::testing::Contains(std::string{"1: Device_Base::PrintShaderSourceWithLineNumbers: L1: "} + invalidShader)); + EXPECT_THAT(collectedErrors.front(), HasSubstr(invalidShader)); } - auto shader = { + std::vector shader = { "#version 320 es", "", "layout(points) in;", @@ -612,28 +625,183 @@ namespace ramses::internal const EffectResource invalidEffect(templateEffect->getVertexShader(), templateEffect->getFragmentShader(), invalidGeometryShader, + SPIRVShaders{}, EDrawMode::Points, templateEffect->getUniformInputs(), templateEffect->getAttributeInputs(), - "invalid effect"); + "invalid effect", EFeatureLevel_Latest); (void)testDevice->uploadShader(invalidEffect); - std::vector expectedResult; - std::size_t l = 1; - for (const auto& line : shader) + for (size_t i = 0u; i < shader.size(); ++i) { - expectedResult.push_back(std::string{"1: Device_Base::PrintShaderSourceWithLineNumbers: L"} + std::to_string(l) + ": " + line); - l++; + EXPECT_THAT(collectedErrors[i], HasSubstr(shader[i])); } + } + ramses::RamsesFramework::SetLogHandler(nullptr); + } + + TEST_F(ADevice, GetsAttributeLocationsCorrectly) + { + ASSERT_TRUE(testDevice != nullptr); + + const std::unique_ptr templateEffect(CreateTestEffectResource()); + const std::string customVertexShader(R"SHADER( + #version 310 es - auto it = std::find(collectedErrors.begin(), collectedErrors.end(), expectedResult[0]); - for (const auto& line : expectedResult) + layout(location=1) in vec2 a_texCoords; + layout(location=0) in vec3 a_position; + + void main(void) { - ASSERT_NE(it, collectedErrors.end()); - EXPECT_EQ(*it, line); - it++; + gl_Position = vec4(a_position.x + a_texCoords.x); } - } - ramses::RamsesFramework::SetLogHandler(nullptr); + )SHADER"); + const std::string customFragmentShader(R"SHADER( + #version 310 es + out highp vec4 fragColor; + void main(void) + { + fragColor = vec4(1.0); + } + )SHADER"); + EffectInputInformationVector attributeInputs; + attributeInputs.push_back(EffectInputInformation("a_texCoords", 1, EDataType::Vector2F, EFixedSemantics::Invalid)); + attributeInputs.push_back(EffectInputInformation("a_position", 1, EDataType::Vector3F, EFixedSemantics::Invalid)); + + const EffectResource testEffect( + customVertexShader, + customFragmentShader, + "", + SPIRVShaders{}, + {}, {}, + attributeInputs, + "uniform test effect", EFeatureLevel_Latest); + + auto shaderGpuResource = testDevice->uploadShader(testEffect); + ASSERT_NE(nullptr, shaderGpuResource); + const DeviceResourceHandle handle = testDevice->registerShader(std::move(shaderGpuResource)); + ASSERT_TRUE(handle.isValid()); + + testDevice->activateShader(handle); + const auto& shaderResource = renderBackend->getContext().getResources().getResourceAs(handle); + EXPECT_EQ(1, shaderResource.getAttributeLocation(DataFieldHandle{ 0u }).getValue()); // tex coords + EXPECT_EQ(0, shaderResource.getAttributeLocation(DataFieldHandle{ 1u }).getValue()); // position + + testDevice->deleteShader(handle); + } + + TEST_F(ADevice, GetsOpaqueUniformLocationsCorrectly) + { + ASSERT_TRUE(testDevice != nullptr); + + const std::unique_ptr templateEffect(CreateTestEffectResource()); + const std::string customVertexShader(R"SHADER( + #version 310 es + + layout(location=11) uniform vec2 u_myVec2; + layout(location=5) uniform sampler2D u_mySampler1; + layout(location=23) uniform vec3 u_myVec3; + layout(location=7) uniform sampler2D u_mySampler2; + + void main(void) + { + gl_Position = vec4(u_myVec2.x + u_myVec3.x) + texture(u_mySampler1, vec2(0.0))+ texture(u_mySampler2, vec2(0.0)); + } + )SHADER"); + const std::string customFragmentShader(R"SHADER( + #version 310 es + out highp vec4 fragColor; + void main(void) + { + fragColor = vec4(1.0); + } + )SHADER"); + EffectInputInformationVector uniformInputs; + uniformInputs.push_back(EffectInputInformation("u_myVec2", 1, EDataType::Vector2F, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("u_mySampler1", 1, EDataType::TextureSampler2D, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("u_myVec3", 1, EDataType::Vector3F, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("u_mySampler2", 1, EDataType::TextureSampler2D, EFixedSemantics::Invalid)); + + const EffectResource testEffect( + customVertexShader, + customFragmentShader, + "", SPIRVShaders{}, {}, + uniformInputs, + {}, + "uniform test effect", EFeatureLevel_Latest); + + auto shaderGpuResource = testDevice->uploadShader(testEffect); + ASSERT_NE(nullptr, shaderGpuResource); + const DeviceResourceHandle handle = testDevice->registerShader(std::move(shaderGpuResource)); + ASSERT_TRUE(handle.isValid()); + + testDevice->activateShader(handle); + const auto& shaderResource = renderBackend->getContext().getResources().getResourceAs(handle); + EXPECT_EQ(11, shaderResource.getUniformLocation(DataFieldHandle{ 0u }).getValue()); + EXPECT_EQ(5, shaderResource.getUniformLocation(DataFieldHandle{ 1u }).getValue()); + EXPECT_EQ(23, shaderResource.getUniformLocation(DataFieldHandle{ 2u }).getValue()); + EXPECT_EQ(7, shaderResource.getUniformLocation(DataFieldHandle{ 3u }).getValue()); + + testDevice->deleteShader(handle); + } + + TEST_F(ADevice, GetsOpaqueUniformLocationsCorrectly_IfShaderHasUBO) + { + ASSERT_TRUE(testDevice != nullptr); + + const std::string customVertexShader(R"SHADER( + #version 310 es + + layout(location=11) uniform vec2 u_myVec2; + layout(location=5) uniform sampler2D u_mySampler1; + layout(std140,binding=1) uniform MyUbo_t + { + vec2 u_myVec2; + } myUbo; + layout(location=23) uniform vec3 u_myVec3; + layout(location=7) uniform sampler2D u_mySampler2; + + void main(void) + { + gl_Position = texture(u_mySampler1, u_myVec2)+ texture(u_mySampler2, myUbo.u_myVec2) * u_myVec3.x; + } + )SHADER"); + const std::string customFragmentShader(R"SHADER( + #version 310 es + out highp vec4 fragColor; + void main(void) + { + fragColor = vec4(1.0); + } + )SHADER"); + EffectInputInformationVector uniformInputs; + uniformInputs.push_back(EffectInputInformation("u_myVec2", 1, EDataType::Vector2F, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("u_mySampler1", 1, EDataType::TextureSampler2D, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("myUbo", 1, EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u })); + uniformInputs.push_back(EffectInputInformation("myUbo.u_myVec2", 1, EDataType::Vector2F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 8u }, UniformBufferFieldOffset{ 0u })); + uniformInputs.push_back(EffectInputInformation("u_myVec3", 1, EDataType::Vector3F, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("u_mySampler2", 1, EDataType::TextureSampler2D, EFixedSemantics::Invalid)); + const EffectResource testEffect( + customVertexShader, + customFragmentShader, + "", SPIRVShaders{}, {}, + uniformInputs, + {}, + "uniform test effect", EFeatureLevel_Latest); + + auto shaderGpuResource = testDevice->uploadShader(testEffect); + ASSERT_NE(nullptr, shaderGpuResource); + const DeviceResourceHandle handle = testDevice->registerShader(std::move(shaderGpuResource)); + ASSERT_TRUE(handle.isValid()); + + testDevice->activateShader(handle); + const auto& shaderResource = renderBackend->getContext().getResources().getResourceAs(handle); + EXPECT_EQ(11, shaderResource.getUniformLocation(DataFieldHandle{ 0u }).getValue()); + EXPECT_EQ(5, shaderResource.getUniformLocation(DataFieldHandle{ 1u }).getValue()); + EXPECT_FALSE(shaderResource.getUniformLocation(DataFieldHandle{ 2u }).isValid()); + EXPECT_EQ(23, shaderResource.getUniformLocation(DataFieldHandle{ 3u }).getValue()); + EXPECT_EQ(7, shaderResource.getUniformLocation(DataFieldHandle{ 4u }).getValue()); + + testDevice->deleteShader(handle); } } diff --git a/tests/integration/renderer-test-utils/RendererTestUtils.cpp b/tests/integration/renderer-test-utils/RendererTestUtils.cpp index 21cd57c7a..25510328c 100644 --- a/tests/integration/renderer-test-utils/RendererTestUtils.cpp +++ b/tests/integration/renderer-test-utils/RendererTestUtils.cpp @@ -140,7 +140,7 @@ namespace ramses::internal ramses::RendererConfig RendererTestUtils::CreateTestRendererConfig() { ramses::RendererConfig rendererConfig(*defaultRendererConfig); - auto& internalRendererConfig = const_cast(rendererConfig.impl().getInternalRendererConfig()); + auto& internalRendererConfig = const_cast(rendererConfig.impl().getInternalRendererConfig()); if (WaylandDisplayForSystemCompositorController.has_value()) { diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/EmbeddedCompositingTestsWithFD.cpp b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/EmbeddedCompositingTestsWithFD.cpp index 803364590..3d9204b82 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/EmbeddedCompositingTestsWithFD.cpp +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/EmbeddedCompositingTestsWithFD.cpp @@ -8,7 +8,7 @@ #include "EmbeddedCompositingTestsWithFD.h" #include "EmbeddedCompositingTestsFramework.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "impl/DisplayConfigImpl.h" #include "internal/Platform/Wayland/UnixDomainSocket.h" #include "internal/Platform/Wayland/WaylandEnvironmentUtils.h" diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiDisplayStreamTextureTests.cpp b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiDisplayStreamTextureTests.cpp index fd191acfc..087a57262 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiDisplayStreamTextureTests.cpp +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiDisplayStreamTextureTests.cpp @@ -8,7 +8,7 @@ #include "MultiDisplayStreamTextureTests.h" #include "TestScenes/EmbeddedCompositorScene.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "ETriangleColor.h" #include "impl/DisplayConfigImpl.h" diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiSceneStreamTextureTests.cpp b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiSceneStreamTextureTests.cpp index 90b7ab54b..5c2cf0c6a 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiSceneStreamTextureTests.cpp +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiSceneStreamTextureTests.cpp @@ -8,7 +8,7 @@ #include "MultiSceneStreamTextureTests.h" #include "TestScenes/EmbeddedCompositorScene.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" #include "ETriangleColor.h" #include "impl/DisplayConfigImpl.h" diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiStreamTextureTests.cpp b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiStreamTextureTests.cpp index ec18bfebe..0397780fd 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiStreamTextureTests.cpp +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/MultiStreamTextureTests.cpp @@ -8,7 +8,7 @@ #include "MultiStreamTextureTests.h" #include "TestScenes/EmbeddedCompositorScene.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" #include "impl/DisplayConfigImpl.h" diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/StreamBufferTests.cpp b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/StreamBufferTests.cpp index 35140ea9d..32528dfee 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/StreamBufferTests.cpp +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestCases/StreamBufferTests.cpp @@ -8,7 +8,7 @@ #include "StreamBufferTests.h" #include "TestScenes/EmbeddedCompositorScene.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/LogMacros.h" namespace ramses::internal diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/OpenGLTriangleDrawer.h b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/OpenGLTriangleDrawer.h index 5d5ddfc36..8bea6c501 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/OpenGLTriangleDrawer.h +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/OpenGLTriangleDrawer.h @@ -8,7 +8,7 @@ #pragma once -#include +#include "internal/Platform/OpenGL/Device_GL_platform.h" #include "ETriangleColor.h" namespace ramses::internal diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/TestWaylandApplication.cpp b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/TestWaylandApplication.cpp index 1618c2679..3335406d7 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/TestWaylandApplication.cpp +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/TestWaylandApplication.cpp @@ -20,7 +20,7 @@ #include "impl/DisplayConfigImpl.h" #include "internal/PlatformAbstraction/PlatformSignal.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Core/Utils/BinaryInputStream.h" namespace ramses::internal diff --git a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/WaylandHandler.cpp b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/WaylandHandler.cpp index 82de76b6c..661cab8dd 100644 --- a/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/WaylandHandler.cpp +++ b/tests/integration/renderer-tests/embedded-compositing-rendering-tests/TestWaylandApplication/WaylandHandler.cpp @@ -10,7 +10,7 @@ #include "SHMBuffer.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/Platform/Wayland/WaylandEnvironmentUtils.h" -#include +#include "internal/Platform/OpenGL/Device_GL_platform.h" #include namespace ramses::internal @@ -512,6 +512,11 @@ namespace ramses::internal return false; } + eglMakeCurrent(egldisplay, window.eglsurface, window.eglsurface, window.eglcontext); + auto version = gladLoadGLES2(eglGetProcAddress); + LOG_INFO(CONTEXT_RENDERER, "WaylandHandler::gladLoadGLES2 version {}", version); + eglMakeCurrent(egldisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + return true; } diff --git a/tests/integration/renderer-tests/renderer-lifecycle-tests/ExternalWindowTests.cpp b/tests/integration/renderer-tests/renderer-lifecycle-tests/ExternalWindowTests.cpp index 3aa394a2a..b515bd37b 100644 --- a/tests/integration/renderer-tests/renderer-lifecycle-tests/ExternalWindowTests.cpp +++ b/tests/integration/renderer-tests/renderer-lifecycle-tests/ExternalWindowTests.cpp @@ -80,6 +80,8 @@ namespace ramses::internal Window_X11 window(dispConfigExternalWindow.impl().getInternalDisplayConfig(), dummyEventHandler, 1); ASSERT_TRUE(window.init()); dispConfig.setX11WindowHandle(X11WindowHandle{window.getNativeWindowHandle()}); +#else + FAIL() << "Test running on unsupported platform"; #endif const displayId_t display = testRenderer.createDisplay(dispConfig); diff --git a/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.cpp b/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.cpp index 6c898cfba..754629379 100644 --- a/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.cpp +++ b/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.cpp @@ -21,6 +21,9 @@ #include "TestScenes/TransformationLinkScene.h" #include "TestScenes/VisibilityScene.h" #include "TestScenes/RenderTargetScene.h" +#include "TestScenes/LogicScene.h" +#include "internal/Core/Utils/File.h" +#include "internal/Core/Utils/ThreadBarrier.h" // These includes are needed because of ramses API usage #include "ramses/renderer/IRendererEventHandler.h" @@ -28,6 +31,9 @@ #include "ramses/renderer/DisplayConfig.h" #include "ramses/client/DataObject.h" #include "ramses/client/SceneReference.h" +#include "ramses/client/logic/LogicEngine.h" +#include "ramses/client/logic/LuaScript.h" +#include "ramses/client/logic/Property.h" #include "impl/RamsesObjectTypeUtils.h" #include "impl/ValidationReportImpl.h" @@ -220,6 +226,40 @@ namespace ramses::internal } #endif + TEST_F(ARendererLifecycleTest, MergeScenes) + { + const sceneId_t sceneId = createScene(MultipleTrianglesScene::THREE_TRIANGLES, glm::vec3(0.0f, 0.0f, 5.0f)); + testScenesAndRenderer.initializeRenderer(); + const displayId_t display = createDisplayForWindow(); + ASSERT_TRUE(display != displayId_t::Invalid()); + + testScenesAndRenderer.publish(sceneId); + testScenesAndRenderer.flush(sceneId); + testRenderer.setSceneMapping(sceneId, display); + ASSERT_TRUE(testScenesAndRenderer.getSceneToState(sceneId, RendererSceneState::Rendered)); + ASSERT_TRUE(checkScreenshot(display, "ARendererInstance_Three_Triangles")); + + auto& client = testScenesAndRenderer.getClient(); + // create two more scenes and save to files + for (size_t i = 0; i < 2; ++i) { + int sign = (i%2 != 0u)? -1 : 1; + const sceneId_t sid = createScene(MultipleTrianglesScene::THREE_TRIANGLES, glm::vec3(3.0f * sign, 1.0f * sign, 3.0f)); + auto& newScene = testScenesAndRenderer.getScenesRegistry().getScene(sid); + ASSERT_TRUE(newScene.saveToFile(fmt::format("newSceneToMerge{}.ramses", i))); + EXPECT_TRUE(client.destroy(newScene)); + } + + auto& renderedScene = testScenesAndRenderer.getScenesRegistry().getScene(sceneId); + for (size_t i = 0; i < 2; ++i) { + ASSERT_TRUE(client.mergeSceneFromFile(renderedScene, fmt::format("newSceneToMerge{}.ramses", i))); + } + + testScenesAndRenderer.flush(sceneId); + ASSERT_TRUE(checkScreenshot(display, "ARendererInstance_MergeScenes")); + testScenesAndRenderer.unpublish(sceneId); + testScenesAndRenderer.destroyRenderer(); + } + TEST_F(ARendererLifecycleTest, UnsubscribeRenderer_ChangeScene_ThenResubscribeRenderer) { const sceneId_t sceneId = createScene(MultipleTrianglesScene::THREE_TRIANGLES, glm::vec3(0.0f, 0.0f, 5.0f)); @@ -319,6 +359,48 @@ namespace ramses::internal testScenesAndRenderer.destroyRenderer(); } + TEST_F(ARendererLifecycleTest, DestroyDisplayAndRemapSceneToOtherDisplay_LocalOnly) + { + ramses::SceneConfig config; + config.setPublicationMode(ramses::EScenePublicationMode::LocalOnly); + const ramses::sceneId_t sceneId = createScene(MultipleTrianglesScene::THREE_TRIANGLES, glm::vec3(0.0f, 0.0f, 5.0f), WindowWidth, WindowHeight, config); + testScenesAndRenderer.initializeRenderer(); + testScenesAndRenderer.publish(sceneId); + testScenesAndRenderer.flush(sceneId); + + { + const ramses::displayId_t display0 = createDisplayForWindow(0u); + ASSERT_TRUE(ramses::displayId_t::Invalid() != display0); + + testRenderer.setSceneMapping(sceneId, display0); + testRenderer.setSceneState(sceneId, ramses::RendererSceneState::Rendered); + testRenderer.doOneLoop(); // calls addSubscriber, but does NOT send the scene + // LocalOnly scenes cannot send the initial flush automatically + testRenderer.doOneLoop(); + testRenderer.doOneLoop(); + testRenderer.setSceneState(sceneId, ramses::RendererSceneState::Available); // unsubscribes the scene + testRenderer.doOneLoop(); + testRenderer.doOneLoop(); + testRenderer.destroyDisplay(display0); + } + + { + testScenesAndRenderer.flush(sceneId); + const ramses::displayId_t display1 = createDisplayForWindow(1u); + ASSERT_TRUE(ramses::displayId_t::Invalid() != display1); + testRenderer.setSceneMapping(sceneId, display1); + testRenderer.setSceneState(sceneId, ramses::RendererSceneState::Rendered); + testRenderer.doOneLoop(); // calls addSubscriber + testScenesAndRenderer.flush(sceneId); // sends the scene ! + ASSERT_TRUE(testScenesAndRenderer.getSceneToState(sceneId, ramses::RendererSceneState::Rendered)); + + ASSERT_TRUE(checkScreenshot(display1, "ARendererInstance_Three_Triangles")); + } + + testScenesAndRenderer.unpublish(sceneId); + testScenesAndRenderer.destroyRenderer(); + } + TEST_F(ARendererLifecycleTest, RenderScene_Threaded) { testScenesAndRenderer.initializeRenderer(); @@ -644,6 +726,10 @@ namespace ramses::internal TestScenes& m_scenes; }; +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif TEST_F(ARendererLifecycleTest, ReferencedScenesWithDataLinkAndRenderOrder) { testScenesAndRenderer.initializeRenderer(); @@ -1105,6 +1191,9 @@ namespace ramses::internal testScenesAndRenderer.unpublish(sceneRefId2); testScenesAndRenderer.destroyRenderer(); } +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif TEST_F(ARendererLifecycleTest, PollingFrameCallbacks_DoesNotBlockIfNoDisplaysExist) { @@ -1253,6 +1342,11 @@ namespace ramses::internal testScenesAndRenderer.destroyRenderer(); } +// expiration is deprecated feature +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif TEST_F(ARendererLifecycleTest, SceneNotExpiredWhenUpdatedAndSubscribed) { testScenesAndRenderer.initializeRenderer(); @@ -1666,6 +1760,9 @@ namespace ramses::internal testScenesAndRenderer.destroyRenderer(); } +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif TEST_F(ARendererLifecycleTest, HandlesSwitchingTriStateVisibilityFullyOffAndOn) { @@ -1987,4 +2084,177 @@ namespace ramses::internal testScenesAndRenderer.unpublish(sceneId); testScenesAndRenderer.destroyRenderer(); } + + static const std::string_view SceneFileName = "multiInstanceTestScene.ramses"; + enum class RenderingMode { DoOneLoop, Threaded }; + class ARendererLifecycleTest_MultipleInstances : public ::testing::TestWithParam + { + protected: + static void SetUpTestSuite() + { + // first create some scene and save it to file + TestScenesAndRenderer testScenesAndRenderer{ ramses::RamsesFrameworkConfig{ EFeatureLevel_Latest } }; + const sceneId_t sceneId = testScenesAndRenderer.getScenesRegistry().createScene(LogicScene::TRIANGLE_LOGIC, + glm::vec3(0.0f, 0.0f, 5.0f), ARendererLifecycleTest::WindowWidth, ARendererLifecycleTest::WindowHeight); + + auto& scene = testScenesAndRenderer.getScenesRegistry().getScene(sceneId); + ASSERT_TRUE(scene.saveToFile(SceneFileName)); + } + + static void TearDownTestSuite() + { + File file{ SceneFileName }; + if (file.exists()) + file.remove(); + } + }; + + class ARendererLifecycleTest_TestInstance + { + public: + ARendererLifecycleTest_TestInstance(uint32_t instanceIdx, RenderingMode renderMode) + : m_instanceIdx{ instanceIdx } + , m_renderMode { renderMode } + { + } + + void createFrameworkAndLoadScene() + { + ramses::RamsesFrameworkConfig cfg{ EFeatureLevel_Latest }; + cfg.setLoggingInstanceName(fmt::format("testInstance{}", m_instanceIdx)); + m_framework = std::make_unique(cfg); + auto client = m_framework->createClient(fmt::format("testClient{}", m_instanceIdx)); + ASSERT_TRUE(client); + m_scene = client->loadSceneFromFile(SceneFileName); + ASSERT_TRUE(m_scene); + m_scene->publish(); + } + + void createRendererAndDisplay() + { + m_renderer = std::make_unique(); + m_renderer->initializeRendererWithFramework(*m_framework, RendererTestUtils::CreateTestRendererConfig()); + if (m_renderMode == RenderingMode::Threaded) + m_renderer->startRendererThread(); + + auto displayConfig = RendererTestUtils::CreateTestDisplayConfig(m_instanceIdx, true); + displayConfig.setWindowRectangle(ARendererLifecycleTest::WindowX, ARendererLifecycleTest::WindowY, ARendererLifecycleTest::WindowWidth, ARendererLifecycleTest::WindowHeight); + m_display = m_renderer->createDisplay(displayConfig); + ASSERT_TRUE(m_display != displayId_t::Invalid()); + + m_renderer->setSceneMapping(m_scene->getSceneId(), m_display); + ASSERT_TRUE(m_renderer->getSceneToState(*m_scene, RendererSceneState::Rendered)); + } + + void updateAndRenderFewFrames() + { + auto le = m_scene->findObject("le"); + ASSERT_TRUE(le); + auto script = le->findObject("script"); + ASSERT_TRUE(script); + + // update logic and render few frames with some changing values ending up at the correct one (one) + for (int x = -4; x <= 1; ++x) + { + EXPECT_TRUE(script->getInputs()->getChild("translation_x")->set(float(x))); + EXPECT_TRUE(le->update()); + EXPECT_TRUE(m_scene->flush()); + + if (m_renderMode == RenderingMode::Threaded) + { + std::this_thread::sleep_for(std::chrono::milliseconds{ 10 }); + } + else + { + m_renderer->doOneLoop(); + } + } + } + + void checkScreenshot() + { + EXPECT_TRUE(m_renderer->performScreenshotCheck(m_display, {}, 0u, 0u, ARendererLifecycleTest::WindowWidth, ARendererLifecycleTest::WindowHeight, "AMultipleInstances_TriangleWithLogic")); + } + + private: + uint32_t m_instanceIdx = 0u; + RenderingMode m_renderMode = RenderingMode::DoOneLoop; + std::unique_ptr m_framework; + ramses::Scene* m_scene = nullptr; + std::unique_ptr m_renderer; + ramses::displayId_t m_display; + }; + + INSTANTIATE_TEST_SUITE_P( + ARendererLifecycleTest_MultipleInstances_TestInstances, + ARendererLifecycleTest_MultipleInstances, + ::testing::Values( + RenderingMode::DoOneLoop, + RenderingMode::Threaded) + ); + + TEST_P(ARendererLifecycleTest_MultipleInstances, MultipleRamsesInstancesInSequence) + { + for (uint32_t i = 0u; i < 3u; ++i) + { + ARendererLifecycleTest_TestInstance testInstance{ i, GetParam() }; + testInstance.createFrameworkAndLoadScene(); + testInstance.createRendererAndDisplay(); + testInstance.updateAndRenderFewFrames(); + testInstance.checkScreenshot(); + } + } + + TEST_P(ARendererLifecycleTest_MultipleInstances, MultipleRamsesInstancesInParallel) + { + static constexpr uint32_t NumInstances = 3u; + std::vector threads; + threads.reserve(NumInstances); + for (uint32_t i = 0u; i < NumInstances; ++i) + { + threads.emplace_back([i] { + ARendererLifecycleTest_TestInstance testInstance{ i, GetParam() }; + testInstance.createFrameworkAndLoadScene(); + testInstance.createRendererAndDisplay(); + testInstance.updateAndRenderFewFrames(); + testInstance.checkScreenshot(); + }); + } + + for (auto& t : threads) + t.join(); + } + + TEST_P(ARendererLifecycleTest_MultipleInstances, MultipleRamsesInstancesInParallel_WithBarriers) + { + static constexpr uint32_t NumInstances = 3u; + ThreadBarrier loadBarrier{ NumInstances }; + ThreadBarrier initRendererBarrier{ NumInstances }; + ThreadBarrier loopBarrier{ NumInstances }; + ThreadBarrier checkScreenshortBarrier{ NumInstances }; + + std::vector threads; + threads.reserve(NumInstances); + for (uint32_t i = 0u; i < NumInstances; ++i) + { + threads.emplace_back([&, i] { + ARendererLifecycleTest_TestInstance testInstance{ i, GetParam() }; + + loadBarrier.wait(); + testInstance.createFrameworkAndLoadScene(); + + initRendererBarrier.wait(); + testInstance.createRendererAndDisplay(); + + loopBarrier.wait(); + testInstance.updateAndRenderFewFrames(); + + checkScreenshortBarrier.wait(); + testInstance.checkScreenshot(); + }); + } + + for (auto& t : threads) + t.join(); + } } diff --git a/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.h b/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.h index 11e0e438e..5776346c5 100644 --- a/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.h +++ b/tests/integration/renderer-tests/renderer-lifecycle-tests/RendererLifecycleTests.h @@ -9,6 +9,7 @@ #pragma once #include "TestScenesAndRenderer.h" +#include "ramses/client/SceneConfig.h" #include "gtest/gtest.h" namespace ramses::internal @@ -21,6 +22,11 @@ namespace ramses::internal , testRenderer(testScenesAndRenderer.getTestRenderer()) {} + static const uint32_t WindowX = 0u; + static const uint32_t WindowY = 0u; + static const uint32_t WindowWidth = 128u; + static const uint32_t WindowHeight = 64u; + protected: displayId_t createDisplayForWindow(uint32_t iviSurfaceIdOffset = 0u, bool iviWindowStartVisible = true) { @@ -38,21 +44,16 @@ namespace ramses::internal } template - sceneId_t createScene(uint32_t state, const glm::vec3& cameraPosition = { 0.f, 0.f, 0.f }, uint32_t vpWidth = WindowWidth, uint32_t vpHeight = WindowHeight) + sceneId_t createScene(uint32_t state, const glm::vec3& cameraPosition = { 0.f, 0.f, 0.f }, uint32_t vpWidth = WindowWidth, uint32_t vpHeight = WindowHeight, const ramses::SceneConfig& config = {}) { - return testScenesAndRenderer.getScenesRegistry().createScene(state, cameraPosition, vpWidth, vpHeight); + return testScenesAndRenderer.getScenesRegistry().createScene(state, cameraPosition, vpWidth, vpHeight, config); } template - void createScene(uint32_t state, sceneId_t sceneId, const glm::vec3& cameraPosition = { 0.f, 0.f, 0.f }) + void createScene(uint32_t state, sceneId_t sceneId, const glm::vec3& cameraPosition = { 0.f, 0.f, 0.f }, const ramses::SceneConfig& config = {}) { - testScenesAndRenderer.getScenesRegistry().createScene(state, sceneId, cameraPosition, WindowWidth, WindowHeight); + testScenesAndRenderer.getScenesRegistry().createScene(state, sceneId, cameraPosition, WindowWidth, WindowHeight, config); } - static const uint32_t WindowX = 0u; - static const uint32_t WindowY = 0u; - static const uint32_t WindowWidth = 128u; - static const uint32_t WindowHeight = 64u; - RamsesFrameworkConfig frameworkConfig{EFeatureLevel_Latest}; TestScenesAndRenderer testScenesAndRenderer; TestRenderer& testRenderer; diff --git a/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.cpp b/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.cpp index e34876dbf..04c13e1e3 100644 --- a/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.cpp +++ b/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.cpp @@ -11,7 +11,6 @@ #include "ramses/renderer/IRendererEventHandler.h" #include "impl/DisplayConfigImpl.h" #include "IRendererTest.h" -#include "impl/DisplayConfigImpl.h" #include "internal/Core/Utils/LogMacros.h" #include "internal/PlatformAbstraction/PlatformTime.h" #include "RendererTestUtils.h" @@ -362,8 +361,9 @@ namespace ramses::internal const auto& testCaseName = testCase->m_name; const bool excludedByFilterIn = processFilterIn && !NameMatchesFilter(testCaseName, filterIn); const bool excludedByFilterOut = processFilterOut && NameMatchesFilter(testCaseName, filterOut); + const bool excludedByFeatureLevel = (std::count(testCase->m_featureLevelsToTest.cbegin(), testCase->m_featureLevelsToTest.cend(), m_testScenesAndRenderer.getFeatureLevel()) == 0); - if (excludedByFilterIn || excludedByFilterOut) + if (excludedByFilterIn || excludedByFilterOut || excludedByFeatureLevel) { delete testCase; } @@ -383,8 +383,8 @@ namespace ramses::internal for (size_t i = 0; i < a.size(); ++i) { - const ramses::internal::DisplayConfig& displayConfigA = a[i].impl().getInternalDisplayConfig(); - const ramses::internal::DisplayConfig& displayConfigB = b[i].impl().getInternalDisplayConfig(); + const auto& displayConfigA = a[i].impl().getInternalDisplayConfig(); + const auto& displayConfigB = b[i].impl().getInternalDisplayConfig(); if (displayConfigA != displayConfigB) { @@ -443,8 +443,8 @@ namespace ramses::internal { assert(i < m_displays.size()); - ramses::internal::DisplayConfig currentDisplayConfig = m_displays[i].config.impl().getInternalDisplayConfig(); - ramses::internal::DisplayConfig requestedDisplayConfig = testCase.m_displayConfigs[i].impl().getInternalDisplayConfig(); + auto currentDisplayConfig = m_displays[i].config.impl().getInternalDisplayConfig(); + auto requestedDisplayConfig = testCase.m_displayConfigs[i].impl().getInternalDisplayConfig(); // ignore wayland ID in comparison as this is different for every test display config requestedDisplayConfig.setWaylandIviSurfaceID(currentDisplayConfig.getWaylandIviSurfaceID()); @@ -583,10 +583,10 @@ namespace ramses::internal { ramses::internal::StringOutputStream str; - str << "\n\n--- Rendering test report begin ---\n"; + if (!m_passedTestCases.empty() || !m_failedTestCases.empty()) { str << "\n Passed rendering test cases: " << m_passedTestCases.size(); - for(const auto& testCase : m_passedTestCases) + for (const auto& testCase : m_passedTestCases) { str << "\n " << testCase->m_name; } @@ -596,12 +596,13 @@ namespace ramses::internal { str << "\n " << testCase->m_name; } + str << "\n Time elapsed: " << static_cast(m_elapsedTime) * 0.001f << " s"; if (m_failedTestCases.empty()) { str << "\n"; str << "\n ------------------"; - str << "\n --- ALL PASSED ---"; + str << "\n ----- PASSED -----"; str << "\n ------------------"; } else @@ -611,10 +612,9 @@ namespace ramses::internal str << "\n !!! FAILED TESTS !!!"; str << "\n !!!!!!!!!!!!!!!!!!!!"; } - - str << "\n\n Total time elapsed: " << static_cast(m_elapsedTime) * 0.001f << " s"; } - str << "\n\n--- End of rendering test report ---\n\n"; + else + str << "\n No rendering tests ran."; return str.release(); } diff --git a/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.h b/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.h index 76710648f..fc43d3f2d 100644 --- a/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.h +++ b/tests/integration/renderer-tests/renderer-test-framework/RendererTestsFramework.h @@ -11,6 +11,7 @@ #include "TestScenesAndRenderer.h" #include "RenderingTestCase.h" #include "internal/PlatformAbstraction/Collections/Pair.h" +#include "internal/glslEffectBlock/GlslangInitializer.h" #include "RendererTestUtils.h" #include @@ -141,6 +142,8 @@ namespace ramses::internal void destroyBuffers(); bool runTestCase(RenderingTestCase& testCase); + GlslangInitializer m_glslangInitializer; + const bool m_generateScreenshots; ramses::internal::TestScenesAndRenderer m_testScenesAndRenderer; ramses::internal::TestRenderer& m_testRenderer; diff --git a/tests/integration/renderer-tests/renderer-test-framework/RenderingTestCase.h b/tests/integration/renderer-tests/renderer-test-framework/RenderingTestCase.h index 11d760fab..b8377f624 100644 --- a/tests/integration/renderer-tests/renderer-test-framework/RenderingTestCase.h +++ b/tests/integration/renderer-tests/renderer-test-framework/RenderingTestCase.h @@ -30,10 +30,18 @@ namespace ramses::internal { } + void enableForAllFeatureLevels(EFeatureLevel startingFrom = EFeatureLevel_01) + { + m_featureLevelsToTest.clear(); + for (EFeatureLevel fl = startingFrom; fl <= EFeatureLevel_Latest; fl = EFeatureLevel{ fl + 1 }) + m_featureLevelsToTest.push_back(fl); + } + const uint32_t m_id; const std::string m_name; DisplayConfigVector m_displayConfigs; IRendererTest& m_rendererTest; bool m_defaultRendererRequired; + std::vector m_featureLevelsToTest{ EFeatureLevel_Latest }; }; } diff --git a/tests/integration/renderer-tests/renderer-test-framework/TestScenes.h b/tests/integration/renderer-tests/renderer-test-framework/TestScenes.h index 83ae4f5b3..e18468287 100644 --- a/tests/integration/renderer-tests/renderer-test-framework/TestScenes.h +++ b/tests/integration/renderer-tests/renderer-test-framework/TestScenes.h @@ -56,23 +56,28 @@ namespace ramses::internal ramses::sceneId_t sceneId, const glm::vec3& cameraPosition, uint32_t vpWidth, - uint32_t vpHeight) + uint32_t vpHeight, + const ramses::SceneConfig& config = {}) { SceneData data; - data.clientScene = m_client.createScene(SceneConfig(sceneId)); + SceneConfig config2 = config; + config2.setSceneId(sceneId); + data.clientScene = m_client.createScene(config2); data.integrationScene = new INTEGRATION_SCENE(*data.clientScene, state, cameraPosition, vpWidth, vpHeight); m_scenes.put(sceneId, data); } + template ramses::sceneId_t createScene( uint32_t state, const glm::vec3& cameraPosition, uint32_t vpWidth, - uint32_t vpHeight) + uint32_t vpHeight, + const ramses::SceneConfig& config = {}) { const ramses::sceneId_t sceneId = m_nextSceneId; m_nextSceneId.getReference()++; - createScene(state, sceneId, cameraPosition, vpWidth, vpHeight); + createScene(state, sceneId, cameraPosition, vpWidth, vpHeight, config); return sceneId; } diff --git a/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.cpp b/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.cpp index a1311e4b0..99f15f0b7 100644 --- a/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.cpp +++ b/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.cpp @@ -48,7 +48,14 @@ namespace ramses::internal void TestScenesAndRenderer::setExpirationTimestamp(ramses::sceneId_t sceneId, FlushTime::Clock::time_point expirationTS) { +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif m_scenes.getScene(sceneId).setExpirationTimestamp(std::chrono::duration_cast(expirationTS.time_since_epoch()).count()); +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif } bool TestScenesAndRenderer::loopTillClientEvent(TestClientEventHandler& handlerWithCondition) @@ -113,4 +120,9 @@ namespace ramses::internal { return m_renderer; } + + ramses::EFeatureLevel TestScenesAndRenderer::getFeatureLevel() const + { + return m_ramsesFramework.getFeatureLevel(); + } } diff --git a/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.h b/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.h index 28e009ec3..233af1ab1 100644 --- a/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.h +++ b/tests/integration/renderer-tests/renderer-test-framework/TestScenesAndRenderer.h @@ -49,6 +49,8 @@ namespace ramses::internal [[nodiscard]] const TestRenderer& getTestRenderer() const; [[nodiscard]] TestRenderer& getTestRenderer(); + [[nodiscard]] EFeatureLevel getFeatureLevel() const; + private: ramses::RamsesFramework m_ramsesFramework; ramses::RamsesClient& m_client; diff --git a/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.cpp b/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.cpp index 13906fdb8..cf14baa42 100644 --- a/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.cpp +++ b/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.cpp @@ -72,6 +72,11 @@ namespace ramses::internal testFramework.createTestCase(DisplayRenderingTest_FramebufferWithoutStencil , *this, "DisplayRenderingTest_FramebufferWithoutStencil").m_displayConfigs.push_back(displayConfigWithoutStencil); testFramework.createTestCase(DisplayRenderingTest_AsyncEffectUploadDisabled, *this, "DisplayRenderingTest_AsyncEffectUploadDisabled").m_displayConfigs.push_back(displayConfigWithoutAsyncEffectUpload); + + ramses::DisplayConfig displayConfigMsaa = RendererTestUtils::CreateTestDisplayConfig(0); + displayConfigMsaa.setWindowRectangle(0, 0, DisplayWidth, DisplayHeight); + displayConfigMsaa.setMultiSampling(4u); + testFramework.createTestCase(DisplayRenderingTest_ReadPixelsMSAA, *this, "DisplayRenderingTest_ReadPixelsMSAA").m_displayConfigs.push_back(displayConfigMsaa); } bool DisplayRenderingTests::run(RendererTestsFramework& testFramework, const RenderingTestCase& testCase) @@ -109,13 +114,15 @@ namespace ramses::internal return RunFramebufferWithoutDepthAndStencilTest(testFramework); case DisplayRenderingTest_FramebufferWithoutStencil: return RunFramebufferWithoutStencil(testFramework); + case DisplayRenderingTest_ReadPixelsMSAA: + return RunTwoScenesTest(testFramework, true); default: assert(!"Invalid renderer test ID!"); return false; } } - bool DisplayRenderingTests::RunTwoScenesTest(RendererTestsFramework& testFramework) + bool DisplayRenderingTests::RunTwoScenesTest(RendererTestsFramework& testFramework, bool msaa) { const ramses::sceneId_t sceneId = testFramework.getScenesRegistry().createScene(ramses::internal::MultipleTrianglesScene::THREE_TRIANGLES, glm::vec3(2.0f, 0.0f, 5.0f), DisplayWidth, DisplayHeight); @@ -127,7 +134,7 @@ namespace ramses::internal testFramework.getSceneToRendered(sceneId); testFramework.getSceneToRendered(otherId); - return testFramework.renderAndCompareScreenshot("ARendererDisplays_TwoScenes"); + return testFramework.renderAndCompareScreenshot("ARendererDisplays_TwoScenes", 0u, msaa ? 0.8f : RendererTestUtils::DefaultMaxAveragePercentPerPixel); } bool DisplayRenderingTests::RunUnpublishTest(RendererTestsFramework& testFramework) diff --git a/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.h b/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.h index 2fb180fc6..5411a96ab 100644 --- a/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.h +++ b/tests/integration/renderer-tests/rendering-tests/DisplayRenderingTests.h @@ -19,7 +19,7 @@ namespace ramses::internal bool run(RendererTestsFramework& testFramework, const RenderingTestCase& testCase) final; private: - static bool RunTwoScenesTest(RendererTestsFramework& testFramework); + static bool RunTwoScenesTest(RendererTestsFramework& testFramework, bool msaa = false); static bool RunUnpublishTest(RendererTestsFramework& testFramework); static bool RunHideTest(RendererTestsFramework& testFramework); static bool RunSceneRenderOrderTest(RendererTestsFramework& testFramework); @@ -52,7 +52,8 @@ namespace ramses::internal DisplayRenderingTest_ResubscribeScene, DisplayRenderingTest_FramebufferWithoutDepthAndStencil, DisplayRenderingTest_FramebufferWithoutStencil, - DisplayRenderingTest_AsyncEffectUploadDisabled + DisplayRenderingTest_AsyncEffectUploadDisabled, + DisplayRenderingTest_ReadPixelsMSAA }; static constexpr uint32_t DisplayWidth = 128u; diff --git a/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.cpp b/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.cpp index 13b979f9e..c01a09b73 100644 --- a/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.cpp +++ b/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.cpp @@ -15,15 +15,16 @@ namespace ramses::internal { void EffectRenderingTests::setUpTestCases(RendererTestsFramework& testFramework) { - testFramework.createTestCaseWithDefaultDisplay(EffectTest_Shaders, *this, "EffectTest_Shaders"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_Discard_Shaders, *this, "EffectTest_Discard_Shaders"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_UniformWithSameNameInBothStages, *this, "EffectTest_UniformWithSameNameInBothStages"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_ExplicitAttributeLocation, *this, "EffectTest_ExplicitAttributeLocation"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_ExplicitAttributeLocationSwapped, *this, "EffectTest_ExplicitAttributeLocationSwapped"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_StructUniform, *this, "EffectTest_StructUniform"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_BoolUniform, *this, "EffectTest_BoolUniform"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_TextureSize, *this, "EffectTest_TextureSize"); - testFramework.createTestCaseWithDefaultDisplay(EffectTest_OptimizedInput, *this, "EffectTest_OptimizedInput"); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_Shaders, *this, "EffectTest_Shaders").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_Discard_Shaders, *this, "EffectTest_Discard_Shaders").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_UniformWithSameNameInBothStages, *this, "EffectTest_UniformWithSameNameInBothStages").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_ExplicitAttributeLocation, *this, "EffectTest_ExplicitAttributeLocation").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_ExplicitAttributeLocationSwapped, *this, "EffectTest_ExplicitAttributeLocationSwapped").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_StructUniform, *this, "EffectTest_StructUniform").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_BoolUniform, *this, "EffectTest_BoolUniform").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_TextureSize, *this, "EffectTest_TextureSize").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_OptimizedInput, *this, "EffectTest_OptimizedInput").enableForAllFeatureLevels(); + testFramework.createTestCaseWithDefaultDisplay(EffectTest_UniformBuffersStd140, *this, "EffectTest_UniformBuffersStd140").enableForAllFeatureLevels(EFeatureLevel_02); } bool EffectRenderingTests::run(RendererTestsFramework& testFramework, const RenderingTestCase& testCase) @@ -48,6 +49,8 @@ namespace ramses::internal return runBasicTest(testFramework, ShaderTestScene::BOOL_UNIFORM, "ShaderTestScene_BoolUniform"); case EffectTest_TextureSize: return runBasicTest(testFramework, ShaderTestScene::TEXTURE_SIZE, "ShaderTestScene_TextureSize"); + case EffectTest_UniformBuffersStd140: + return runBasicTest(testFramework, ShaderTestScene::UNIFORM_BUFFERS_STD140, "ShaderTestScene_UniformBuffersStd140"); default: assert(!"Invalid renderer test ID!"); return false; diff --git a/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.h b/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.h index c23006a1f..4079c9b57 100644 --- a/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.h +++ b/tests/integration/renderer-tests/rendering-tests/EffectRenderingTests.h @@ -33,6 +33,7 @@ namespace ramses::internal EffectTest_StructUniform, EffectTest_BoolUniform, EffectTest_TextureSize, + EffectTest_UniformBuffersStd140, }; }; } diff --git a/tests/integration/renderer-tests/rendering-tests/RenderingTests.h b/tests/integration/renderer-tests/rendering-tests/RenderingTests.h index c582e0258..dd733ac34 100644 --- a/tests/integration/renderer-tests/rendering-tests/RenderingTests.h +++ b/tests/integration/renderer-tests/rendering-tests/RenderingTests.h @@ -47,14 +47,14 @@ namespace ramses::internal m_testFramework.filterTestCases(filterIn, filterOut); } - bool runTests() + [[nodiscard]] bool runTests() { return m_testFramework.runAllTests(); } - void logReport() + [[nodiscard]] std::string generateReport() const { - fmt::print("{}\n", m_testFramework.generateReport()); + return m_testFramework.generateReport(); } protected: diff --git a/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.cpp b/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.cpp index 478957d18..235b63fd9 100644 --- a/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.cpp +++ b/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.cpp @@ -26,6 +26,7 @@ #include "TestScenes/ArrayBufferScene.h" #include "TestScenes/GeometryShaderScene.h" #include "TestScenes/ArrayResourceScene.h" +#include "TestScenes/MultipleTexturesScene.h" namespace ramses::internal { @@ -40,7 +41,7 @@ namespace ramses::internal testFramework.createTestCaseWithDefaultDisplay(RenderStateTest_StencilTest3, *this, "RenderStateTest_StencilTest3"); testFramework.createTestCaseWithDefaultDisplay(RenderStateTest_ScissorTest, *this, "RenderStateTest_ScissorTest"); - testFramework.createTestCaseWithDefaultDisplay(AppearanceTest_RedTriangles, *this, "AppearanceTest_RedTriangles"); + testFramework.createTestCaseWithDefaultDisplay(AppearanceTest_RedTriangles, *this, "AppearanceTest_RedTriangles").enableForAllFeatureLevels(); testFramework.createTestCaseWithDefaultDisplay(AppearanceTest_GreenTriangles, *this, "AppearanceTest_GreenTriangles"); testFramework.createTestCaseWithDefaultDisplay(AppearanceTest_ChangeAppearance, *this, "AppearanceTest_ChangeAppearance"); testFramework.createTestCaseWithDefaultDisplay(AppearanceTest_TrianglesWithSharedColor, *this, "AppearanceTest_TrianglesWithSharedColor"); @@ -56,6 +57,8 @@ namespace ramses::internal testFramework.createTestCaseWithDefaultDisplay(CameraTest_Perspective, *this, "CameraTest_Perspective"); testFramework.createTestCaseWithDefaultDisplay(CameraTest_Orthographic, *this, "CameraTest_Orthographic"); testFramework.createTestCaseWithDefaultDisplay(CameraTest_Viewport, *this, "CameraTest_Viewport"); + testFramework.createTestCaseWithDefaultDisplay(CameraTest_Perspective_UBO, *this, "CameraTest_Perspective_UBO"); + testFramework.createTestCaseWithDefaultDisplay(CameraTest_Orthographic_UBO, *this, "CameraTest_Orthographic_UBO"); testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_DeleteMeshNode, *this, "SceneModificationTest_DeleteMeshNode"); testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_Invisible, *this, "SceneModificationTest_NoVisibility"); @@ -64,6 +67,10 @@ namespace ramses::internal testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_RotateAndScale, *this, "SceneModificationTest_RotateAndScale"); testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_CameraTransformation, *this, "SceneModificationTest_CameraTransformation"); testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_MeshRenderOrder, *this, "SceneModificationTest_MeshRenderOrder"); + testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_RotateAndScale_UBO1, *this, "SceneModificationTest_RotateAndScale_UBO1"); + testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_RotateAndScale_UBO2, *this, "SceneModificationTest_RotateAndScale_UBO2"); + testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_RotateAndScale_UBO3, *this, "SceneModificationTest_RotateAndScale_UBO3"); + testFramework.createTestCaseWithDefaultDisplay(SceneModificationTest_CameraTransformation_UBO, *this, "SceneModificationTest_CameraTransformation_UBO"); testFramework.createTestCaseWithDefaultDisplay(GeometryTest_SharedAppearance, *this, "GeometryTest_SharedAppearance"); testFramework.createTestCaseWithDefaultDisplay(GeometryTest_TriangleListWithoutIndexArray, *this, "GeometryTest_TriangleListWithoutIndexArray"); @@ -135,7 +142,7 @@ namespace ramses::internal testFramework.createTestCaseWithDefaultDisplay(ArrayResource_InterleavedVertexAttribute_SingleAttrib, *this, "ArrayResource_InterleavedVertexAttribute_SingleAttrib"); testFramework.createTestCaseWithDefaultDisplay(ArrayResource_InterleavedVertexAttribute_StartVertexOffset, *this, "ArrayResource_InterleavedVertexAttribute_StartVertexOffset"); - testFramework.createTestCaseWithDefaultDisplay(GeometryShaderGlslV320_PointsInTriangleStripOut, *this, "GeometryShaderGlslV320_PointsInTriangleStripOut"); + testFramework.createTestCaseWithDefaultDisplay(GeometryShaderGlslV320_PointsInTriangleStripOut, *this, "GeometryShaderGlslV320_PointsInTriangleStripOut").enableForAllFeatureLevels(); testFramework.createTestCaseWithDefaultDisplay(GeometryShaderGlslV320_PointsInLineStripOut, *this, "GeometryShaderGlslV320_PointsInLineStripOut"); testFramework.createTestCaseWithDefaultDisplay(GeometryShaderGlslV320_PointsInPointsOut, *this, "GeometryShaderGlslV320_PointsInPointsOut"); testFramework.createTestCaseWithDefaultDisplay(GeometryShaderGlslV320_TrianglesInTriangleStripOut, *this, "GeometryShaderGlslV320_TrianglesInTriangleStripOut"); @@ -147,6 +154,8 @@ namespace ramses::internal testFramework.createTestCaseWithDefaultDisplay(GeometryShaderGlslV310Extension_TrianglesInPointsOut, *this, "GeometryShaderGlslV310Extension_TrianglesInPointsOut"); testFramework.createTestCaseWithDefaultDisplay(EulerRotationConventions, *this, "EulerRotationConventions"); + testFramework.createTestCaseWithDefaultDisplay(MultipleTextures_ThreeMultiplexedTextures, *this, "MultipleTextures_ThreeMultiplexedTextures"); + testFramework.createTestCaseWithDefaultDisplay(MultipleTextures_ThreeMultiplexedTextures_UBO, *this, "MultipleTextures_ThreeMultiplexedTextures_UBO"); testFramework.createTestCaseWithDefaultDisplay(Display_SetClearColor, *this, "Display_SetClearColor").m_displayConfigs.front().setClearColor({0.5f, 0.25f, 0.75f, 1.f}); @@ -204,6 +213,10 @@ namespace ramses::internal return runBasicTest(testFramework, MultipleTrianglesScene::ORTHOGRAPHIC_CAMERA, "MultipleTrianglesScene_OrthographicCamera"); case CameraTest_Viewport: return runBasicTest(testFramework, RenderPassScene::PASSES_WITH_LEFT_AND_RIGHT_VIEWPORT, "RenderPassScene_LeftRightViewport"); + case CameraTest_Perspective_UBO: + return runBasicTest(testFramework, MultipleTrianglesScene::PERSPECTIVE_CAMERA_UBO, "MultipleTrianglesScene_PerspectiveCamera"); + case CameraTest_Orthographic_UBO: + return runBasicTest(testFramework, MultipleTrianglesScene::ORTHOGRAPHIC_CAMERA_UBO, "MultipleTrianglesScene_OrthographicCamera"); case SceneModificationTest_DeleteMeshNode: return runBasicTest(testFramework, HierarchicalRedTrianglesScene::DELETE_MESHNODE, "HierarchicalRedTrianglesScene_DeleteMeshNode"); @@ -219,6 +232,14 @@ namespace ramses::internal return runBasicTest(testFramework, MultipleTrianglesScene::CAMERA_TRANSFORMATION, "MultipleTrianglesScene_CameraTransformation"); case SceneModificationTest_MeshRenderOrder: return runBasicTest(testFramework, MultipleTrianglesScene::TRIANGLES_REORDERED, "MultipleTrianglesScene_RenderingOrderChanged"); + case SceneModificationTest_RotateAndScale_UBO1: + return runBasicTest(testFramework, HierarchicalRedTrianglesScene::ROTATE_AND_SCALE_UBO1, "HierarchicalRedTrianglesScene_RotateAndScale"); + case SceneModificationTest_RotateAndScale_UBO2: + return runBasicTest(testFramework, HierarchicalRedTrianglesScene::ROTATE_AND_SCALE_UBO2, "HierarchicalRedTrianglesScene_RotateAndScale"); + case SceneModificationTest_RotateAndScale_UBO3: + return runBasicTest(testFramework, HierarchicalRedTrianglesScene::ROTATE_AND_SCALE_UBO3, "HierarchicalRedTrianglesScene_RotateAndScale"); + case SceneModificationTest_CameraTransformation_UBO: + return runBasicTest(testFramework, MultipleTrianglesScene::CAMERA_TRANSFORMATION_UBO, "MultipleTrianglesScene_CameraTransformation"); case GeometryTest_SharedAppearance: return runBasicTest(testFramework, MultipleGeometryScene::MULTI_TRIANGLE_LIST_GEOMETRY_WITH_INDEX_ARRAY, "MultipleGeometryScene_MultipleGeometry"); @@ -396,6 +417,10 @@ namespace ramses::internal case EulerRotationConventions: return runBasicTest(testFramework, MultipleTrianglesScene::EULER_ROTATION_CONVENTIONS, "MultipleTriangleScene_EulerRotationConventions"); + case MultipleTextures_ThreeMultiplexedTextures: + return runBasicTest(testFramework, MultipleTexturesScene::THREE_MULTIPLEXED_TEXTURES, "MultipleTextures_ThreeTextures"); + case MultipleTextures_ThreeMultiplexedTextures_UBO: + return runBasicTest(testFramework, MultipleTexturesScene::THREE_MULTIPLEXED_TEXTURES_UBO, "MultipleTextures_ThreeTextures"); default: assert(!"Invalid renderer test ID!"); diff --git a/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.h b/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.h index 05b86eff5..864f456a7 100644 --- a/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.h +++ b/tests/integration/renderer-tests/rendering-tests/SceneRenderingTests.h @@ -57,6 +57,8 @@ namespace ramses::internal CameraTest_Perspective, CameraTest_Orthographic, CameraTest_Viewport, + CameraTest_Perspective_UBO, + CameraTest_Orthographic_UBO, SceneModificationTest_DeleteMeshNode, SceneModificationTest_Invisible, @@ -65,6 +67,10 @@ namespace ramses::internal SceneModificationTest_RotateAndScale, SceneModificationTest_CameraTransformation, SceneModificationTest_MeshRenderOrder, + SceneModificationTest_RotateAndScale_UBO1, + SceneModificationTest_RotateAndScale_UBO2, + SceneModificationTest_RotateAndScale_UBO3, + SceneModificationTest_CameraTransformation_UBO, GeometryTest_SharedAppearance, GeometryTest_32bitIndices, @@ -153,7 +159,9 @@ namespace ramses::internal GeometryShaderGlslV310Extension_TrianglesInTriangleStripOut, GeometryShaderGlslV310Extension_TrianglesInPointsOut, - EulerRotationConventions + EulerRotationConventions, + MultipleTextures_ThreeMultiplexedTextures, + MultipleTextures_ThreeMultiplexedTextures_UBO, }; }; } diff --git a/tests/integration/renderer-tests/rendering-tests/main.cpp b/tests/integration/renderer-tests/rendering-tests/main.cpp index d012c495f..525f8baa3 100644 --- a/tests/integration/renderer-tests/rendering-tests/main.cpp +++ b/tests/integration/renderer-tests/rendering-tests/main.cpp @@ -61,19 +61,36 @@ int main(int argc, const char *argv[]) #endif RendererTestUtils::SetDefaultConfigForAllTests(rendererConfig, displayConfig); - RenderingTests renderingTests(filterInTestStrings, filterOutTestStrings, generateBitmaps, config); + bool renderingTestsSuccess = false; + std::array reports; - for (uint32_t i = 0; i < repeatCount; ++i) + for (EFeatureLevel featureLevel = EFeatureLevel_01; featureLevel <= EFeatureLevel_Latest; featureLevel = EFeatureLevel{ featureLevel + 1 }) { - const bool renderingTestsSuccess = renderingTests.runTests(); - renderingTests.logReport(); + fmt::print("\nStarting feature level 0{} rendering tests\n\n", featureLevel); + if (!config.setFeatureLevel(featureLevel)) + return 1; - if (!renderingTestsSuccess) + RenderingTests renderingTests(filterInTestStrings, filterOutTestStrings, generateBitmaps, config); + for (uint32_t i = 0; i < repeatCount; ++i) { - fmt::print("Some rendering tests failed! Look above for more detailed info.\n"); - return 1; + renderingTestsSuccess = renderingTests.runTests(); + reports[featureLevel-1] = renderingTests.generateReport(); + fmt::print("\nFinished feature level 0{} rendering tests\n", featureLevel); + fmt::print("{}\n", reports[featureLevel-1]); + + if (!renderingTestsSuccess) + { + fmt::print("Some rendering tests failed! Look above for more detailed info.\n"); + return 1; + } } } + for (EFeatureLevel featureLevel = EFeatureLevel_01; featureLevel <= EFeatureLevel_Latest; featureLevel = EFeatureLevel{ featureLevel + 1 }) + { + fmt::print("\nFeature level 0{}:", featureLevel); + fmt::print("{}\n", reports[featureLevel-1]); + } + return 0; } diff --git a/tests/integration/renderer-tests/res/AMultipleInstances_TriangleWithLogic.PNG b/tests/integration/renderer-tests/res/AMultipleInstances_TriangleWithLogic.PNG new file mode 100644 index 000000000..7ee4e9dd0 Binary files /dev/null and b/tests/integration/renderer-tests/res/AMultipleInstances_TriangleWithLogic.PNG differ diff --git a/tests/integration/renderer-tests/res/ARendererInstance_MergeScenes.PNG b/tests/integration/renderer-tests/res/ARendererInstance_MergeScenes.PNG new file mode 100644 index 000000000..7b6d47c78 Binary files /dev/null and b/tests/integration/renderer-tests/res/ARendererInstance_MergeScenes.PNG differ diff --git a/tests/integration/renderer-tests/res/MultipleTextures_ThreeTextures.PNG b/tests/integration/renderer-tests/res/MultipleTextures_ThreeTextures.PNG new file mode 100644 index 000000000..dd33aa9a1 Binary files /dev/null and b/tests/integration/renderer-tests/res/MultipleTextures_ThreeTextures.PNG differ diff --git a/tests/integration/renderer-tests/res/ShaderTestScene_UniformBuffersStd140.PNG b/tests/integration/renderer-tests/res/ShaderTestScene_UniformBuffersStd140.PNG new file mode 100644 index 000000000..55b22388e Binary files /dev/null and b/tests/integration/renderer-tests/res/ShaderTestScene_UniformBuffersStd140.PNG differ diff --git a/tests/integration/shared-lib-tests/CMakeLists.txt b/tests/integration/shared-lib-tests/CMakeLists.txt index a5242512a..99042b01c 100644 --- a/tests/integration/shared-lib-tests/CMakeLists.txt +++ b/tests/integration/shared-lib-tests/CMakeLists.txt @@ -10,7 +10,7 @@ createModule( NAME ramses-shared-lib-tests TYPE BINARY ENABLE_INSTALL ${ramses-sdk_ENABLE_INSTALL} - INCLUDE_PATHS ${PROJECT_SOURCE_DIR}/tests/unittests/client/logic/shared + INCLUDE_PATHS ${PROJECT_SOURCE_DIR}/tests/unittests/client/utils SRC_FILES LoggerTest.cpp RendererEventGrabber.h LogHandler.h diff --git a/tests/integration/test-content/BlitPassScene.cpp b/tests/integration/test-content/BlitPassScene.cpp index 973368121..308073d0a 100644 --- a/tests/integration/test-content/BlitPassScene.cpp +++ b/tests/integration/test-content/BlitPassScene.cpp @@ -194,7 +194,7 @@ namespace ramses::internal if (BLITS_DEPTH_STENCIL_BUFFER == state) { //add another mesh that is filtered by stencil - ramses::MeshNode& meshNode2 = createMesh(getEffectRenderOneBuffer(), TriangleAppearance::EColor_Green); + ramses::MeshNode& meshNode2 = createMesh(getEffectRenderOneBuffer(), TriangleAppearance::EColor::Green); meshNode2.getAppearance()->setStencilFunction(ramses::EStencilFunc::NotEqual, 0u, 0xff); ramses::Node& transNode2 = *m_scene.createNode(); diff --git a/tests/integration/test-content/CameraDataLinkScene.cpp b/tests/integration/test-content/CameraDataLinkScene.cpp index c9f668800..1acc109ce 100644 --- a/tests/integration/test-content/CameraDataLinkScene.cpp +++ b/tests/integration/test-content/CameraDataLinkScene.cpp @@ -38,8 +38,8 @@ namespace ramses::internal void CameraDataLinkScene::setUpConsumerScene() { ramses::Effect* effect = getTestEffect("ramses-test-client-basic"); - Triangle triangle1(m_scene, *effect, TriangleAppearance::EColor_Red); - Triangle triangle2(m_scene, *effect, TriangleAppearance::EColor_Green); + Triangle triangle1(m_scene, *effect, TriangleAppearance::EColor::Red); + Triangle triangle2(m_scene, *effect, TriangleAppearance::EColor::Green); ramses::MeshNode* mesh1 = m_scene.createMeshNode(); ramses::MeshNode* mesh2 = m_scene.createMeshNode(); diff --git a/tests/integration/test-content/DataLinkScene.cpp b/tests/integration/test-content/DataLinkScene.cpp index 176b97513..8a0202f2c 100644 --- a/tests/integration/test-content/DataLinkScene.cpp +++ b/tests/integration/test-content/DataLinkScene.cpp @@ -21,8 +21,8 @@ namespace ramses::internal : IntegrationScene(scene, cameraPosition) { ramses::Effect* effect = getTestEffect("ramses-test-client-basic"); - Triangle triangle1(scene, *effect, TriangleAppearance::EColor_Red); - Triangle triangle2(scene, *effect, TriangleAppearance::EColor_Green); + Triangle triangle1(scene, *effect, TriangleAppearance::EColor::Red); + Triangle triangle2(scene, *effect, TriangleAppearance::EColor::Green); ramses::DataObject* colorData = scene.createDataObject(ramses::EDataType::Vector4F, "dataLinkColorData"); diff --git a/tests/integration/test-content/HierarchicalRedTrianglesScene.cpp b/tests/integration/test-content/HierarchicalRedTrianglesScene.cpp index d9a814da4..708a80aea 100644 --- a/tests/integration/test-content/HierarchicalRedTrianglesScene.cpp +++ b/tests/integration/test-content/HierarchicalRedTrianglesScene.cpp @@ -11,6 +11,8 @@ #include "ramses/client/ramses-utils.h" #include "ramses/client/Scene.h" #include "ramses/client/MeshNode.h" +#include "ramses/client/Appearance.h" +#include "ramses/client/Effect.h" namespace ramses::internal { @@ -25,8 +27,8 @@ namespace ramses::internal , m_scaleNode1(*m_scene.createNode()) , m_scaleNode2(*m_scene.createNode()) { - ramses::Effect* effect = getTestEffect("ramses-test-client-basic"); - Triangle redTriangle(m_scene, *effect, TriangleAppearance::EColor_Red); + ramses::Effect* effect = createTestEffect(state); + Triangle redTriangle(m_scene, *effect, TriangleAppearance::EColor::Red); m_groupNode = m_scene.createNode(); std::array subGroups{}; @@ -95,10 +97,19 @@ namespace ramses::internal m_groupNode->setVisibility(ramses::EVisibilityMode::Off); break; case ROTATE_AND_SCALE: - m_scaleNode1.setScaling({0.3f, 1.f, 1.f}); - m_rotateNode1.setRotation({0.f, 0.f, -90.f}, ramses::ERotationType::Euler_XYZ); - m_scaleNode2.setScaling({0.3f, 1.f, 1.f}); - m_rotateNode2.setRotation({0.f, 0.f, -90.f}, ramses::ERotationType::Euler_XYZ); + case ROTATE_AND_SCALE_UBO1: + case ROTATE_AND_SCALE_UBO2: + case ROTATE_AND_SCALE_UBO3: + m_scaleNode1.setScaling({ 0.3f, 1.f, 1.f }); + m_rotateNode1.setRotation({ 0.f, 0.f, -90.f }, ramses::ERotationType::Euler_XYZ); + m_scaleNode2.setScaling({ 0.3f, 1.f, 1.f }); + m_rotateNode2.setRotation({ 0.f, 0.f, -90.f }, ramses::ERotationType::Euler_XYZ); + if (state != ROTATE_AND_SCALE) + { + const auto uniform = redTriangle.GetAppearance().getEffect().findUniformInput("generalUbo.variant"); + assert(uniform); + redTriangle.GetAppearance().setInputValue(*uniform, static_cast(state - ROTATE_AND_SCALE_UBO1 + 1)); + } break; case DELETE_MESHNODE: destroySubTree(m_subGroup2Node); @@ -108,6 +119,19 @@ namespace ramses::internal } } + Effect* HierarchicalRedTrianglesScene::createTestEffect(uint32_t state) + { + switch (state) + { + case ROTATE_AND_SCALE_UBO1: + case ROTATE_AND_SCALE_UBO2: + case ROTATE_AND_SCALE_UBO3: + return getTestEffect("ramses-test-client-basic-ubo"); + default: + return getTestEffect("ramses-test-client-basic"); + } + } + void HierarchicalRedTrianglesScene::destroySubTree(ramses::Node* rootNode) { if (rootNode != nullptr) diff --git a/tests/integration/test-content/IntegrationScene.cpp b/tests/integration/test-content/IntegrationScene.cpp index 08b8896e8..d1636d07e 100644 --- a/tests/integration/test-content/IntegrationScene.cpp +++ b/tests/integration/test-content/IntegrationScene.cpp @@ -45,6 +45,9 @@ namespace ramses::internal effectDesc.setUniformSemantic("modelMatrix", ramses::EEffectUniformSemantic::ModelMatrix); effectDesc.setUniformSemantic("cameraPosition", ramses::EEffectUniformSemantic::CameraWorldPosition); effectDesc.setUniformSemantic("u_customTexture", ramses::EEffectUniformSemantic::TextTexture); + effectDesc.setUniformSemantic("modelUbo", ramses::EEffectUniformSemantic::ModelBlock); + effectDesc.setUniformSemantic("cameraUbo", ramses::EEffectUniformSemantic::CameraBlock); + effectDesc.setUniformSemantic("modelCameraUbo", ramses::EEffectUniformSemantic::ModelCameraBlock); effectDesc.setAttributeSemantic("a_customPosition", ramses::EEffectAttributeSemantic::TextPositions); effectDesc.setAttributeSemantic("a_customTexCoord", ramses::EEffectAttributeSemantic::TextTextureCoordinates); diff --git a/tests/integration/test-content/LogicScene.cpp b/tests/integration/test-content/LogicScene.cpp new file mode 100644 index 000000000..832a79220 --- /dev/null +++ b/tests/integration/test-content/LogicScene.cpp @@ -0,0 +1,50 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "TestScenes/LogicScene.h" +#include "ramses/client/Scene.h" +#include "ramses/client/MeshNode.h" +#include "ramses/client/logic/LogicEngine.h" +#include "ramses/client/logic/NodeBinding.h" +#include "ramses/client/logic/LuaScript.h" +#include "ramses/client/logic/Property.h" + +namespace ramses::internal +{ + LogicScene::LogicScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition, uint32_t vpWidth, uint32_t vpHeight) + : IntegrationScene{ scene, cameraPosition, vpWidth, vpHeight } + , m_triangle{ scene, *getTestEffect("ramses-test-client-basic"), TriangleAppearance::EColor::Red } + { + m_meshNode = m_scene.createMeshNode("red triangle mesh node"); + m_meshNode->setAppearance(m_triangle.GetAppearance()); + m_meshNode->setGeometry(m_triangle.GetGeometry()); + m_meshNode->setTranslation({ 0.f, 0.f, 0.f }); + addMeshNodeToDefaultRenderGroup(*m_meshNode); + + if (state == TRIANGLE_LOGIC) + { + const std::string_view luaScriptSrc = R"( + function interface(IN, OUT) + IN.translation_x = Type:Float() + OUT.translation = Type:Vec3f() + end + + function run(IN, OUT) + OUT.translation = { IN.translation_x, 0, 0 } + end + )"; + + auto le = m_scene.createLogicEngine("le"); + auto binding = le->createNodeBinding(*m_meshNode); + auto script = le->createLuaScript(luaScriptSrc, {}, "script"); + le->link(*script->getOutputs()->getChild("translation"), *binding->getInputs()->getChild("translation")); + script->getInputs()->getChild("translation_x")->set(1.f); + le->update(); + } + } +} diff --git a/tests/integration/test-content/MsaaRenderBufferScene.cpp b/tests/integration/test-content/MsaaRenderBufferScene.cpp index 5b7689569..bbd4aa4ca 100644 --- a/tests/integration/test-content/MsaaRenderBufferScene.cpp +++ b/tests/integration/test-content/MsaaRenderBufferScene.cpp @@ -125,7 +125,7 @@ namespace ramses::internal ramses::MeshNode& MsaaRenderBufferScene::createMesh() { const ramses::Effect& effect = getEffectRenderOneBuffer(); - ramses::MeshNode& meshNode = CommonRenderBufferTestScene::createMesh(effect, TriangleAppearance::EColor_White); + ramses::MeshNode& meshNode = CommonRenderBufferTestScene::createMesh(effect, TriangleAppearance::EColor::White); const std::array vertexPositionsData{ ramses::vec3f{ -1.f, -1.f, 0.f }, diff --git a/tests/integration/test-content/MultiTransformationLinkScene.cpp b/tests/integration/test-content/MultiTransformationLinkScene.cpp index 82cabd9c3..2d0a972e4 100644 --- a/tests/integration/test-content/MultiTransformationLinkScene.cpp +++ b/tests/integration/test-content/MultiTransformationLinkScene.cpp @@ -17,9 +17,9 @@ namespace ramses::internal : IntegrationScene(scene, cameraPosition) , m_scaleFactor(10.f / NumRows) , m_dummyEffect(*getTestEffect("ramses-test-client-basic")) - , m_redTriangle(m_scene, m_dummyEffect, TriangleAppearance::EColor_Red) - , m_greenTriangle(m_scene, m_dummyEffect, TriangleAppearance::EColor_Green) - , m_blueTriangle(m_scene, m_dummyEffect, TriangleAppearance::EColor_Blue) + , m_redTriangle(m_scene, m_dummyEffect, TriangleAppearance::EColor::Red) + , m_greenTriangle(m_scene, m_dummyEffect, TriangleAppearance::EColor::Green) + , m_blueTriangle(m_scene, m_dummyEffect, TriangleAppearance::EColor::Blue) { switch (state) { diff --git a/tests/integration/test-content/MultiTypeLinkScene.cpp b/tests/integration/test-content/MultiTypeLinkScene.cpp index 83e97a783..a2db9a172 100644 --- a/tests/integration/test-content/MultiTypeLinkScene.cpp +++ b/tests/integration/test-content/MultiTypeLinkScene.cpp @@ -26,8 +26,8 @@ namespace ramses::internal { ramses::Effect* effect = getTestEffect("ramses-test-client-basic"); ramses::Effect* effectTex = getTestEffect("ramses-test-client-textured"); - Triangle triangle1(scene, *effect, TriangleAppearance::EColor_Blue); - Triangle triangle2(scene, *effectTex, TriangleAppearance::EColor_Green); + Triangle triangle1(scene, *effect, TriangleAppearance::EColor::Blue); + Triangle triangle2(scene, *effectTex, TriangleAppearance::EColor::None); ramses::DataObject* colorData = scene.createDataObject(ramses::EDataType::Vector4F); diff --git a/tests/integration/test-content/MultipleRenderTargetScene.cpp b/tests/integration/test-content/MultipleRenderTargetScene.cpp index 52037f1f0..3fb6bb9c6 100644 --- a/tests/integration/test-content/MultipleRenderTargetScene.cpp +++ b/tests/integration/test-content/MultipleRenderTargetScene.cpp @@ -38,18 +38,20 @@ namespace ramses::internal initFinalRenderPass(state); } - const ramses::Effect& MultipleRenderTargetScene::getMRTEffect(uint32_t state) + const ramses::Effect& MultipleRenderTargetScene::getMRTEffect(uint32_t state, TriangleAppearance::EColor& color) { switch (state) { case TWO_COLOR_BUFFERS: case TWO_COLOR_BUFFERS_RGBA8_AND_RGBA4: case SHADER_WRITES_TWO_COLOR_BUFFERS_RT_HAS_ONE: + color = TriangleAppearance::EColor::None; return getEffectRenderTwoBuffers(); case SHADER_WRITES_ONE_COLOR_BUFFER_RT_HAS_TWO: case COLOR_WRITTEN_BY_TWO_DIFFERENT_RTS: case DEPTH_WRITTEN_AND_USED_BY_DIFFERENT_RT: case DEPTH_WRITTEN_AND_READ: + color = TriangleAppearance::EColor::Red; return getEffectRenderOneBuffer(); default: assert(false); @@ -164,7 +166,9 @@ namespace ramses::internal void MultipleRenderTargetScene::initMRTPass(uint32_t state) { - ramses::MeshNode& meshNode = createMesh(getMRTEffect(state)); + TriangleAppearance::EColor color = TriangleAppearance::EColor::None; + const auto& effect = getMRTEffect(state, color); + ramses::MeshNode& meshNode = createMesh(effect, color); ramses::Node& transNode = *m_scene.createNode(); transNode.addChild(meshNode); @@ -194,7 +198,7 @@ namespace ramses::internal camera.setViewport(0u, 0u, 8u, 16u); camera.setFrustum(camera.getLeftPlane() * 0.5f, camera.getRightPlane() * 0.5f, camera.getBottomPlane(), camera.getTopPlane(), camera.getNearPlane(), camera.getFarPlane()); - ramses::MeshNode& meshNode2 = createMesh(getMRTEffect(state), TriangleAppearance::EColor_Blue); + ramses::MeshNode& meshNode2 = createMesh(getMRTEffect(state, color), TriangleAppearance::EColor::Blue); transNode.addChild(meshNode2); meshNode2.getAppearance()->setDepthFunction(ramses::EDepthFunc::NotEqual); diff --git a/tests/integration/test-content/MultipleTexturesScene.cpp b/tests/integration/test-content/MultipleTexturesScene.cpp new file mode 100644 index 000000000..34a1a11c5 --- /dev/null +++ b/tests/integration/test-content/MultipleTexturesScene.cpp @@ -0,0 +1,79 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "TestScenes/MultipleTexturesScene.h" +#include "TestScenes/Triangle.h" +#include "ramses/client/ramses-utils.h" + +#include "ramses/client/Scene.h" +#include "ramses/client/Appearance.h" +#include "ramses/client/UniformInput.h" +#include "ramses/client/AttributeInput.h" +#include "ramses/client/Effect.h" +#include "ramses/client/Geometry.h" + +namespace ramses::internal +{ + + MultipleTexturesScene::MultipleTexturesScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition) + : IntegrationScene(scene, cameraPosition) + { + auto* effect = createEffect(state); + + const auto* texture1 = ramses::RamsesUtils::CreateTextureResourceFromPng("res/ramses-test-client-file-loading-texture.png", m_scene); + const auto* texture2 = ramses::RamsesUtils::CreateTextureResourceFromPng("res/ramses-test-client-logo-cropped.png", m_scene); + const auto* texture3 = ramses::RamsesUtils::CreateTextureResourceFromPng("res/ramses-test-client-cube-px.png", m_scene); + + const auto* texSampler1 = m_scene.createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Nearest, *texture1); + const auto* texSampler2 = m_scene.createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Nearest, *texture2); + const auto* texSampler3 = m_scene.createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Nearest, *texture3); + + const auto* texCoords = scene.createArrayResource(3u, std::array{ vec2f{0.f, 0.f}, vec2f{1.f, 0.f}, vec2f{1.f, 1.f} }.data()); + + const std::array translation = { + -1.0f, 0.0f, -12.0f, + 0.0f, -1.0f, -12.0f, + 1.0f, 0.0f, -12.0f }; + + + for (int i = 0; i < 3; ++i) + { + Triangle triangle(m_scene, *effect, TriangleAppearance::EColor::None); + + ramses::MeshNode* meshNode = m_scene.createMeshNode("triangle mesh node"); + addMeshNodeToDefaultRenderGroup(*meshNode); + + ramses::Node* trafoNode = m_scene.createNode("transformation node"); + trafoNode->setTranslation({translation[i * 3 + 0], translation[i * 3 + 1], translation[i * 3 + 2]}); + + meshNode->setParent(*trafoNode); + + auto& appearance = triangle.GetAppearance(); + appearance.setInputValue(*effect->findUniformInput("u_multiplexer"), i + 1); + appearance.setInputTexture(*effect->findUniformInput("u_texture1"), *texSampler1); + appearance.setInputTexture(*effect->findUniformInput("u_texture2"), *texSampler2); + appearance.setInputTexture(*effect->findUniformInput("u_texture3"), *texSampler3); + meshNode->setAppearance(appearance); + + auto& geometry = triangle.GetGeometry(); + geometry.setInputBuffer(*effect->findAttributeInput("a_texcoord"), *texCoords); + meshNode->setGeometry(geometry); + } + } + + ramses::Effect* MultipleTexturesScene::createEffect(uint32_t state) + { + if(state == THREE_MULTIPLEXED_TEXTURES) + return getTestEffect("ramses-test-client-multiple-textures"); + + if (state == THREE_MULTIPLEXED_TEXTURES_UBO) + return getTestEffect("ramses-test-client-multiple-textures-ubo"); + + return nullptr; + } +} diff --git a/tests/integration/test-content/MultipleTrianglesScene.cpp b/tests/integration/test-content/MultipleTrianglesScene.cpp index f2e0c5b56..5ba4d3e64 100644 --- a/tests/integration/test-content/MultipleTrianglesScene.cpp +++ b/tests/integration/test-content/MultipleTrianglesScene.cpp @@ -13,13 +13,15 @@ #include "ramses/client/OrthographicCamera.h" #include "ramses/client/Appearance.h" #include "ramses/client/DataObject.h" +#include "ramses/client/Appearance.h" +#include "ramses/client/Effect.h" #include namespace ramses::internal { MultipleTrianglesScene::MultipleTrianglesScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition, uint32_t vpWidth, uint32_t vpHeight) : IntegrationScene(scene, cameraPosition, vpWidth, vpHeight) - , m_Effect(getTestEffect("ramses-test-client-basic")) + , m_Effect(createTestEffect(state)) , m_meshNode1(nullptr) , m_meshNode2(nullptr) , m_meshNode3(nullptr) @@ -27,24 +29,24 @@ namespace ramses::internal , m_meshNode5(nullptr) , m_meshNode6(nullptr) , m_meshNode7(nullptr) - , m_whiteTriangle(scene, *m_Effect, TriangleAppearance::EColor_White) - , m_redTriangle(scene, *m_Effect, TriangleAppearance::EColor_Red) - , m_greenTriangle(scene, *m_Effect, TriangleAppearance::EColor_Green) - , m_blueTriangle(scene, *m_Effect, TriangleAppearance::EColor_Blue) + , m_whiteTriangle(scene, *m_Effect, TriangleAppearance::EColor::White) + , m_redTriangle(scene, *m_Effect, TriangleAppearance::EColor::Red) + , m_greenTriangle(scene, *m_Effect, TriangleAppearance::EColor::Green) + , m_blueTriangle(scene, *m_Effect, TriangleAppearance::EColor::Blue) , m_yellowLine(scene, *m_Effect, Line::EColor_Yellow, ramses::EDrawMode::Lines) , m_whiteQuad(scene, *m_Effect, MultiTriangleGeometry::EColor_White) , m_triangleFan(scene, *m_Effect, MultiTriangleGeometry::EColor_Red, 1.f, MultiTriangleGeometry::EGeometryType_TriangleFan) , m_lineStrip (scene, *m_Effect, Line::EColor_Red, ramses::EDrawMode::LineStrip) , m_linePoints (scene, *m_Effect, Line::EColor_White, ramses::EDrawMode::Points) - , m_redTransparentTriangle (scene, *m_Effect, TriangleAppearance::EColor_Red, 0.6f) - , m_greenTransparentTriangle(scene, *m_Effect, TriangleAppearance::EColor_Green, 0.6f) - , m_blueTransparentTriangle (scene, *m_Effect, TriangleAppearance::EColor_Blue, 0.6f) - , m_colorMaskRedTriangle (scene, *m_Effect, TriangleAppearance::EColor_White) - , m_colorMaskGreenTriangle (scene, *m_Effect, TriangleAppearance::EColor_White) - , m_colorMaskBlueTriangle (scene, *m_Effect, TriangleAppearance::EColor_White) - , m_CCWTriangle (scene, *m_Effect, TriangleAppearance::EColor_White, 1.f, TriangleGeometry::EVerticesOrder_CCW) - , m_CWTriangle (scene, *m_Effect, TriangleAppearance::EColor_White, 1.f, TriangleGeometry::EVerticesOrder_CW) - , m_CWTriangleCCWIndices (scene, *m_Effect, TriangleAppearance::EColor_White, 1.f, TriangleGeometry::EVerticesOrder_CW) + , m_redTransparentTriangle (scene, *m_Effect, TriangleAppearance::EColor::Red, 0.6f) + , m_greenTransparentTriangle(scene, *m_Effect, TriangleAppearance::EColor::Green, 0.6f) + , m_blueTransparentTriangle (scene, *m_Effect, TriangleAppearance::EColor::Blue, 0.6f) + , m_colorMaskRedTriangle (scene, *m_Effect, TriangleAppearance::EColor::White) + , m_colorMaskGreenTriangle (scene, *m_Effect, TriangleAppearance::EColor::White) + , m_colorMaskBlueTriangle (scene, *m_Effect, TriangleAppearance::EColor::White) + , m_CCWTriangle (scene, *m_Effect, TriangleAppearance::EColor::White, 1.f, TriangleGeometry::EVerticesOrder_CCW) + , m_CWTriangle (scene, *m_Effect, TriangleAppearance::EColor::White, 1.f, TriangleGeometry::EVerticesOrder_CW) + , m_CWTriangleCCWIndices (scene, *m_Effect, TriangleAppearance::EColor::White, 1.f, TriangleGeometry::EVerticesOrder_CW) { m_colorMaskRedTriangle.GetAppearance().setColorWriteMask(false, true, true, true); m_colorMaskGreenTriangle.GetAppearance().setColorWriteMask(true, false, true, true); @@ -67,6 +69,13 @@ namespace ramses::internal setState(state); } + Effect* MultipleTrianglesScene::createTestEffect(uint32_t state) + { + if(state == PERSPECTIVE_CAMERA_UBO || state == ORTHOGRAPHIC_CAMERA_UBO || state == CAMERA_TRANSFORMATION_UBO) + return getTestEffect("ramses-test-client-basic-ubo"); + return getTestEffect("ramses-test-client-basic"); + } + void MultipleTrianglesScene::setState(uint32_t state) { ramses::Node* rotate = nullptr; @@ -176,6 +185,7 @@ namespace ramses::internal addMeshNodeToDefaultRenderGroup(*m_meshNode3, 0); break; case CAMERA_TRANSFORMATION: + case CAMERA_TRANSFORMATION_UBO: m_meshNode1->setAppearance(m_redTriangle.GetAppearance()); m_meshNode2->setAppearance(m_greenTriangle.GetAppearance()); m_meshNode3->setAppearance(m_blueTriangle.GetAppearance()); @@ -285,6 +295,7 @@ namespace ramses::internal addMeshNodeToDefaultRenderGroup(*m_meshNode3, 2); break; case PERSPECTIVE_CAMERA: + case PERSPECTIVE_CAMERA_UBO: { m_meshNode1->setAppearance(m_redTriangle.GetAppearance()); m_meshNode2->setAppearance(m_greenTriangle.GetAppearance()); @@ -296,6 +307,7 @@ namespace ramses::internal } break; case ORTHOGRAPHIC_CAMERA: + case ORTHOGRAPHIC_CAMERA_UBO: { m_meshNode1->setAppearance(m_redTriangle.GetAppearance()); m_meshNode2->setAppearance(m_greenTriangle.GetAppearance()); @@ -353,6 +365,15 @@ namespace ramses::internal default: break; } + + if (state == ORTHOGRAPHIC_CAMERA_UBO || state == PERSPECTIVE_CAMERA_UBO || state == CAMERA_TRANSFORMATION_UBO) + { + const auto uniform = m_redTriangle.GetAppearance().getEffect().findUniformInput("generalUbo.variant"); + assert(uniform); + m_redTriangle.GetAppearance().setInputValue(*uniform, 1); + m_greenTriangle.GetAppearance().setInputValue(*uniform, 2); + m_blueTriangle.GetAppearance().setInputValue(*uniform, 3); + } } void MultipleTrianglesScene::setGeometries(uint32_t state) diff --git a/tests/integration/test-content/RenderBufferScene.cpp b/tests/integration/test-content/RenderBufferScene.cpp index af0c9423d..aeb7cfad5 100644 --- a/tests/integration/test-content/RenderBufferScene.cpp +++ b/tests/integration/test-content/RenderBufferScene.cpp @@ -165,7 +165,7 @@ namespace ramses::internal ramses::Node& farTriangleTransNode = *m_scene.createNode(); farTriangleTransNode.translate({ 0.5f, 0.0f, zTranslate }); - ramses::MeshNode& meshNode2 = createMesh(getEffectRenderOneBuffer(), TriangleAppearance::EColor_Blue); + ramses::MeshNode& meshNode2 = createMesh(getEffectRenderOneBuffer(), TriangleAppearance::EColor::Blue); farTriangleTransNode.addChild(meshNode2); transNode.addChild(farTriangleTransNode); diff --git a/tests/integration/test-content/RenderPassClearScene.cpp b/tests/integration/test-content/RenderPassClearScene.cpp index ecea31b22..b65034873 100644 --- a/tests/integration/test-content/RenderPassClearScene.cpp +++ b/tests/integration/test-content/RenderPassClearScene.cpp @@ -27,9 +27,9 @@ namespace ramses::internal RenderPassClearScene::RenderPassClearScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition) : IntegrationScene(scene, cameraPosition) , m_effect(*getTestEffect("ramses-test-client-basic")) - , m_blueTriangle(scene, m_effect, TriangleAppearance::EColor_Blue) - , m_redTriangle(scene, m_effect, TriangleAppearance::EColor_Red) - , m_greenTriangle(scene, m_effect, TriangleAppearance::EColor_Green) + , m_blueTriangle(scene, m_effect, TriangleAppearance::EColor::Blue) + , m_redTriangle(scene, m_effect, TriangleAppearance::EColor::Red) + , m_greenTriangle(scene, m_effect, TriangleAppearance::EColor::Green) , m_colorBuffer(*m_scene.createRenderBuffer(200u, 200u, ramses::ERenderBufferFormat::RGBA8, ramses::ERenderBufferAccessMode::ReadWrite)) , m_depthStencilBuffer(*m_scene.createRenderBuffer(200u, 200u, ramses::ERenderBufferFormat::Depth24_Stencil8, ramses::ERenderBufferAccessMode::ReadWrite)) { diff --git a/tests/integration/test-content/RenderPassOnceScene.cpp b/tests/integration/test-content/RenderPassOnceScene.cpp index bdf6395a3..cf27fd07b 100644 --- a/tests/integration/test-content/RenderPassOnceScene.cpp +++ b/tests/integration/test-content/RenderPassOnceScene.cpp @@ -64,7 +64,7 @@ namespace ramses::internal void RenderPassOnceScene::initInputRenderPass() { ramses::MeshNode* meshNode = m_scene.createMeshNode(); - Triangle blueTriangle(m_scene, *getTestEffect("ramses-test-client-basic"), TriangleAppearance::EColor_Blue); + Triangle blueTriangle(m_scene, *getTestEffect("ramses-test-client-basic"), TriangleAppearance::EColor::Blue); meshNode->setAppearance(blueTriangle.GetAppearance()); meshNode->setGeometry(blueTriangle.GetGeometry()); diff --git a/tests/integration/test-content/RenderPassScene.cpp b/tests/integration/test-content/RenderPassScene.cpp index c64cdfa4d..2f36852ec 100644 --- a/tests/integration/test-content/RenderPassScene.cpp +++ b/tests/integration/test-content/RenderPassScene.cpp @@ -17,8 +17,8 @@ namespace ramses::internal RenderPassScene::RenderPassScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition) : IntegrationScene(scene, cameraPosition) , m_effect(*getTestEffect("ramses-test-client-basic")) - , m_blueTriangle(scene, m_effect, TriangleAppearance::EColor_Blue) - , m_whiteTriangle(scene, m_effect, TriangleAppearance::EColor_White) + , m_blueTriangle(scene, m_effect, TriangleAppearance::EColor::Blue) + , m_whiteTriangle(scene, m_effect, TriangleAppearance::EColor::White) { ramses::MeshNode* meshNode1 = m_scene.createMeshNode(); ramses::MeshNode* meshNode2 = m_scene.createMeshNode(); diff --git a/tests/integration/test-content/RenderTargetScene.cpp b/tests/integration/test-content/RenderTargetScene.cpp index 03d256cdf..16544837a 100644 --- a/tests/integration/test-content/RenderTargetScene.cpp +++ b/tests/integration/test-content/RenderTargetScene.cpp @@ -149,13 +149,13 @@ namespace ramses::internal ramses::MeshNode* meshNode = m_scene.createMeshNode(); if (state == PERSPECTIVE_PROJECTION || state == ORTHOGRAPHIC_PROJECTION) { - Triangle blueTriangle(m_scene, *getTestEffect("ramses-test-client-basic"), TriangleAppearance::EColor_Blue); + Triangle blueTriangle(m_scene, *getTestEffect("ramses-test-client-basic"), TriangleAppearance::EColor::Blue); meshNode->setAppearance(blueTriangle.GetAppearance()); meshNode->setGeometry(blueTriangle.GetGeometry()); } else { - Triangle greyTriangle(m_scene, *getTestEffect("ramses-test-client-basic"), TriangleAppearance::EColor_Grey); + Triangle greyTriangle(m_scene, *getTestEffect("ramses-test-client-basic"), TriangleAppearance::EColor::Grey); meshNode->setAppearance(greyTriangle.GetAppearance()); meshNode->setGeometry(greyTriangle.GetGeometry()); } diff --git a/tests/integration/test-content/ShaderTestScene.cpp b/tests/integration/test-content/ShaderTestScene.cpp index d584672ac..060464354 100644 --- a/tests/integration/test-content/ShaderTestScene.cpp +++ b/tests/integration/test-content/ShaderTestScene.cpp @@ -23,7 +23,7 @@ namespace ramses::internal ShaderTestScene::ShaderTestScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition) : IntegrationScene(scene, cameraPosition) , m_effect(*getTestEffect(GetEffectNameFromState(state))) - , m_triangle(scene, m_effect, TriangleAppearance::EColor_Red) + , m_triangle(scene, m_effect, TriangleAppearance::EColor::None) { ramses::MeshNode* meshNode = m_scene.createMeshNode("red triangle mesh node"); addMeshNodeToDefaultRenderGroup(*meshNode); @@ -34,6 +34,16 @@ namespace ramses::internal transNode->setTranslation({0.f, 0.f, -12.f}); meshNode->setParent(*transNode); + switch (state) + { + case DISCARD: + case OPTIMIZED_INPUT: + m_triangle.setColor(TriangleAppearance::EColor::Red); + break; + default: + break; + }; + initInputs(state); } @@ -53,11 +63,12 @@ namespace ramses::internal return "ramses-test-client-textureSize"; case BOOL_UNIFORM: return "ramses-test-client-boolUniform"; + case UNIFORM_BUFFERS_STD140: + return "ramses-test-client-uniform-buffers-std140"; default: assert(false && "Unknown state!"); return ""; }; - } void ShaderTestScene::initInputs(uint32_t state) @@ -149,5 +160,71 @@ namespace ramses::internal assert(status); } } + else if (state == UNIFORM_BUFFERS_STD140) + { + // scalars + optInput = m_effect.findUniformInput("scalarsUBO.uBool"); + appearance.setInputValue(*optInput, true); + optInput = m_effect.findUniformInput("scalarsUBO.uInt"); + appearance.setInputValue(*optInput, -111); + optInput = m_effect.findUniformInput("scalarsUBO.uFloat"); + appearance.setInputValue(*optInput, 333.f); + + // vector and matrix + optInput = m_effect.findUniformInput("vecMatUBO.uVec2f"); + appearance.setInputValue(*optInput, vec2f(123.f, 124.f)); + optInput = m_effect.findUniformInput("vecMatUBO.uVec3f"); + appearance.setInputValue(*optInput, vec3f(456.f, 457.f, 458.f)); + optInput = m_effect.findUniformInput("vecMatUBO.uVec4f"); + appearance.setInputValue(*optInput, vec4f(678.f)); + optInput = m_effect.findUniformInput("vecMatUBO.uMat22f"); + appearance.setInputValue(*optInput, matrix22f(222.f, 223.f, 224.f, 225.f)); + optInput = m_effect.findUniformInput("vecMatUBO.uMat33f"); + appearance.setInputValue(*optInput, matrix33f(333.0f, 334.0f, 335.0f, 336.0f, 337.0f, 338.0f, 339.f, 330.f, 331.0f)); + optInput = m_effect.findUniformInput("vecMatUBO.uMat44f"); + appearance.setInputValue(*optInput, matrix44f(444.f)); + + // scalar arrays + optInput = m_effect.findUniformInput("arraysUBO.uBool"); + appearance.setInputValue(*optInput, 5u, std::array{ true, false, true, false, true }.data()); + optInput = m_effect.findUniformInput("arraysUBO.uInt"); + appearance.setInputValue(*optInput, 7u, std::array{ 2, 3, 5, 7, 11, 13, 17 }.data()); + optInput = m_effect.findUniformInput("arraysUBO.uFloat"); + appearance.setInputValue(*optInput, 5u, std::array{ 33.0f, 66.0f, 99.0f, 0.33f, 0.66f }.data()); + + // vector and matrix arrays + optInput = m_effect.findUniformInput("vecMatArraysUBO.uVec2f"); + appearance.setInputValue(*optInput, 3u, std::array{ vec2f(1.0), vec2f(2.0), vec2f(3.0) }.data()); + optInput = m_effect.findUniformInput("vecMatArraysUBO.uVec3f"); + appearance.setInputValue(*optInput, 3u, std::array{ vec3f(1.0), vec3f(2.0), vec3f(3.0) }.data()); + optInput = m_effect.findUniformInput("vecMatArraysUBO.uVec4f"); + appearance.setInputValue(*optInput, 3u, std::array{ vec4f(1.0), vec4f(2.0), vec4f(3.0) }.data()); + optInput = m_effect.findUniformInput("vecMatArraysUBO.uMat22f"); + appearance.setInputValue(*optInput, 3u, std::array{ matrix22f(4.0), matrix22f(5.0), matrix22f(6.0) }.data()); + optInput = m_effect.findUniformInput("vecMatArraysUBO.uMat33f"); + appearance.setInputValue(*optInput, 3u, std::array{ matrix33f(4.0), matrix33f(5.0), matrix33f(6.0) }.data()); + optInput = m_effect.findUniformInput("vecMatArraysUBO.uMat44f"); + appearance.setInputValue(*optInput, 3u, std::array{ matrix44f(4.0), matrix44f(5.0), matrix44f(6.0) }.data()); + + // struct array + optInput = m_effect.findUniformInput("confidenceUBO.uFloat"); + appearance.setInputValue(*optInput, 777.f); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[0].uVec3f"); + appearance.setInputValue(*optInput, vec3f(11.f)); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[0].uFloat"); + appearance.setInputValue(*optInput, 12.f); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[0].uMat33f"); + appearance.setInputValue(*optInput, matrix33f(13.0)); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[0].uInt"); + appearance.setInputValue(*optInput, 14); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[1].uVec3f"); + appearance.setInputValue(*optInput, vec3f(21.f)); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[1].uFloat"); + appearance.setInputValue(*optInput, 22.f); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[1].uMat33f"); + appearance.setInputValue(*optInput, matrix33f(23.0)); + optInput = m_effect.findUniformInput("confidenceUBO.uStruct[1].uInt"); + appearance.setInputValue(*optInput, 24); + } } } diff --git a/tests/integration/test-content/SingleAppearanceScene.cpp b/tests/integration/test-content/SingleAppearanceScene.cpp index 710f9d2ce..ce84ecdf2 100644 --- a/tests/integration/test-content/SingleAppearanceScene.cpp +++ b/tests/integration/test-content/SingleAppearanceScene.cpp @@ -23,7 +23,7 @@ namespace ramses::internal { ramses::Effect* effect = getTestEffect("ramses-test-client-basic"); - Triangle redTriangle(m_scene, *effect, TriangleAppearance::EColor_Red); + Triangle redTriangle(m_scene, *effect, TriangleAppearance::EColor::Red); const std::array translation = { -1.0f, 0.0f, -12.0f, @@ -59,7 +59,7 @@ namespace ramses::internal case CHANGE_APPEARANCE: { ramses::Effect* effectExt = getTestEffect("ramses-test-client-basic-extended"); - Triangle blueTriangle(m_scene, *effectExt, TriangleAppearance::EColor_Blue); + Triangle blueTriangle(m_scene, *effectExt, TriangleAppearance::EColor::Blue); ramses::Appearance& appearance = blueTriangle.GetAppearance(); appearance.setInputValue(*effectExt->findUniformInput("redgreen_offset"), ramses::vec2f{ 0.5f, 0.5f }); diff --git a/tests/integration/test-content/TestScenes/CommonRenderBufferTestScene.h b/tests/integration/test-content/TestScenes/CommonRenderBufferTestScene.h index 57df8f3a5..bfe8841f8 100644 --- a/tests/integration/test-content/TestScenes/CommonRenderBufferTestScene.h +++ b/tests/integration/test-content/TestScenes/CommonRenderBufferTestScene.h @@ -32,7 +32,7 @@ namespace ramses::internal const ramses::Effect& getEffectRenderTwoBuffers(); ramses::PerspectiveCamera& createCamera(float nearPlane = 1.0f, float farPlane = 100.0f); const ramses::MeshNode& createQuadWithTexture(const ramses::RenderBuffer& renderBuffer); - ramses::MeshNode& createMesh(const ramses::Effect& effect, TriangleAppearance::EColor color = TriangleAppearance::EColor_Red); + ramses::MeshNode& createMesh(const ramses::Effect& effect, TriangleAppearance::EColor color = TriangleAppearance::EColor::Red); ramses::RenderPass* addRenderPassUsingRenderBufferAsQuadTexture(const ramses::MeshNode& quad); }; diff --git a/tests/integration/test-content/TestScenes/HierarchicalRedTrianglesScene.h b/tests/integration/test-content/TestScenes/HierarchicalRedTrianglesScene.h index ce8ff771a..364950269 100644 --- a/tests/integration/test-content/TestScenes/HierarchicalRedTrianglesScene.h +++ b/tests/integration/test-content/TestScenes/HierarchicalRedTrianglesScene.h @@ -31,10 +31,14 @@ namespace ramses::internal VISIBILITY_OFF, REENABLED_FULL_VISIBILITY, ROTATE_AND_SCALE, + ROTATE_AND_SCALE_UBO1, + ROTATE_AND_SCALE_UBO2, + ROTATE_AND_SCALE_UBO3, DELETE_MESHNODE }; private: + Effect* createTestEffect(uint32_t state); void destroySubTree(ramses::Node* rootNode); ramses::Node* m_groupNode; diff --git a/tests/integration/test-content/TestScenes/LogicScene.h b/tests/integration/test-content/TestScenes/LogicScene.h new file mode 100644 index 000000000..ea76de139 --- /dev/null +++ b/tests/integration/test-content/TestScenes/LogicScene.h @@ -0,0 +1,36 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "IntegrationScene.h" +#include "Triangle.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" + +namespace ramses +{ + class MeshNode; +} + +namespace ramses::internal +{ + class LogicScene : public IntegrationScene + { + public: + LogicScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition, uint32_t vpWidth = IntegrationScene::DefaultViewportWidth, uint32_t vpHeight = IntegrationScene::DefaultViewportHeight); + + enum + { + TRIANGLE_LOGIC = 0, + }; + + private: + ramses::MeshNode* m_meshNode = nullptr; + Triangle m_triangle; + }; +} diff --git a/tests/integration/test-content/TestScenes/MultipleRenderTargetScene.h b/tests/integration/test-content/TestScenes/MultipleRenderTargetScene.h index 010be786c..67fbce991 100644 --- a/tests/integration/test-content/TestScenes/MultipleRenderTargetScene.h +++ b/tests/integration/test-content/TestScenes/MultipleRenderTargetScene.h @@ -39,7 +39,7 @@ namespace ramses::internal }; private: - const ramses::Effect& getMRTEffect(uint32_t state); + const ramses::Effect& getMRTEffect(uint32_t state, TriangleAppearance::EColor& color); ramses::RenderTarget& createMRTRenderTarget(uint32_t state); static ramses::RenderBuffer& InitRenderBuffer(ramses::Scene& scene, uint32_t state); const ramses::MeshNode& createQuadWithTexture(const ramses::RenderBuffer& renderBuffer, const glm::vec3& translation, const glm::vec4& modulateColor = glm::vec4(1.f, 1.f, 1.f, 1.f)); diff --git a/tests/integration/test-content/TestScenes/MultipleTexturesScene.h b/tests/integration/test-content/TestScenes/MultipleTexturesScene.h new file mode 100644 index 000000000..0a5efcc95 --- /dev/null +++ b/tests/integration/test-content/TestScenes/MultipleTexturesScene.h @@ -0,0 +1,33 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "IntegrationScene.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "ramses/client/MeshNode.h" +#include "internal/PlatformAbstraction/Collections/Vector.h" + + +namespace ramses::internal +{ + class MultipleTexturesScene : public IntegrationScene + { + public: + MultipleTexturesScene(ramses::Scene& scene, uint32_t state, const glm::vec3& cameraPosition); + + enum + { + THREE_MULTIPLEXED_TEXTURES = 0, + THREE_MULTIPLEXED_TEXTURES_UBO, + }; + + private: + Effect* createEffect(uint32_t state); + }; +} diff --git a/tests/integration/test-content/TestScenes/MultipleTrianglesScene.h b/tests/integration/test-content/TestScenes/MultipleTrianglesScene.h index 7bda99636..e6b8aaef1 100644 --- a/tests/integration/test-content/TestScenes/MultipleTrianglesScene.h +++ b/tests/integration/test-content/TestScenes/MultipleTrianglesScene.h @@ -35,6 +35,7 @@ namespace ramses::internal BLENDING_DST_COLOR_AND_ALPHA, COLOR_MASK, CAMERA_TRANSFORMATION, + CAMERA_TRANSFORMATION_UBO, FACE_CULLING, DEPTH_FUNC, DRAW_MODE, @@ -49,8 +50,11 @@ namespace ramses::internal THREE_TRIANGLES_WITH_SHARED_COLOR, THREE_TRIANGLES_WITH_UNSHARED_COLOR, EULER_ROTATION_CONVENTIONS, + PERSPECTIVE_CAMERA_UBO, + ORTHOGRAPHIC_CAMERA_UBO, }; private: + Effect* createTestEffect(uint32_t state); void setGeometries(uint32_t state); void setTransformations(uint32_t state); diff --git a/tests/integration/test-content/TestScenes/ShaderTestScene.h b/tests/integration/test-content/TestScenes/ShaderTestScene.h index b2e193477..bfb53c759 100644 --- a/tests/integration/test-content/TestScenes/ShaderTestScene.h +++ b/tests/integration/test-content/TestScenes/ShaderTestScene.h @@ -28,6 +28,7 @@ namespace ramses::internal STRUCT_UNIFORM, TEXTURE_SIZE, BOOL_UNIFORM, + UNIFORM_BUFFERS_STD140, }; private: diff --git a/tests/integration/test-content/TestScenes/Triangle.h b/tests/integration/test-content/TestScenes/Triangle.h index 5a0d1b1f9..1d83f7e8b 100644 --- a/tests/integration/test-content/TestScenes/Triangle.h +++ b/tests/integration/test-content/TestScenes/Triangle.h @@ -42,6 +42,7 @@ namespace ramses::internal return m_geometry.GetGeometry(); } + void setColor(TriangleAppearance::EColor color, float alpha = 1.f); void bindColor(const DataObject& colorDataObject); void unbindColor(); diff --git a/tests/integration/test-content/TestScenes/TriangleAppearance.h b/tests/integration/test-content/TestScenes/TriangleAppearance.h index 54aeba807..fecb07850 100644 --- a/tests/integration/test-content/TestScenes/TriangleAppearance.h +++ b/tests/integration/test-content/TestScenes/TriangleAppearance.h @@ -29,13 +29,14 @@ namespace ramses::internal class TriangleAppearance { public: - enum EColor + enum class EColor { - EColor_Red = 0, - EColor_Blue, - EColor_Green, - EColor_White, - EColor_Grey + Red, + Blue, + Green, + White, + Grey, + None // won't set any color }; TriangleAppearance(ramses::Scene& scene, const Effect& effect, enum EColor color, float alpha = 1.f); diff --git a/tests/integration/test-content/TextureLinkScene.cpp b/tests/integration/test-content/TextureLinkScene.cpp index 4c4d960c0..0fd893a2e 100644 --- a/tests/integration/test-content/TextureLinkScene.cpp +++ b/tests/integration/test-content/TextureLinkScene.cpp @@ -30,8 +30,8 @@ namespace ramses::internal : IntegrationScene(scene, cameraPosition, vpWidth, vpHeight) { ramses::Effect* effect = (state == DATA_CONSUMER_MS) ? getTestEffect("ramses-test-client-render-one-buffer-ms") : getTestEffect("ramses-test-client-textured"); - Triangle triangle1(scene, *effect, TriangleAppearance::EColor_Red); - Triangle triangle2(scene, *effect, TriangleAppearance::EColor_Green); + Triangle triangle1(scene, *effect, TriangleAppearance::EColor::None); + Triangle triangle2(scene, *effect, TriangleAppearance::EColor::None); ramses::MeshNode* mesh1 = scene.createMeshNode(); ramses::MeshNode* mesh2 = scene.createMeshNode(); diff --git a/tests/integration/test-content/TransformationLinkScene.cpp b/tests/integration/test-content/TransformationLinkScene.cpp index c60188d9d..201837b70 100644 --- a/tests/integration/test-content/TransformationLinkScene.cpp +++ b/tests/integration/test-content/TransformationLinkScene.cpp @@ -31,7 +31,7 @@ namespace ramses::internal rightProviderNode->setTranslation({2.0f, 0.0f, 0.0f}); scene.createTransformationDataProvider(*rightProviderNode, transformProviderDataId_Right); - TriangleAppearance::EColor color = TriangleAppearance::EColor_Red; + TriangleAppearance::EColor color = TriangleAppearance::EColor::Red; ramses::MeshNode* mesh = nullptr; switch (state) { @@ -46,7 +46,7 @@ namespace ramses::internal if (TRANSFORMATION_CONSUMER_OVERRIDEN == state) { - color = TriangleAppearance::EColor_Blue; + color = TriangleAppearance::EColor::Blue; ramses::Node* parentTransformWhichWillBeOverridden = m_scene.createNode(); parentTransformWhichWillBeOverridden->setTranslation({1.2f, 1.2f, 0.0f}); consumerGroupNode->setParent(*parentTransformWhichWillBeOverridden); @@ -59,7 +59,7 @@ namespace ramses::internal } case TRANSFORMATION_CONSUMER_AND_PROVIDER: { - color = TriangleAppearance::EColor_White; + color = TriangleAppearance::EColor::White; ramses::Node* consumerGroupNode = m_scene.createNode("transform consumer"); scene.createTransformationDataConsumer(*consumerGroupNode, transformConsumerDataId); @@ -80,7 +80,7 @@ namespace ramses::internal } case TRANSFORMATION_PROVIDER: { - color = TriangleAppearance::EColor_Green; + color = TriangleAppearance::EColor::Green; ramses::Node* rotateNode = m_scene.createNode(); rotateNode->setRotation({0.0f, 0.0f, -60.0f}, ramses::ERotationType::Euler_XYZ); diff --git a/tests/integration/test-content/Triangle.cpp b/tests/integration/test-content/Triangle.cpp index 674f738d9..42e457bf0 100644 --- a/tests/integration/test-content/Triangle.cpp +++ b/tests/integration/test-content/Triangle.cpp @@ -27,6 +27,11 @@ namespace ramses::internal { } + void Triangle::setColor(TriangleAppearance::EColor color, float alpha) + { + m_appearance.setColor(color, alpha); + } + void Triangle::bindColor(const DataObject& colorDataObject) { m_appearance.bindColor(colorDataObject); diff --git a/tests/integration/test-content/TriangleAppearance.cpp b/tests/integration/test-content/TriangleAppearance.cpp index 8883e2d64..16aefd140 100644 --- a/tests/integration/test-content/TriangleAppearance.cpp +++ b/tests/integration/test-content/TriangleAppearance.cpp @@ -23,8 +23,9 @@ namespace ramses::internal TriangleAppearance::TriangleAppearance(ramses::Scene& scene, const Effect& effect, enum TriangleAppearance::EColor color, float alpha) : m_appearance(createAppearance(effect, scene)) { - m_colorInput = effect.findUniformInput("color"); - if (m_colorInput.has_value()) { + if (color != EColor::None) + { + m_colorInput = effect.findUniformInput("color"); setColor(color, alpha); } } @@ -36,31 +37,29 @@ namespace ramses::internal void TriangleAppearance::setColor(enum EColor color, float alpha) { + if (!m_colorInput) + m_colorInput = m_appearance.getEffect().findUniformInput("color"); + assert(m_colorInput.has_value()); + [[maybe_unused]] bool status = false; switch (color) { - case EColor_Red: - assert(m_colorInput.has_value()); + case EColor::Red: status = m_appearance.setInputValue(*m_colorInput, vec4f{ 1.f, 0.f, 0.f, alpha }); break; - case EColor_Blue: - assert(m_colorInput.has_value()); + case EColor::Blue: status = m_appearance.setInputValue(*m_colorInput, vec4f{ 0.f, 0.f, 1.f, alpha }); break; - case EColor_Green: - assert(m_colorInput.has_value()); + case EColor::Green: status = m_appearance.setInputValue(*m_colorInput, vec4f{ 0.f, 1.f, 0.f, alpha }); break; - case EColor_White: - assert(m_colorInput.has_value()); + case EColor::White: status = m_appearance.setInputValue(*m_colorInput, vec4f{ 1.f, 1.f, 1.f, alpha }); break; - case EColor_Grey: - assert(m_colorInput.has_value()); + case EColor::Grey: status = m_appearance.setInputValue(*m_colorInput, vec4f{ 0.5f, 0.5f, 0.5f, alpha }); break; - default: - assert(false && "Chosen color for triangle is not available!"); + case EColor::None: break; } diff --git a/tests/integration/test-content/VisibilityScene.cpp b/tests/integration/test-content/VisibilityScene.cpp index 847e50f74..eab12f7b7 100644 --- a/tests/integration/test-content/VisibilityScene.cpp +++ b/tests/integration/test-content/VisibilityScene.cpp @@ -19,8 +19,8 @@ namespace ramses::internal : IntegrationScene(scene, cameraPosition, vpWidth, vpHeight) { ramses::Effect* effect = getTestEffect("ramses-test-client-basic"); - Triangle triangle1(m_scene, *effect, TriangleAppearance::EColor_Red, 1.f, TriangleGeometry::EVerticesOrder_CCW); - Triangle triangle2(m_scene, *effect, TriangleAppearance::EColor_Blue, 1.f, TriangleGeometry::EVerticesOrder_CW); // different vertices order forces different indices resource used + Triangle triangle1(m_scene, *effect, TriangleAppearance::EColor::Red, 1.f, TriangleGeometry::EVerticesOrder_CCW); + Triangle triangle2(m_scene, *effect, TriangleAppearance::EColor::Blue, 1.f, TriangleGeometry::EVerticesOrder_CW); // different vertices order forces different indices resource used triangle2.GetAppearance().setCullingMode(ramses::ECullMode::Disabled); auto triangle1mesh = m_scene.createMeshNode("triangle1"); diff --git a/tests/integration/test-content/res/ramses-test-client-basic-ubo.frag b/tests/integration/test-content/res/ramses-test-client-basic-ubo.frag new file mode 100644 index 000000000..2aa2bc39f --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-basic-ubo.frag @@ -0,0 +1,17 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 310 es + +uniform highp vec4 color; + +out highp vec4 fragColor; +void main(void) +{ + fragColor = color; +} diff --git a/tests/integration/test-content/res/ramses-test-client-basic-ubo.vert b/tests/integration/test-content/res/ramses-test-client-basic-ubo.vert new file mode 100644 index 000000000..05a2f9b99 --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-basic-ubo.vert @@ -0,0 +1,45 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 310 es + +layout(std140, binding=0) uniform general_t +{ + int variant; +} generalUbo; + +layout(std140, binding=1) uniform modelBlock_t +{ + highp mat4 modelMat; +} modelUbo; + +layout(std140, binding=2) uniform cameraBlock_t +{ + highp mat4 projMat; + highp mat4 viewMat; + highp vec3 cameraPos; +} cameraUbo; + +layout(std140, binding=3) uniform modelCameraBlock_t +{ + highp mat4 mvpMat; + highp mat4 mvMat; + highp mat4 normalMat; +} modelCameraUbo; + +in vec3 a_position; + +void main() +{ + if (generalUbo.variant == 1) + gl_Position = cameraUbo.projMat * cameraUbo.viewMat * modelUbo.modelMat * vec4(a_position, 1.0); + if (generalUbo.variant == 2) + gl_Position = modelCameraUbo.mvpMat * vec4(a_position, 1.0); + if (generalUbo.variant == 3) + gl_Position = cameraUbo.projMat * modelCameraUbo.mvMat * vec4(a_position, 1.0); +} diff --git a/tests/integration/test-content/res/ramses-test-client-multiple-textures-ubo.frag b/tests/integration/test-content/res/ramses-test-client-multiple-textures-ubo.frag new file mode 100644 index 000000000..abb2c69ab --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-multiple-textures-ubo.frag @@ -0,0 +1,36 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 320 es + +precision highp float; + +layout(std140, binding=3) uniform MultiplexSelectorT +{ + int u_multiplexer; +}; + +uniform sampler2D u_texture1; +uniform sampler2D u_texture2; +uniform sampler2D u_texture3; + +in vec2 v_texcoord; +out vec4 fragColor; + +void main(void) +{ + vec4 color = vec4(0.0); + if(u_multiplexer == 1) + color = texture(u_texture1, v_texcoord); + if(u_multiplexer == 2) + color = texture(u_texture2, v_texcoord); + if(u_multiplexer == 3) + color = texture(u_texture3, v_texcoord); + + fragColor = color; +} diff --git a/tests/integration/test-content/res/ramses-test-client-multiple-textures-ubo.vert b/tests/integration/test-content/res/ramses-test-client-multiple-textures-ubo.vert new file mode 100644 index 000000000..d7a2eaafa --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-multiple-textures-ubo.vert @@ -0,0 +1,32 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 320 es + +layout(std140, binding=1) uniform modelBlock_t +{ + highp mat4 modelMat; +} modelUbo; + +layout(std140, binding=2) uniform cameraBlock_t +{ + highp mat4 projMat; + highp mat4 viewMat; + highp vec3 cameraPos; +} cameraUbo; + +in vec3 a_position; +in vec2 a_texcoord; + +out vec2 v_texcoord; + +void main() +{ + gl_Position = cameraUbo.projMat * cameraUbo.viewMat * modelUbo.modelMat * vec4(a_position, 1.0); + v_texcoord = a_texcoord; +} diff --git a/tests/integration/test-content/res/ramses-test-client-multiple-textures.frag b/tests/integration/test-content/res/ramses-test-client-multiple-textures.frag new file mode 100644 index 000000000..659f71b51 --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-multiple-textures.frag @@ -0,0 +1,32 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 320 es + +precision highp float; + +uniform int u_multiplexer; +uniform sampler2D u_texture1; +uniform sampler2D u_texture2; +uniform sampler2D u_texture3; + +in vec2 v_texcoord; +out vec4 fragColor; + +void main(void) +{ + vec4 color = vec4(0.0); + if(u_multiplexer == 1) + color = texture(u_texture1, v_texcoord); + if(u_multiplexer == 2) + color = texture(u_texture2, v_texcoord); + if(u_multiplexer == 3) + color = texture(u_texture3, v_texcoord); + + fragColor = color; +} diff --git a/tests/integration/test-content/res/ramses-test-client-multiple-textures.vert b/tests/integration/test-content/res/ramses-test-client-multiple-textures.vert new file mode 100644 index 000000000..d88683060 --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-multiple-textures.vert @@ -0,0 +1,22 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 320 es + +uniform highp mat4 mvpMatrix; + +in vec3 a_position; +in vec2 a_texcoord; + +out vec2 v_texcoord; + +void main() +{ + gl_Position = mvpMatrix * vec4(a_position, 1.0); + v_texcoord = a_texcoord; +} diff --git a/tests/integration/test-content/res/ramses-test-client-uniform-buffers-std140.frag b/tests/integration/test-content/res/ramses-test-client-uniform-buffers-std140.frag new file mode 100644 index 000000000..3250b4190 --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-uniform-buffers-std140.frag @@ -0,0 +1,19 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 320 es + +precision highp float; + +in vec4 v_fragColor; +out vec4 fragColor; + +void main(void) +{ + fragColor = v_fragColor; +} diff --git a/tests/integration/test-content/res/ramses-test-client-uniform-buffers-std140.vert b/tests/integration/test-content/res/ramses-test-client-uniform-buffers-std140.vert new file mode 100644 index 000000000..d6eb42c5a --- /dev/null +++ b/tests/integration/test-content/res/ramses-test-client-uniform-buffers-std140.vert @@ -0,0 +1,129 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#version 320 es + +precision highp float; + +// non-UBO inputs/outputs +uniform highp mat4 mvpMatrix; +in vec3 a_position; +out vec4 v_fragColor; + +layout(std140, binding=0) uniform UboTypeScalars +{ + bool uBool; + int uInt; + uint uUInt; // not supported in API + float uFloat; +} scalarsUBO; + +layout(std140, binding=1) uniform UboTypeVecAndMat +{ + vec2 uVec2f; + vec3 uVec3f; + vec4 uVec4f; + mat2 uMat22f; + mat3 uMat33f; + mat4 uMat44f; +} vecMatUBO; + +layout(std140, binding=2) uniform UboTypeScalarArrays +{ + bool uBool[5]; + int uInt[7]; + float uFloat[5]; +} arraysUBO; + +layout(std140, binding=3) uniform UboTypeVecAndMatArrays +{ + vec2 uVec2f[3]; + vec3 uVec3f[3]; + vec4 uVec4f[3]; + mat2 uMat22f[3]; + mat3 uMat33f[3]; + mat4 uMat44f[3]; +} vecMatArraysUBO; + +struct MyStruct +{ + vec3 uVec3f; + float uFloat; + mat3 uMat33f; + int uInt; +}; +layout(std140, binding=4) uniform UboTypeConfidence +{ + float uFloat; + MyStruct uStruct[2]; + +} confidenceUBO; + +void main() +{ + bool fail = false; + + // scalars + if(scalarsUBO.uBool != true) + fail = true; + if(scalarsUBO.uInt != -111) + fail = true; + if(scalarsUBO.uFloat != 333.f) + fail = true; + + // vector and matrix types + if(vecMatUBO.uVec2f != vec2(123.0f, 124.0f)) + fail = true; + if(vecMatUBO.uVec3f != vec3(456.0f, 457.0f, 458.0f)) + fail = true; + if(vecMatUBO.uVec4f != vec4(678.0f)) + fail = true; + if(vecMatUBO.uMat22f != mat2(222.0f, 223.0f, 224.0f, 225.0f)) + fail = true; + if(vecMatUBO.uMat33f != mat3(333.0f, 334.0f, 335.0f, 336.0f, 337.0f, 338.0f, 339.f, 330.f, 331.0f)) + fail = true; + if(vecMatUBO.uMat44f != mat4(444.0f)) + fail = true; + + // arrays of scalars + if(arraysUBO.uBool != bool[5](true, false, true, false, true)) + fail = true; + if(arraysUBO.uInt != int[7](2, 3, 5, 7, 11, 13, 17)) + fail = true; + if(arraysUBO.uFloat != float[5](33.0f, 66.0f, 99.0f, 0.33f, 0.66f)) + fail = true; + + // arrays of vector and matrix + if(vecMatArraysUBO.uVec2f != vec2[3](vec2(1.0), vec2(2.0), vec2(3.0))) + fail = true; + if(vecMatArraysUBO.uVec3f != vec3[3](vec3(1.0), vec3(2.0), vec3(3.0))) + fail = true; + if(vecMatArraysUBO.uVec4f != vec4[3](vec4(1.0), vec4(2.0), vec4(3.0))) + fail = true; + if(vecMatArraysUBO.uMat22f != mat2[3](mat2(4.0), mat2(5.0), mat2(6.0))) + fail = true; + if(vecMatArraysUBO.uMat33f != mat3[3](mat3(4.0), mat3(5.0), mat3(6.0))) + fail = true; + if(vecMatArraysUBO.uMat44f != mat4[3](mat4(4.0), mat4(5.0), mat4(6.0))) + fail = true; + + // struct array + if(confidenceUBO.uFloat != 777.0f) + fail = true; + if(confidenceUBO.uStruct[0] != MyStruct(vec3(11.0), 12.0, mat3(13.0), 14)) + fail = true; + if(confidenceUBO.uStruct[1] != MyStruct(vec3(21.0), 22.0, mat3(23.0), 24)) + fail = true; + + if(fail) + v_fragColor = vec4(1.0f); + else + v_fragColor = vec4(1.0f, 0.f, 0.5f, 1.0f); + + gl_Position = mvpMatrix * vec4(a_position, 1.0); +} diff --git a/tests/integration/viewer-tests/CMakeLists.txt b/tests/integration/viewer-tests/CMakeLists.txt index 48c3cc5f5..1435b80c5 100644 --- a/tests/integration/viewer-tests/CMakeLists.txt +++ b/tests/integration/viewer-tests/CMakeLists.txt @@ -17,7 +17,7 @@ createModule( TYPE BINARY ENABLE_INSTALL ${ramses-sdk_ENABLE_INSTALL} INCLUDE_PATHS ${PROJECT_SOURCE_DIR}/tools/ramses-viewer - ${PROJECT_SOURCE_DIR}/tests/unittests/client/logic/shared + ${PROJECT_SOURCE_DIR}/tests/unittests/client/utils SRC_FILES LogicViewerAppTest.cpp RESOURCE_FOLDERS res diff --git a/tests/integration/viewer-tests/LogicViewerAppTest.cpp b/tests/integration/viewer-tests/LogicViewerAppTest.cpp index e873a76e1..66810eda2 100644 --- a/tests/integration/viewer-tests/LogicViewerAppTest.cpp +++ b/tests/integration/viewer-tests/LogicViewerAppTest.cpp @@ -120,7 +120,7 @@ Pos=0,0 Size=540,720 Collapsed=0 -[Window][Scene[1]: simple triangle scene (FeatureLevel 01)] +[Window][Scene[1]: simple triangle scene (FeatureLevel 02)] Pos=0,0 Size=540,720 Collapsed=0 @@ -574,7 +574,12 @@ namespace ramses::internal EXPECT_EQ("143262", str); // image differences } - TYPED_TEST(ALogicViewerApp_T, emptyParam) + TEST_F(ALogicViewerGuiApp, emptyParam) + { + EXPECT_EQ(0, this->createApp()); + } + + TEST_F(ALogicViewerHeadlessApp, emptyParam) { EXPECT_EQ(static_cast(CLI::ExitCodes::RequiredError), this->createApp()); } @@ -596,13 +601,13 @@ namespace ramses::internal TYPED_TEST(ALogicViewerApp_T, luaFileDoesNotExist) { testing::internal::CaptureStderr(); - EXPECT_EQ(static_cast(CLI::ExitCodes::ValidationError), this->createApp({ ramsesFile, "notExisting.lua" })); + EXPECT_EQ(static_cast(CLI::ExitCodes::ValidationError), this->createApp({ ramsesFile, "--lua", "notExisting.lua" })); EXPECT_THAT(testing::internal::GetCapturedStderr(), testing::HasSubstr("File does not exist: notExisting.lua")); } TYPED_TEST(ALogicViewerApp_T, writeLuaSimplified) { - EXPECT_EQ(0, this->createApp({ "--write-config", ramsesFile })); + EXPECT_EQ(0, this->createApp({"--write-config", "--", ramsesFile})); EXPECT_FALSE(this->m_app->getSettings()->luaPreferSimplified); this->m_app->getSettings()->luaPreferSimplified = true; EXPECT_EQ(ViewerApp::ExitCode::Ok, this->m_app->run()); @@ -611,7 +616,7 @@ namespace ramses::internal TYPED_TEST(ALogicViewerApp_T, writeLuaNotSimplifiedIdentifiers) { - EXPECT_EQ(0, this->createApp({ "--write-config", ramsesFile })); + EXPECT_EQ(0, this->createApp({"--write-config", "--", ramsesFile})); EXPECT_FALSE(this->m_app->getSettings()->luaPreferIdentifiers); this->m_app->getSettings()->luaPreferIdentifiers = true; EXPECT_EQ(ViewerApp::ExitCode::Ok, this->m_app->run()); @@ -620,7 +625,7 @@ namespace ramses::internal TYPED_TEST(ALogicViewerApp_T, writeLuaNotSimplifiedObjectIds) { - EXPECT_EQ(0, this->createApp({ "--write-config", ramsesFile })); + EXPECT_EQ(0, this->createApp({"--write-config", "--", ramsesFile})); EXPECT_FALSE(this->m_app->getSettings()->luaPreferObjectIds); this->m_app->getSettings()->luaPreferObjectIds = true; EXPECT_EQ(ViewerApp::ExitCode::Ok, this->m_app->run()); @@ -629,7 +634,7 @@ namespace ramses::internal TYPED_TEST(ALogicViewerApp_T, writeDefaultLuaConfiguration) { - EXPECT_EQ(0, this->createApp({ "--write-config", ramsesFile })); + EXPECT_EQ(0, this->createApp({"--write-config", "--", ramsesFile})); EXPECT_EQ(ViewerApp::ExitCode::Ok, this->m_app->run()); EXPECT_TRUE(fs::exists(luaFile)); EXPECT_EQ(Result(), this->m_app->getLogicViewer()->loadLuaFile(luaFile)); @@ -667,8 +672,8 @@ namespace ramses::internal EXPECT_TRUE(m_app->doOneLoop()); EXPECT_TRUE(m_app->doOneLoop()); EXPECT_TRUE(m_app->doOneLoop()); - auto imgui = m_app->getImguiClientHelper(); - imgui->windowClosed(ramses::displayId_t()); + auto ctrl = m_app->getRendererControl(); + ctrl->windowClosed(ramses::displayId_t()); EXPECT_FALSE(m_app->doOneLoop()); } @@ -680,8 +685,8 @@ namespace ramses::internal EXPECT_TRUE(m_app->doOneLoop()); EXPECT_TRUE(m_app->doOneLoop()); EXPECT_TRUE(m_app->doOneLoop()); - auto imgui = m_app->getImguiClientHelper(); - imgui->windowClosed(ramses::displayId_t()); + auto ctrl = m_app->getRendererControl(); + ctrl->windowClosed(ramses::displayId_t()); EXPECT_FALSE(m_app->doOneLoop()); } @@ -968,7 +973,8 @@ namespace ramses::internal end )"); EXPECT_TRUE(keyPress(ramses::EKeyCode_F5)); // reload configuration - EXPECT_TRUE(keyPress(ramses::EKeyCode_F11)); // hide UI + EXPECT_TRUE(keyPress(ramses::EKeyCode_F11)); // hide main window + EXPECT_TRUE(keyPress(ramses::EKeyCode_F10)); // hide Logic window EXPECT_EQ(Result(), m_app->getLogicViewer()->call("screenshot")); EXPECT_TRUE(CompareImage("screenshot.png", "ALogicViewerApp_clearColorCmdLine.png", 0.5f)); // increased tolerance due to some platforms being 1/255 off covering large area (as background) diff --git a/tests/unittests/CMakeLists.txt b/tests/unittests/CMakeLists.txt index 69778a098..45a1f9681 100644 --- a/tests/unittests/CMakeLists.txt +++ b/tests/unittests/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(framework-test-utils) add_subdirectory(framework) +add_subdirectory(glslang-init-gtest-env) add_subdirectory(client) if(ANY_WINDOW_TYPE_ENABLED) diff --git a/tests/unittests/client/AppearanceTest.cpp b/tests/unittests/client/AppearanceTest.cpp index 14442e80e..f3a2172ed 100644 --- a/tests/unittests/client/AppearanceTest.cpp +++ b/tests/unittests/client/AppearanceTest.cpp @@ -16,35 +16,18 @@ #include "ramses/client/RenderBuffer.h" #include "ramses/client/TextureSamplerExternal.h" #include "TestEffectCreator.h" +#include "FeatureLevelTestValues.h" #include "impl/EffectImpl.h" #include "impl/DataObjectImpl.h" #include "impl/TextureSamplerImpl.h" #include "impl/AppearanceImpl.h" #include "impl/AppearanceUtils.h" +#include "impl/EffectInputImpl.h" namespace ramses::internal { - class AAppearanceTest : public ::testing::Test + class AAppearanceTest : public TestWithSharedEffectPerFeatureLevel { - public: - - static void SetUpTestSuite() - { - sharedTestState = std::make_unique(false); - } - - static void TearDownTestSuite() - { - sharedTestState = nullptr; - } - - void SetUp() override - { - EXPECT_TRUE(sharedTestState != nullptr); - sharedTestState->recreateAppearence(); - appearance = sharedTestState->appearance; - } - protected: struct TextureInputInfo { @@ -58,110 +41,117 @@ namespace ramses::internal TextureCube* textureCube = nullptr; }; - static void GetTexture2DInputInfo(TextureInputInfo& info) + void GetTexture2DInputInfo(TextureInputInfo& info) { - info.input = sharedTestState->effect->findUniformInput("texture2dInput"); + info.input = m_sharedTestState.effect->findUniformInput("texture2dInput"); EXPECT_TRUE(info.input.has_value()); const std::vector mipData{ { std::byte{1}, std::byte{2}, std::byte{3} } }; - Texture2D* texture = sharedTestState->getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); + Texture2D* texture = m_sharedTestState.getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); EXPECT_TRUE(texture != nullptr); info.texture2D = texture; - ramses::TextureSampler* sampler = sharedTestState->getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); + ramses::TextureSampler* sampler = m_sharedTestState.getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); EXPECT_TRUE(sampler != nullptr); info.sampler = sampler; } - static void GetTexture2DMSInputInfo(TextureInputInfo& info) + void GetTexture2DMSInputInfo(TextureInputInfo& info) { - info.input = sharedTestState->effect->findUniformInput("texture2dMSInput"); + info.input = m_sharedTestState.effect->findUniformInput("texture2dMSInput"); EXPECT_TRUE(info.input.has_value()); - ramses::RenderBuffer* renderBuffer = sharedTestState->getScene().createRenderBuffer(2u, 2u, ERenderBufferFormat::RGB8, ERenderBufferAccessMode::ReadWrite, 4u); + ramses::RenderBuffer* renderBuffer = m_sharedTestState.getScene().createRenderBuffer(2u, 2u, ERenderBufferFormat::RGB8, ERenderBufferAccessMode::ReadWrite, 4u); EXPECT_TRUE(renderBuffer != nullptr); info.renderBuffer = renderBuffer; - TextureSamplerMS* samplerMS = sharedTestState->getScene().createTextureSamplerMS(*renderBuffer, "renderBuffer"); + TextureSamplerMS* samplerMS = m_sharedTestState.getScene().createTextureSamplerMS(*renderBuffer, "renderBuffer"); EXPECT_TRUE(samplerMS != nullptr); info.samplerMS = samplerMS; } - static void GetTexture3DInputInfo(TextureInputInfo& info) + void GetTexture3DInputInfo(TextureInputInfo& info) { - info.input = sharedTestState->effect->findUniformInput("texture3dInput"); + info.input = m_sharedTestState.effect->findUniformInput("texture3dInput"); EXPECT_TRUE(info.input.has_value()); const std::vector mipData{ { std::byte{1}, std::byte{2}, std::byte{3} } }; - Texture3D* texture = sharedTestState->getScene().createTexture3D(ETextureFormat::RGB8, 1u, 1u, 1u, mipData, false); + Texture3D* texture = m_sharedTestState.getScene().createTexture3D(ETextureFormat::RGB8, 1u, 1u, 1u, mipData, false); EXPECT_TRUE(texture != nullptr); info.texture3D = texture; - ramses::TextureSampler* sampler = sharedTestState->getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); + ramses::TextureSampler* sampler = m_sharedTestState.getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); EXPECT_TRUE(sampler != nullptr); info.sampler = sampler; } - static void GetTextureCubeInputInfo(TextureInputInfo& info) + void GetTextureCubeInputInfo(TextureInputInfo& info) { - info.input = sharedTestState->effect->findUniformInput("textureCubeInput"); + info.input = m_sharedTestState.effect->findUniformInput("textureCubeInput"); EXPECT_TRUE(info.input.has_value()); const std::vector data = { std::byte{1}, std::byte{2}, std::byte{3} }; std::vector mipData{ { data, data, data, data, data, data } }; - TextureCube* texture = sharedTestState->getScene().createTextureCube(ETextureFormat::RGB8, 1u, mipData, false); + TextureCube* texture = m_sharedTestState.getScene().createTextureCube(ETextureFormat::RGB8, 1u, mipData, false); EXPECT_TRUE(texture != nullptr); info.textureCube = texture; - ramses::TextureSampler* sampler = sharedTestState->getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); + ramses::TextureSampler* sampler = m_sharedTestState.getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); EXPECT_TRUE(sampler != nullptr); info.sampler = sampler; } - static void GetTextureExternalInputInfo(TextureInputInfo& info) + void GetTextureExternalInputInfo(TextureInputInfo& info) { - info.input = sharedTestState->effect->findUniformInput("textureExternalInput"); + info.input = m_sharedTestState.effect->findUniformInput("textureExternalInput"); EXPECT_TRUE(info.input.has_value()); - TextureSamplerExternal* sampler = sharedTestState->getScene().createTextureSamplerExternal(ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear); + TextureSamplerExternal* sampler = m_sharedTestState.getScene().createTextureSamplerExternal(ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear); EXPECT_TRUE(sampler != nullptr); info.samplerExternal = sampler; } - static std::unique_ptr sharedTestState; - Appearance* appearance{nullptr}; - }; - - std::unique_ptr AAppearanceTest::sharedTestState; + template + static void BuildUniformBuffer(std::vector& buffer, const T& value) { + const auto* expectedRaw = reinterpret_cast(&value); + buffer.insert(buffer.end(), expectedRaw, expectedRaw + sizeof(T)); + }; - class AAppearanceTestWithSemanticUniforms : public AAppearanceTest - { - public: - static void SetUpTestSuite() + static std::vector GetUniformBufferData(const ramses::Appearance& appearance, const ramses::UniformInput& uniformInput) { - sharedTestState = std::make_unique(true); + const auto& iscene = appearance.getScene().impl().getIScene(); + const auto dataInstance = appearance.impl().getUniformDataInstance(); + const auto dataField = uniformInput.impl().getDataFieldHandle(); + const auto* uniformBufferData = iscene.getUniformBuffer(iscene.getDataUniformBuffer(dataInstance, dataField)).data.data(); + + const auto bufferDataSize = uniformInput.impl().getUniformBufferElementSize().getValue(); + return { uniformBufferData, uniformBufferData + bufferDataSize }; } + + Appearance& m_appearance{ m_sharedTestState.recreateAppearence() }; }; - TEST_F(AAppearanceTest, getsTheSameEffectUsedToCreateIt) + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(AAppearanceTest); + + TEST_P(AAppearanceTest, getsTheSameEffectUsedToCreateIt) { - const Effect& effect = appearance->getEffect(); - EXPECT_EQ(&effect, sharedTestState->effect); + const Effect& effect = m_appearance.getEffect(); + EXPECT_EQ(&effect, m_sharedTestState.effect); - const ramses::internal::DataLayout uniformLayout = sharedTestState->getInternalScene().getDataLayout(appearance->impl().getUniformDataLayout()); + const ramses::internal::DataLayout uniformLayout = m_sharedTestState.getInternalScene().getDataLayout(m_appearance.impl().getUniformDataLayout()); const ramses::internal::ResourceContentHash& effectHashFromUniformLayout = uniformLayout.getEffectHash(); - EXPECT_EQ(appearance->getEffect().impl().getLowlevelResourceHash(), effectHashFromUniformLayout); + EXPECT_EQ(m_appearance.getEffect().impl().getLowlevelResourceHash(), effectHashFromUniformLayout); } - TEST_F(AAppearanceTest, setGetBlendingFactors) + TEST_P(AAppearanceTest, setGetBlendingFactors) { - bool stat = appearance->setBlendingFactors(EBlendFactor::One, EBlendFactor::SrcAlpha, EBlendFactor::OneMinusSrcAlpha, EBlendFactor::DstAlpha); + bool stat = m_appearance.setBlendingFactors(EBlendFactor::One, EBlendFactor::SrcAlpha, EBlendFactor::OneMinusSrcAlpha, EBlendFactor::DstAlpha); EXPECT_TRUE(stat); EBlendFactor srcColor = EBlendFactor::Zero; EBlendFactor destColor = EBlendFactor::Zero; EBlendFactor srcAlpha = EBlendFactor::Zero; EBlendFactor destAlpha = EBlendFactor::Zero; - stat = appearance->getBlendingFactors(srcColor, destColor, srcAlpha, destAlpha); + stat = m_appearance.getBlendingFactors(srcColor, destColor, srcAlpha, destAlpha); EXPECT_TRUE(stat); EXPECT_EQ(EBlendFactor::One, srcColor); EXPECT_EQ(EBlendFactor::SrcAlpha, destColor); @@ -169,655 +159,774 @@ namespace ramses::internal EXPECT_EQ(EBlendFactor::DstAlpha, destAlpha); } - TEST_F(AAppearanceTest, setGetBlendingColor) + TEST_P(AAppearanceTest, setGetBlendingColor) { vec4f color{ std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max(), std::numeric_limits::max() }; //default values - bool stat = appearance->getBlendingColor(color); + bool stat = m_appearance.getBlendingColor(color); EXPECT_TRUE(stat); EXPECT_EQ(color, vec4f(0.f, 0.f, 0.f, 0.f)); const vec4f colorToSet{ 0.1f, 0.2f, 0.3f, 0.4f }; - stat = appearance->setBlendingColor(colorToSet); + stat = m_appearance.setBlendingColor(colorToSet); EXPECT_TRUE(stat); - stat = appearance->getBlendingColor(color); + stat = m_appearance.getBlendingColor(color); EXPECT_TRUE(stat); EXPECT_EQ(colorToSet, color); } - TEST_F(AAppearanceTest, setGetDepthWrite) + TEST_P(AAppearanceTest, setGetDepthWrite) { EDepthWrite depthWriteMode = EDepthWrite::Disabled; - EXPECT_TRUE(appearance->setDepthWrite(EDepthWrite::Enabled)); - EXPECT_TRUE(appearance->getDepthWriteMode(depthWriteMode)); + EXPECT_TRUE(m_appearance.setDepthWrite(EDepthWrite::Enabled)); + EXPECT_TRUE(m_appearance.getDepthWriteMode(depthWriteMode)); EXPECT_EQ(EDepthWrite::Enabled, depthWriteMode); - EXPECT_TRUE(appearance->setDepthWrite(EDepthWrite::Disabled)); - EXPECT_TRUE(appearance->getDepthWriteMode(depthWriteMode)); + EXPECT_TRUE(m_appearance.setDepthWrite(EDepthWrite::Disabled)); + EXPECT_TRUE(m_appearance.getDepthWriteMode(depthWriteMode)); EXPECT_EQ(EDepthWrite::Disabled, depthWriteMode); - EXPECT_TRUE(appearance->setDepthWrite(EDepthWrite::Enabled)); - EXPECT_TRUE(appearance->getDepthWriteMode(depthWriteMode)); + EXPECT_TRUE(m_appearance.setDepthWrite(EDepthWrite::Enabled)); + EXPECT_TRUE(m_appearance.getDepthWriteMode(depthWriteMode)); EXPECT_EQ(EDepthWrite::Enabled, depthWriteMode); } - TEST_F(AAppearanceTest, setGetDepthFunction) + TEST_P(AAppearanceTest, setGetDepthFunction) { EDepthFunc depthFunc = EDepthFunc::Disabled; - EXPECT_TRUE(appearance->getDepthFunction(depthFunc)); + EXPECT_TRUE(m_appearance.getDepthFunction(depthFunc)); EXPECT_EQ(EDepthFunc::LessEqual, depthFunc); - EXPECT_TRUE(appearance->setDepthFunction(EDepthFunc::GreaterEqual)); - EXPECT_TRUE(appearance->getDepthFunction(depthFunc)); + EXPECT_TRUE(m_appearance.setDepthFunction(EDepthFunc::GreaterEqual)); + EXPECT_TRUE(m_appearance.getDepthFunction(depthFunc)); EXPECT_EQ(EDepthFunc::GreaterEqual, depthFunc); } - TEST_F(AAppearanceTest, setGetScissorTest) + TEST_P(AAppearanceTest, setGetScissorTest) { EScissorTest mode = EScissorTest::Disabled; - EXPECT_TRUE(appearance->setScissorTest(EScissorTest::Enabled, 1, 2, 3u, 4u)); - EXPECT_TRUE(appearance->getScissorTestState(mode)); + EXPECT_TRUE(m_appearance.setScissorTest(EScissorTest::Enabled, 1, 2, 3u, 4u)); + EXPECT_TRUE(m_appearance.getScissorTestState(mode)); EXPECT_EQ(EScissorTest::Enabled, mode); int16_t x = 0; int16_t y = 0; uint16_t width = 0u; uint16_t height = 0; - EXPECT_TRUE(appearance->getScissorRegion(x, y, width, height)); + EXPECT_TRUE(m_appearance.getScissorRegion(x, y, width, height)); EXPECT_EQ(1, x); EXPECT_EQ(2, y); EXPECT_EQ(3u, width); EXPECT_EQ(4u, height); } - TEST_F(AAppearanceTest, setGetStencilFunc) + TEST_P(AAppearanceTest, setGetStencilFunc) { - bool stat = appearance->setStencilFunction(EStencilFunc::Equal, 2u, 0xef); + bool stat = m_appearance.setStencilFunction(EStencilFunc::Equal, 2u, 0xef); EXPECT_TRUE(stat); EStencilFunc func = EStencilFunc::Disabled; uint8_t ref = 0; uint8_t mask = 0; - stat = appearance->getStencilFunction(func, ref, mask); + stat = m_appearance.getStencilFunction(func, ref, mask); EXPECT_TRUE(stat); EXPECT_EQ(EStencilFunc::Equal, func); EXPECT_EQ(2u, ref); EXPECT_EQ(0xef, mask); } - TEST_F(AAppearanceTest, setGetStencilOperation) + TEST_P(AAppearanceTest, setGetStencilOperation) { - bool stat = appearance->setStencilOperation(EStencilOperation::Decrement, EStencilOperation::Increment, EStencilOperation::DecrementWrap); + bool stat = m_appearance.setStencilOperation(EStencilOperation::Decrement, EStencilOperation::Increment, EStencilOperation::DecrementWrap); EXPECT_TRUE(stat); EStencilOperation sfail = EStencilOperation::Zero; EStencilOperation dpfail = EStencilOperation::Zero; EStencilOperation dppass = EStencilOperation::Zero; - stat = appearance->getStencilOperation(sfail, dpfail, dppass); + stat = m_appearance.getStencilOperation(sfail, dpfail, dppass); EXPECT_TRUE(stat); EXPECT_EQ(EStencilOperation::Decrement, sfail); EXPECT_EQ(EStencilOperation::Increment, dpfail); EXPECT_EQ(EStencilOperation::DecrementWrap, dppass); } - TEST_F(AAppearanceTest, setGetBlendOperations) + TEST_P(AAppearanceTest, setGetBlendOperations) { - EXPECT_TRUE(appearance->setBlendingOperations(EBlendOperation::Subtract, EBlendOperation::Max)); + EXPECT_TRUE(m_appearance.setBlendingOperations(EBlendOperation::Subtract, EBlendOperation::Max)); EBlendOperation opColor = EBlendOperation::Disabled; EBlendOperation opAlpha = EBlendOperation::Disabled; - EXPECT_TRUE(appearance->getBlendingOperations(opColor, opAlpha)); + EXPECT_TRUE(m_appearance.getBlendingOperations(opColor, opAlpha)); EXPECT_EQ(EBlendOperation::Subtract, opColor); EXPECT_EQ(EBlendOperation::Max, opAlpha); } - TEST_F(AAppearanceTest, setGetCullMode) + TEST_P(AAppearanceTest, setGetCullMode) { ECullMode mode = ECullMode::Disabled; - EXPECT_TRUE(appearance->setCullingMode(ECullMode::FrontFacing)); - EXPECT_TRUE(appearance->getCullingMode(mode)); + EXPECT_TRUE(m_appearance.setCullingMode(ECullMode::FrontFacing)); + EXPECT_TRUE(m_appearance.getCullingMode(mode)); EXPECT_EQ(ECullMode::FrontFacing, mode); - EXPECT_TRUE(appearance->setCullingMode(ECullMode::Disabled)); - EXPECT_TRUE(appearance->getCullingMode(mode)); + EXPECT_TRUE(m_appearance.setCullingMode(ECullMode::Disabled)); + EXPECT_TRUE(m_appearance.getCullingMode(mode)); EXPECT_EQ(ECullMode::Disabled, mode); } - TEST_F(AAppearanceTest, hasDrawModeTrianglesByDefault) + TEST_P(AAppearanceTest, hasDrawModeTrianglesByDefault) { EDrawMode mode; - EXPECT_TRUE(appearance->getDrawMode(mode)); + EXPECT_TRUE(m_appearance.getDrawMode(mode)); EXPECT_EQ(EDrawMode::Triangles, mode); } - TEST_F(AAppearanceTest, setGetDrawMode) + TEST_P(AAppearanceTest, setGetDrawMode) { EDrawMode mode = EDrawMode::Lines; - EXPECT_TRUE(appearance->setDrawMode(EDrawMode::Points)); - EXPECT_TRUE(appearance->getDrawMode(mode)); + EXPECT_TRUE(m_appearance.setDrawMode(EDrawMode::Points)); + EXPECT_TRUE(m_appearance.getDrawMode(mode)); EXPECT_EQ(EDrawMode::Points, mode); } - TEST_F(AAppearanceTest, setGetColorWriteMask) + TEST_P(AAppearanceTest, setGetColorWriteMask) { bool writeR = false; bool writeG = false; bool writeB = false; bool writeA = false; - EXPECT_TRUE(appearance->setColorWriteMask(true, false, true, false)); - EXPECT_TRUE(appearance->getColorWriteMask(writeR, writeG, writeB, writeA)); + EXPECT_TRUE(m_appearance.setColorWriteMask(true, false, true, false)); + EXPECT_TRUE(m_appearance.getColorWriteMask(writeR, writeG, writeB, writeA)); EXPECT_TRUE(writeR); EXPECT_FALSE(writeG); EXPECT_TRUE(writeB); EXPECT_FALSE(writeA); - EXPECT_TRUE(appearance->setColorWriteMask(false, true, false, true)); - EXPECT_TRUE(appearance->getColorWriteMask(writeR, writeG, writeB, writeA)); + EXPECT_TRUE(m_appearance.setColorWriteMask(false, true, false, true)); + EXPECT_TRUE(m_appearance.getColorWriteMask(writeR, writeG, writeB, writeA)); EXPECT_FALSE(writeR); EXPECT_TRUE(writeG); EXPECT_FALSE(writeB); EXPECT_TRUE(writeA); } - TEST_F(AAppearanceTest, reportsErrorWhenGetSetMismatchingInputTypeScalar) + TEST_P(AAppearanceTest, reportsErrorWhenGetSetMismatchingInputTypeScalar) { - const auto optUniform = sharedTestState->effect->findUniformInput("integerInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("integerInput"); ASSERT_TRUE(optUniform.has_value()); const float value = 42; float getValue = 0; - EXPECT_FALSE(appearance->setInputValue(*optUniform, value)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, getValue)); } - TEST_F(AAppearanceTest, reportsErrorWhenGetSetMismatchingInputTypeArray) + TEST_P(AAppearanceTest, reportsErrorWhenGetSetMismatchingInputTypeArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("integerInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("integerInput"); ASSERT_TRUE(optUniform.has_value()); const float values[] = { 42, 43, 44, 45, 46, 47 }; float getValues[6]; - EXPECT_FALSE(appearance->setInputValue(*optUniform, 6u, values)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 6u, getValues)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 6u, values)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 6u, getValues)); } - TEST_F(AAppearanceTest, reportsErrorWhenGetSetMismatchingInputTypeTexture) + TEST_P(AAppearanceTest, reportsErrorWhenGetSetMismatchingInputTypeTexture) { - const auto optUniform = sharedTestState->effect->findUniformInput("integerInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("integerInput"); ASSERT_TRUE(optUniform.has_value()); const std::vector mipData{ { std::byte{1}, std::byte{2}, std::byte{3} } }; - Texture2D* texture = sharedTestState->getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); + Texture2D* texture = m_sharedTestState.getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); ASSERT_TRUE(texture != nullptr); - ramses::TextureSampler* textureSampler = sharedTestState->getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); + ramses::TextureSampler* textureSampler = m_sharedTestState.getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); ASSERT_TRUE(textureSampler != nullptr); - EXPECT_FALSE(appearance->setInputTexture(*optUniform, *textureSampler)); + EXPECT_FALSE(m_appearance.setInputTexture(*optUniform, *textureSampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureSampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureSampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture)); } - TEST_F(AAppearanceTest, reportsErrorWhenSetInputTextureFromADifferentScene) + TEST_P(AAppearanceTest, reportsErrorWhenSetInputTextureFromADifferentScene) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dInput"); ASSERT_TRUE(optUniform.has_value()); const std::vector mipData{ { std::byte{1}, std::byte{2}, std::byte{3} } }; - ramses::Scene& anotherScene = *sharedTestState->getClient().createScene(sceneId_t(1u)); + ramses::Scene& anotherScene = *m_sharedTestState.getClient().createScene(sceneId_t(1u)); Texture2D* texture = anotherScene.createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); ASSERT_TRUE(texture != nullptr); ramses::TextureSampler* textureSampler = anotherScene.createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); ASSERT_TRUE(textureSampler != nullptr); - EXPECT_FALSE(appearance->setInputTexture(*optUniform, *textureSampler)); + EXPECT_FALSE(m_appearance.setInputTexture(*optUniform, *textureSampler)); EXPECT_TRUE(anotherScene.destroy(*texture)); - EXPECT_TRUE(sharedTestState->getClient().destroy(anotherScene)); + EXPECT_TRUE(m_sharedTestState.getClient().destroy(anotherScene)); } - TEST_F(AAppearanceTest, getsSamplerSetToUniformInput) + TEST_P(AAppearanceTest, getsSamplerSetToUniformInput) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dInput"); ASSERT_TRUE(optUniform.has_value()); const std::vector mipData{ { std::byte{1}, std::byte{2}, std::byte{3} } }; - Texture2D* texture = sharedTestState->getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); + Texture2D* texture = m_sharedTestState.getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); ASSERT_TRUE(texture != nullptr); - ramses::TextureSampler* textureSampler = sharedTestState->getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); + ramses::TextureSampler* textureSampler = m_sharedTestState.getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); ASSERT_TRUE(textureSampler != nullptr); - EXPECT_TRUE(appearance->setInputTexture(*optUniform, *textureSampler)); + EXPECT_TRUE(m_appearance.setInputTexture(*optUniform, *textureSampler)); const ramses::TextureSampler* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTexture(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTexture(*optUniform, actualSampler)); EXPECT_EQ(textureSampler, actualSampler); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureSampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureSampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture)); } - TEST_F(AAppearanceTest, getsNullSamplerIfNoneSetToUniformInput) + TEST_P(AAppearanceTest, getsNullSamplerIfNoneSetToUniformInput) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dInput"); ASSERT_TRUE(optUniform.has_value()); const ramses::TextureSampler* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTexture(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTexture(*optUniform, actualSampler)); EXPECT_EQ(nullptr, actualSampler); } - TEST_F(AAppearanceTest, getsNullSamplerMSIfNoneSetToUniformInput) + TEST_P(AAppearanceTest, getsNullSamplerMSIfNoneSetToUniformInput) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dMSInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dMSInput"); ASSERT_TRUE(optUniform.has_value()); const TextureSamplerMS* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTextureMS(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTextureMS(*optUniform, actualSampler)); EXPECT_EQ(nullptr, actualSampler); } - TEST_F(AAppearanceTest, getsNullSamplerExternalIfNoneSetToUniformInput) + TEST_P(AAppearanceTest, getsNullSamplerExternalIfNoneSetToUniformInput) { - const auto optUniform = sharedTestState->effect->findUniformInput("textureExternalInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("textureExternalInput"); ASSERT_TRUE(optUniform.has_value()); const TextureSamplerExternal* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTextureExternal(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTextureExternal(*optUniform, actualSampler)); EXPECT_EQ(nullptr, actualSampler); } - TEST_F(AAppearanceTest, failsToGetSamplerSetToUniformIfInputHasWrongType) + TEST_P(AAppearanceTest, failsToGetSamplerSetToUniformIfInputHasWrongType) { - const auto optUniform = sharedTestState->effect->findUniformInput("integerInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("integerInput"); ASSERT_TRUE(optUniform.has_value()); const ramses::TextureSampler* actualSampler = nullptr; - EXPECT_FALSE(appearance->getInputTexture(*optUniform, actualSampler)); + EXPECT_FALSE(m_appearance.getInputTexture(*optUniform, actualSampler)); EXPECT_EQ(nullptr, actualSampler); } - TEST_F(AAppearanceTest, failsToGetSamplerMSIfInputHasWrongType) + TEST_P(AAppearanceTest, failsToGetSamplerMSIfInputHasWrongType) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dInput"); ASSERT_TRUE(optUniform.has_value()); const TextureSamplerMS* actualSampler = nullptr; - EXPECT_FALSE(appearance->getInputTextureMS(*optUniform, actualSampler)); + EXPECT_FALSE(m_appearance.getInputTextureMS(*optUniform, actualSampler)); EXPECT_EQ(nullptr, actualSampler); } - TEST_F(AAppearanceTest, failsToGetSamplerExternalIfInputHasWrongType) + TEST_P(AAppearanceTest, failsToGetSamplerExternalIfInputHasWrongType) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dInput"); ASSERT_TRUE(optUniform.has_value()); const TextureSamplerExternal* actualSampler = nullptr; - EXPECT_FALSE(appearance->getInputTextureExternal(*optUniform, actualSampler)); + EXPECT_FALSE(m_appearance.getInputTextureExternal(*optUniform, actualSampler)); EXPECT_EQ(nullptr, actualSampler); } + /// Uniform buffer + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeUniformBuffer) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const auto optUniform = m_sharedTestState.effect->findUniformInput("uniformBlock"); + ASSERT_TRUE(optUniform.has_value()); + + const auto optUniformMat44 = m_sharedTestState.effect->findUniformInput("uniformBlock.ubMat44"); + ASSERT_TRUE(optUniformMat44.has_value()); + + const auto optUniformFloatArray = m_sharedTestState.effect->findUniformInput("uniformBlock.ubFloat"); + ASSERT_TRUE(optUniformFloatArray.has_value()); + + const auto optUniformMat33 = m_sharedTestState.effect->findUniformInput("uniformBlock.ubMat33"); + ASSERT_TRUE(optUniformMat33.has_value()); + + EXPECT_TRUE(m_appearance.setInputValue(*optUniformMat44, ramses::matrix44f{ 123.f })); + EXPECT_TRUE(m_appearance.setInputValue(*optUniformFloatArray, 3u, std::array{ 1.f, 2.f, 3.f }.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniformMat33, ramses::matrix33f{ 456.f })); + + ramses::matrix44f ubMat44Out; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformMat44, ubMat44Out)); + EXPECT_EQ(ramses::matrix44f{ 123.f }, ubMat44Out); + + std::array ubFloatArrayOut{}; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformFloatArray, 3u, ubFloatArrayOut.data())); + EXPECT_THAT(ubFloatArrayOut, ::testing::ElementsAre( 1.f, 2.f, 3.f)); + + ramses::matrix33f ubMat33Out; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformMat33, ubMat33Out)); + EXPECT_EQ(ramses::matrix33f{ 456.f }, ubMat33Out); + + std::vector expectedBufferValues; + BuildUniformBuffer(expectedBufferValues, ramses::matrix44f{ 123.f }); + //float[3] array is represented in memory as 3x vec4f + BuildUniformBuffer(expectedBufferValues, ramses::vec4f{ 1.0 }); + BuildUniformBuffer(expectedBufferValues, ramses::vec4f{ 2.0 }); + BuildUniformBuffer(expectedBufferValues, ramses::vec4f{ 3.0 }); + //matrix33 is represented as as 3x vec4f + BuildUniformBuffer(expectedBufferValues, ramses::vec4f{ 456.f, 0.f , 0.f , 0.f }); + BuildUniformBuffer(expectedBufferValues, ramses::vec4f{ 0.f , 456.f , 0.f , 0.f }); + BuildUniformBuffer(expectedBufferValues, ramses::vec4f{ 0.f , 0.f , 456.f , 0.f }); + + const auto actualUniformBufferValues(GetUniformBufferData(m_appearance, *optUniform)); + EXPECT_EQ(actualUniformBufferValues, expectedBufferValues); + } + + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeUniformBuffer_AnonymousBuffer) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const auto optUniform = m_sharedTestState.effect->findUniformInput("anon@ubo_binding=2"); + ASSERT_TRUE(optUniform.has_value()); + + const auto optUniformBool = m_sharedTestState.effect->findUniformInput("ubBool"); + ASSERT_TRUE(optUniformBool.has_value()); + + const auto optUniformMat33 = m_sharedTestState.effect->findUniformInput("ubMat33"); + ASSERT_TRUE(optUniformMat33.has_value()); + + const auto optUniformMat22 = m_sharedTestState.effect->findUniformInput("ubMat22"); + ASSERT_TRUE(optUniformMat22.has_value()); + + const auto optUniformIVec4 = m_sharedTestState.effect->findUniformInput("ubIVec4"); + ASSERT_TRUE(optUniformIVec4.has_value()); + + const auto optUniformVec2 = m_sharedTestState.effect->findUniformInput("ubVec2"); + ASSERT_TRUE(optUniformVec2.has_value()); + + const auto optUniformInt = m_sharedTestState.effect->findUniformInput("ubInt"); + ASSERT_TRUE(optUniformInt.has_value()); + + EXPECT_TRUE(m_appearance.setInputValue(*optUniformBool, true)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniformMat33, ramses::matrix33f{ 12.f })); + EXPECT_TRUE(m_appearance.setInputValue(*optUniformMat22, ramses::matrix22f{ 34.f })); + EXPECT_TRUE(m_appearance.setInputValue(*optUniformIVec4, ramses::vec4i{ 5, 6, 7, 8 })); + EXPECT_TRUE(m_appearance.setInputValue(*optUniformVec2, ramses::vec2f{ 9.f, 10.f })); + EXPECT_TRUE(m_appearance.setInputValue(*optUniformInt, 11)); + + bool ubBoolOut{}; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformBool, ubBoolOut)); + EXPECT_TRUE(ubBoolOut); + + ramses::matrix33f ubMat33Out; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformMat33, ubMat33Out)); + EXPECT_EQ(ramses::matrix33f{ 12.f }, ubMat33Out); + + ramses::matrix22f ubMat22Out; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformMat22, ubMat22Out)); + EXPECT_EQ(ramses::matrix22f{ 34.f }, ubMat22Out); + + ramses::vec4i ubIVec4Out; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformIVec4, ubIVec4Out)); + EXPECT_EQ(ramses::vec4i(5, 6, 7, 8), ubIVec4Out); + + ramses::vec2f ubVec2Out; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformVec2, ubVec2Out)); + EXPECT_EQ(ramses::vec2f(9.f, 10.f), ubVec2Out); + + int32_t ubIntOut = 0; + EXPECT_TRUE(m_appearance.getInputValue(*optUniformInt, ubIntOut)); + EXPECT_EQ(11, ubIntOut); + + std::vector expectedBufferValues; + BuildUniformBuffer(expectedBufferValues, bool(true)); + BuildUniformBuffer(expectedBufferValues, std::array{}); // padding after bool to reach vec4 + BuildUniformBuffer(expectedBufferValues, glm::mat3x4{ 12.f }); + BuildUniformBuffer(expectedBufferValues, glm::mat2x4{ 34.f }); + BuildUniformBuffer(expectedBufferValues, glm::ivec4{ 5, 6, 7, 8 }); + BuildUniformBuffer(expectedBufferValues, glm::vec2{ 9.f, 10.f }); + BuildUniformBuffer(expectedBufferValues, int32_t(11)); + + const auto actualUniformBufferValues(GetUniformBufferData(m_appearance, *optUniform)); + EXPECT_EQ(actualUniformBufferValues, expectedBufferValues); + } + /// Bool - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeBool) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeBool) { - const auto optUniform = sharedTestState->effect->findUniformInput("boolInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("boolInput"); ASSERT_TRUE(optUniform.has_value()); bool value = true; bool& valueR = value; const bool& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); bool getValue = false; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeBoolArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeBoolArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("boolInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("boolInputArray"); ASSERT_TRUE(optUniform.has_value()); bool values[] = {true, false, true}; bool getValues[3] = {false}; - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values)); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues)); EXPECT_EQ(values, absl::MakeSpan(getValues)); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values)); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, values)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, values)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, values)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, values)); } /// Int32 - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeInt32) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeInt32) { - const auto optUniform = sharedTestState->effect->findUniformInput("integerInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("integerInput"); ASSERT_TRUE(optUniform.has_value()); int32_t value = 42; int32_t& valueR = value; const int32_t& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); int32_t getValue = 0; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeInt32Array) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeInt32Array) { - const auto optUniform = sharedTestState->effect->findUniformInput("integerInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("integerInputArray"); ASSERT_TRUE(optUniform.has_value()); const int32_t value = 42; int32_t values[] = { value, value * 2, value * 3 }; int32_t getValues[3] = { 0 }; - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values)); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues)); EXPECT_EQ(values, absl::MakeSpan(getValues)); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values)); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, values)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, values)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, values)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, values)); } /// Float - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeFloat) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeFloat) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); ASSERT_TRUE(optUniform.has_value()); float value = 42; float& valueR = value; const float& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); float getValue = 0; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeFloatArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeFloatArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInputArray"); ASSERT_TRUE(optUniform.has_value()); const float value = 42; const float values[] = { value, value * 2, value * 3 }; float getValues[3] = { 0 }; - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values)); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues)); EXPECT_EQ(values, absl::MakeSpan(getValues)); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values)); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues)); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues)); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector2i) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector2i) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec2iInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec2iInput"); ASSERT_TRUE(optUniform.has_value()); vec2i value{ 42, 24 }; vec2i& valueR = value; const vec2i& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); vec2i getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector2iArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector2iArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec2iInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec2iInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = { vec2i{42, 43}, vec2i{44, 45}, vec2i{46, 47} }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector3i) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector3i) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec3iInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec3iInput"); ASSERT_TRUE(optUniform.has_value()); vec3i value{ 42, 24, 4422 }; vec3i& valueR = value; const vec3i& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); vec3i getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector3iArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector3iArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec3iInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec3iInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = { vec3i{42, 43, 444}, vec3i{44, 45, 555}, vec3i{46, 47, 666} }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector4i) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector4i) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec4iInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec4iInput"); ASSERT_TRUE(optUniform.has_value()); vec4i value{ 42, 24, 44, 22 }; vec4i& valueR = value; const vec4i& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); vec4i getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector4iArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector4iArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec4iInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec4iInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = { vec4i{42, 43, 444, 555}, vec4i{44, 45, 666, 777}, vec4i{46, 47, 888, 999} }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector2f) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector2f) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec2fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec2fInput"); ASSERT_TRUE(optUniform.has_value()); vec2f value{ 42.f, 24.f }; vec2f& valueR = value; const vec2f& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); vec2f getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector2fArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector2fArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec2fInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec2fInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = { vec2f{42.f, 43.f}, vec2f{44.f, 45.f}, vec2f{46.f, 47.f} }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector3f) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector3f) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec3fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec3fInput"); ASSERT_TRUE(optUniform.has_value()); vec3f value{ 42.f, 24.f, 44.f }; vec3f& valueR = value; const vec3f& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); vec3f getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector3fArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector3fArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec3fInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec3fInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = { vec3f{42.f, 43.f, 444.f}, vec3f{44.f, 45.f, 666.f}, vec3f{46.f, 47.f, 888.f} }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector4f) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector4f) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec4fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec4fInput"); ASSERT_TRUE(optUniform.has_value()); vec4f value{ 42.f, 24.f, 44.f, 55.f }; vec4f& valueR = value; const vec4f& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); vec4f getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeVector4fArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeVector4fArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec4fInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec4fInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = { vec4f{42.f, 43.f, 444.f, 555.f}, vec4f{44.f, 45.f, 666.f, 777.f}, vec4f{46.f, 47.f, 888.f, 999.f} }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } /// matrix22f - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeMatrix22f) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeMatrix22f) { - const auto optUniform = sharedTestState->effect->findUniformInput("matrix22fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("matrix22fInput"); ASSERT_TRUE(optUniform.has_value()); matrix22f value{ 42.f, 43.f, 44.f, 45.f }; matrix22f& valueR = value; const matrix22f& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); matrix22f getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeMatrix22fArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeMatrix22fArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("matrix22fInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("matrix22fInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = @@ -828,39 +937,39 @@ namespace ramses::internal }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } /// Matrix33f - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeMatrix33f) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeMatrix33f) { - const auto optUniform = sharedTestState->effect->findUniformInput("matrix33fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("matrix33fInput"); ASSERT_TRUE(optUniform.has_value()); matrix33f value{ 42.f, 43.f, 44.f, 45.f, 46.f, 47.f, 48.f, 49.f, 50.f }; matrix33f& valueR = value; const matrix33f& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); matrix33f getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeMatrix33fArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeMatrix33fArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("matrix33fInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("matrix33fInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = @@ -871,39 +980,39 @@ namespace ramses::internal }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } /// Matrix44f - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeMatrix44f) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeMatrix44f) { - const auto optUniform = sharedTestState->effect->findUniformInput("matrix44fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("matrix44fInput"); ASSERT_TRUE(optUniform.has_value()); matrix44f value{ 42.f, 43.f, 44.f, 45.f, 46.f, 47.f, 48.f, 49.f, 50.f, 51.f, 52.f, 53.f, 54.f, 55.f, 56.f, 57.f }; matrix44f& valueR = value; const matrix44f& valueCR = value; auto valueM = value; - EXPECT_TRUE(appearance->setInputValue(*optUniform, value)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, valueCR)); - EXPECT_TRUE(appearance->setInputValue(*optUniform, std::move(valueM))); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, valueCR)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, std::move(valueM))); matrix44f getValue; - EXPECT_TRUE(appearance->getInputValue(*optUniform, getValue)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, getValue)); EXPECT_EQ(value, getValue); } - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeMatrix44fArray) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeMatrix44fArray) { - const auto optUniform = sharedTestState->effect->findUniformInput("matrix44fInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("matrix44fInputArray"); ASSERT_TRUE(optUniform.has_value()); const std::vector values = @@ -914,231 +1023,258 @@ namespace ramses::internal }; std::vector getValues(values.size()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 3u, values.data())); - EXPECT_TRUE(appearance->getInputValue(*optUniform, 3u, getValues.data())); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 3u, values.data())); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, 3u, getValues.data())); EXPECT_EQ(values, getValues); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 0u, values.data())); - EXPECT_FALSE(appearance->setInputValue(*optUniform, 11u, values.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 0u, getValues.data())); - EXPECT_FALSE(appearance->getInputValue(*optUniform, 11u, getValues.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 0u, values.data())); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, 11u, values.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 0u, getValues.data())); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, 11u, getValues.data())); } /// Texture2D - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeTexture2D) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeTexture2D) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dInput"); ASSERT_TRUE(optUniform.has_value()); const std::vector mipData{ { std::byte{1}, std::byte{2}, std::byte{3} } }; - Texture2D* texture = sharedTestState->getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); + Texture2D* texture = m_sharedTestState.getScene().createTexture2D(ETextureFormat::RGB8, 1u, 1u, mipData, false); ASSERT_TRUE(texture != nullptr); - ramses::TextureSampler* textureSampler = sharedTestState->getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); + ramses::TextureSampler* textureSampler = m_sharedTestState.getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Linear, *texture); ASSERT_TRUE(textureSampler != nullptr); - EXPECT_TRUE(appearance->setInputTexture(*optUniform, *textureSampler)); + EXPECT_TRUE(m_appearance.setInputTexture(*optUniform, *textureSampler)); const ramses::TextureSampler* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTexture(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTexture(*optUniform, actualSampler)); EXPECT_EQ(textureSampler, actualSampler); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureSampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureSampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture)); } /// Texture2DMS - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeTexture2DMS) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeTexture2DMS) { - const auto optUniform = sharedTestState->effect->findUniformInput("texture2dMSInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("texture2dMSInput"); ASSERT_TRUE(optUniform.has_value()); - ramses::RenderBuffer* renderBuffer = sharedTestState->getScene().createRenderBuffer(2u, 2u, ERenderBufferFormat::RGB8, ERenderBufferAccessMode::ReadWrite, 4u); - TextureSamplerMS* textureSampler = sharedTestState->getScene().createTextureSamplerMS(*renderBuffer, "renderBuffer"); + ramses::RenderBuffer* renderBuffer = m_sharedTestState.getScene().createRenderBuffer(2u, 2u, ERenderBufferFormat::RGB8, ERenderBufferAccessMode::ReadWrite, 4u); + TextureSamplerMS* textureSampler = m_sharedTestState.getScene().createTextureSamplerMS(*renderBuffer, "renderBuffer"); ASSERT_TRUE(textureSampler != nullptr); EXPECT_EQ(textureSampler->impl().getTextureDataType(), ramses::internal::EDataType::TextureSampler2DMS); - EXPECT_TRUE(appearance->setInputTexture(*optUniform, *textureSampler)); + EXPECT_TRUE(m_appearance.setInputTexture(*optUniform, *textureSampler)); const TextureSamplerMS* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTextureMS(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTextureMS(*optUniform, actualSampler)); EXPECT_EQ(textureSampler, actualSampler); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureSampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*renderBuffer)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureSampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*renderBuffer)); } /// TextureCube - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeTextureCube) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeTextureCube) { - const auto optUniform = sharedTestState->effect->findUniformInput("textureCubeInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("textureCubeInput"); ASSERT_TRUE(optUniform.has_value()); const std::vector texData = { std::byte{1}, std::byte{2}, std::byte{3} }; std::vector mipData{ { texData, texData, texData, texData, texData, texData } }; - TextureCube* texture = sharedTestState->getScene().createTextureCube(ETextureFormat::RGB8, 1u, mipData, false); + TextureCube* texture = m_sharedTestState.getScene().createTextureCube(ETextureFormat::RGB8, 1u, mipData, false); ASSERT_TRUE(texture != nullptr); - ramses::TextureSampler* textureSampler = sharedTestState->getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Linear, ETextureSamplingMethod::Linear, *texture); + ramses::TextureSampler* textureSampler = m_sharedTestState.getScene().createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Linear, ETextureSamplingMethod::Linear, *texture); ASSERT_TRUE(textureSampler != nullptr); - EXPECT_TRUE(appearance->setInputTexture(*optUniform, *textureSampler)); + EXPECT_TRUE(m_appearance.setInputTexture(*optUniform, *textureSampler)); const ramses::TextureSampler* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTexture(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTexture(*optUniform, actualSampler)); EXPECT_EQ(textureSampler, actualSampler); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureSampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureSampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture)); } /// TextureExternal - TEST_F(AAppearanceTest, canHandleUniformInputsOfTypeTextureExternal) + TEST_P(AAppearanceTest, canHandleUniformInputsOfTypeTextureExternal) { - const auto optUniform = sharedTestState->effect->findUniformInput("textureExternalInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("textureExternalInput"); ASSERT_TRUE(optUniform.has_value()); - TextureSamplerExternal* textureSampler = sharedTestState->getScene().createTextureSamplerExternal(ETextureSamplingMethod::Linear, ETextureSamplingMethod::Linear); + TextureSamplerExternal* textureSampler = m_sharedTestState.getScene().createTextureSamplerExternal(ETextureSamplingMethod::Linear, ETextureSamplingMethod::Linear); ASSERT_TRUE(textureSampler != nullptr); EXPECT_EQ(textureSampler->impl().getTextureDataType(), ramses::internal::EDataType::TextureSamplerExternal); - EXPECT_TRUE(appearance->setInputTexture(*optUniform, *textureSampler)); + EXPECT_TRUE(m_appearance.setInputTexture(*optUniform, *textureSampler)); const TextureSamplerExternal* actualSampler = nullptr; - EXPECT_TRUE(appearance->getInputTextureExternal(*optUniform, actualSampler)); + EXPECT_TRUE(m_appearance.getInputTextureExternal(*optUniform, actualSampler)); EXPECT_EQ(textureSampler, actualSampler); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureSampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureSampler)); } /// Binding data objects - TEST_F(AAppearanceTest, uniformInputIsNotBoundInitially) + TEST_P(AAppearanceTest, uniformInputIsNotBoundInitially) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); ASSERT_TRUE(optUniform.has_value()); - EXPECT_FALSE(appearance->isInputBound(*optUniform)); + EXPECT_FALSE(m_appearance.isInputBound(*optUniform)); } - TEST_F(AAppearanceTest, canBindDataObjectToUniformInput) + TEST_P(AAppearanceTest, canBindDataObjectToUniformInput) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); ASSERT_TRUE(optUniform.has_value()); - auto dataObject = sharedTestState->getScene().createDataObject(ramses::EDataType::Float); + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Float); ASSERT_TRUE(dataObject != nullptr); - EXPECT_TRUE(appearance->bindInput(*optUniform, *dataObject)); - EXPECT_TRUE(appearance->isInputBound(*optUniform)); - EXPECT_EQ(dataObject->impl().getDataReference(), appearance->getDataObjectBoundToInput(*optUniform)->impl().getDataReference()); + EXPECT_TRUE(m_appearance.bindInput(*optUniform, *dataObject)); + EXPECT_TRUE(m_appearance.isInputBound(*optUniform)); + EXPECT_EQ(dataObject->impl().getDataReference(), m_appearance.getDataObjectBoundToInput(*optUniform)->impl().getDataReference()); - EXPECT_TRUE(appearance->unbindInput(*optUniform)); - EXPECT_FALSE(appearance->isInputBound(*optUniform)); - EXPECT_EQ(nullptr, appearance->getDataObjectBoundToInput(*optUniform)); + EXPECT_TRUE(m_appearance.unbindInput(*optUniform)); + EXPECT_FALSE(m_appearance.isInputBound(*optUniform)); + EXPECT_EQ(nullptr, m_appearance.getDataObjectBoundToInput(*optUniform)); } - TEST_F(AAppearanceTest, failsToSetOrGetValueIfInputBound) + TEST_P(AAppearanceTest, failsToSetOrGetValueIfInputBound) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); ASSERT_TRUE(optUniform.has_value()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 666.f)); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 666.f)); - auto dataObject = sharedTestState->getScene().createDataObject(ramses::EDataType::Float); + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Float); ASSERT_TRUE(dataObject != nullptr); dataObject->setValue(333.f); - EXPECT_TRUE(appearance->bindInput(*optUniform, *dataObject)); + EXPECT_TRUE(m_appearance.bindInput(*optUniform, *dataObject)); const float setValue = 0.111f; float value = 0.f; - EXPECT_FALSE(appearance->setInputValue(*optUniform, setValue)); + EXPECT_FALSE(m_appearance.setInputValue(*optUniform, setValue)); EXPECT_TRUE(dataObject->getValue(value)); EXPECT_FLOAT_EQ(333.f, value); // failed setter does not modify data object value = 0.f; - EXPECT_FALSE(appearance->getInputValue(*optUniform, value)); + EXPECT_FALSE(m_appearance.getInputValue(*optUniform, value)); EXPECT_FLOAT_EQ(0.f, value); // failed getter does not modify out parameter - EXPECT_TRUE(appearance->unbindInput(*optUniform)); + EXPECT_TRUE(m_appearance.unbindInput(*optUniform)); - EXPECT_TRUE(appearance->getInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, value)); EXPECT_EQ(666.f, value); // failed setter did not modify previously set value } - TEST_F(AAppearanceTest, failsToBindDataObjectToArrayUniformInput) + TEST_P(AAppearanceTest, failsToBindDataObjectToArrayUniformInput) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInputArray"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInputArray"); ASSERT_TRUE(optUniform.has_value()); - auto dataObject = sharedTestState->getScene().createDataObject(ramses::EDataType::Float); + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Float); ASSERT_TRUE(dataObject != nullptr); - EXPECT_FALSE(appearance->bindInput(*optUniform, *dataObject)); + EXPECT_FALSE(m_appearance.bindInput(*optUniform, *dataObject)); } - TEST_F(AAppearanceTest, failsToBindDataObjectFromADifferentScene) + TEST_P(AAppearanceTest, failsToBindDataObjectFromADifferentScene) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); ASSERT_TRUE(optUniform.has_value()); - ramses::Scene& anotherScene = *sharedTestState->getClient().createScene(sceneId_t(1u)); + ramses::Scene& anotherScene = *m_sharedTestState.getClient().createScene(sceneId_t(1u)); auto dataObject = anotherScene.createDataObject(ramses::EDataType::Float); ASSERT_TRUE(dataObject != nullptr); - EXPECT_FALSE(appearance->bindInput(*optUniform, *dataObject)); + EXPECT_FALSE(m_appearance.bindInput(*optUniform, *dataObject)); - EXPECT_TRUE(sharedTestState->getClient().destroy(anotherScene)); + EXPECT_TRUE(m_sharedTestState.getClient().destroy(anotherScene)); } - TEST_F(AAppearanceTest, failsToBindDataObjectOfMismatchingType) + TEST_P(AAppearanceTest, failsToBindDataObjectOfMismatchingType) { - const auto optUniform = sharedTestState->effect->findUniformInput("vec4fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("vec4fInput"); ASSERT_TRUE(optUniform.has_value()); - auto dataObject = sharedTestState->getScene().createDataObject(ramses::EDataType::Float); + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Float); ASSERT_TRUE(dataObject != nullptr); - EXPECT_FALSE(appearance->bindInput(*optUniform, *dataObject)); - EXPECT_FALSE(appearance->isInputBound(*optUniform)); + EXPECT_FALSE(m_appearance.bindInput(*optUniform, *dataObject)); + EXPECT_FALSE(m_appearance.isInputBound(*optUniform)); } - TEST_F(AAppearanceTestWithSemanticUniforms, failsToBindDataObjectIfInputHasSemantics) + TEST_P(AAppearanceTest, failsToBindDataObjectIfInputHasSemantics) { - const auto optUniform = sharedTestState->effect->findUniformInput("matrix44fInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("mvMatrix"); ASSERT_TRUE(optUniform.has_value()); - auto dataObject = sharedTestState->getScene().createDataObject(ramses::EDataType::Matrix44F); + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Matrix44F); ASSERT_TRUE(dataObject != nullptr); - EXPECT_FALSE(appearance->bindInput(*optUniform, *dataObject)); + EXPECT_FALSE(m_appearance.bindInput(*optUniform, *dataObject)); } - TEST_F(AAppearanceTest, unbindingDataObjectFallsBackToPreviouslySetValue) + TEST_P(AAppearanceTest, failsToCreateDataObjectFromUniformBuffer) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const auto optUniform = m_sharedTestState.effect->findUniformInput("uniformBlock"); ASSERT_TRUE(optUniform.has_value()); - EXPECT_TRUE(appearance->setInputValue(*optUniform, 666.f)); - auto dataObject = sharedTestState->getScene().createDataObject(ramses::EDataType::Float); + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::UniformBuffer); + EXPECT_EQ(dataObject, nullptr); + } + + TEST_P(AAppearanceTest, failsToBindDataObjectToUniformBufferField) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const auto optUniform = m_sharedTestState.effect->findUniformInput("uniformBlock.ubMat44"); + ASSERT_TRUE(optUniform.has_value()); + + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Matrix44F); ASSERT_TRUE(dataObject != nullptr); - EXPECT_TRUE(appearance->bindInput(*optUniform, *dataObject)); + EXPECT_FALSE(m_appearance.bindInput(*optUniform, *dataObject)); + EXPECT_FALSE(m_appearance.isInputBound(*optUniform)); + } + + TEST_P(AAppearanceTest, unbindingDataObjectFallsBackToPreviouslySetValue) + { + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); + ASSERT_TRUE(optUniform.has_value()); + EXPECT_TRUE(m_appearance.setInputValue(*optUniform, 666.f)); + + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Float); + ASSERT_TRUE(dataObject != nullptr); + + EXPECT_TRUE(m_appearance.bindInput(*optUniform, *dataObject)); dataObject->setValue(13.f); - EXPECT_TRUE(appearance->unbindInput(*optUniform)); + EXPECT_TRUE(m_appearance.unbindInput(*optUniform)); float value = 0.f; - EXPECT_TRUE(appearance->getInputValue(*optUniform, value)); + EXPECT_TRUE(m_appearance.getInputValue(*optUniform, value)); EXPECT_FLOAT_EQ(666.f, value); } - TEST_F(AAppearanceTest, failsToUnbindIfInputIsNotBound) + TEST_P(AAppearanceTest, failsToUnbindIfInputIsNotBound) { - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); ASSERT_TRUE(optUniform.has_value()); - EXPECT_FALSE(appearance->unbindInput(*optUniform)); + EXPECT_FALSE(m_appearance.unbindInput(*optUniform)); } /// Validation - TEST_F(AAppearanceTest, reportsErrorWhenValidatedWithInvalidTextureSampler) + TEST_P(AAppearanceTest, reportsErrorWhenValidatedWithInvalidTextureSampler) { TextureInputInfo texture2DInputInfo; GetTexture2DInputInfo(texture2DInputInfo); @@ -1155,7 +1291,7 @@ namespace ramses::internal TextureInputInfo textureExternalInfo; GetTextureExternalInputInfo(textureExternalInfo); - Appearance* newAppearance = sharedTestState->getScene().createAppearance(*sharedTestState->effect, "New Appearance"); + Appearance* newAppearance = m_sharedTestState.getScene().createAppearance(*m_sharedTestState.effect, "New Appearance"); ASSERT_TRUE(nullptr != newAppearance); EXPECT_TRUE(newAppearance->setInputTexture(*texture2DInputInfo.input, *texture2DInputInfo.sampler)); @@ -1167,20 +1303,20 @@ namespace ramses::internal newAppearance->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DInputInfo.sampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DMSInputInfo.samplerMS)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DInputInfo.sampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DMSInputInfo.samplerMS)); report.clear(); newAppearance->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*newAppearance)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DInputInfo.texture2D)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DMSInputInfo.renderBuffer)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureCubeInputInfo.sampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureCubeInputInfo.textureCube)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*newAppearance)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DInputInfo.texture2D)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DMSInputInfo.renderBuffer)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureCubeInputInfo.sampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureCubeInputInfo.textureCube)); } - TEST_F(AAppearanceTest, reportsErrorWhenValidatedWithInvalidTexture) + TEST_P(AAppearanceTest, reportsErrorWhenValidatedWithInvalidTexture) { TextureInputInfo texture2DInputInfo; GetTexture2DInputInfo(texture2DInputInfo); @@ -1197,7 +1333,7 @@ namespace ramses::internal TextureInputInfo textureExternalInfo; GetTextureExternalInputInfo(textureExternalInfo); - Appearance* newAppearance = sharedTestState->getScene().createAppearance(*sharedTestState->effect, "New Appearance"); + Appearance* newAppearance = m_sharedTestState.getScene().createAppearance(*m_sharedTestState.effect, "New Appearance"); ASSERT_TRUE(nullptr != newAppearance); EXPECT_TRUE(newAppearance->setInputTexture(*texture2DInputInfo.input, *texture2DInputInfo.sampler)); EXPECT_TRUE(newAppearance->setInputTexture(*texture2DMSInputInfo.input, *texture2DMSInputInfo.samplerMS)); @@ -1208,20 +1344,20 @@ namespace ramses::internal newAppearance->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DInputInfo.texture2D)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DMSInputInfo.renderBuffer)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DInputInfo.texture2D)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DMSInputInfo.renderBuffer)); report.clear(); newAppearance->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*newAppearance)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DInputInfo.sampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DMSInputInfo.samplerMS)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureCubeInputInfo.sampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureCubeInputInfo.textureCube)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*newAppearance)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DInputInfo.sampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DMSInputInfo.samplerMS)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureCubeInputInfo.sampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureCubeInputInfo.textureCube)); } - TEST_F(AAppearanceTest, reportsErrorWhenValidatedWithBoundDataObjectThatWasDestroyed) + TEST_P(AAppearanceTest, reportsErrorWhenValidatedWithBoundDataObjectThatWasDestroyed) { TextureInputInfo texture2DInputInfo; GetTexture2DInputInfo(texture2DInputInfo); @@ -1238,7 +1374,7 @@ namespace ramses::internal TextureInputInfo textureExternalInfo; GetTextureExternalInputInfo(textureExternalInfo); - Appearance* newAppearance = sharedTestState->getScene().createAppearance(*sharedTestState->effect, "New Appearance"); + Appearance* newAppearance = m_sharedTestState.getScene().createAppearance(*m_sharedTestState.effect, "New Appearance"); ASSERT_TRUE(nullptr != newAppearance); EXPECT_TRUE(newAppearance->setInputTexture(*texture2DInputInfo.input, *texture2DInputInfo.sampler)); EXPECT_TRUE(newAppearance->setInputTexture(*texture2DMSInputInfo.input, *texture2DMSInputInfo.samplerMS)); @@ -1249,10 +1385,10 @@ namespace ramses::internal newAppearance->validate(report); EXPECT_FALSE(report.hasIssue()); - const auto optUniform = sharedTestState->effect->findUniformInput("floatInput"); + const auto optUniform = m_sharedTestState.effect->findUniformInput("floatInput"); ASSERT_TRUE(optUniform.has_value()); - auto dataObject = sharedTestState->getScene().createDataObject(ramses::EDataType::Float); + auto dataObject = m_sharedTestState.getScene().createDataObject(ramses::EDataType::Float); ASSERT_TRUE(dataObject != nullptr); EXPECT_TRUE(newAppearance->bindInput(*optUniform, *dataObject)); @@ -1260,45 +1396,45 @@ namespace ramses::internal newAppearance->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*dataObject)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*dataObject)); report.clear(); newAppearance->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*newAppearance)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DInputInfo.sampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DInputInfo.texture2D)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DMSInputInfo.samplerMS)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*texture2DMSInputInfo.renderBuffer)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureCubeInputInfo.sampler)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*textureCubeInputInfo.textureCube)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*newAppearance)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DInputInfo.sampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DInputInfo.texture2D)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DMSInputInfo.samplerMS)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*texture2DMSInputInfo.renderBuffer)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureCubeInputInfo.sampler)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*textureCubeInputInfo.textureCube)); } - TEST_F(AAppearanceTest, failsWhenWrongBlendingOperationsSet) + TEST_P(AAppearanceTest, failsWhenWrongBlendingOperationsSet) { - bool stat = appearance->setBlendingOperations(EBlendOperation::Subtract, EBlendOperation::ReverseSubtract); + bool stat = m_appearance.setBlendingOperations(EBlendOperation::Subtract, EBlendOperation::ReverseSubtract); EXPECT_TRUE(stat); - stat = appearance->setBlendingOperations(EBlendOperation::Add, EBlendOperation::Disabled); + stat = m_appearance.setBlendingOperations(EBlendOperation::Add, EBlendOperation::Disabled); EXPECT_FALSE(stat); - stat = appearance->setBlendingOperations(EBlendOperation::Disabled, EBlendOperation::Add); + stat = m_appearance.setBlendingOperations(EBlendOperation::Disabled, EBlendOperation::Add); EXPECT_FALSE(stat); EBlendOperation opColor = EBlendOperation::Disabled; EBlendOperation opAlpha = EBlendOperation::Disabled; - EXPECT_TRUE(appearance->getBlendingOperations(opColor, opAlpha)); + EXPECT_TRUE(m_appearance.getBlendingOperations(opColor, opAlpha)); EXPECT_EQ(EBlendOperation::Subtract, opColor); EXPECT_EQ(EBlendOperation::ReverseSubtract, opAlpha); } - TEST_F(AAppearanceTest, defaultBlendingFactors) + TEST_P(AAppearanceTest, defaultBlendingFactors) { EBlendFactor srcColor = EBlendFactor::Zero; EBlendFactor destColor = EBlendFactor::Zero; EBlendFactor srcAlpha = EBlendFactor::Zero; EBlendFactor destAlpha = EBlendFactor::Zero; - bool stat = appearance->getBlendingFactors(srcColor, destColor, srcAlpha, destAlpha); + bool stat = m_appearance.getBlendingFactors(srcColor, destColor, srcAlpha, destAlpha); EXPECT_TRUE(stat); EXPECT_EQ(EBlendFactor::SrcAlpha, srcColor); EXPECT_EQ(EBlendFactor::OneMinusSrcAlpha, destColor); @@ -1306,255 +1442,259 @@ namespace ramses::internal EXPECT_EQ(EBlendFactor::One, destAlpha); } - TEST_F(AAppearanceTest, defaultDepthWriteMode) + TEST_P(AAppearanceTest, defaultDepthWriteMode) { EDepthWrite depthWriteMode = EDepthWrite::Disabled; - EXPECT_TRUE(appearance->getDepthWriteMode(depthWriteMode)); + EXPECT_TRUE(m_appearance.getDepthWriteMode(depthWriteMode)); EXPECT_EQ(EDepthWrite::Enabled, depthWriteMode); } - TEST_F(AAppearanceTest, defaultScissorRegion) + TEST_P(AAppearanceTest, defaultScissorRegion) { int16_t x = std::numeric_limits::max(); int16_t y = std::numeric_limits::max(); uint16_t width = std::numeric_limits::max(); uint16_t height = std::numeric_limits::max(); - EXPECT_TRUE(appearance->getScissorRegion(x, y, width, height)); + EXPECT_TRUE(m_appearance.getScissorRegion(x, y, width, height)); EXPECT_EQ(0, x); EXPECT_EQ(0, y); EXPECT_EQ(0u, width); EXPECT_EQ(0u, height); } - TEST_F(AAppearanceTest, defaultStencilFunc) + TEST_P(AAppearanceTest, defaultStencilFunc) { EStencilFunc func = EStencilFunc::Always; uint8_t ref = std::numeric_limits::max(); uint8_t mask = std::numeric_limits::max(); - bool stat = appearance->getStencilFunction(func, ref, mask); + bool stat = m_appearance.getStencilFunction(func, ref, mask); EXPECT_TRUE(stat); EXPECT_EQ(EStencilFunc::Disabled, func); EXPECT_EQ(0u, ref); EXPECT_EQ(0xFF, mask); } - TEST_F(AAppearanceTest, defaultBlendingOperations) + TEST_P(AAppearanceTest, defaultBlendingOperations) { EBlendOperation opColor = EBlendOperation::Add; EBlendOperation opAlpha = EBlendOperation::Subtract; - EXPECT_TRUE(appearance->getBlendingOperations(opColor, opAlpha)); + EXPECT_TRUE(m_appearance.getBlendingOperations(opColor, opAlpha)); EXPECT_EQ(EBlendOperation::Disabled, opColor); EXPECT_EQ(EBlendOperation::Disabled, opAlpha); } - TEST_F(AAppearanceTest, defaultCullMode) + TEST_P(AAppearanceTest, defaultCullMode) { ECullMode mode = ECullMode::Disabled; - EXPECT_TRUE(appearance->getCullingMode(mode)); + EXPECT_TRUE(m_appearance.getCullingMode(mode)); EXPECT_EQ(ECullMode::BackFacing, mode); } - TEST_F(AAppearanceTest, defaultColorWriteMask) + TEST_P(AAppearanceTest, defaultColorWriteMask) { bool writeR = false; bool writeG = false; bool writeB = false; bool writeA = false; - EXPECT_TRUE(appearance->getColorWriteMask(writeR, writeG, writeB, writeA)); + EXPECT_TRUE(m_appearance.getColorWriteMask(writeR, writeG, writeB, writeA)); EXPECT_TRUE(writeR); EXPECT_TRUE(writeG); EXPECT_TRUE(writeB); EXPECT_TRUE(writeA); } - TEST_F(AAppearanceTest, defaultGetInputValue) + TEST_P(AAppearanceTest, defaultGetInputValue) { { auto intOut = std::numeric_limits::max(); - auto uniformItegerInput = sharedTestState->effect->findUniformInput("integerInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformItegerInput, intOut)); + auto uniformItegerInput = m_sharedTestState.effect->findUniformInput("integerInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformItegerInput, intOut)); EXPECT_EQ(intOut, 0); } { auto floatOut = std::numeric_limits::max(); - auto uniformFloatInput = sharedTestState->effect->findUniformInput("floatInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformFloatInput, floatOut)); + auto uniformFloatInput = m_sharedTestState.effect->findUniformInput("floatInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformFloatInput, floatOut)); EXPECT_FLOAT_EQ(floatOut, 0.0f); } { vec2i vec2iOut(42); - auto uniformVec2iInput = sharedTestState->effect->findUniformInput("vec2iInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformVec2iInput, vec2iOut)); + auto uniformVec2iInput = m_sharedTestState.effect->findUniformInput("vec2iInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformVec2iInput, vec2iOut)); EXPECT_EQ(vec2iOut.x, 0); EXPECT_EQ(vec2iOut.y, 0); } { vec3i vec3iOut(42); - auto uniformVec3iInput = sharedTestState->effect->findUniformInput("vec3iInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformVec3iInput, vec3iOut)); + auto uniformVec3iInput = m_sharedTestState.effect->findUniformInput("vec3iInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformVec3iInput, vec3iOut)); EXPECT_EQ(vec3iOut, vec3i{0}); } { vec4i vec4iOut(42); - auto uniformVec4iInput = sharedTestState->effect->findUniformInput("vec4iInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformVec4iInput, vec4iOut)); + auto uniformVec4iInput = m_sharedTestState.effect->findUniformInput("vec4iInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformVec4iInput, vec4iOut)); EXPECT_EQ(vec4iOut, vec4i{0}); } { vec2f vec2fOut(42.f); - auto uniformVec2fInput = sharedTestState->effect->findUniformInput("vec2fInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformVec2fInput, vec2fOut)); + auto uniformVec2fInput = m_sharedTestState.effect->findUniformInput("vec2fInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformVec2fInput, vec2fOut)); EXPECT_EQ(vec2fOut, vec2f{0.f}); } { vec3f vec3fOut(42.f); - auto uniformVec3fInput = sharedTestState->effect->findUniformInput("vec3fInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformVec3fInput, vec3fOut)); + auto uniformVec3fInput = m_sharedTestState.effect->findUniformInput("vec3fInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformVec3fInput, vec3fOut)); EXPECT_EQ(vec3fOut, vec3f{0.f}); } { vec4f vec4fOut(42.f); - auto uniformVec4fInput = sharedTestState->effect->findUniformInput("vec4fInput"); - EXPECT_TRUE(appearance->getInputValue(*uniformVec4fInput, vec4fOut)); + auto uniformVec4fInput = m_sharedTestState.effect->findUniformInput("vec4fInput"); + EXPECT_TRUE(m_appearance.getInputValue(*uniformVec4fInput, vec4fOut)); EXPECT_EQ(vec4fOut, vec4f{0.f}); } { - auto uniformMatrix22fInput = sharedTestState->effect->findUniformInput("matrix22fInput"); + auto uniformMatrix22fInput = m_sharedTestState.effect->findUniformInput("matrix22fInput"); matrix22f matrix22fOut = {42, 43, 44, 45}; - EXPECT_TRUE(appearance->getInputValue(*uniformMatrix22fInput, matrix22fOut)); + EXPECT_TRUE(m_appearance.getInputValue(*uniformMatrix22fInput, matrix22fOut)); for (const auto& i : matrix22fOut) EXPECT_FLOAT_EQ(i, 0.0f); } { - auto uniformMatrix33fInput = sharedTestState->effect->findUniformInput("matrix33fInput"); + auto uniformMatrix33fInput = m_sharedTestState.effect->findUniformInput("matrix33fInput"); matrix33f matrix33fOut = {42, 43, 44, 45, 46, 47, 48, 49, 50}; - EXPECT_TRUE(appearance->getInputValue(*uniformMatrix33fInput, matrix33fOut)); + EXPECT_TRUE(m_appearance.getInputValue(*uniformMatrix33fInput, matrix33fOut)); for (const auto& i : matrix33fOut) EXPECT_FLOAT_EQ(i, 0.0f); } { - auto uniformMatrix44fInput = sharedTestState->effect->findUniformInput("matrix44fInput"); + auto uniformMatrix44fInput = m_sharedTestState.effect->findUniformInput("matrix44fInput"); matrix44f matrix44fOut = {42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57}; - EXPECT_TRUE(appearance->getInputValue(*uniformMatrix44fInput, matrix44fOut)); + EXPECT_TRUE(m_appearance.getInputValue(*uniformMatrix44fInput, matrix44fOut)); for (const auto& i : matrix44fOut) EXPECT_FLOAT_EQ(i, 0.0f); } { - auto integerInputArrayInput = sharedTestState->effect->findUniformInput("integerInputArray"); + auto integerInputArrayInput = m_sharedTestState.effect->findUniformInput("integerInputArray"); int32_t integerInputArray[] = {42, 42, 42}; - EXPECT_TRUE(appearance->getInputValue(*integerInputArrayInput, 3u, integerInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*integerInputArrayInput, 3u, integerInputArray)); for (const auto& i : integerInputArray) EXPECT_EQ(i, 0); } { - auto floatInputArrayInput = sharedTestState->effect->findUniformInput("floatInputArray"); + auto floatInputArrayInput = m_sharedTestState.effect->findUniformInput("floatInputArray"); float floatInputArray[] = {42, 42, 42}; - EXPECT_TRUE(appearance->getInputValue(*floatInputArrayInput, 3u, floatInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*floatInputArrayInput, 3u, floatInputArray)); for (const auto& i : floatInputArray) EXPECT_FLOAT_EQ(i, 0.0f); } { - auto vec2iInputArrayInput = sharedTestState->effect->findUniformInput("vec2iInputArray"); + auto vec2iInputArrayInput = m_sharedTestState.effect->findUniformInput("vec2iInputArray"); vec2i vec2iInputArray[] = {vec2i{42, 43}, vec2i{44, 45}, vec2i{46, 47}}; - EXPECT_TRUE(appearance->getInputValue(*vec2iInputArrayInput, 3u, vec2iInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*vec2iInputArrayInput, 3u, vec2iInputArray)); for (const auto& i : vec2iInputArray) EXPECT_EQ(i, vec2i{0}); } { - auto vec3iInputArrayInput = sharedTestState->effect->findUniformInput("vec3iInputArray"); + auto vec3iInputArrayInput = m_sharedTestState.effect->findUniformInput("vec3iInputArray"); vec3i vec3iInputArray[] = {vec3i{42, 43, 44}, vec3i{45, 46, 47}, vec3i{48, 49, 50}}; - EXPECT_TRUE(appearance->getInputValue(*vec3iInputArrayInput, 3u, vec3iInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*vec3iInputArrayInput, 3u, vec3iInputArray)); for (const auto& i : vec3iInputArray) EXPECT_EQ(i, vec3i{0}); } { - auto vec4iInputArrayInput = sharedTestState->effect->findUniformInput("vec4iInputArray"); + auto vec4iInputArrayInput = m_sharedTestState.effect->findUniformInput("vec4iInputArray"); vec4i vec4iInputArray[] = {vec4i{42, 43, 44, 45}, vec4i{46, 47, 48, 49}, vec4i{50, 51, 52, 53}}; - EXPECT_TRUE(appearance->getInputValue(*vec4iInputArrayInput, 3u, vec4iInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*vec4iInputArrayInput, 3u, vec4iInputArray)); for (const auto& i : vec4iInputArray) EXPECT_EQ(i, vec4i{0}); } { - auto vec2fInputArrayInput = sharedTestState->effect->findUniformInput("vec2fInputArray"); + auto vec2fInputArrayInput = m_sharedTestState.effect->findUniformInput("vec2fInputArray"); vec2f vec2fInputArray[] = {vec2f{42, 43}, vec2f{44, 45}, vec2f{46, 47}}; - EXPECT_TRUE(appearance->getInputValue(*vec2fInputArrayInput, 3u, vec2fInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*vec2fInputArrayInput, 3u, vec2fInputArray)); for (const auto& i : vec2fInputArray) EXPECT_EQ(i, vec2f{0}); } { - auto vec3fInputArrayInput = sharedTestState->effect->findUniformInput("vec3fInputArray"); + auto vec3fInputArrayInput = m_sharedTestState.effect->findUniformInput("vec3fInputArray"); vec3f vec3fInputArray[] = {vec3f{42, 43, 44}, vec3f{45, 46, 47}, vec3f{48, 49, 50}}; - EXPECT_TRUE(appearance->getInputValue(*vec3fInputArrayInput, 3u, vec3fInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*vec3fInputArrayInput, 3u, vec3fInputArray)); for (const auto& i : vec3fInputArray) EXPECT_EQ(i, vec3f{0}); } { - auto vec4fInputArrayInput = sharedTestState->effect->findUniformInput("vec4fInputArray"); + auto vec4fInputArrayInput = m_sharedTestState.effect->findUniformInput("vec4fInputArray"); vec4f vec4fInputArray[] = {vec4f{42, 43, 44, 45}, vec4f{46, 47, 48, 49}, vec4f{50, 51, 52, 53}}; - EXPECT_TRUE(appearance->getInputValue(*vec4fInputArrayInput, 3u, vec4fInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*vec4fInputArrayInput, 3u, vec4fInputArray)); for (const auto& i : vec4fInputArray) EXPECT_EQ(i, vec4f{0}); } { - auto matrix22fInputArrayInput = sharedTestState->effect->findUniformInput("matrix22fInputArray"); + auto matrix22fInputArrayInput = m_sharedTestState.effect->findUniformInput("matrix22fInputArray"); matrix22f matrix22fInputArray[3] = {{42, 43, 44, 45}, {46, 47, 48, 49}, {50, 51, 52, 53}}; - EXPECT_TRUE(appearance->getInputValue(*matrix22fInputArrayInput, 3u, matrix22fInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*matrix22fInputArrayInput, 3u, matrix22fInputArray)); for (const auto& i : matrix22fInputArray) EXPECT_EQ(i, matrix22f{0.0f}); } { - auto matrix33fInputArrayInput = sharedTestState->effect->findUniformInput("matrix33fInputArray"); + auto matrix33fInputArrayInput = m_sharedTestState.effect->findUniformInput("matrix33fInputArray"); matrix33f matrix33fInputArray[3] = {{42, 43, 44, 46, 47, 48, 50, 51, 52}, {54, 55, 56, 46, 47, 48, 42, 43, 44}, {54, 55, 56, 46, 47, 48, 50, 51, 52}}; - EXPECT_TRUE(appearance->getInputValue(*matrix33fInputArrayInput, 3u, matrix33fInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*matrix33fInputArrayInput, 3u, matrix33fInputArray)); for (const auto& i : matrix33fInputArray) EXPECT_EQ(i, matrix33f{0.0f}); } { - auto matrix44fInputArrayInput = sharedTestState->effect->findUniformInput("matrix44fInputArray"); + auto matrix44fInputArrayInput = m_sharedTestState.effect->findUniformInput("matrix44fInputArray"); matrix44f matrix44fInputArray[3] = {{42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57}, {46, 47, 48, 49, 42, 43, 44, 45, 54, 55, 56, 57, 46, 47, 48, 49}, {50, 51, 52, 53, 54, 55, 56, 57, 42, 43, 44, 45, 50, 51, 52, 53}}; - EXPECT_TRUE(appearance->getInputValue(*matrix44fInputArrayInput, 3u, matrix44fInputArray)); + EXPECT_TRUE(m_appearance.getInputValue(*matrix44fInputArrayInput, 3u, matrix44fInputArray)); for (const auto& i : matrix44fInputArray) EXPECT_EQ(i, matrix44f{0.0f}); } } - class AnAppearanceWithGeometryShader : public AAppearanceTest + class AnAppearanceWithGeometryShader : public TestWithSharedEffectPerFeatureLevel { public: - - static void SetUpTestSuite() + AnAppearanceWithGeometryShader() + : TestWithSharedEffectPerFeatureLevel{ true } { - sharedTestState = std::make_unique(false, true); } + + protected: + Appearance& m_appearance{ m_sharedTestState.recreateAppearence() }; }; - TEST_F(AnAppearanceWithGeometryShader, HasInitialDrawModeOfGeometryShadersRequirement) + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(AnAppearanceWithGeometryShader); + + TEST_P(AnAppearanceWithGeometryShader, HasInitialDrawModeOfGeometryShadersRequirement) { EDrawMode mode; - EXPECT_TRUE(appearance->getDrawMode(mode)); + EXPECT_TRUE(m_appearance.getDrawMode(mode)); EXPECT_EQ(EDrawMode::Lines, mode); } - TEST_F(AnAppearanceWithGeometryShader, RefusesToChangeDrawingMode_WhenIncompatibleToGeometryShader) + TEST_P(AnAppearanceWithGeometryShader, RefusesToChangeDrawingMode_WhenIncompatibleToGeometryShader) { // Shader uses lines, can't change to incompatible types - EXPECT_FALSE(appearance->setDrawMode(EDrawMode::Points)); - EXPECT_FALSE(appearance->setDrawMode(EDrawMode::Triangles)); - EXPECT_FALSE(appearance->setDrawMode(EDrawMode::TriangleFan)); + EXPECT_FALSE(m_appearance.setDrawMode(EDrawMode::Points)); + EXPECT_FALSE(m_appearance.setDrawMode(EDrawMode::Triangles)); + EXPECT_FALSE(m_appearance.setDrawMode(EDrawMode::TriangleFan)); EDrawMode mode; - EXPECT_TRUE(appearance->getDrawMode(mode)); + EXPECT_TRUE(m_appearance.getDrawMode(mode)); EXPECT_EQ(EDrawMode::Lines, mode); } - TEST_F(AnAppearanceWithGeometryShader, AllowsChangingDrawMode_IfNewModeIsStillCompatible) + TEST_P(AnAppearanceWithGeometryShader, AllowsChangingDrawMode_IfNewModeIsStillCompatible) { // Shader uses lines, change to line strip is ok - still produces lines for the geometry stage - EXPECT_TRUE(appearance->setDrawMode(EDrawMode::LineStrip)); + EXPECT_TRUE(m_appearance.setDrawMode(EDrawMode::LineStrip)); EDrawMode mode; - EXPECT_TRUE(appearance->getDrawMode(mode)); + EXPECT_TRUE(m_appearance.getDrawMode(mode)); EXPECT_EQ(EDrawMode::LineStrip, mode); } diff --git a/tests/unittests/client/CMakeLists.txt b/tests/unittests/client/CMakeLists.txt index 8230c550c..f25afaa92 100644 --- a/tests/unittests/client/CMakeLists.txt +++ b/tests/unittests/client/CMakeLists.txt @@ -14,30 +14,27 @@ if(ramses-sdk_TEXT_SUPPORT) text/*.cpp) endif() -if(ramses-sdk_ENABLE_LOGIC) - file(GLOB_RECURSE RAMSES_CLIENT_LOGIC_TEST_FILES - logic/*.cpp - logic/*.h - ) - - set(RAMSES_CLIENT_LOGIC_TEST_INCLUDE_DIRS - logic/shared - ) -endif() +file(GLOB_RECURSE RAMSES_CLIENT_LOGIC_TEST_FILES + logic/*.cpp + logic/*.h +) createModule( NAME ramses-client-test TYPE BINARY INCLUDE_PATHS . - ${RAMSES_CLIENT_LOGIC_TEST_INCLUDE_DIRS} + utils SRC_FILES *.h *.cpp + utils/*.h + utils/*.cpp ${RAMSES_CLIENT_TEXT_TEST_FILES} ${RAMSES_CLIENT_LOGIC_TEST_FILES} RESOURCE_FOLDERS res DEPENDENCIES ramses-client framework-test-utils ramses-gmock-main + glslang-init-gtest-env ) makeTestFromTarget( diff --git a/tests/unittests/client/ClientApplicationLogicTest.cpp b/tests/unittests/client/ClientApplicationLogicTest.cpp index 3473fa0ab..ee5b03cfb 100644 --- a/tests/unittests/client/ClientApplicationLogicTest.cpp +++ b/tests/unittests/client/ClientApplicationLogicTest.cpp @@ -29,7 +29,7 @@ namespace ramses::internal : dummyGuid(555) , logic(dummyGuid, frameworkLock) , sceneId(44u) - , dummyScene(SceneInfo(sceneId)) + , dummyScene(SceneInfo{ sceneId }) { logic.init(resourceComponent, scenegraphProviderComponent); } @@ -181,8 +181,8 @@ namespace ramses::internal { public: AClientApplicationLogicWithRealComponents() - : resComp(stats, fwlock) - , sceneComp(clientId, commSystem, connStatusUpdateNotifier, resComp, fwlock, ramses::EFeatureLevel_Latest) + : resComp(stats, fwlock, EFeatureLevel_Latest) + , sceneComp(clientId, commSystem, connStatusUpdateNotifier, resComp, fwlock, EFeatureLevel_Latest) , logic(clientId, fwlock) { logic.init(resComp, sceneComp); @@ -206,7 +206,7 @@ namespace ramses::internal TEST_F(AClientApplicationLogicWithRealComponents, keepsResourcesAliveForNewSubscriberForShadowCopyScene) { - ClientScene clientScene{ SceneInfo(sceneId) }; + ClientScene clientScene{ SceneInfo{sceneId} }; logic.createScene(clientScene, false); logic.publishScene(sceneId, EScenePublicationMode::LocalAndRemote); auto res = new TextureResource(EResourceType::Texture2D, TextureMetaInfo(1u, 1u, 1u, EPixelStorageFormat::R8, false, {}, { 1u }), {}); @@ -234,7 +234,7 @@ namespace ramses::internal TEST_F(AClientApplicationLogicWithRealComponents, keepsAlsoOldResourcesAliveForNewSubscriberForShadowCopyScene) { - ClientScene clientScene{ SceneInfo(sceneId) }; + ClientScene clientScene{ SceneInfo{sceneId} }; logic.createScene(clientScene, false); logic.publishScene(sceneId, EScenePublicationMode::LocalAndRemote); auto res = new TextureResource(EResourceType::Texture2D, TextureMetaInfo(1u, 1u, 1u, EPixelStorageFormat::R8, false, {}, { 1u }), {}); diff --git a/tests/unittests/client/DeserializationContextTest.cpp b/tests/unittests/client/DeserializationContextTest.cpp new file mode 100644 index 000000000..c6aee0b07 --- /dev/null +++ b/tests/unittests/client/DeserializationContextTest.cpp @@ -0,0 +1,74 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "impl/SerializationContext.h" +#include "impl/SceneConfigImpl.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/Core/Utils/BinaryOutputStream.h" +#include "internal/Core/Utils/BinaryInputStream.h" + +using namespace testing; + +namespace ramses::internal +{ + template + class DeserializationContextTest : public ::testing::Test + { + }; + + using HandleTypes = ::testing::Types< + RenderableHandle, + RenderStateHandle, + CameraHandle, + NodeHandle, + TransformHandle, + DataLayoutHandle, + DataInstanceHandle, + UniformBufferHandle, + TextureSamplerHandle, + RenderGroupHandle, + RenderPassHandle, + BlitPassHandle, + PickableObjectHandle, + RenderTargetHandle, + RenderBufferHandle, + DataBufferHandle, + TextureBufferHandle, + DataSlotHandle, + SceneReferenceHandle>; + + TYPED_TEST_SUITE(DeserializationContextTest, HandleTypes); + + TYPED_TEST(DeserializationContextTest, returnsMappedHandle) + { + SceneConfigImpl sceneConfigImpl; + + SceneMergeHandleMapping mapping; + TypeParam handle{42u}; + TypeParam handle2{13u}; + TypeParam mappedHandle{99u}; + mapping.addMapping(handle, mappedHandle); + DeserializationContext deserializationContext(sceneConfigImpl, &mapping); + EXPECT_NE(nullptr, deserializationContext.getSceneMergeHandleMapping()); + + // write two handles to stream + BinaryOutputStream outStream; + outStream << handle; + outStream << handle2; + + BinaryInputStream inStream(outStream.getData()); + + // deserialize mapped handle + TypeParam deserializedHandle; + deserializationContext.deserializeAndMap(inStream, deserializedHandle); + EXPECT_EQ(mappedHandle, deserializedHandle); + } +} diff --git a/tests/unittests/client/EffectDescriptionTest.cpp b/tests/unittests/client/EffectDescriptionTest.cpp index 1314c087f..482eb693d 100644 --- a/tests/unittests/client/EffectDescriptionTest.cpp +++ b/tests/unittests/client/EffectDescriptionTest.cpp @@ -23,24 +23,35 @@ namespace ramses::internal protected: EEffectUniformSemantic getSemanticForUniform(std::string_view inputName) { - EFixedSemantics* internalSemantic = effectDesc.impl().getSemanticsMap().get(std::string{inputName}); - if (internalSemantic == nullptr) + auto internalSemanticIt = effectDesc.impl().getSemanticsMap().find(std::string{inputName}); + if (internalSemanticIt == effectDesc.impl().getSemanticsMap().end()) { return EEffectUniformSemantic::Invalid; } - return EffectInputSemanticUtils::GetEffectUniformSemanticFromInternal(*internalSemantic); + return EffectInputSemanticUtils::GetEffectUniformSemanticFromInternal(internalSemanticIt->second); + } + + EEffectUniformSemantic getSemanticForUniform(UniformBufferBinding uboBinding) + { + auto internalSemanticIt = effectDesc.impl().getSemanticsMap().find(uboBinding); + if (internalSemanticIt == effectDesc.impl().getSemanticsMap().end()) + { + return EEffectUniformSemantic::Invalid; + } + + return EffectInputSemanticUtils::GetEffectUniformSemanticFromInternal(internalSemanticIt->second); } EEffectAttributeSemantic getSemanticForAttribute(std::string_view inputName) { - EFixedSemantics* internalSemantic = effectDesc.impl().getSemanticsMap().get(std::string{inputName}); - if (internalSemantic == nullptr) + auto internalSemanticIt = effectDesc.impl().getSemanticsMap().find(std::string{ inputName }); + if (internalSemanticIt == effectDesc.impl().getSemanticsMap().end()) { return EEffectAttributeSemantic::Invalid; } - return EffectInputSemanticUtils::GetEffectAttributeSemanticFromInternal(*internalSemantic); + return EffectInputSemanticUtils::GetEffectAttributeSemanticFromInternal(internalSemanticIt->second); } EffectDescription effectDesc; @@ -122,7 +133,7 @@ namespace ramses::internal TEST_F(EffectDescriptionTest, addSemanticNameAsNULLReportsError) { - EXPECT_FALSE(effectDesc.setUniformSemantic({}, EEffectUniformSemantic::ViewMatrix)); + EXPECT_FALSE(effectDesc.setUniformSemantic("", EEffectUniformSemantic::ViewMatrix)); EXPECT_EQ(0u, effectDesc.impl().getSemanticsMap().size()); } @@ -131,6 +142,7 @@ namespace ramses::internal const char* semantic1 = "my_semantic"; const char* semantic2 = "my_semantic2"; const char* semantic3 = "my_semantic3"; + const UniformBufferBinding uboBinding{ 1u }; const EEffectUniformSemantic semanticType1 = EEffectUniformSemantic::ViewMatrix; const EEffectUniformSemantic semanticType2 = EEffectUniformSemantic::ViewMatrix; const EEffectAttributeSemantic semanticType3 = EEffectAttributeSemantic::TextPositions; @@ -144,11 +156,14 @@ namespace ramses::internal EXPECT_EQ(semanticType2, getSemanticForUniform(semantic2)); EXPECT_EQ(2u, effectDesc.impl().getSemanticsMap().size()); + EXPECT_TRUE(effectDesc.setUniformSemantic(uboBinding.getValue(), EEffectUniformSemantic::ModelBlock)); + EXPECT_EQ(EEffectUniformSemantic::ModelBlock, getSemanticForUniform(uboBinding)); + EXPECT_TRUE(effectDesc.setAttributeSemantic(semantic3, semanticType3)); EXPECT_EQ(semanticType1, getSemanticForUniform(semantic1)); EXPECT_EQ(semanticType2, getSemanticForUniform(semantic2)); EXPECT_EQ(semanticType3, getSemanticForAttribute(semantic3)); - EXPECT_EQ(3u, effectDesc.impl().getSemanticsMap().size()); + EXPECT_EQ(4u, effectDesc.impl().getSemanticsMap().size()); } TEST_F(EffectDescriptionTest, retrievesUnknownTypeForSemanticNotAdded) diff --git a/tests/unittests/client/EffectInputTest.cpp b/tests/unittests/client/EffectInputTest.cpp index 04507ef58..8977d4600 100644 --- a/tests/unittests/client/EffectInputTest.cpp +++ b/tests/unittests/client/EffectInputTest.cpp @@ -17,29 +17,14 @@ #include "internal/Core/Utils/File.h" #include "internal/Core/Utils/BinaryFileOutputStream.h" #include "internal/Core/Utils/BinaryFileInputStream.h" +#include "FeatureLevelTestValues.h" using namespace testing; namespace ramses::internal { - class AnEffectInput : public ::testing::Test + class AnEffectInput : public TestWithSharedEffectPerFeatureLevel { - public: - static void SetUpTestSuite() - { - sharedTestState = std::make_unique(true); - } - - static void TearDownTestSuite() - { - sharedTestState = nullptr; - } - - void SetUp() override - { - EXPECT_TRUE(sharedTestState != nullptr); - } - protected: static void CompareInput(const EffectInput& input1, const EffectInput& input2) { @@ -49,27 +34,38 @@ namespace ramses::internal EXPECT_EQ(input1.impl().getElementCount(), input2.impl().getElementCount()); EXPECT_EQ(input1.impl().getInputIndex(), input2.impl().getInputIndex()); EXPECT_EQ(input1.impl().getEffectHash(), input2.impl().getEffectHash()); + EXPECT_EQ(input1.impl().getUniformBufferBinding(), input2.impl().getUniformBufferBinding()); + EXPECT_EQ(input1.impl().getUniformBufferFieldOffset(), input2.impl().getUniformBufferFieldOffset()); + EXPECT_EQ(input1.impl().getUniformBufferElementSize(), input2.impl().getUniformBufferElementSize()); } - static std::unique_ptr sharedTestState; + static constexpr std::array testUniformIndexValues + { + // 4=vec3, 24u=UB, 25=UB.mat44, 28u=Sampler + 4u, 24u, 25u, 28u + }; }; - std::unique_ptr AnEffectInput::sharedTestState; + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(AnEffectInput); - TEST_F(AnEffectInput, InitializedToDefaultUponCreation) + TEST_P(AnEffectInput, InitializedToDefaultUponCreation) { EffectInputImpl input; EXPECT_EQ("", input.getName()); - EXPECT_EQ(0u, input.getElementCount()); + EXPECT_EQ(std::numeric_limits::max(), input.getElementCount()); EXPECT_EQ(ramses::internal::ResourceContentHash::Invalid(), input.getEffectHash()); EXPECT_EQ(ramses::internal::EDataType::Invalid, input.getInternalDataType()); EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, input.getSemantics()); EXPECT_EQ(static_cast(-1), input.getInputIndex()); + EXPECT_FALSE(input.getUniformBufferBinding().isValid()); + EXPECT_FALSE(input.getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(input.getUniformBufferElementSize().isValid()); + } - TEST_F(AnEffectInput, UniformInputIsInitializedToGivenValues) + TEST_P(AnEffectInput, UniformInputIsInitializedToGivenValues) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; UniformInput input{ *effect->findUniformInput("texture2dInput") }; EXPECT_STREQ("texture2dInput", input.getName()); @@ -79,12 +75,15 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EDataType::TextureSampler2D, input.impl().getInternalDataType()); EXPECT_EQ(ramses::internal::EFixedSemantics::TextTexture, input.impl().getSemantics()); EXPECT_EQ(EEffectUniformSemantic::TextTexture, input.getSemantics()); - EXPECT_EQ(24u, input.impl().getInputIndex()); + EXPECT_EQ((GetParam() < EFeatureLevel_02 ? 25u : 38u), input.impl().getInputIndex()); + EXPECT_FALSE(input.impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(input.impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(input.impl().getUniformBufferElementSize().isValid()); } - TEST_F(AnEffectInput, AttributeInputIsInitializedToGivenValues) + TEST_P(AnEffectInput, AttributeInputIsInitializedToGivenValues) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; AttributeInput input{ *effect->getAttributeInput(1u) }; EXPECT_STREQ("vec2fArrayInput", input.getName()); @@ -94,9 +93,12 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EFixedSemantics::TextPositionsAttribute, input.impl().getSemantics()); EXPECT_EQ(EEffectAttributeSemantic::TextPositions, input.getSemantics()); EXPECT_EQ(1u, input.impl().getInputIndex()); + EXPECT_FALSE(input.impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(input.impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(input.impl().getUniformBufferElementSize().isValid()); } - TEST_F(AnEffectInput, ReturnsCorrectDataType) + TEST_P(AnEffectInput, ReturnsCorrectDataType) { const ramses::internal::ResourceContentHash effectHash(1u, 0); const std::string inputName("test"); @@ -104,135 +106,145 @@ namespace ramses::internal const size_t index = 66u; EffectInputImpl input; - input.initialize(effectHash, inputName, ramses::internal::EDataType::UInt16, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::UInt16, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::UInt16); - input.initialize(effectHash, inputName, ramses::internal::EDataType::UInt32, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::UInt32, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::UInt32); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Bool, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Bool, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Bool); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Int32, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Int32, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Int32); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Vector2I, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Vector2I, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Vector2I); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Vector3I, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Vector3I, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Vector3I); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Vector4I, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Vector4I, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Vector4I); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Float, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Float, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Float); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Vector2F, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Vector2F, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Vector2F); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Vector3F, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Vector3F, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Vector3F); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Vector4F, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Vector4F, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Vector4F); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Matrix22F, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Matrix22F, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Matrix22F); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Matrix33F, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Matrix33F, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Matrix33F); - input.initialize(effectHash, inputName, ramses::internal::EDataType::Matrix44F, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::Matrix44F, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::Matrix44F); - input.initialize(effectHash, inputName, ramses::internal::EDataType::TextureSampler2D, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::TextureSampler2D, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::TextureSampler2D); - input.initialize(effectHash, inputName, ramses::internal::EDataType::TextureSampler2DMS, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::TextureSampler2DMS, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::TextureSampler2DMS); - input.initialize(effectHash, inputName, ramses::internal::EDataType::TextureSampler3D, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::TextureSampler3D, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::TextureSampler3D); - input.initialize(effectHash, inputName, ramses::internal::EDataType::TextureSamplerCube, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::TextureSamplerCube, semantics }, index); EXPECT_EQ(input.getDataType(), ramses::EDataType::TextureSamplerCube); - input.initialize(effectHash, inputName, ramses::internal::EDataType::TextureSamplerExternal, semantics, 1u, index); + input.initialize(effectHash, EffectInputInformation{ inputName, 1u, ramses::internal::EDataType::TextureSamplerExternal, semantics }, index); + EXPECT_EQ(input.getDataType(), ramses::EDataType::TextureSamplerExternal); } - TEST_F(AnEffectInput, CanBeCopyAndMoveConstructed_Uniform) + TEST_P(AnEffectInput, CanBeCopyAndMoveConstructed_Uniform) { - const auto creference = sharedTestState->effect->getUniformInput(5u); - UniformInput inputCopy{*creference}; - CompareInput(inputCopy, *creference); + for (const auto uniformIdx : testUniformIndexValues) + { + const auto creference = m_sharedTestState.effect->getUniformInput(uniformIdx); + UniformInput inputCopy{ *creference }; + CompareInput(inputCopy, *creference); - auto reference = sharedTestState->effect->getUniformInput(5u); - UniformInput inputMove{std::move(*reference)}; - CompareInput(inputMove, *creference); + auto reference = m_sharedTestState.effect->getUniformInput(uniformIdx); + UniformInput inputMove{ std::move(*reference) }; + CompareInput(inputMove, *creference); + } } - TEST_F(AnEffectInput, CanBeCopyAndMoveAssigned_Uniform) + TEST_P(AnEffectInput, CanBeCopyAndMoveAssigned_Uniform) { - const auto creference = sharedTestState->effect->getUniformInput(4u); - UniformInput inputCopy{*sharedTestState->effect->getUniformInput(5u)}; - inputCopy = *creference; - CompareInput(inputCopy, *creference); - - auto reference = sharedTestState->effect->getUniformInput(4u); - UniformInput inputMove{std::move(*sharedTestState->effect->getUniformInput(5u))}; - inputMove = std::move(*reference); - CompareInput(inputMove, *creference); + for (const auto uniformIdx : testUniformIndexValues) + { + const auto creference = m_sharedTestState.effect->getUniformInput(uniformIdx); + UniformInput inputCopy{ *m_sharedTestState.effect->getUniformInput(5) }; + inputCopy = *creference; + CompareInput(inputCopy, *creference); + + auto reference = m_sharedTestState.effect->getUniformInput(uniformIdx); + UniformInput inputMove{ std::move(*m_sharedTestState.effect->getUniformInput(5)) }; + inputMove = std::move(*reference); + CompareInput(inputMove, *creference); + } } - TEST_F(AnEffectInput, CanBeSelfAssigned_Uniform) + TEST_P(AnEffectInput, CanBeSelfAssigned_Uniform) { - const auto reference = sharedTestState->effect->getUniformInput(5u); - UniformInput input{*reference}; + for (const auto uniformIdx : testUniformIndexValues) + { + const auto reference = m_sharedTestState.effect->getUniformInput(uniformIdx); + UniformInput input{ *reference }; #ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wself-move" #pragma clang diagnostic ignored "-Wself-assign-overloaded" #endif - input = input; - CompareInput(input, *reference); + input = input; + CompareInput(input, *reference); - input = std::move(input); - // NOLINTNEXTLINE(bugprone-use-after-move) - CompareInput(input, *reference); + input = std::move(input); + // NOLINTNEXTLINE(bugprone-use-after-move) + CompareInput(input, *reference); #ifdef __clang__ #pragma clang diagnostic pop #endif + } } - TEST_F(AnEffectInput, CanBeCopyAndMoveConstructed_Attribute) + TEST_P(AnEffectInput, CanBeCopyAndMoveConstructed_Attribute) { - const auto creference = sharedTestState->effect->getAttributeInput(1u); + const auto creference = m_sharedTestState.effect->getAttributeInput(1u); AttributeInput inputCopy{*creference}; CompareInput(inputCopy, *creference); - auto reference = sharedTestState->effect->getAttributeInput(1u); + auto reference = m_sharedTestState.effect->getAttributeInput(1u); AttributeInput inputMove{std::move(*reference)}; CompareInput(inputMove, *creference); } - TEST_F(AnEffectInput, CanBeCopyAndMoveAssigned_Attribute) + TEST_P(AnEffectInput, CanBeCopyAndMoveAssigned_Attribute) { - const auto creference = sharedTestState->effect->getAttributeInput(1u); - AttributeInput inputCopy{*sharedTestState->effect->getAttributeInput(2u)}; + const auto creference = m_sharedTestState.effect->getAttributeInput(1u); + AttributeInput inputCopy{*m_sharedTestState.effect->getAttributeInput(2u)}; inputCopy = *creference; CompareInput(inputCopy, *creference); - auto reference = sharedTestState->effect->getAttributeInput(1u); - AttributeInput inputMove{*sharedTestState->effect->getAttributeInput(2u)}; + auto reference = m_sharedTestState.effect->getAttributeInput(1u); + AttributeInput inputMove{*m_sharedTestState.effect->getAttributeInput(2u)}; inputMove = std::move(*reference); CompareInput(inputMove, *creference); } - TEST_F(AnEffectInput, CanBeSelfAssigned_Attribute) + TEST_P(AnEffectInput, CanBeSelfAssigned_Attribute) { - const auto reference = sharedTestState->effect->getAttributeInput(1u); + const auto reference = m_sharedTestState.effect->getAttributeInput(1u); AttributeInput input{*reference}; #ifdef __clang__ diff --git a/tests/unittests/client/EffectTest.cpp b/tests/unittests/client/EffectTest.cpp index be52d2a7f..d29d807df 100644 --- a/tests/unittests/client/EffectTest.cpp +++ b/tests/unittests/client/EffectTest.cpp @@ -12,107 +12,82 @@ #include "ramses/client/UniformInput.h" #include "ramses/client/AttributeInput.h" #include "impl/EffectInputImpl.h" +#include "FeatureLevelTestValues.h" #include "gtest/gtest.h" using namespace testing; namespace ramses::internal { - class AnEffect : public ::testing::Test + class AnEffect : public TestWithSharedEffectPerFeatureLevel { - public: - static void SetUpTestSuite() - { - sharedTestState = std::make_unique(); - } - - static void TearDownTestSuite() - { - sharedTestState = nullptr; - } - - void SetUp() override - { - EXPECT_TRUE(sharedTestState != nullptr); - } - - static std::unique_ptr sharedTestState; }; - std::unique_ptr AnEffect::sharedTestState; - - class AnEffectWithSemantics : public AnEffect - { - public: - static void SetUpTestSuite() - { - sharedTestState = std::make_unique(true); - } - }; + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(AnEffect); - TEST_F(AnEffect, hasProperNumberOfInputs) + TEST_P(AnEffect, hasProperNumberOfInputs) { - const Effect* effect = sharedTestState->effect; - EXPECT_EQ(29u, effect->getUniformInputCount()); + const Effect* effect = m_sharedTestState.effect; + EXPECT_EQ((GetParam() < EFeatureLevel_02 ? 30u : 43u), effect->getUniformInputCount()); EXPECT_EQ(4u, effect->getAttributeInputCount()); } - TEST_F(AnEffect, hasNoGeometryShaderWhenNotCreatedWithSuch) + TEST_P(AnEffect, hasNoGeometryShaderWhenNotCreatedWithSuch) { - EXPECT_FALSE(sharedTestState->effect->hasGeometryShader()); + EXPECT_FALSE(m_sharedTestState.effect->hasGeometryShader()); } - TEST_F(AnEffect, reportsErrorWhenAskedForGeometryInputType_ButNoGeometryShaderProvided) + TEST_P(AnEffect, reportsErrorWhenAskedForGeometryInputType_ButNoGeometryShaderProvided) { EDrawMode mode; - EXPECT_FALSE(sharedTestState->effect->getGeometryShaderInputType(mode)); + EXPECT_FALSE(m_sharedTestState.effect->getGeometryShaderInputType(mode)); } - TEST_F(AnEffect, reportsErrorWhenAskingForNonExistingUniformInput) + TEST_P(AnEffect, reportsErrorWhenAskingForNonExistingUniformInput) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->getUniformInput(99u); EXPECT_FALSE(optInput.has_value()); } - TEST_F(AnEffect, reportsErrorWhenAskingForNonExistingAttributeInput) + TEST_P(AnEffect, reportsErrorWhenAskingForNonExistingAttributeInput) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->getAttributeInput(99u); EXPECT_FALSE(optInput.has_value()); } - TEST_F(AnEffect, reportsErrorWhenAskingForNonExistingUniformName) + TEST_P(AnEffect, reportsErrorWhenAskingForNonExistingUniformName) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findUniformInput("xxx"); EXPECT_FALSE(optInput.has_value()); } - TEST_F(AnEffect, reportsErrorWhenAskingForNonExistingAttributeName) + TEST_P(AnEffect, reportsErrorWhenAskingForNonExistingAttributeName) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findAttributeInput("xxx"); EXPECT_FALSE(optInput.has_value()); } - TEST_F(AnEffect, reportsErrorWhenAskingForNonExistingUniformSemantic) + TEST_P(AnEffect, reportsErrorWhenAskingForNonExistingUniformSemantic) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findUniformInput(EEffectUniformSemantic::NormalMatrix); EXPECT_FALSE(optInput.has_value()); } - TEST_F(AnEffect, reportsErrorWhenAskingForNonExistingAttributeSemantic) + TEST_P(AnEffect, reportsErrorWhenAskingForNonExistingAttributeSemantic) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findAttributeInput(EEffectAttributeSemantic::Invalid); EXPECT_FALSE(optInput.has_value()); } - TEST_F(AnEffect, getsUniformInputByIndex) + TEST_P(AnEffect, getsUniformInputByIndex) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->getUniformInput(5u); ASSERT_TRUE(optInput.has_value()); @@ -124,41 +99,142 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); EXPECT_EQ(5u, optInput->impl().getInputIndex()); + EXPECT_FALSE(optInput->impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferElementSize().isValid()); + } + + TEST_P(AnEffect, getsUniformInputByIndex_UniformBuffer) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->getUniformInput(24u); + ASSERT_TRUE(optInput.has_value()); + + EXPECT_STREQ("uniformBlock", optInput->getName()); + EXPECT_EQ(1u, optInput->getElementCount()); + EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::UniformBuffer, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); + EXPECT_EQ(24u, optInput->impl().getInputIndex()); + EXPECT_EQ(optInput->impl().getUniformBufferBinding().getValue(), 1u); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_EQ(optInput->impl().getUniformBufferElementSize().getValue(), 160u); + } + + TEST_P(AnEffect, getsUniformInputByIndex_UniformBufferField) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->getUniformInput(26u); + ASSERT_TRUE(optInput.has_value()); + + EXPECT_STREQ("uniformBlock.ubFloat", optInput->getName()); + EXPECT_EQ(3u, optInput->getElementCount()); + EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); + EXPECT_EQ(ramses::EDataType::Float, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::Float, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); + EXPECT_EQ(26u, optInput->impl().getInputIndex()); + EXPECT_EQ(optInput->impl().getUniformBufferBinding().getValue(), 1u); + EXPECT_EQ(optInput->impl().getUniformBufferFieldOffset().getValue(), 64u); + EXPECT_EQ(optInput->impl().getUniformBufferElementSize().getValue(), 16u); + } + + TEST_P(AnEffect, getsUniformInputByIndex_AnonymousUniformBuffer) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->getUniformInput(28u); + ASSERT_TRUE(optInput.has_value()); + + EXPECT_STREQ("anon@ubo_binding=2", optInput->getName()); + EXPECT_EQ(1u, optInput->getElementCount()); + EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::UniformBuffer, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); + EXPECT_EQ(28u, optInput->impl().getInputIndex()); + EXPECT_EQ(optInput->impl().getUniformBufferBinding().getValue(), 2u); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_EQ(optInput->impl().getUniformBufferElementSize().getValue(), 124u); } - TEST_F(AnEffectWithSemantics, findsUniformInputBySemantic) + TEST_P(AnEffect, getsUniformInputByIndex_AnonymousUniformBufferField) { - const Effect* effect = sharedTestState->effect; + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->getUniformInput(30u); + ASSERT_TRUE(optInput.has_value()); + + EXPECT_STREQ("ubMat33", optInput->getName()); + EXPECT_EQ(1u, optInput->getElementCount()); + EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); + EXPECT_EQ(ramses::EDataType::Matrix33F, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::Matrix33F, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); + EXPECT_EQ(30u, optInput->impl().getInputIndex()); + EXPECT_EQ(optInput->impl().getUniformBufferBinding().getValue(), 2u); + EXPECT_EQ(optInput->impl().getUniformBufferFieldOffset().getValue(), 16u); // mat33 has vec4 alignment + EXPECT_EQ(optInput->impl().getUniformBufferElementSize().getValue(), 48u); + } + + TEST_P(AnEffect, findsUniformInputBySemantic) + { + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findUniformInput(EEffectUniformSemantic::ModelViewMatrix); ASSERT_TRUE(optInput.has_value()); - EXPECT_STREQ("matrix44fInput", optInput->getName()); + EXPECT_STREQ("mvMatrix", optInput->getName()); EXPECT_EQ(1u, optInput->getElementCount()); EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); EXPECT_EQ(ramses::EDataType::Matrix44F, optInput->getDataType()); EXPECT_EQ(ramses::internal::EDataType::Matrix44F, optInput->impl().getInternalDataType()); EXPECT_EQ(ramses::internal::EFixedSemantics::ModelViewMatrix, optInput->impl().getSemantics()); EXPECT_EQ(EEffectUniformSemantic::ModelViewMatrix, optInput->getSemantics()); + EXPECT_FALSE(optInput->impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferElementSize().isValid()); } - TEST_F(AnEffect, getsAttributeInputByIndex) + TEST_P(AnEffect, findsUniformInputBySemantic_UniformBlock) { - const Effect* effect = sharedTestState->effect; - const std::optional optInput = effect->getAttributeInput(1u); + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->findUniformInput(EEffectUniformSemantic::ModelBlock); ASSERT_TRUE(optInput.has_value()); - EXPECT_STREQ("vec2fArrayInput", optInput->getName()); + EXPECT_STREQ("ubWithSemantics", optInput->getName()); + EXPECT_EQ(1u, optInput->getElementCount()); EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); - EXPECT_EQ(ramses::EDataType::Vector2F, optInput->getDataType()); - EXPECT_EQ(ramses::internal::EDataType::Vector2Buffer, optInput->impl().getInternalDataType()); - EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); - EXPECT_EQ(EEffectAttributeSemantic::Invalid, optInput->getSemantics()); - EXPECT_EQ(1u, optInput->impl().getInputIndex()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::UniformBuffer, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::ModelBlock, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::ModelBlock, optInput->getSemantics()); + EXPECT_EQ(35u, optInput->impl().getInputIndex()); + EXPECT_EQ(3u, optInput->impl().getUniformBufferBinding().getValue()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_EQ(64u, optInput->impl().getUniformBufferElementSize().getValue()); } - TEST_F(AnEffectWithSemantics, getsAttributeInputByIndex) + TEST_P(AnEffect, getsAttributeInputByIndex) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->getAttributeInput(1u); ASSERT_TRUE(optInput.has_value()); @@ -169,11 +245,14 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EFixedSemantics::TextPositionsAttribute, optInput->impl().getSemantics()); EXPECT_EQ(EEffectAttributeSemantic::TextPositions, optInput->getSemantics()); EXPECT_EQ(1u, optInput->impl().getInputIndex()); + EXPECT_FALSE(optInput->impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferElementSize().isValid()); } - TEST_F(AnEffectWithSemantics, findsAttributeInputBySemantic) + TEST_P(AnEffect, findsAttributeInputBySemantic) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findAttributeInput(EEffectAttributeSemantic::TextPositions); ASSERT_TRUE(optInput.has_value()); @@ -183,11 +262,14 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EDataType::Vector2Buffer, optInput->impl().getInternalDataType()); EXPECT_EQ(ramses::internal::EFixedSemantics::TextPositionsAttribute, optInput->impl().getSemantics()); EXPECT_EQ(EEffectAttributeSemantic::TextPositions, optInput->getSemantics()); + EXPECT_FALSE(optInput->impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferElementSize().isValid()); } - TEST_F(AnEffect, findsUniformInputByName) + TEST_P(AnEffect, findsUniformInputByName) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findUniformInput("vec3fInputArray"); ASSERT_TRUE(optInput.has_value()); @@ -199,11 +281,87 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); EXPECT_EQ(5u, optInput->impl().getInputIndex()); + EXPECT_FALSE(optInput->impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferElementSize().isValid()); + } + + TEST_P(AnEffect, findsUniformInputByName_UniformBuffer) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->findUniformInput("uniformBlock"); + ASSERT_TRUE(optInput.has_value()); + + EXPECT_STREQ("uniformBlock", optInput->getName()); + EXPECT_EQ(1u, optInput->getElementCount()); + EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::UniformBuffer, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); + EXPECT_EQ(24u, optInput->impl().getInputIndex()); + EXPECT_EQ(optInput->impl().getUniformBufferBinding().getValue(), 1u); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_EQ(optInput->impl().getUniformBufferElementSize().getValue(), 160u); + } + + TEST_P(AnEffect, findsUniformInputByName_UniformBufferField) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->findUniformInput("uniformBlock.ubMat33"); + ASSERT_TRUE(optInput.has_value()); + + EXPECT_STREQ("uniformBlock.ubMat33", optInput->getName()); + EXPECT_EQ(1u, optInput->getElementCount()); + EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); + EXPECT_EQ(ramses::EDataType::Matrix33F, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::Matrix33F, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); + EXPECT_EQ(27u, optInput->impl().getInputIndex()); + EXPECT_EQ(optInput->impl().getUniformBufferBinding().getValue(), 1u); + EXPECT_EQ(optInput->impl().getUniformBufferFieldOffset().getValue(), 112u); + EXPECT_EQ(optInput->impl().getUniformBufferElementSize().getValue(), 48u); } - TEST_F(AnEffect, findsAllTextureTypesOfUniformInputByName) + TEST_P(AnEffect, findsUniformInputByLayoutBinding) { - const Effect* effect = sharedTestState->effect; + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->findUniformInputAtBinding(1u); + ASSERT_TRUE(optInput.has_value()); + + EXPECT_STREQ("uniformBlock", optInput->getName()); + EXPECT_EQ(1u, optInput->getElementCount()); + EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, optInput->getDataType()); + EXPECT_EQ(ramses::internal::EDataType::UniformBuffer, optInput->impl().getInternalDataType()); + EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); + EXPECT_EQ(EEffectUniformSemantic::Invalid, optInput->getSemantics()); + EXPECT_EQ(24u, optInput->impl().getInputIndex()); + EXPECT_EQ(optInput->getUniformBufferBinding(), 1u); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_EQ(optInput->impl().getUniformBufferElementSize().getValue(), 160u); + } + + TEST_P(AnEffect, reportsErrorWhenAskingForNonExistingUniformBufferBinding) + { + const Effect* effect = m_sharedTestState.effect; + const std::optional optInput = effect->findUniformInputAtBinding(999u); + EXPECT_FALSE(optInput.has_value()); + } + + TEST_P(AnEffect, findsAllTextureTypesOfUniformInputByName) + { + const Effect* effect = m_sharedTestState.effect; const std::optional optInput2d = effect->findUniformInput("texture2dInput"); const std::optional optInput3d = effect->findUniformInput("texture3dInput"); const std::optional optInputcube = effect->findUniformInput("textureCubeInput"); @@ -219,24 +377,9 @@ namespace ramses::internal EXPECT_EQ(ramses::EDataType::TextureSamplerExternal, optInputExternalTexture->getDataType()); } - TEST_F(AnEffect, findsAttributeInputByName) + TEST_P(AnEffect, findsAttributeInputByName) { - const Effect* effect = sharedTestState->effect; - const std::optional optInput = effect->findAttributeInput("vec2fArrayInput"); - ASSERT_TRUE(optInput.has_value()); - - EXPECT_STREQ("vec2fArrayInput", optInput->getName()); - EXPECT_EQ(effect->impl().getLowlevelResourceHash(), optInput->impl().getEffectHash()); - EXPECT_EQ(ramses::EDataType::Vector2F, optInput->getDataType()); - EXPECT_EQ(ramses::internal::EDataType::Vector2Buffer, optInput->impl().getInternalDataType()); - EXPECT_EQ(ramses::internal::EFixedSemantics::Invalid, optInput->impl().getSemantics()); - EXPECT_EQ(EEffectAttributeSemantic::Invalid, optInput->getSemantics()); - EXPECT_EQ(1u, optInput->impl().getInputIndex()); - } - - TEST_F(AnEffectWithSemantics, findsAttributeInputByName) - { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); @@ -247,11 +390,14 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EFixedSemantics::TextPositionsAttribute, optInput->impl().getSemantics()); EXPECT_EQ(EEffectAttributeSemantic::TextPositions, optInput->getSemantics()); EXPECT_EQ(1u, optInput->impl().getInputIndex()); + EXPECT_FALSE(optInput->impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferElementSize().isValid()); } - TEST_F(AnEffectWithSemantics, findsTextureInputWithSemantics) + TEST_P(AnEffect, findsTextureInputWithSemantics) { - const Effect* effect = sharedTestState->effect; + const Effect* effect = m_sharedTestState.effect; const std::optional optInput = effect->findUniformInput("texture2dInput"); ASSERT_TRUE(optInput.has_value()); @@ -261,10 +407,13 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EDataType::TextureSampler2D, optInput->impl().getInternalDataType()); EXPECT_EQ(ramses::internal::EFixedSemantics::TextTexture, optInput->impl().getSemantics()); EXPECT_EQ(EEffectUniformSemantic::TextTexture, optInput->getSemantics()); - EXPECT_EQ(24u, optInput->impl().getInputIndex()); + EXPECT_EQ((GetParam() < EFeatureLevel_02 ? 25u : 38u), optInput->impl().getInputIndex()); + EXPECT_FALSE(optInput->impl().getUniformBufferBinding().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferFieldOffset().isValid()); + EXPECT_FALSE(optInput->impl().getUniformBufferElementSize().isValid()); } - TEST_F(AnEffect, canNotCreateEffectWhenTextPositionsSemanticsHasWrongType) + TEST_P(AnEffect, canNotCreateEffectWhenTextPositionsSemanticsHasWrongType) { EffectDescription effectDesc; effectDesc.setVertexShader( @@ -282,15 +431,87 @@ namespace ramses::internal "}"); /// Can create ... - EXPECT_NE(static_cast(nullptr), sharedTestState->getScene().impl().createEffect(effectDesc, "")); + EXPECT_NE(static_cast(nullptr), m_sharedTestState.getScene().createEffect(effectDesc, "")); effectDesc.setAttributeSemantic("a_position", EEffectAttributeSemantic::TextPositions); /// Can not create ... - EXPECT_EQ(static_cast(nullptr), sharedTestState->getScene().impl().createEffect(effectDesc, "")); + EXPECT_EQ(static_cast(nullptr), m_sharedTestState.getScene().createEffect(effectDesc, "")); + } + + TEST_P(AnEffect, canNotCreateEffectWhenSettingSemanticOnUniformBufferField) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + EffectDescription effectDesc; + effectDesc.setVertexShader( + "#version 320 es\n" + "precision highp float;" + "in vec3 a_position;" + "layout(std140,binding=1) uniform ub_t { mat4 ubMat4; } uniformBlock;" + "void main()" + "{" + " gl_Position = uniformBlock.ubMat4 * vec4(1.0);" + "}"); + effectDesc.setFragmentShader( + "#version 320 es\n" + "precision highp float;" + "out vec4 fragColor;" + "void main(void)\n" + "{" + " fragColor = vec4(1.0, 1.0, 1.0, 1.0);" + "}"); + + /// Can create ... + EXPECT_NE(nullptr, m_sharedTestState.getScene().createEffect(effectDesc, "")); + + effectDesc.setUniformSemantic("uniformBlock.ubMat4", EEffectUniformSemantic::ModelViewProjectionMatrix); + + /// Can not create ... + EXPECT_EQ(nullptr, m_sharedTestState.getScene().createEffect(effectDesc, "")); + + EXPECT_THAT(m_sharedTestState.getScene().getLastEffectErrorMessages(), + ::testing::HasSubstr("uniformBlock.ubMat4: can not have semantic because it is declared in a uniform block")); } - TEST_F(AnEffect, canRetrieveGLSLErrorMessageFromClient) + TEST_P(AnEffect, canNotCreateEffectWhenSettingSemanticOnUniformBuffer) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + EffectDescription effectDesc; + effectDesc.setVertexShader( + "#version 320 es\n" + "precision highp float;" + "in vec3 a_position;" + "layout(std140,binding=1) uniform ub_t { float ubFloat; } uniformBlock;" + "void main()" + "{" + " gl_Position = vec4(uniformBlock.ubFloat, 1.0, 1.0, 1.0);" + "}"); + effectDesc.setFragmentShader( + "#version 320 es\n" + "precision highp float;" + "out vec4 fragColor;" + "void main(void)\n" + "{" + " fragColor = vec4(1.0, 1.0, 1.0, 1.0);" + "}"); + + /// Can create ... + EXPECT_NE(nullptr, m_sharedTestState.getScene().createEffect(effectDesc, "")); + + effectDesc.setUniformSemantic("uniformBlock", EEffectUniformSemantic::ModelViewProjectionMatrix); + + /// Can not create ... + EXPECT_EQ(nullptr, m_sharedTestState.getScene().createEffect(effectDesc, "")); + + EXPECT_THAT(m_sharedTestState.getScene().getLastEffectErrorMessages(), + ::testing::HasSubstr("uniformBlock: input type DATATYPE_UNIFORMBUFFER not compatible with semantic EFixedSemantics::ModelViewProjectionMatrix")); + } + + TEST_P(AnEffect, canRetrieveGLSLErrorMessageFromClient) { EffectDescription effectDesc; @@ -306,10 +527,10 @@ namespace ramses::internal "{" " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);" "}"); - const Effect* effect = sharedTestState->getScene().createEffect(effectDesc); + const Effect* effect = m_sharedTestState.getScene().createEffect(effectDesc); EXPECT_EQ(nullptr, effect); using namespace ::testing; - EXPECT_THAT(sharedTestState->getScene().getLastEffectErrorMessages(), + EXPECT_THAT(m_sharedTestState.getScene().getLastEffectErrorMessages(), AnyOf(Eq("[GLSL Compiler] vertex shader Shader Parsing Error:\n" "ERROR: 2:5: '' : syntax error\n" "ERROR: 1 compilation errors. No code generated.\n\n\n"), @@ -318,7 +539,7 @@ namespace ramses::internal "ERROR: 1 compilation errors. No code generated.\n\n\n"))); } - TEST_F(AnEffect, clientDeletesEffectErrorMessagesOfLastEffect) + TEST_P(AnEffect, clientDeletesEffectErrorMessagesOfLastEffect) { EffectDescription effectDesc; @@ -333,9 +554,9 @@ namespace ramses::internal "{" " gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);" "}"); - const Effect* effect1 = sharedTestState->getScene().createEffect(effectDesc); + const Effect* effect1 = m_sharedTestState.getScene().createEffect(effectDesc); EXPECT_EQ(nullptr, effect1); - EXPECT_NE("", sharedTestState->getScene().getLastEffectErrorMessages()); + EXPECT_NE("", m_sharedTestState.getScene().getLastEffectErrorMessages()); effectDesc.setVertexShader("#version 100\n" "attribute float inp;\n" @@ -344,12 +565,12 @@ namespace ramses::internal " gl_Position = vec4(0.0)\n;" "}\n"); - const Effect* effect2 = sharedTestState->getScene().createEffect(effectDesc); + const Effect* effect2 = m_sharedTestState.getScene().createEffect(effectDesc); EXPECT_NE(nullptr, effect2); - EXPECT_EQ("", sharedTestState->getScene().getLastEffectErrorMessages()); + EXPECT_EQ("", m_sharedTestState.getScene().getLastEffectErrorMessages()); } - TEST_F(AnEffect, canNotCreateEffectWhenTextTextureCoordinatesSemanticsHasWrongType) + TEST_P(AnEffect, canNotCreateEffectWhenTextTextureCoordinatesSemanticsHasWrongType) { EffectDescription effectDesc; effectDesc.setVertexShader( @@ -367,15 +588,15 @@ namespace ramses::internal "}"); /// Can create ... - EXPECT_NE(static_cast(nullptr), sharedTestState->getScene().impl().createEffect(effectDesc, "")); + EXPECT_NE(static_cast(nullptr), m_sharedTestState.getScene().createEffect(effectDesc, "")); effectDesc.setAttributeSemantic("a_texcoord", EEffectAttributeSemantic::TextTextureCoordinates); /// Can not create ... - EXPECT_EQ(static_cast(nullptr), sharedTestState->getScene().impl().createEffect(effectDesc, "")); + EXPECT_EQ(static_cast(nullptr), m_sharedTestState.getScene().createEffect(effectDesc, "")); } - TEST_F(AnEffect, canNotCreateEffectWhenTextTextureSemanticsHasWrongType) + TEST_P(AnEffect, canNotCreateEffectWhenTextTextureSemanticsHasWrongType) { EffectDescription effectDesc; effectDesc.setVertexShader( @@ -393,15 +614,15 @@ namespace ramses::internal "}"); /// Can create ... - EXPECT_NE(static_cast(nullptr), sharedTestState->getScene().impl().createEffect(effectDesc, "")); + EXPECT_NE(static_cast(nullptr), m_sharedTestState.getScene().createEffect(effectDesc, "")); effectDesc.setUniformSemantic("u_texture", EEffectUniformSemantic::TextTexture); /// Can not create ... - EXPECT_EQ(static_cast(nullptr), sharedTestState->getScene().impl().createEffect(effectDesc, "")); + EXPECT_EQ(static_cast(nullptr), m_sharedTestState.getScene().createEffect(effectDesc, "")); } - TEST_F(AnEffect, supportsBoolUniforms) + TEST_P(AnEffect, supportsBoolUniforms) { const char* vertShader = R"SHADER( #version 320 es @@ -430,16 +651,16 @@ namespace ramses::internal effectDesc.setVertexShader(vertShader); effectDesc.setFragmentShader(fragShader); - const Effect* effect = sharedTestState->getScene().createEffect(effectDesc); + const Effect* effect = m_sharedTestState.getScene().createEffect(effectDesc); - EXPECT_EQ("", sharedTestState->getScene().getLastEffectErrorMessages()); + EXPECT_EQ("", m_sharedTestState.getScene().getLastEffectErrorMessages()); ASSERT_NE(nullptr, effect); const std::optional optUniform = effect->findUniformInput("u_theBool"); ASSERT_TRUE(optUniform.has_value()); - Appearance* appearance = sharedTestState->getScene().createAppearance(*effect); + Appearance* appearance = m_sharedTestState.getScene().createAppearance(*effect); ASSERT_NE(nullptr, appearance); EXPECT_TRUE(appearance->setInputValue(*optUniform, true)); @@ -448,7 +669,6 @@ namespace ramses::internal class AnEffectWithGeometryShader : public AnEffect { protected: - const char* m_vertShader = R"SHADER( #version 320 es void main(void) @@ -466,7 +686,9 @@ namespace ramses::internal })SHADER"; }; - TEST_F(AnEffectWithGeometryShader, providesExpectedGeometryInputType_Points) + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(AnEffectWithGeometryShader); + + TEST_P(AnEffectWithGeometryShader, providesExpectedGeometryInputType_Points) { EffectDescription effectDesc; effectDesc.setVertexShader(m_vertShader); @@ -481,7 +703,7 @@ namespace ramses::internal } )SHADER"); - Effect* effect = sharedTestState->getScene().createEffect(effectDesc); + Effect* effect = m_sharedTestState.getScene().createEffect(effectDesc); ASSERT_NE(nullptr, effect); EXPECT_TRUE(effect->hasGeometryShader()); @@ -490,7 +712,7 @@ namespace ramses::internal EXPECT_EQ(geometryShaderInput, EDrawMode::Points); } - TEST_F(AnEffectWithGeometryShader, providesExpectedGeometryInputType_Lines) + TEST_P(AnEffectWithGeometryShader, providesExpectedGeometryInputType_Lines) { EffectDescription effectDesc; effectDesc.setVertexShader(m_vertShader); @@ -505,7 +727,7 @@ namespace ramses::internal } )SHADER"); - Effect* effect = sharedTestState->getScene().createEffect(effectDesc); + Effect* effect = m_sharedTestState.getScene().createEffect(effectDesc); ASSERT_NE(nullptr, effect); EXPECT_TRUE(effect->hasGeometryShader()); EDrawMode geometryShaderInput; @@ -513,7 +735,7 @@ namespace ramses::internal EXPECT_EQ(geometryShaderInput, EDrawMode::Lines); } - TEST_F(AnEffectWithGeometryShader, providesExpectedGeometryInputType_Triangles) + TEST_P(AnEffectWithGeometryShader, providesExpectedGeometryInputType_Triangles) { EffectDescription effectDesc; effectDesc.setVertexShader(m_vertShader); @@ -528,14 +750,14 @@ namespace ramses::internal } )SHADER"); - Effect* effect = sharedTestState->getScene().createEffect(effectDesc); + Effect* effect = m_sharedTestState.getScene().createEffect(effectDesc); ASSERT_NE(nullptr, effect); EDrawMode geometryShaderInput; EXPECT_TRUE(effect->getGeometryShaderInputType(geometryShaderInput)); EXPECT_EQ(geometryShaderInput, EDrawMode::Triangles); } - TEST_F(AnEffectWithGeometryShader, providesExpectedGeometryInputType_whenMultipleIdenticalEffectsCreated) + TEST_P(AnEffectWithGeometryShader, providesExpectedGeometryInputType_whenMultipleIdenticalEffectsCreated) { EffectDescription effectDesc; effectDesc.setVertexShader(m_vertShader); @@ -550,8 +772,8 @@ namespace ramses::internal } )SHADER"); - Effect* effect1 = sharedTestState->getScene().createEffect(effectDesc); - Effect* effect2 = sharedTestState->getScene().createEffect(effectDesc); + Effect* effect1 = m_sharedTestState.getScene().createEffect(effectDesc); + Effect* effect2 = m_sharedTestState.getScene().createEffect(effectDesc); ASSERT_NE(nullptr, effect1); ASSERT_NE(nullptr, effect2); EDrawMode geometryShaderInput; @@ -561,7 +783,7 @@ namespace ramses::internal EXPECT_EQ(geometryShaderInput, EDrawMode::Triangles); } - TEST_F(AnEffect, sceneValiadationProducesShaderWarnings) + TEST_P(AnEffect, sceneValiadationProducesShaderWarnings) { EffectDescription effectDesc; @@ -597,16 +819,16 @@ namespace ramses::internal } )SHADER"); - const auto* effect = sharedTestState->getScene().createEffect(effectDesc); + const auto* effect = m_sharedTestState.getScene().createEffect(effectDesc); EXPECT_NE(nullptr, effect); ValidationReport report; - sharedTestState->getScene().validate(report); + m_sharedTestState.getScene().validate(report); EXPECT_TRUE(report.hasIssue()); EXPECT_THAT(report.impl().toString(), HasSubstr("Precision mismatch: 'v_texcoord'. (Vertex: smooth out lowp 2-component vector of float, Fragment: smooth in highp 2-component vector of float)")); ValidationReport report2; - sharedTestState->getScene().validate(report2); + m_sharedTestState.getScene().validate(report2); EXPECT_EQ(report.getIssues(), report2.getIssues()); } } diff --git a/tests/unittests/client/logic/api/LogicEngineTest_Compatibility.cpp b/tests/unittests/client/FeatureLevelCompatibilityTest.cpp similarity index 55% rename from tests/unittests/client/logic/api/LogicEngineTest_Compatibility.cpp rename to tests/unittests/client/FeatureLevelCompatibilityTest.cpp index 7bad2486c..9c2f891c9 100644 --- a/tests/unittests/client/logic/api/LogicEngineTest_Compatibility.cpp +++ b/tests/unittests/client/FeatureLevelCompatibilityTest.cpp @@ -6,42 +6,44 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "LogicEngineTest_Base.h" - #include "RamsesTestUtils.h" #include "WithTempDirectory.h" #include "PropertyLinkTestUtils.h" - -#include "ramses/client/logic/Property.h" -#include "ramses/client/logic/RenderBufferBinding.h" +#include "FeatureLevelTestValues.h" #include "ramses/client/EffectDescription.h" #include "ramses/client/Effect.h" #include "ramses/client/Scene.h" +#include "ramses/client/OrthographicCamera.h" +#include "ramses/client/Appearance.h" +#include "ramses/client/logic/DataArray.h" +#include "ramses/client/logic/LuaInterface.h" +#include "ramses/client/logic/LuaScript.h" +#include "ramses/client/logic/Property.h" +#include "ramses/client/logic/AnimationNode.h" +#include "ramses/client/logic/AppearanceBinding.h" +#include "ramses/client/logic/NodeBinding.h" +#include "ramses/client/logic/CameraBinding.h" +#include "ramses/client/logic/RenderBufferBinding.h" #include "ramses/client/PerspectiveCamera.h" #include "ramses/client/UniformInput.h" -#include "ramses/framework/RamsesVersion.h" - -#include "internal/logic/ApiObjects.h" -#include "internal/logic/FileUtils.h" - -#include "internal/logic/flatbuffers/generated/LogicEngineGen.h" -#include "fmt/format.h" - -#include namespace ramses::internal { // These tests will always break on incompatible file format changes. - class ALogicEngine_Binary_Compatibility : public ::testing::Test + class AFeatureLevelCompatibility : public ::testing::TestWithParam { protected: - static void checkBaseContents(LogicEngine& logicEngine, ramses::Scene& ramsesScene) + void checkBaseContents() { - ASSERT_NE(nullptr, logicEngine.findObject("nestedModuleMath")); - ASSERT_NE(nullptr, logicEngine.findObject("moduleMath")); - ASSERT_NE(nullptr, logicEngine.findObject("moduleTypes")); - const auto script1 = logicEngine.findObject("script1"); + auto logicEngine = m_scene->findObject("testAssetLogic"); + ASSERT_TRUE(logicEngine); + EXPECT_TRUE(logicEngine->update()); + + ASSERT_NE(nullptr, logicEngine->findObject("nestedModuleMath")); + ASSERT_NE(nullptr, logicEngine->findObject("moduleMath")); + ASSERT_NE(nullptr, logicEngine->findObject("moduleTypes")); + const auto script1 = logicEngine->findObject("script1"); ASSERT_NE(nullptr, script1); EXPECT_NE(nullptr, script1->getInputs()->getChild("intInput")); EXPECT_NE(nullptr, script1->getInputs()->getChild("int64Input")); @@ -59,7 +61,7 @@ namespace ramses::internal EXPECT_NE(nullptr, script1->getOutputs()->getChild("floatOutput")); EXPECT_NE(nullptr, script1->getOutputs()->getChild("nodeTranslation")); EXPECT_NE(nullptr, script1->getInputs()->getChild("floatInput")); - const auto script2 = logicEngine.findObject("script2"); + const auto script2 = logicEngine->findObject("script2"); ASSERT_NE(nullptr, script2); EXPECT_NE(nullptr, script2->getInputs()->getChild("floatInput")); EXPECT_NE(nullptr, script2->getOutputs()->getChild("cameraViewport")->getChild("offsetX")); @@ -67,28 +69,28 @@ namespace ramses::internal EXPECT_NE(nullptr, script2->getOutputs()->getChild("cameraViewport")->getChild("width")); EXPECT_NE(nullptr, script2->getOutputs()->getChild("cameraViewport")->getChild("height")); EXPECT_NE(nullptr, script2->getOutputs()->getChild("floatUniform")); - const auto animNode = logicEngine.findObject("animNode"); + const auto animNode = logicEngine->findObject("animNode"); ASSERT_NE(nullptr, animNode); EXPECT_EQ(1u, animNode->getInputs()->getChildCount()); ASSERT_EQ(2u, animNode->getOutputs()->getChildCount()); EXPECT_NE(nullptr, animNode->getOutputs()->getChild("channel")); - ASSERT_NE(nullptr, logicEngine.findObject("animNodeWithDataProperties")); - EXPECT_EQ(2u, logicEngine.findObject("animNodeWithDataProperties")->getInputs()->getChildCount()); - EXPECT_NE(nullptr, logicEngine.findObject("timerNode")); + ASSERT_NE(nullptr, logicEngine->findObject("animNodeWithDataProperties")); + EXPECT_EQ(2u, logicEngine->findObject("animNodeWithDataProperties")->getInputs()->getChildCount()); + EXPECT_NE(nullptr, logicEngine->findObject("timerNode")); - const auto nodeBinding = logicEngine.findObject("nodebinding"); + const auto nodeBinding = logicEngine->findObject("nodebinding"); ASSERT_NE(nullptr, nodeBinding); EXPECT_NE(nullptr, nodeBinding->getInputs()->getChild("enabled")); - EXPECT_TRUE(logicEngine.isLinked(*nodeBinding)); - const auto cameraBinding = logicEngine.findObject("camerabinding"); + EXPECT_TRUE(logicEngine->isLinked(*nodeBinding)); + const auto cameraBinding = logicEngine->findObject("camerabinding"); ASSERT_NE(nullptr, cameraBinding); - const auto appearanceBinding = logicEngine.findObject("appearancebinding"); + const auto appearanceBinding = logicEngine->findObject("appearancebinding"); ASSERT_NE(nullptr, appearanceBinding); - EXPECT_NE(nullptr, logicEngine.findObject("dataarray")); + EXPECT_NE(nullptr, logicEngine->findObject("dataarray")); std::vector expectedLinks; - const auto intf = logicEngine.findObject("intf"); + const auto intf = logicEngine->findObject("intf"); ASSERT_NE(nullptr, intf); intf->getInputs()->getChild("struct")->getChild("floatInput")->set(42.5f); expectedLinks.push_back({ intf->getOutputs()->getChild("struct")->getChild("floatInput"), script1->getInputs()->getChild("floatInput"), false }); @@ -102,13 +104,13 @@ namespace ramses::internal expectedLinks.push_back({ script2->getOutputs()->getChild("floatUniform"), appearanceBinding->getInputs()->getChild("floatUniform"), false }); expectedLinks.push_back({ animNode->getOutputs()->getChild("channel"), appearanceBinding->getInputs()->getChild("animatedFloatUniform"), false }); - const auto triLogicIntf = logicEngine.findObject("Interface_CameraCrane"); + const auto triLogicIntf = logicEngine->findObject("Interface_CameraCrane"); ASSERT_TRUE(triLogicIntf); - const auto triLogicScript = logicEngine.findObject("CameraCrane"); + const auto triLogicScript = logicEngine->findObject("CameraCrane"); ASSERT_TRUE(triLogicScript); - const auto triCamNode = logicEngine.findObject("triangleCamNodeBinding"); + const auto triCamNode = logicEngine->findObject("triangleCamNodeBinding"); ASSERT_TRUE(triCamNode); - const auto triCamBinding = logicEngine.findObject("triangleCamBinding"); + const auto triCamBinding = logicEngine->findObject("triangleCamBinding"); ASSERT_TRUE(triCamBinding); expectedLinks.push_back({ triLogicIntf->getOutputs()->getChild("CraneGimbal")->getChild("Yaw"), triLogicScript->getInputs()->getChild("yaw"), false }); expectedLinks.push_back({ triLogicIntf->getOutputs()->getChild("CraneGimbal")->getChild("Pitch"), triLogicScript->getInputs()->getChild("pitch"), false }); @@ -116,14 +118,14 @@ namespace ramses::internal expectedLinks.push_back({ triLogicIntf->getOutputs()->getChild("Viewport")->getChild("Height"), triCamBinding->getInputs()->getChild("viewport")->getChild("height"), false }); expectedLinks.push_back({ triLogicScript->getOutputs()->getChild("translation"), triCamNode->getInputs()->getChild("translation"), false }); - PropertyLinkTestUtils::ExpectLinks(logicEngine, expectedLinks); + PropertyLinkTestUtils::ExpectLinks(*logicEngine, expectedLinks); - EXPECT_TRUE(logicEngine.update()); + EXPECT_TRUE(logicEngine->update()); // Values on Ramses are updated according to expectations vec3f translation; - auto node = ramsesScene.findObject("test node"); - auto camera = ramsesScene.findObject("test camera"); + auto node = m_scene->findObject("test node"); + auto camera = m_scene->findObject("test camera"); node->getTranslation(translation); EXPECT_EQ(translation, vec3f(42.5f, 2.f, 3.f)); // test that linked value from script propagated to ramses scene @@ -137,29 +139,29 @@ namespace ramses::internal // Animation node is linked and can be animated EXPECT_FLOAT_EQ(2.f, *animNode->getOutputs()->getChild("duration")->get()); animNode->getInputs()->getChild("progress")->set(0.75f); - EXPECT_TRUE(logicEngine.update()); + EXPECT_TRUE(logicEngine->update()); - auto appearance = ramsesScene.findObject("test appearance"); + auto appearance = m_scene->findObject("test appearance"); const auto uniform = appearance->getEffect().getUniformInput(1); ASSERT_TRUE(uniform.has_value()); float floatValue = 0.f; appearance->getInputValue(*uniform, floatValue); EXPECT_FLOAT_EQ(1.5f, floatValue); - EXPECT_EQ(957, *logicEngine.findObject("script2")->getOutputs()->getChild("nestedModulesResult")->get()); + EXPECT_EQ(957, *logicEngine->findObject("script2")->getOutputs()->getChild("nestedModulesResult")->get()); - EXPECT_TRUE(logicEngine.findObject("renderpassbinding")); - EXPECT_TRUE(logicEngine.findObject("anchorpoint")); + EXPECT_TRUE(logicEngine->findObject("renderpassbinding")); + EXPECT_TRUE(logicEngine->findObject("anchorpoint")); - const auto cameraBindingPersp = logicEngine.findObject("camerabindingPersp"); - const auto cameraBindingPerspWithFrustumPlanes = logicEngine.findObject("camerabindingPerspWithFrustumPlanes"); + const auto cameraBindingPersp = logicEngine->findObject("camerabindingPersp"); + const auto cameraBindingPerspWithFrustumPlanes = logicEngine->findObject("camerabindingPerspWithFrustumPlanes"); ASSERT_TRUE(cameraBindingPersp && cameraBindingPerspWithFrustumPlanes); EXPECT_EQ(4u, cameraBindingPersp->getInputs()->getChild("frustum")->getChildCount()); EXPECT_EQ(6u, cameraBindingPerspWithFrustumPlanes->getInputs()->getChild("frustum")->getChildCount()); - EXPECT_TRUE(logicEngine.findObject("rendergroupbinding")); - EXPECT_TRUE(logicEngine.findObject("skin")); - const auto dataArray = logicEngine.findObject("dataarrayOfArrays"); + EXPECT_TRUE(logicEngine->findObject("rendergroupbinding")); + EXPECT_TRUE(logicEngine->findObject("skin")); + const auto dataArray = logicEngine->findObject("dataarrayOfArrays"); ASSERT_TRUE(dataArray); EXPECT_EQ(EPropertyType::Array, dataArray->getDataType()); EXPECT_EQ(2u, dataArray->getNumElements()); @@ -167,88 +169,115 @@ namespace ramses::internal ASSERT_TRUE(data); const std::vector> expectedData{ { 1.f, 2.f, 3.f, 4.f, 5.f }, { 6.f, 7.f, 8.f, 9.f, 10.f } }; EXPECT_EQ(expectedData, *data); - EXPECT_TRUE(logicEngine.findObject("meshnodebinding")); - auto rbBinding = logicEngine.findObject("renderBufferBinding"); + EXPECT_TRUE(logicEngine->findObject("meshnodebinding")); + auto rbBinding = logicEngine->findObject("renderBufferBinding"); ASSERT_TRUE(rbBinding); - EXPECT_EQ(ramsesScene.findObject("renderBuffer"), &rbBinding->getRenderBuffer()); + EXPECT_EQ(m_scene->findObject("renderBuffer"), &rbBinding->getRenderBuffer()); } - static void expectFeatureLevel02Content(const LogicEngine& /*logicEngine*/, ramses::Scene& /*ramsesScene*/) + void checkUniformBufferInput(bool exists) { - // features added in future feature level expected to be present + const auto& triangleEffect = m_scene->findObject("triangle appearance")->getEffect(); + auto uboInput = triangleEffect.findUniformInput("colorBlock"); + ASSERT_EQ(exists, uboInput.has_value()); + if (exists) + { + EXPECT_EQ(EDataType::UniformBuffer, uboInput->getDataType()); + } + + auto uboSemanticInput = triangleEffect.findUniformInput("modelCameraBlock"); + ASSERT_EQ(exists, uboSemanticInput.has_value()); + if (exists) + { + EXPECT_EQ(EDataType::UniformBuffer, uboSemanticInput->getDataType()); + EXPECT_EQ(EEffectUniformSemantic::ModelCameraBlock, uboSemanticInput->getSemantics()); + } } - static void expectFeatureLevel02ContentNotPresent(const LogicEngine& /*logicEngine*/) + void expectFeatureLevel02Content() { - // features added in future feature level expected NOT to be present in previous feature levels + const auto appearanceBindingLo = m_scene->findObject("triangle appearance binding"); + ASSERT_TRUE(appearanceBindingLo); + const auto appearanceBinding = appearanceBindingLo->as(); + ASSERT_TRUE(appearanceBinding); + EXPECT_EQ(1.f, appearanceBinding->getInputs()->getChild("colorBlock.color[0].c1")->get()); + EXPECT_EQ(0.1f, appearanceBinding->getInputs()->getChild("colorBlock.color[0].c2")->get()); + EXPECT_EQ(0.2f, appearanceBinding->getInputs()->getChild("colorBlock.color[1].c1")->get()); + EXPECT_EQ(1.f, appearanceBinding->getInputs()->getChild("colorBlock.color[1].c2")->get()); + + checkUniformBufferInput(true); } - static void checkContents(LogicEngine& logicEngine, ramses::Scene& scene) + void expectFeatureLevel02ContentNotPresent() { - const ramses::EFeatureLevel featureLevel = scene.getRamsesClient().getRamsesFramework().getFeatureLevel(); + checkUniformBufferInput(false); + } + void checkContents() + { // check for content expected to exist // higher feature level always contains content supported by lower level - switch (featureLevel) + switch (GetParam()) { - //case ramses::EFeatureLevel_02: - // expectFeatureLevel02Content(logicEngine, scene); - // [[fallthrough]]; + case ramses::EFeatureLevel_02: + expectFeatureLevel02Content(); + [[fallthrough]]; case ramses::EFeatureLevel_01: - checkBaseContents(logicEngine, scene); + checkBaseContents(); break; } // check for content expected to not exist // lower feature level never contains content supported only in higher level - switch (featureLevel) + switch (GetParam()) { case ramses::EFeatureLevel_01: - expectFeatureLevel02ContentNotPresent(logicEngine); - // [[fallthrough]]; - //case EFeatureLevel_02: - // break; + expectFeatureLevel02ContentNotPresent(); + [[fallthrough]]; + case EFeatureLevel_02: + break; } } - static void saveAndReloadAndCheckContents(ramses::Scene& scene) + void saveAndReloadAndCheckContents() { - WithTempDirectory tempDir; + EXPECT_TRUE(m_scene->saveToFile("temp.ramses", {})); + m_ramses.getClient().destroy(*m_scene); - EXPECT_TRUE(scene.saveToFile("temp.ramses", {})); + m_scene = m_ramses.getClient().loadSceneFromFile("temp.ramses"); + ASSERT_TRUE(m_scene); - auto& client = scene.getRamsesClient(); - client.destroy(scene); - auto otherScene = client.loadSceneFromFile("temp.ramses"); - auto logicEngineAnother = otherScene->findObject("testAssetLogic"); - EXPECT_TRUE(logicEngineAnother->update()); - - checkContents(*logicEngineAnother, *otherScene); - client.destroy(*otherScene); + checkContents(); } - ramses::Scene* loadRamsesScene(ramses::EFeatureLevel featureLevel) + void loadScene() { - switch(featureLevel) + switch(GetParam()) { case ramses::EFeatureLevel_01: - return &m_ramses.loadSceneFromFile("res/testScene_01.ramses"); + m_scene = &m_ramses.loadSceneFromFile("../res/testScene_01.ramses"); + break; + case ramses::EFeatureLevel_02: + m_scene = &m_ramses.loadSceneFromFile("../res/testScene_02.ramses"); + break; + default: + assert(false); + break; } - return nullptr; } - RamsesTestSetup m_ramses; + WithTempDirectory m_tempDir; + RamsesTestSetup m_ramses{ GetParam() }; + Scene* m_scene = nullptr; }; - TEST_F(ALogicEngine_Binary_Compatibility, CanLoadAndUpdateABinaryFileExportedWithLastCompatibleVersionOfEngine_FeatureLevel01) + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(AFeatureLevelCompatibility) + + // disabled until UBO isolated within FL02 + TEST_P(AFeatureLevelCompatibility, CanLoadExportedBinaryAndVerifyContent) { - ramses::Scene* scene = loadRamsesScene(ramses::EFeatureLevel_01); - ASSERT_TRUE(scene); - auto* logicEngine = scene->findObject("testAssetLogic"); - ASSERT_TRUE(logicEngine); - EXPECT_TRUE(logicEngine->update()); - - checkContents(*logicEngine, *scene); - saveAndReloadAndCheckContents(*scene); + loadScene(); + checkContents(); + saveAndReloadAndCheckContents(); } } diff --git a/tests/unittests/client/GeometryTest.cpp b/tests/unittests/client/GeometryTest.cpp index f8fe2eb71..90b3a7127 100644 --- a/tests/unittests/client/GeometryTest.cpp +++ b/tests/unittests/client/GeometryTest.cpp @@ -9,6 +9,7 @@ #include #include "ClientTestUtils.h" #include "TestEffectCreator.h" +#include "FeatureLevelTestValues.h" #include "ramses/client/Geometry.h" #include "ramses/client/ArrayResource.h" @@ -29,50 +30,33 @@ using namespace testing; namespace ramses::internal { - class GeometryTest : public ::testing::Test + class GeometryTest : public TestWithSharedEffectPerFeatureLevel { - public: - static void SetUpTestSuite() - { - sharedTestState = new TestEffectCreator; - } - - static void TearDownTestSuite() - { - delete sharedTestState; - sharedTestState = nullptr; - } - - void SetUp() override - { - EXPECT_TRUE(sharedTestState != nullptr); - } - protected: - static void CheckHashSetToInternalScene(const Geometry& geometryBinding, ramses::internal::DataFieldHandle field, const Resource& resource, uint32_t expectedInstancingDivisor) + void CheckHashSetToInternalScene(const Geometry& geometryBinding, ramses::internal::DataFieldHandle field, const Resource& resource, uint32_t expectedInstancingDivisor) { const ramses::internal::ResourceContentHash expectedHash = resource.impl().getLowlevelResourceHash(); - const ramses::internal::ResourceField& actualDataResource = sharedTestState->getInternalScene().getDataResource(geometryBinding.impl().getAttributeDataInstance(), field); + const ramses::internal::ResourceField& actualDataResource = m_sharedTestState.getInternalScene().getDataResource(geometryBinding.impl().getAttributeDataInstance(), field); EXPECT_EQ(expectedHash, actualDataResource.hash); EXPECT_EQ(expectedInstancingDivisor, actualDataResource.instancingDivisor); } - static void CheckDataBufferSetToInternalScene(const Geometry& geometryBinding, ramses::internal::DataFieldHandle field, const ArrayBufferImpl& dataBuffer, uint32_t expectedInstancingDivisor) + void CheckDataBufferSetToInternalScene(const Geometry& geometryBinding, ramses::internal::DataFieldHandle field, const ArrayBufferImpl& dataBuffer, uint32_t expectedInstancingDivisor) { const ramses::internal::DataBufferHandle dataBufferHandle = dataBuffer.getDataBufferHandle(); - const ramses::internal::ResourceField& actualDataResource = sharedTestState->getInternalScene().getDataResource(geometryBinding.impl().getAttributeDataInstance(), field); + const ramses::internal::ResourceField& actualDataResource = m_sharedTestState.getInternalScene().getDataResource(geometryBinding.impl().getAttributeDataInstance(), field); EXPECT_EQ(dataBufferHandle, actualDataResource.dataBuffer); EXPECT_EQ(expectedInstancingDivisor, actualDataResource.instancingDivisor); } - static ArrayResource* SetVec3fArrayInput(Geometry& geometry) + ArrayResource* SetVec3fArrayInput(Geometry& geometry) { const vec3f vert{ 0.f, 1.f, 2.f }; - auto vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vec3Vertices"); + auto vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vec3Vertices"); EXPECT_TRUE(vertices != nullptr); assert(vertices); - const auto optInput = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); EXPECT_TRUE(optInput.has_value()); assert(optInput != std::nullopt); EXPECT_TRUE(geometry.setInputBuffer(*optInput, *vertices)); @@ -80,14 +64,14 @@ namespace ramses::internal return vertices; } - static ArrayResource* SetVec2fArrayInput(Geometry& geometry) + ArrayResource* SetVec2fArrayInput(Geometry& geometry) { const vec2f vert{ 0.f, 1.f }; - auto vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vec2Vertices"); + auto vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vec2Vertices"); EXPECT_TRUE(vertices != nullptr); assert(vertices); - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); EXPECT_TRUE(optInput.has_value()); assert(optInput != std::nullopt); EXPECT_TRUE(geometry.setInputBuffer(*optInput, *vertices)); @@ -95,14 +79,14 @@ namespace ramses::internal return vertices; } - static ArrayResource* SetVec4fArrayInput(Geometry& geometry) + ArrayResource* SetVec4fArrayInput(Geometry& geometry) { const vec4f vert{ 0.f, 1.f, 2.f, 3.f }; - auto vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vec4Vertices"); + auto vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vec4Vertices"); EXPECT_TRUE(vertices != nullptr); assert(vertices); - const auto optInput = sharedTestState->effect->findAttributeInput("vec4fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec4fArrayInput"); EXPECT_TRUE(optInput.has_value()); assert(optInput != std::nullopt); EXPECT_TRUE(geometry.setInputBuffer(*optInput, *vertices)); @@ -110,14 +94,14 @@ namespace ramses::internal return vertices; } - static ArrayResource* SetFloatArrayInput(Geometry& geometry) + ArrayResource* SetFloatArrayInput(Geometry& geometry) { float verts[8] = { 0.1f }; - auto vertices = sharedTestState->getScene().createArrayResource(8u, verts, "floatVertices"); + auto vertices = m_sharedTestState.getScene().createArrayResource(8u, verts, "floatVertices"); EXPECT_TRUE(vertices != nullptr); assert(vertices); - const auto optInput = sharedTestState->effect->findAttributeInput("floatArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("floatArrayInput"); EXPECT_TRUE(optInput.has_value()); assert(optInput != std::nullopt); EXPECT_TRUE(geometry.setInputBuffer(*optInput, *vertices)); @@ -125,10 +109,10 @@ namespace ramses::internal return vertices; } - static ArrayResource* SetIndicesInput(Geometry& geometry) + ArrayResource* SetIndicesInput(Geometry& geometry) { uint32_t inds[3] = { 0u }; - auto indices = sharedTestState->getScene().createArrayResource(3u, inds, "indices"); + auto indices = m_sharedTestState.getScene().createArrayResource(3u, inds, "indices"); EXPECT_TRUE(indices != nullptr); assert(indices); @@ -137,131 +121,129 @@ namespace ramses::internal return indices; } - - static TestEffectCreator* sharedTestState; }; - TestEffectCreator* GeometryTest::sharedTestState = nullptr; + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(GeometryTest); - TEST_F(GeometryTest, CanGetEffect) + TEST_P(GeometryTest, CanGetEffect) { - Effect* emptyEffect = TestEffects::CreateTestEffect(sharedTestState->getScene()); + Effect* emptyEffect = TestEffects::CreateTestEffect(m_sharedTestState.getScene()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*emptyEffect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*emptyEffect, "geometry"); ASSERT_TRUE(geometry != nullptr); const Effect& resultEffect = geometry->getEffect(); EXPECT_EQ(resultEffect.getResourceId(), emptyEffect->getResourceId()); EXPECT_EQ(resultEffect.impl().getLowlevelResourceHash(), emptyEffect->impl().getLowlevelResourceHash()); - const uint32_t fieldCount = sharedTestState->getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()).getFieldCount(); + const uint32_t fieldCount = m_sharedTestState.getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()).getFieldCount(); EXPECT_EQ(1u, fieldCount); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getScene().destroy(*emptyEffect); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getScene().destroy(*emptyEffect); } - TEST_F(GeometryTest, dataLayoutHasOnlyIndicesForEmptyEffect) + TEST_P(GeometryTest, dataLayoutHasOnlyIndicesForEmptyEffect) { - Effect* emptyEffect = TestEffects::CreateTestEffect(sharedTestState->getScene()); + Effect* emptyEffect = TestEffects::CreateTestEffect(m_sharedTestState.getScene()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*emptyEffect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*emptyEffect, "geometry"); ASSERT_TRUE(geometry != nullptr); - const uint32_t fieldCount = sharedTestState->getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()).getFieldCount(); + const uint32_t fieldCount = m_sharedTestState.getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()).getFieldCount(); EXPECT_EQ(1u, fieldCount); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getScene().destroy(*emptyEffect); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getScene().destroy(*emptyEffect); } - TEST_F(GeometryTest, dataLayoutHasRightEffectHash) + TEST_P(GeometryTest, dataLayoutHasRightEffectHash) { - Effect* emptyEffect = TestEffects::CreateTestEffect(sharedTestState->getScene()); + Effect* emptyEffect = TestEffects::CreateTestEffect(m_sharedTestState.getScene()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*emptyEffect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*emptyEffect, "geometry"); ASSERT_TRUE(geometry != nullptr); - const ramses::internal::DataLayout geometryLayout = sharedTestState->getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()); + const ramses::internal::DataLayout geometryLayout = m_sharedTestState.getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()); const ramses::internal::ResourceContentHash& effectHashFromGeometryLayout = geometryLayout.getEffectHash(); EXPECT_EQ(emptyEffect->impl().getLowlevelResourceHash(), effectHashFromGeometryLayout); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getScene().destroy(*emptyEffect); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getScene().destroy(*emptyEffect); } - TEST_F(GeometryTest, indicesFieldIsCreatedAtFixedSlot) + TEST_P(GeometryTest, indicesFieldIsCreatedAtFixedSlot) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const ramses::internal::DataFieldHandle indicesField(GeometryImpl::IndicesDataFieldIndex); - const ramses::internal::EFixedSemantics semantics = sharedTestState->getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()).getField(indicesField).semantics; + const ramses::internal::EFixedSemantics semantics = m_sharedTestState.getInternalScene().getDataLayout(geometry->impl().getAttributeDataLayout()).getField(indicesField).semantics; EXPECT_EQ(ramses::internal::EFixedSemantics::Indices, semantics); - sharedTestState->getScene().destroy(*geometry); + m_sharedTestState.getScene().destroy(*geometry); } - TEST_F(GeometryTest, canSetResource) + TEST_P(GeometryTest, canSetResource) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const vec3f vert{ 0.f, 1.f, 2.f }; - ArrayResource* const vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vertices"); + ArrayResource* const vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vertices"); ASSERT_TRUE(vertices != nullptr); - const auto optInput = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInput.has_value()); EXPECT_TRUE(geometry->setInputBuffer(*optInput, *vertices, 13u)); CheckHashSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(3u), *vertices, 13u); // first field is indices - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getScene().destroy(*vertices); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getScene().destroy(*vertices); } - TEST_F(GeometryTest, reportsErrorWhenSettingResourceWithMismatchingTypeInEffect) + TEST_P(GeometryTest, reportsErrorWhenSettingResourceWithMismatchingTypeInEffect) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const vec2f vert{ 1.f, 2.f }; - ArrayResource* const vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vertices"); + ArrayResource* const vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vertices"); ASSERT_TRUE(vertices != nullptr); - const auto optInput = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInput.has_value()); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices)); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getScene().destroy(*vertices); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getScene().destroy(*vertices); } - TEST_F(GeometryTest, reportsErrorWhenSettingVec2ArrayResourceFromAnotherScene) + TEST_P(GeometryTest, reportsErrorWhenSettingVec2ArrayResourceFromAnotherScene) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const vec2f vert{ 1.f, 2.f }; - ramses::Scene& anotherScene(*sharedTestState->getClient().createScene(sceneId_t{ 0xf00 })); + ramses::Scene& anotherScene(*m_sharedTestState.getClient().createScene(sceneId_t{ 0xf00 })); ArrayResource* const vertices = anotherScene.createArrayResource(1u, &vert, "vec2Vertices"); ASSERT_TRUE(vertices != nullptr); - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices)); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getClient().destroy(anotherScene); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getClient().destroy(anotherScene); } - TEST_F(GeometryTest, reportsErrorWhenSettingIndexDataBufferFromAnotherScene) + TEST_P(GeometryTest, reportsErrorWhenSettingIndexDataBufferFromAnotherScene) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ramses::Scene* otherScene = sharedTestState->getClient().createScene(sceneId_t(777u)); + ramses::Scene* otherScene = m_sharedTestState.getClient().createScene(sceneId_t(777u)); ASSERT_NE(nullptr, otherScene); ArrayBuffer* const indices = otherScene->createArrayBuffer(ramses::EDataType::UInt32, 3u, "indices"); @@ -269,62 +251,62 @@ namespace ramses::internal EXPECT_FALSE(geometry->setIndices(*indices)); - sharedTestState->getScene().destroy(*indices); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getClient().destroy(*otherScene); + m_sharedTestState.getScene().destroy(*indices); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getClient().destroy(*otherScene); } - TEST_F(GeometryTest, reportsErrorWhenSettingVertexDataBufferFromAnotherScene) + TEST_P(GeometryTest, reportsErrorWhenSettingVertexDataBufferFromAnotherScene) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ramses::Scene* otherScene = sharedTestState->getClient().createScene(sceneId_t(777u)); + ramses::Scene* otherScene = m_sharedTestState.getClient().createScene(sceneId_t(777u)); ASSERT_NE(nullptr, otherScene); ArrayBuffer* const vertices = otherScene->createArrayBuffer(ramses::EDataType::Float, 3u, "vertices"); ASSERT_NE(nullptr, vertices); - const auto optInput = sharedTestState->effect->findAttributeInput("floatArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("floatArrayInput"); ASSERT_TRUE(optInput.has_value()); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices)); - sharedTestState->getScene().destroy(*vertices); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getClient().destroy(*otherScene); + m_sharedTestState.getScene().destroy(*vertices); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getClient().destroy(*otherScene); } - TEST_F(GeometryTest, reportsErrorWhenSettingArrayBufferByteBlobFromAnotherScene) + TEST_P(GeometryTest, reportsErrorWhenSettingArrayBufferByteBlobFromAnotherScene) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ramses::Scene* otherScene = sharedTestState->getClient().createScene(sceneId_t(777u)); + ramses::Scene* otherScene = m_sharedTestState.getClient().createScene(sceneId_t(777u)); ASSERT_NE(nullptr, otherScene); ArrayBuffer* const vertices = otherScene->createArrayBuffer(ramses::EDataType::ByteBlob, 3u, "vertices"); ASSERT_NE(nullptr, vertices); - const auto optInputVec2 = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInputVec2 = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInputVec2.has_value()); - const auto optInputVec3 = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInputVec3 = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInputVec3.has_value()); constexpr uint16_t nonZeroStride = 13u; EXPECT_FALSE(geometry->setInputBuffer(*optInputVec2, *vertices, 0u, nonZeroStride)); EXPECT_FALSE(geometry->setInputBuffer(*optInputVec3, *vertices, 2 * sizeof(float), nonZeroStride)); - sharedTestState->getScene().destroy(*vertices); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getClient().destroy(*otherScene); + m_sharedTestState.getScene().destroy(*vertices); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getClient().destroy(*otherScene); } - TEST_F(GeometryTest, reportsErrorWhenSettingArrayResourceByteBlobFromAnotherScene) + TEST_P(GeometryTest, reportsErrorWhenSettingArrayResourceByteBlobFromAnotherScene) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ramses::Scene* otherScene = sharedTestState->getClient().createScene(sceneId_t(777u)); + ramses::Scene* otherScene = m_sharedTestState.getClient().createScene(sceneId_t(777u)); ASSERT_NE(nullptr, otherScene); const std::byte data[4] = { std::byte{0} }; @@ -332,44 +314,44 @@ namespace ramses::internal ASSERT_NE(nullptr, vertices); - const auto optInputVec2 = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInputVec2 = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInputVec2.has_value()); - const auto optInputVec3 = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInputVec3 = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInputVec3.has_value()); constexpr uint16_t nonZeroStride = 13u; EXPECT_FALSE(geometry->setInputBuffer(*optInputVec2, *vertices, 0u, nonZeroStride)); EXPECT_FALSE(geometry->setInputBuffer(*optInputVec3, *vertices, 2 * sizeof(float), nonZeroStride)); - sharedTestState->getScene().destroy(*vertices); - sharedTestState->getScene().destroy(*geometry); - sharedTestState->getClient().destroy(*otherScene); + m_sharedTestState.getScene().destroy(*vertices); + m_sharedTestState.getScene().destroy(*geometry); + m_sharedTestState.getClient().destroy(*otherScene); } - TEST_F(GeometryTest, reportsErrorWhenSettingUint16ArrayIndicesFromAnotherScene) + TEST_P(GeometryTest, reportsErrorWhenSettingUint16ArrayIndicesFromAnotherScene) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); uint16_t inds[3] = { 0u }; - ramses::Scene& anotherScene(*sharedTestState->getClient().createScene(sceneId_t{ 0xf00 })); + ramses::Scene& anotherScene(*m_sharedTestState.getClient().createScene(sceneId_t{ 0xf00 })); ArrayResource* const indices = anotherScene.createArrayResource(3u, inds, "indices"); ASSERT_TRUE(indices != nullptr); EXPECT_EQ(0u, geometry->impl().getIndicesCount()); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - sharedTestState->getClient().destroy(anotherScene); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + m_sharedTestState.getClient().destroy(anotherScene); } - TEST_F(GeometryTest, canSetIndicesResource16) + TEST_P(GeometryTest, canSetIndicesResource16) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const uint16_t inds[3] = { 0u }; - ArrayResource* const indices = sharedTestState->getScene().createArrayResource(3u, inds, "indices"); + ArrayResource* const indices = m_sharedTestState.getScene().createArrayResource(3u, inds, "indices"); ASSERT_TRUE(indices != nullptr); EXPECT_EQ(0u, geometry->impl().getIndicesCount()); @@ -377,17 +359,17 @@ namespace ramses::internal CheckHashSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(0u), *indices, 0u); EXPECT_EQ(indices->impl().getElementCount(), geometry->impl().getIndicesCount()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, canSetIndicesResource32) + TEST_P(GeometryTest, canSetIndicesResource32) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const uint32_t inds[3] = { 0u }; - ArrayResource* const indices = sharedTestState->getScene().createArrayResource(3u, inds, "indices"); + ArrayResource* const indices = m_sharedTestState.getScene().createArrayResource(3u, inds, "indices"); ASSERT_TRUE(indices != nullptr); EXPECT_EQ(0u, geometry->impl().getIndicesCount()); @@ -395,16 +377,16 @@ namespace ramses::internal CheckHashSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(0u), *indices, 0u); EXPECT_EQ(indices->impl().getElementCount(), geometry->impl().getIndicesCount()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, canSetIndicesDataBuffer16) + TEST_P(GeometryTest, canSetIndicesDataBuffer16) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ArrayBuffer* const indices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::UInt16, 1u, "index data buffer"); + ArrayBuffer* const indices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::UInt16, 1u, "index data buffer"); ASSERT_TRUE(indices != nullptr); EXPECT_EQ(0u, geometry->impl().getIndicesCount()); @@ -412,16 +394,16 @@ namespace ramses::internal CheckDataBufferSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(0u), indices->impl(), 0u); EXPECT_EQ(indices->impl().getElementCount(), geometry->impl().getIndicesCount()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, canSetIndicesDataBuffer32) + TEST_P(GeometryTest, canSetIndicesDataBuffer32) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ArrayBuffer* const indices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::UInt32, 1u, "index data buffer"); + ArrayBuffer* const indices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::UInt32, 1u, "index data buffer"); ASSERT_TRUE(indices != nullptr); EXPECT_EQ(0u, geometry->impl().getIndicesCount()); @@ -429,211 +411,211 @@ namespace ramses::internal CheckDataBufferSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(0u), indices->impl(), 0u); EXPECT_EQ(indices->impl().getElementCount(), geometry->impl().getIndicesCount()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceFLoat) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceFLoat) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const float inds[4] = { .0f, .0f, .0f, .0f }; - ArrayResource* const indices = sharedTestState->getScene().createArrayResource(4u, inds, "indices"); + ArrayResource* const indices = m_sharedTestState.getScene().createArrayResource(4u, inds, "indices"); ASSERT_TRUE(indices); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceVec2F) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceVec2F) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const vec2f indice{ 1.f, 2.f }; - ArrayResource* const indices = sharedTestState->getScene().createArrayResource(1u, &indice, "indices"); + ArrayResource* const indices = m_sharedTestState.getScene().createArrayResource(1u, &indice, "indices"); ASSERT_TRUE(indices); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceVec3F) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceVec3F) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const vec3f indice{ 1.f, 2.f, 3.f }; - ArrayResource* const indices = sharedTestState->getScene().createArrayResource(1u, &indice, "indices"); + ArrayResource* const indices = m_sharedTestState.getScene().createArrayResource(1u, &indice, "indices"); ASSERT_TRUE(indices); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceVec4F) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceVec4F) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const vec4f indice{ 1.f, 2.f, 3.f, 4.f }; - ArrayResource* const indices = sharedTestState->getScene().createArrayResource(1u, &indice, "indices"); + ArrayResource* const indices = m_sharedTestState.getScene().createArrayResource(1u, &indice, "indices"); ASSERT_TRUE(indices); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferFloat) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferFloat) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const float inds[4] = { .0f, .0f, .0f, .0f }; - ArrayBuffer* indices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Float, 1u, "indices"); + ArrayBuffer* indices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Float, 1u, "indices"); ASSERT_TRUE(indices); indices->updateData(0u, 1u, inds); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferVec2F) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferVec2F) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const float inds[4] = { .0f, .0f, .0f, .0f }; - ArrayBuffer* indices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Vector2F, 1u, "indices"); + ArrayBuffer* indices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Vector2F, 1u, "indices"); ASSERT_TRUE(indices); indices->updateData(0u, 1u, inds); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferVec3F) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferVec3F) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const float inds[4] = { .0f, .0f, .0f, .0f }; - ArrayBuffer* indices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Vector3F, 1u, "indices"); + ArrayBuffer* indices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Vector3F, 1u, "indices"); ASSERT_TRUE(indices); indices->updateData(0u, 1u, inds); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferVec4F) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferVec4F) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const float inds[4] = { .0f, .0f, .0f, .0f }; - ArrayBuffer* indices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Vector4F, 1u, "indices"); + ArrayBuffer* indices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Vector4F, 1u, "indices"); ASSERT_TRUE(indices); indices->updateData(0u, 1u, inds); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferByteBlob) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayBufferByteBlob) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); - ArrayBuffer* const indices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 1u, "indices"); + ArrayBuffer* const indices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 1u, "indices"); ASSERT_TRUE(indices); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceByteBlob) + TEST_P(GeometryTest, reportsErrorWhenSetIndicesWithWrongTypeArrayResourceByteBlob) { - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const std::byte inds[4] = { std::byte{0}, std::byte{1}, std::byte{2}, std::byte{3} }; - ArrayResource* const indices = sharedTestState->getScene().createArrayResource(sizeof(inds), inds, "indices"); + ArrayResource* const indices = m_sharedTestState.getScene().createArrayResource(sizeof(inds), inds, "indices"); ASSERT_TRUE(indices); EXPECT_FALSE(geometry->setIndices(*indices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indices)); } - TEST_F(GeometryTest, canSetAttributeResourceInput) + TEST_P(GeometryTest, canSetAttributeResourceInput) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const vec3f vert{ 0.f, 1.f, 2.f }; - ArrayResource* const vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vertices"); + ArrayResource* const vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vertices"); ASSERT_TRUE(vertices != nullptr); EXPECT_TRUE(geometry->setInputBuffer(*optInput, *vertices)); CheckHashSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(3u), *vertices, 0u); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, canSetAttributeVertexDataBufferInput) + TEST_P(GeometryTest, canSetAttributeVertexDataBufferInput) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ArrayBuffer* const vertices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Vector3F, 3u, "vertices"); + ArrayBuffer* const vertices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Vector3F, 3u, "vertices"); ASSERT_TRUE(vertices != nullptr); EXPECT_TRUE(geometry->setInputBuffer(*optInput, *vertices, 16u)); CheckDataBufferSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(3u), vertices->impl(), 16u); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, canVertexDataBufferInput_ArrayBufferByteBlob) + TEST_P(GeometryTest, canVertexDataBufferInput_ArrayBufferByteBlob) { - const auto optInputVec2 = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInputVec2 = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInputVec2.has_value()); - const auto optInputVec3 = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInputVec3 = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInputVec3.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ArrayBuffer* const interleavedVertices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 5 * sizeof(float) *3u, "vertices"); + ArrayBuffer* const interleavedVertices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 5 * sizeof(float) *3u, "vertices"); ASSERT_TRUE(interleavedVertices != nullptr); constexpr uint16_t nonZeroStride = 17u; @@ -642,23 +624,23 @@ namespace ramses::internal CheckDataBufferSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(2u), interleavedVertices->impl(), 0u); CheckDataBufferSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(3u), interleavedVertices->impl(), 0u); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*interleavedVertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*interleavedVertices)); } - TEST_F(GeometryTest, canSetVertexDataBufferInput_ArrayResourceByteBlob) + TEST_P(GeometryTest, canSetVertexDataBufferInput_ArrayResourceByteBlob) { - const auto optInputVec2 = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInputVec2 = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInputVec2.has_value()); - const auto optInputVec3 = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInputVec3 = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInputVec3.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const float data[10] = { 1.f }; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) interleaved vertices passed as byte blob - ArrayResource* const interleavedVertices = sharedTestState->getScene().createArrayResource(sizeof(data), reinterpret_cast(data)); + ArrayResource* const interleavedVertices = m_sharedTestState.getScene().createArrayResource(sizeof(data), reinterpret_cast(data)); ASSERT_TRUE(interleavedVertices != nullptr); constexpr uint16_t nonZeroStride = 17u; @@ -667,138 +649,138 @@ namespace ramses::internal CheckHashSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(2u), *interleavedVertices, 0u); CheckHashSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(3u), *interleavedVertices, 0u); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*interleavedVertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*interleavedVertices)); } - TEST_F(GeometryTest, canSetArrayBufferByteBlobToSingleAttribute) + TEST_P(GeometryTest, canSetArrayBufferByteBlobToSingleAttribute) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); - ArrayBuffer* const vertices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 1u, "vertices"); + ArrayBuffer* const vertices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 1u, "vertices"); ASSERT_TRUE(vertices); EXPECT_TRUE(geometry->setInputBuffer(*optInput, *vertices)); CheckDataBufferSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(2u), vertices->impl(), 0u); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, canSetArrayResourceByteBlobToSingleAttribute) + TEST_P(GeometryTest, canSetArrayResourceByteBlobToSingleAttribute) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const float data[10] = { 1.f }; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) interleaved vertices passed as byte blob - ArrayResource* const vertices = sharedTestState->getScene().createArrayResource(sizeof(data), reinterpret_cast(data)); + ArrayResource* const vertices = m_sharedTestState.getScene().createArrayResource(sizeof(data), reinterpret_cast(data)); ASSERT_TRUE(vertices); EXPECT_TRUE(geometry->setInputBuffer(*optInput, *vertices)); CheckHashSetToInternalScene(*geometry, ramses::internal::DataFieldHandle(2u), *vertices, 0u); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, cannotSetStrideAndOffsetToNonByteBlobVertexDataBuffers) + TEST_P(GeometryTest, cannotSetStrideAndOffsetToNonByteBlobVertexDataBuffers) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); - ArrayBuffer* const vertices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Vector2F, 1u, "vertices"); + ArrayBuffer* const vertices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Vector2F, 1u, "vertices"); ASSERT_TRUE(vertices); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices, 1u, 2u)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, cannotSetStrideAndOffsetToNonByteBlobVertexArrayResource) + TEST_P(GeometryTest, cannotSetStrideAndOffsetToNonByteBlobVertexArrayResource) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); const vec2f vert{ 0.f, 1.f }; - const auto vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vertices"); + const auto vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vertices"); ASSERT_TRUE(vertices); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices, 1u, 2u)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, reportsErrorWhenSettingAttributeResourceInputWithWrongType) + TEST_P(GeometryTest, reportsErrorWhenSettingAttributeResourceInputWithWrongType) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); const vec3f vert{ 0.f, 1.f, 2.f }; - ArrayResource* const vertices = sharedTestState->getScene().createArrayResource(1u, &vert, "vertices"); + ArrayResource* const vertices = m_sharedTestState.getScene().createArrayResource(1u, &vert, "vertices"); ASSERT_TRUE(vertices != nullptr); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, reportsErrorWhenSettingAttributeVertexDataBufferInputWithWrongTypeUInt16) + TEST_P(GeometryTest, reportsErrorWhenSettingAttributeVertexDataBufferInputWithWrongTypeUInt16) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); - ArrayBuffer* const vertices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::UInt16, 1u, "vertices"); + ArrayBuffer* const vertices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::UInt16, 1u, "vertices"); ASSERT_TRUE(vertices); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, reportsErrorWhenSettingAttributeVertexDataBufferInputWithWrongTypeUInt32) + TEST_P(GeometryTest, reportsErrorWhenSettingAttributeVertexDataBufferInputWithWrongTypeUInt32) { - const auto optInput = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInput.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry); - ArrayBuffer* const vertices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::UInt32, 1u, "vertices"); + ArrayBuffer* const vertices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::UInt32, 1u, "vertices"); ASSERT_TRUE(vertices); EXPECT_FALSE(geometry->setInputBuffer(*optInput, *vertices)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertices)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedEffectResource) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedEffectResource) { - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); auto floatArray = SetFloatArrayInput(*geometry); auto vec2fArray = SetVec2fArrayInput(*geometry); auto vec3fArray = SetVec3fArrayInput(*geometry); @@ -808,27 +790,27 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*sharedTestState->effect)); - sharedTestState->effect = nullptr; + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*m_sharedTestState.effect)); + m_sharedTestState.effect = nullptr; report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); // restore the effect in sharedTestState after this test case - sharedTestState->effect = TestEffectCreator::createEffect(sharedTestState->getScene(), false); - ASSERT_TRUE(nullptr != sharedTestState->effect); - - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + m_sharedTestState.effect = TestEffectCreator::CreateEffect(m_sharedTestState.getScene(), false, GetParam()); + ASSERT_TRUE(nullptr != m_sharedTestState.effect); + + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedIndicesResource) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedIndicesResource) { - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); auto floatArray = SetFloatArrayInput(*geometry); auto vec2fArray = SetVec2fArrayInput(*geometry); auto vec3fArray = SetVec3fArrayInput(*geometry); @@ -838,21 +820,21 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputFloatArrayResource) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputFloatArrayResource) { - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); auto floatArray = SetFloatArrayInput(*geometry); auto vec2fArray = SetVec2fArrayInput(*geometry); auto vec3fArray = SetVec3fArrayInput(*geometry); @@ -862,21 +844,21 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputVec2ArrayResource) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputVec2ArrayResource) { - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); auto floatArray = SetFloatArrayInput(*geometry); auto vec2fArray = SetVec2fArrayInput(*geometry); auto vec3fArray = SetVec3fArrayInput(*geometry); @@ -886,21 +868,21 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputVec3ArrayResource) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputVec3ArrayResource) { - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); auto floatArray = SetFloatArrayInput(*geometry); auto vec2fArray = SetVec2fArrayInput(*geometry); auto vec3fArray = SetVec3fArrayInput(*geometry); @@ -910,21 +892,21 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputVec4ArrayResource) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedInputVec4ArrayResource) { - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); auto floatArray = SetFloatArrayInput(*geometry); auto vec2fArray = SetVec2fArrayInput(*geometry); auto vec3fArray = SetVec3fArrayInput(*geometry); @@ -934,29 +916,29 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedArrayBufferByteBlob) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedArrayBufferByteBlob) { - const auto optInputVec2 = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInputVec2 = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInputVec2.has_value()); - const auto optInputVec3 = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInputVec3 = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInputVec3.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); - ArrayBuffer* const interleavedVertices = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 5 * sizeof(float) * 3u, "vertices"); + ArrayBuffer* const interleavedVertices = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::ByteBlob, 5 * sizeof(float) * 3u, "vertices"); ASSERT_TRUE(interleavedVertices != nullptr); std::vector dummyData(interleavedVertices->getMaximumNumberOfElements(), std::byte{0x00}); interleavedVertices->updateData(0u, 1u, dummyData.data()); @@ -971,30 +953,30 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*interleavedVertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*interleavedVertices)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedArrayResourceByteBlobl) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedArrayResourceByteBlobl) { - const auto optInputVec2 = sharedTestState->effect->findAttributeInput("vec2fArrayInput"); + const auto optInputVec2 = m_sharedTestState.effect->findAttributeInput("vec2fArrayInput"); ASSERT_TRUE(optInputVec2.has_value()); - const auto optInputVec3 = sharedTestState->effect->findAttributeInput("vec3fArrayInput"); + const auto optInputVec3 = m_sharedTestState.effect->findAttributeInput("vec3fArrayInput"); ASSERT_TRUE(optInputVec3.has_value()); - Geometry* const geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* const geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); ASSERT_TRUE(geometry != nullptr); uint32_t data[4] = { 0u }; // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) interleaved vertices passed as byte blob - ArrayResource* const interleavedVertices = sharedTestState->getScene().createArrayResource(sizeof(data), reinterpret_cast(data)); + ArrayResource* const interleavedVertices = m_sharedTestState.getScene().createArrayResource(sizeof(data), reinterpret_cast(data)); ASSERT_TRUE(interleavedVertices != nullptr); auto floatArray = SetFloatArrayInput(*geometry); @@ -1007,24 +989,24 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*interleavedVertices)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*interleavedVertices)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*floatArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*floatArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithDestroyedVertexDataBuffer) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithDestroyedVertexDataBuffer) { - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); - ArrayBuffer* const vertexDataBuffer = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Float, 3, "vertices"); + ArrayBuffer* const vertexDataBuffer = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Float, 3, "vertices"); ASSERT_TRUE(vertexDataBuffer != nullptr); - const auto optInput = sharedTestState->effect->findAttributeInput("floatArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("floatArrayInput"); ASSERT_TRUE(optInput.has_value()); geometry->setInputBuffer(*optInput, *vertexDataBuffer); const float data[] = { 0 }; @@ -1038,28 +1020,28 @@ namespace ramses::internal geometry->validate(report); EXPECT_FALSE(report.hasIssue()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertexDataBuffer)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertexDataBuffer)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } - TEST_F(GeometryTest, reportsErrorWhenValidatedWithVertexDataBufferThatHasWrongType) + TEST_P(GeometryTest, reportsErrorWhenValidatedWithVertexDataBufferThatHasWrongType) { //It is possible that a data buffer gets deleted, and new data buffer gets created with same //handle. Unfortunately validate can not check if a data buffer was destroyed and re-created //but it can at least check that the assigned data buffer is of a correct type - Geometry* geometry = sharedTestState->getScene().createGeometry(*sharedTestState->effect, "geometry"); + Geometry* geometry = m_sharedTestState.getScene().createGeometry(*m_sharedTestState.effect, "geometry"); - ArrayBuffer* const vertexDataBuffer = sharedTestState->getScene().createArrayBuffer(ramses::EDataType::Float, 3, "vertices"); + ArrayBuffer* const vertexDataBuffer = m_sharedTestState.getScene().createArrayBuffer(ramses::EDataType::Float, 3, "vertices"); ASSERT_TRUE(vertexDataBuffer != nullptr); - const auto optInput = sharedTestState->effect->findAttributeInput("floatArrayInput"); + const auto optInput = m_sharedTestState.effect->findAttributeInput("floatArrayInput"); ASSERT_TRUE(optInput.has_value()); geometry->setInputBuffer(*optInput, *vertexDataBuffer); const float data[] = { 0 }; @@ -1075,18 +1057,18 @@ namespace ramses::internal //delete data buffer and create new one with same handle ramses::internal::DataBufferHandle dataBufferHandle = vertexDataBuffer->impl().getDataBufferHandle(); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vertexDataBuffer)); - ASSERT_FALSE(sharedTestState->getScene().impl().getIScene().isDataBufferAllocated(dataBufferHandle)); - sharedTestState->getScene().impl().getIScene().allocateDataBuffer(ramses::internal::EDataBufferType::VertexBuffer, ramses::internal::EDataType::Vector2F, 10 * sizeof(float), dataBufferHandle); - ASSERT_TRUE(sharedTestState->getScene().impl().getIScene().isDataBufferAllocated(dataBufferHandle)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vertexDataBuffer)); + ASSERT_FALSE(m_sharedTestState.getScene().impl().getIScene().isDataBufferAllocated(dataBufferHandle)); + m_sharedTestState.getScene().impl().getIScene().allocateDataBuffer(ramses::internal::EDataBufferType::VertexBuffer, ramses::internal::EDataType::Vector2F, 10 * sizeof(float), dataBufferHandle); + ASSERT_TRUE(m_sharedTestState.getScene().impl().getIScene().isDataBufferAllocated(dataBufferHandle)); report.clear(); geometry->validate(report); EXPECT_TRUE(report.hasError()); - EXPECT_TRUE(sharedTestState->getScene().destroy(*geometry)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec2fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec3fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*vec4fArray)); - EXPECT_TRUE(sharedTestState->getScene().destroy(*indicesArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*geometry)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec2fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec3fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*vec4fArray)); + EXPECT_TRUE(m_sharedTestState.getScene().destroy(*indicesArray)); } } diff --git a/tests/unittests/client/GlslEffectTest.cpp b/tests/unittests/client/GlslEffectTest.cpp index 17fe41ee9..f15b1062c 100644 --- a/tests/unittests/client/GlslEffectTest.cpp +++ b/tests/unittests/client/GlslEffectTest.cpp @@ -29,7 +29,14 @@ namespace ramses::internal )SHADER"; const std::string basicFragmentShader = R"SHADER( #version 320 es - out lowp vec4 colorOut; + layout(location=0) out lowp vec4 colorOut; + void main(void) + { + colorOut = vec4(0.0); + })SHADER"; + const std::string basicFragmentShader310 = R"SHADER( + #version 310 es + layout(location=0) out lowp vec4 colorOut; void main(void) { colorOut = vec4(0.0); @@ -44,7 +51,7 @@ namespace ramses::internal } )SHADER"; const std::vector emptyCompilerDefines{}; - const HashMap emptySemanticInputs{}; + const SemanticsMap emptySemanticInputs{}; protected: static void VerifyUniformInputExists(const EffectResource& effect, std::string_view uniformName) @@ -52,12 +59,23 @@ namespace ramses::internal const DataFieldHandle effecthandle = effect.getUniformDataFieldHandleByName(std::string(uniformName)); EXPECT_TRUE(effecthandle.isValid()); }; + + static void CheckSPIRVShaderSanity(const uint32_t* spirvShader) + { + //check alignment + auto spirvShaderAddress = reinterpret_cast(spirvShader); + EXPECT_EQ(0u, spirvShaderAddress % sizeof(uint32_t)); + + // simply sanity check on contents of SPIRV data + constexpr uint32_t spirvMagicNumber = 0x07230203; + EXPECT_EQ(spirvMagicNumber, spirvShader[0]); + } }; TEST_F(AGlslEffect, canParseBasicShaders) { - GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(0u, res->getUniformInputs().size()); @@ -68,8 +86,8 @@ namespace ramses::internal TEST_F(AGlslEffect, canParseBasicShaders_WithGeometryShader) { - GlslEffect ge(basicVertexShader, basicFragmentShader, basicGeometryShader, emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, basicFragmentShader, basicGeometryShader, emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(0u, res->getUniformInputs().size()); @@ -89,8 +107,8 @@ namespace ramses::internal } )SHADER"; - GlslEffect ge(basicVertexShader, basicFragmentShader, geometryShaderTriangles, emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, basicFragmentShader, geometryShaderTriangles, emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(0u, res->getUniformInputs().size()); @@ -101,8 +119,8 @@ namespace ramses::internal TEST_F(AGlslEffect, usesPassedName) { - GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, "someName"); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, "someName"); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(std::string("someName"), res->getName()); @@ -110,43 +128,43 @@ namespace ramses::internal TEST_F(AGlslEffect, rejectsEmptyVertexShader) { - GlslEffect ge("", basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge("", basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } TEST_F(AGlslEffect, rejectsBrokenVertexShader) { - GlslEffect ge("foo", basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge("foo", basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } TEST_F(AGlslEffect, rejectsEmptyFragmentShader) { - GlslEffect ge(basicVertexShader, "", "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, "", "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } TEST_F(AGlslEffect, rejectsBrokenFragmentShader) { - GlslEffect ge(basicVertexShader, "bar", "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, "bar", "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } TEST_F(AGlslEffect, acceptsEmptyGeometryShader) { - GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_TRUE(res); } TEST_F(AGlslEffect, rejectsBrokenGeometryShader) { - GlslEffect ge(basicVertexShader, basicFragmentShader, "bar", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, basicFragmentShader, "bar", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } @@ -165,8 +183,8 @@ namespace ramses::internal std::vector compilerDefines; compilerDefines.emplace_back("DEFINE_ZERO vec4(0.0)"); compilerDefines.emplace_back("DEFINE_ONE vec4(1.0)"); - GlslEffect ge(vertexShader, fragmentShader, "", compilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", compilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_THAT(res->getVertexShader(), ::testing::HasSubstr(compilerDefines[0])); @@ -191,8 +209,8 @@ namespace ramses::internal std::vector compilerDefines; compilerDefines.emplace_back("FIRST_DEFINE foo"); compilerDefines.emplace_back("OTHER_DEFINE bar"); - GlslEffect ge(vertexShader, fragmentShader, "", compilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", compilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); const char* expectedVertexShader = @@ -216,218 +234,1387 @@ namespace ramses::internal EXPECT_STREQ(expectedFragmentShader, res->getFragmentShader()); } - TEST_F(AGlslEffect, acceptsGLSLESShaders_Version300es) + TEST_F(AGlslEffect, acceptsGLSLESShaders_Version300es) + { + const char* vertexShader = R"SHADER( + #version 300 es + in lowp vec3 a_position; + out lowp vec3 v_position; + void main(void) + { + v_position = a_position; + gl_Position = vec4(a_position, 1.0); + })SHADER"; + const char* fragmentShader = R"SHADER( + #version 300 es + in lowp vec3 v_position; + out lowp vec4 color; + void main(void) + { + color = vec4(v_position, 1.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + + EXPECT_TRUE(res); + } + + TEST_F(AGlslEffect, acceptsGLSLESShaders_Version310es) + { + const char* vertexShader = R"SHADER( + #version 310 es + in lowp vec3 a_position; + out lowp vec3 v_position; + void main(void) + { + v_position = a_position; + gl_Position = vec4(a_position, 1.0); + })SHADER"; + const char* fragmentShader = R"SHADER( + #version 310 es + in lowp vec3 v_position; + out lowp vec4 color; + void main(void) + { + color = vec4(v_position, 1.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + + EXPECT_TRUE(res); + } + + TEST_F(AGlslEffect, acceptsGLSLESShaders_Version310esWithGeometryShaderExtension) + { + const char* vertexShader = R"SHADER( + #version 310 es + in lowp vec3 a_position; + out lowp vec3 v_position; + void main(void) + { + v_position = a_position; + gl_Position = vec4(a_position, 1.0); + })SHADER"; + const char* fragmentShader = R"SHADER( + #version 310 es + in lowp vec3 v_position; + out lowp vec4 color; + void main(void) + { + color = vec4(v_position, 1.0); + })SHADER"; + + const std::string geometryShader = R"SHADER( + #version 310 es + #extension GL_EXT_geometry_shader : enable + layout(points) in; + layout(points, max_vertices = 1) out; + void main() { + gl_Position = vec4(0.0); + EmitVertex(); + } + )SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, geometryShader, emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + + EXPECT_EQ(EDrawMode::Points, res->getGeometryShaderInputType()); + + EXPECT_TRUE(res); + } + + TEST_F(AGlslEffect, doesNotAcceptMixedES2VertexAndES3FragmentShaders) + { + const char* vertexShader = + "#version 100\n" + "attribute lowp vec3 a_position;\n" + "varying lowp vec3 v_position;\n" + "void main(void)\n" + "{\n" + " v_position = a_position;\n" + " gl_Position = vec4(a_position, 1.0);\n" + "}\n"; + const char* fragmentShader = + "#version 300 es\n" + "in lowp vec3 v_position;\n" + "out lowp vec4 color;\n" + "void main(void)\n" + "{\n" + " color = vec4(v_position, 1.0);\n" + "}\n"; + + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + + EXPECT_FALSE(res); + } + + TEST_F(AGlslEffect, doesNotAcceptMixedES3VertexAndES2FragmentShaders) + { + const char* vertexShader = + "#version 300 es\n" + "in lowp vec3 a_position;\n" + "out lowp vec3 v_position;\n" + "void main(void)\n" + "{\n" + " v_position = a_position;\n" + " gl_Position = vec4(a_position, 1.0);\n" + "}\n"; + const char* fragmentShader = + "#version 100\n" + "varying lowp vec3 v_position;\n" + "void main(void)\n" + "{\n" + " gl_FragColor = vec4(v_position, 1.0);\n" + "}\n"; + + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + + EXPECT_FALSE(res); + } + + TEST_F(AGlslEffect, canParseShaderInputs) + { + const char* vertexShader = R"SHADER( + #version 320 es + precision highp float; + uniform bool uniformBool1; + uniform mat4 uniformWithSemantic; + uniform mat3 matrix3x3; + uniform mat2 matrix2x2; + in vec3 attributeWithSemantic; + in float attributeFloat; + + void main(void) + { + gl_Position = vec4(0.0); + })SHADER"; + const char* fragmentShader = R"SHADER( + #version 320 es + precision highp float; + uniform bool uniformBool2; + uniform sampler2D uniformSampler; + uniform vec4 uniformVec; + out vec4 colorOut; + void main(void) + { + colorOut = vec4(0.0); + })SHADER"; + const std::string geometryShader = R"SHADER( + #version 320 es + precision highp float; + layout(points) in; + layout(points, max_vertices = 1) out; + out vec4 g_colorOut; + uniform bool uniformBool3; + uniform float uniformGeomFloat; + uniform vec4 uniformGeomVec; + uniform sampler2D uniformGeomSampler; + void main() { + gl_Position = uniformGeomVec + vec4(uniformGeomFloat); + g_colorOut = texture(uniformGeomSampler, vec2(0.0)); + EmitVertex(); + } + )SHADER"; + + const SemanticsMap semantics{ + {"uniformWithSemantic", EFixedSemantics::ModelViewProjectionMatrix}, + {"attributeWithSemantic", EFixedSemantics::CameraWorldPosition} + }; + + GlslEffect ge(vertexShader, fragmentShader, geometryShader, emptyCompilerDefines, semantics, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + const EffectInputInformationVector& attributes = res->getAttributeInputs(); + + ASSERT_EQ(11u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("uniformBool1", 1, ramses::internal::EDataType::Bool, EFixedSemantics::Invalid), uniforms[0]); + EXPECT_EQ(EffectInputInformation("uniformWithSemantic", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::ModelViewProjectionMatrix), uniforms[1]); + EXPECT_EQ(EffectInputInformation("matrix3x3", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid), uniforms[2]); + EXPECT_EQ(EffectInputInformation("matrix2x2", 1, ramses::internal::EDataType::Matrix22F, EFixedSemantics::Invalid), uniforms[3]); + EXPECT_EQ(EffectInputInformation("uniformBool2", 1, ramses::internal::EDataType::Bool, EFixedSemantics::Invalid), uniforms[4]); + EXPECT_EQ(EffectInputInformation("uniformSampler", 1, ramses::internal::EDataType::TextureSampler2D, EFixedSemantics::Invalid), uniforms[5]); + EXPECT_EQ(EffectInputInformation("uniformVec", 1, ramses::internal::EDataType::Vector4F, EFixedSemantics::Invalid), uniforms[6]); + EXPECT_EQ(EffectInputInformation("uniformBool3", 1, ramses::internal::EDataType::Bool, EFixedSemantics::Invalid), uniforms[7]); + EXPECT_EQ(EffectInputInformation("uniformGeomFloat", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid), uniforms[8]); + EXPECT_EQ(EffectInputInformation("uniformGeomVec", 1, ramses::internal::EDataType::Vector4F, EFixedSemantics::Invalid), uniforms[9]); + EXPECT_EQ(EffectInputInformation("uniformGeomSampler", 1, ramses::internal::EDataType::TextureSampler2D, EFixedSemantics::Invalid), uniforms[10]); + + ASSERT_EQ(2u, attributes.size()); + EXPECT_EQ(EffectInputInformation("attributeWithSemantic", 1, ramses::internal::EDataType::Vector3Buffer, EFixedSemantics::CameraWorldPosition), attributes[0]); + EXPECT_EQ(EffectInputInformation("attributeFloat", 1, ramses::internal::EDataType::FloatBuffer, EFixedSemantics::Invalid), attributes[1]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_UBOs) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } uniformBuffer1; + + layout(std140,binding=2) uniform uniformBuffer_t2 + { + mat4 uboMat1; + float uboFloat1; + mat3 uboMat2; + } uniformBuffer2; + + void main(void) + { + gl_Position = uniformBuffer1.uboMat1 * uniformBuffer2.uboMat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(8u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("uniformBuffer1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u}, UniformBufferElementSize{ 272u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.uboMat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.uboFloat1", 10, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u}, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 64u}), uniforms[2]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.uboMat2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 224u }), uniforms[3]); + + EXPECT_EQ(EffectInputInformation("uniformBuffer2", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 128 }, UniformBufferFieldOffset{}), uniforms[4]); + EXPECT_EQ(EffectInputInformation("uniformBuffer2.uboMat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[5]); + EXPECT_EQ(EffectInputInformation("uniformBuffer2.uboFloat1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 64u }), uniforms[6]); + EXPECT_EQ(EffectInputInformation("uniformBuffer2.uboMat2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 80u }), uniforms[7]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_AnonymousUBOs) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + }; + + layout(std140,binding=2) uniform uniformBuffer_t2 + { + mat4 ubo2Mat1; + float ubo2Float1; + mat3 ubo2Mat2; + }; + + void main(void) + { + gl_Position = ubo1Mat1 * ubo2Mat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(8u, uniforms.size()); + //The "name" assigned to anonymous UBOs by glslang is (wrong and) irrelevant, it's checked here in the test for simplification + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u}, UniformBufferElementSize{ 272u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("ubo1Mat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("ubo1Float1", 10, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u}, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 64u}), uniforms[2]); + EXPECT_EQ(EffectInputInformation("ubo1Mat2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 224u }), uniforms[3]); + + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=2", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 128 }, UniformBufferFieldOffset{}), uniforms[4]); + EXPECT_EQ(EffectInputInformation("ubo2Mat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[5]); + EXPECT_EQ(EffectInputInformation("ubo2Float1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 64u }), uniforms[6]); + EXPECT_EQ(EffectInputInformation("ubo2Mat2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 2u}, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 80u }), uniforms[7]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_UBORedefinedInOtherStage_Anonymous) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + }; + + void main(void) + { + gl_Position = ubo1Mat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + }; + out vec4 colorOut; + void main(void) + { + colorOut = ubo1Mat1 *vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(4u, uniforms.size()); + //The "name" assigned to anonymous UBOs by glslang is (wrong and) irrelevant, it's checked here in the test for simplification + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 272u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("ubo1Mat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("ubo1Float1", 10, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 64u }), uniforms[2]); + EXPECT_EQ(EffectInputInformation("ubo1Mat2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 224u }), uniforms[3]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_UBORedefinedInOtherStage_Anonymous_2) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + }; + + void main(void) + { + gl_Position = ubo1Mat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + + layout(std140,binding=2) uniform uniformBuffer_t2 + { + mat4 ubo2Mat1; + }; + + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + }; + out vec4 colorOut; + void main(void) + { + colorOut = ubo2Mat1* ubo1Mat1 *vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(6u, uniforms.size()); + //The "name" assigned to anonymous UBOs by glslang is (wrong and) irrelevant, it's checked here in the test for simplification + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=2", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 2u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("ubo2Mat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 2u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 272u }, UniformBufferFieldOffset{}), uniforms[2]); + EXPECT_EQ(EffectInputInformation("ubo1Mat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[3]); + EXPECT_EQ(EffectInputInformation("ubo1Float1", 10, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 64u }), uniforms[4]); + EXPECT_EQ(EffectInputInformation("ubo1Mat2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 224u }), uniforms[5]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_SeveralAnonymousUBOs) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t1 + { + mat4 uboMat1; + }; + + layout(std140,binding=2) uniform uniformBuffer_t2 + { + mat4 uboMat2; + }; + + void main(void) + { + gl_Position = uboMat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=3) uniform uniformBuffer_t3 + { + mat4 uboMat3; + }; + + layout(std140,binding=4) uniform uniformBuffer_t4 + { + mat4 uboMat4; + }; + out vec4 colorOut; + void main(void) + { + colorOut = uboMat4 *vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + ASSERT_EQ(8u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("uboMat1", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=2", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 2u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{}), uniforms[2]); + EXPECT_EQ(EffectInputInformation("uboMat2", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 2u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[3]); + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=3", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 3u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{}), uniforms[4]); + EXPECT_EQ(EffectInputInformation("uboMat3", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 3u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[5]); + EXPECT_EQ(EffectInputInformation("anon@ubo_binding=4", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 4u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{}), uniforms[6]); + EXPECT_EQ(EffectInputInformation("uboMat4", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 4u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[7]); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_DifferentTypeName_DifferentStages) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t1 + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + } ub1; + + void main(void) + { + gl_Position = ub1.ubo1Mat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t2 + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + } ub1; + out vec4 colorOut; + void main(void) + { + colorOut = ub1.ubo1Mat1 *vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("ub1: uniform with same name but different data type declared in multiple stages")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_DifferentTypeName_SameStage) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t1 + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + } ub1; + + layout(std140,binding=1) uniform uniformBuffer_t2 + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + } ub2; + + void main(void) + { + gl_Position = ub1.ubo1Mat1 * ub2.ubo1Mat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("ub1: several uniform buffers with same binding but different definition at binding: 1")); + } + + TEST_F(AGlslEffect, canParseShaderInputs_UBOsWithStruct) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + struct TheStruct + { + float ubFloat1; + float ubFloat2; + mat3 ubMat3; + float ubFloat3; + }; + layout(std140,binding=1) uniform uniformBuffer_t + { + TheStruct ubStruct1; + TheStruct ubStruct2; + } ub1; + + void main(void) + { + gl_Position = ub1.ubStruct1.ubFloat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(9u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("ub1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 160u }, UniformBufferFieldOffset{}), uniforms[0]); + + EXPECT_EQ(EffectInputInformation("ub1.ubStruct1.ubFloat1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct1.ubFloat2", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 4u }), uniforms[2]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct1.ubMat3", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 16u }), uniforms[3]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct1.ubFloat3", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 64u }), uniforms[4]); + + EXPECT_EQ(EffectInputInformation("ub1.ubStruct2.ubFloat1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 80u + 0u }), uniforms[5]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct2.ubFloat2", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 80u + 4u }), uniforms[6]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct2.ubMat3", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 80u + 16u }), uniforms[7]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct2.ubFloat3", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 80u + 64u }), uniforms[8]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_UBOsWithStructOfStructs) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + struct Fish + { + float plankton1; + mat3 plankton2; + }; + + struct Shark + { + Fish fish1; + Fish fish2; + }; + + layout(std140,binding=1) uniform orcaUbo_t + { + Shark shark1; + Shark shark2; + } orcaUbo; + + void main(void) + { + gl_Position = orcaUbo.shark1.fish2.plankton1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(9u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("orcaUbo", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 256u }, UniformBufferFieldOffset{}), uniforms[0]); + + EXPECT_EQ(EffectInputInformation("orcaUbo.shark1.fish1.plankton1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 4u } , UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark1.fish1.plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 48u } , UniformBufferFieldOffset{ 16u }), uniforms[2]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark1.fish2.plankton1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 4u } , UniformBufferFieldOffset{ 64u }), uniforms[3]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark1.fish2.plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 48u } , UniformBufferFieldOffset{ 80u }), uniforms[4]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark2.fish1.plankton1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 4u } , UniformBufferFieldOffset{ 128u }), uniforms[5]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark2.fish1.plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 48u } , UniformBufferFieldOffset{ 144u }), uniforms[6]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark2.fish2.plankton1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 4u } , UniformBufferFieldOffset{ 192u }), uniforms[7]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark2.fish2.plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u } , UniformBufferElementSize{ 48u } , UniformBufferFieldOffset{ 208u }), uniforms[8]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_UBOsWithStrucstOfStructArrays) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + struct Fish + { + float plankton1[2]; + mat3 plankton2; + }; + + struct Shark + { + Fish fish[2]; + }; + + layout(std140,binding=1) uniform orcaUbo_t + { + Shark shark[2]; + } orcaUbo; + + void main(void) + { + gl_Position = orcaUbo.shark[0].fish[1].plankton1[0] * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(9u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("orcaUbo", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 320u }, UniformBufferFieldOffset{}), uniforms[0]); + + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[0].fish[0].plankton1", 2, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[0].fish[0].plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 32u }), uniforms[2]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[0].fish[1].plankton1", 2, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 80u }), uniforms[3]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[0].fish[1].plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 112u }), uniforms[4]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[1].fish[0].plankton1", 2, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 160u }), uniforms[5]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[1].fish[0].plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 192u }), uniforms[6]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[1].fish[1].plankton1", 2, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 16u }, UniformBufferFieldOffset{ 240u }), uniforms[7]); + EXPECT_EQ(EffectInputInformation("orcaUbo.shark[1].fish[1].plankton2", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 272u }), uniforms[8]); + } + + TEST_F(AGlslEffect, canParseShaderInputs_UBOsWithStructArray) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + struct TheStruct + { + float ubFloat1; + float ubFloat2; + mat3 ubMat3; + float ubFloat3; + }; + layout(std140,binding=1) uniform uniformBuffer_t + { + TheStruct ubStruct[2]; + } ub1; + + void main(void) + { + gl_Position = ub1.ubStruct[0].ubFloat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(9u, uniforms.size()); + + EXPECT_EQ(EffectInputInformation("ub1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 160u }, UniformBufferFieldOffset{}), uniforms[0]); + + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[0].ubFloat1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[0].ubFloat2", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 4u }), uniforms[2]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[0].ubMat3", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 16u }), uniforms[3]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[0].ubFloat3", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 64u }), uniforms[4]); + + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[1].ubFloat1", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 80u + 0u }), uniforms[5]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[1].ubFloat2", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 80u + 4u }), uniforms[6]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[1].ubMat3", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 48u }, UniformBufferFieldOffset{ 80u + 16u }), uniforms[7]); + EXPECT_EQ(EffectInputInformation("ub1.ubStruct[1].ubFloat3", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 4u }, UniformBufferFieldOffset{ 80u + 64u }), uniforms[8]); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfUBOLayoutNotSetToStd140) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1; + mat3 uboMat2; + } uniformBuffer1; + + void main(void) + { + gl_Position = uniformBuffer1.uboMat1 * vec4(0.0); + })SHADER"; + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + out vec4 colorOut; + void main(void) + { + colorOut = vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("Failed creating effect input for uniform block uniformBuffer1 of type uniformBuffer_t. Layout must be explicitly set to std140")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfUBOIsArray) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1; + mat3 uboMat2; + } uniformBuffer[2]; + + void main(void) + { + gl_Position = vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("Failed creating effect input for uniform block uniformBuffer[] of type uniformBuffer_t. Uniform block arrays are not supported")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_InDifferentStages) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } uniformBuffer1; + + void main(void) + { + gl_Position = uniformBuffer1.uboMat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + + mat3 uboMat3; // add a field to the UBO + } uniformBuffer1; + + out vec4 colorOut; + void main(void) + { + colorOut = vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("[GLSL Compiler] Shader Program Linker Error:\n" + "ERROR: Linking unknown stage and fragment stages: fragment block member has no corresponding member in unknown stage block:\n" + " fragment stage: Block: uniformBuffer_t, Member: uboMat3\n" + " unknown stage stage: Block: uniformBuffer_t, Member: n/a")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_InDifferentStages_AnonymousUBOs) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + }; + + void main(void) + { + gl_Position = uboMat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + + mat3 uboMat3; // add a field to the UBO + }; + + out vec4 colorOut; + void main(void) + { + colorOut = vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("[GLSL Compiler] Shader Program Linker Error:\n" + "ERROR: Linking unknown stage and fragment stages: fragment block member has no corresponding member in unknown stage block:\n" + " fragment stage: Block: uniformBuffer_t, Member: uboMat3\n" + " unknown stage stage: Block: uniformBuffer_t, Member: n/a")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_InSameStage) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } uniformBuffer1; + + layout(std140,binding=1) uniform uniformBuffer_t2 + { + mat4 uboMat1; + float uboFloat1; + mat3 uboMat2; + } uniformBuffer2; + + void main(void) + { + gl_Position = uniformBuffer1.uboMat1 * uniformBuffer2.uboMat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: several uniform buffers with same binding but different definition at binding: 1")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_InSameStage_AnonymousUBOs) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + }; + + layout(std140,binding=1) uniform uniformBuffer_t2 + { + mat4 ubo2Mat1; + float ubo2Float1; + mat3 ubo2Mat2; + }; + + void main(void) + { + gl_Position = uboMat1 * ubo2Mat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("anon@ubo_binding=1: several uniform buffers with same binding but different definition at binding: 1")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_NameIsDifferent) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } uniformBuffer1; + + layout(std140,binding=1) uniform uniformBuffer_t2 + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } uniformBuffer2; + + void main(void) + { + gl_Position = uniformBuffer1.uboMat1 * uniformBuffer2.uboMat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: several uniform buffers with same binding but different definition at binding: 1")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameName_InDifferentStages) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } sameUboName; + + void main(void) + { + gl_Position = sameUboName.uboMat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + + layout(std140,binding=2) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } sameUboName; + + out vec4 colorOut; + void main(void) + { + colorOut = vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("[GLSL Compiler] Shader Program Linker Error:\n" + "ERROR: Linking unknown stage and fragment stages: Layout binding qualifier must match:\n" + " unknown stage stage: Block: uniformBuffer_t Instance: sameUboName: \"layout( binding=1 column_major std140) uniform\"\n" + " fragment stage: Block: uniformBuffer_t Instance: sameUboName: \"layout( binding=2 column_major std140) uniform")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfUBOsAndUniformUseSameName_InSameStage) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } sameUboName; + + uniform float sameUboName; + + void main(void) + { + gl_Position = sameUboName.uboMat1 * vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("vertex shader Shader Parsing Error:\nERROR: 2:9: 'sameUboName' : redefinition")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfUBOsAndUniformUseSameName_InDifferentStages) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 uboMat1; + float uboFloat1[10]; + mat3 uboMat2; + } sameUboName; + + void main(void) + { + gl_Position = sameUboName.uboMat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + + uniform float sameUboName; + + out vec4 colorOut; + void main(void) + { + colorOut = vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("[GLSL Compiler] Shader Program Linker Error:\n" + "ERROR: Linking unknown stage and fragment stages: Types must match:\n" + "ERROR: Linking unknown stage and fragment stages: Precision qualifiers must match:\n" + "ERROR: Linking unknown stage and fragment stages: Layout matrix qualifier must match:\n" + "ERROR: Linking unknown stage and fragment stages: Layout packing qualifier must match:\n" + " unknown stage stage: \"layout( binding=1 column_major std140) uniform {layout( column_major std140 offset=0) uniform highp mat4x4 uboMat1, layout( column_major std140 offset=64) uniform highp float uboFloat1[10], layout( column_major std140 offset=224) uniform highp mat3x3 uboMat2} sameUboName\"\n" + " fragment stage: \" uniform highp float sameUboName")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfDifferentUBOsUseSameBinding_UbosWithSameSize) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t1 + { + mat4 uboMat1; + mat4 uboMat2; + } uniformBuffer1; + + void main(void) + { + gl_Position = uniformBuffer1.uboMat1 * vec4(0.0); + })SHADER"; + + const char* fragmentShader = R"SHADER( + #version 310 es + precision highp float; + + layout(std140,binding=1) uniform uniformBuffer_t2 + { + mat4 uboMat1; + vec4 v1; + vec4 v2; + vec4 v3; + vec4 v4; + } uniformBuffer1; + + out vec4 colorOut; + void main(void) + { + colorOut = uniformBuffer1.v1 + vec4(0.0); + })SHADER"; + + GlslEffect ge(vertexShader, fragmentShader, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_FALSE(res); + + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: uniform with same name but different data type declared in multiple stages")); + } + + TEST_F(AGlslEffect, canParseShaderInputs_CanAssignSemanticToUbo_UsingUniformBufferBinding) { const char* vertexShader = R"SHADER( - #version 300 es - in lowp vec3 a_position; - out lowp vec3 v_position; - void main(void) + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t { - v_position = a_position; - gl_Position = vec4(a_position, 1.0); - })SHADER"; - const char* fragmentShader = R"SHADER( - #version 300 es - in lowp vec3 v_position; - out lowp vec4 color; + mat4 modelMat; + } uniformBuffer1; + void main(void) { - color = vec4(v_position, 1.0); })SHADER"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + const SemanticsMap semanticsMap{ {UniformBufferBinding{ 1u }, EFixedSemantics::ModelBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); - EXPECT_TRUE(res); + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(2u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("uniformBuffer1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::ModelBlock, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.modelMat", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); } - TEST_F(AGlslEffect, acceptsGLSLESShaders_Version310es) + TEST_F(AGlslEffect, canParseShaderInputs_CanAssignSemanticToUBO_ModelBlock) { const char* vertexShader = R"SHADER( #version 310 es - in lowp vec3 a_position; - out lowp vec3 v_position; + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 modelMat; + } uniformBuffer1; + void main(void) { - v_position = a_position; - gl_Position = vec4(a_position, 1.0); })SHADER"; - const char* fragmentShader = R"SHADER( + + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::ModelBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(2u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("uniformBuffer1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::ModelBlock, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.modelMat", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfUboSemanticInvalid_WrongTypeInModelBlock) + { + const char* vertexShader = R"SHADER( #version 310 es - in lowp vec3 v_position; - out lowp vec4 color; + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat3 modelMat; + } uniformBuffer1; + void main(void) { - color = vec4(v_position, 1.0); })SHADER"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); - - EXPECT_TRUE(res); + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::ModelBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: is a uniform buffer that does not have correct format for semantic :EFixedSemantics::ModelBlock")); } - TEST_F(AGlslEffect, acceptsGLSLESShaders_Version310esWithGeometryShaderExtension) + TEST_F(AGlslEffect, failsCreatingEffectIfUboSemanticInvalid_WrongFormatInModelBlock) { const char* vertexShader = R"SHADER( #version 310 es - in lowp vec3 a_position; - out lowp vec3 v_position; + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 modelMat; + mat4 someOtherMatrixIDecidedLooksCoolHere; + } uniformBuffer1; + void main(void) { - v_position = a_position; - gl_Position = vec4(a_position, 1.0); })SHADER"; - const char* fragmentShader = R"SHADER( + + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::ModelBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: is a uniform buffer that does not have correct format for semantic :EFixedSemantics::ModelBlock")); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfUboSemanticInvalid_SettingModelBlockOnNonUbo) + { + const char* vertexShader = R"SHADER( #version 310 es - in lowp vec3 v_position; - out lowp vec4 color; + precision highp float; + + uniform mat4 modelMat; void main(void) { - color = vec4(v_position, 1.0); })SHADER"; - const std::string geometryShader = R"SHADER( + const SemanticsMap semanticsMap{ {"modelMat", EFixedSemantics::ModelBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("modelMat: input type DATATYPE_MATRIX44F not compatible with semantic EFixedSemantics::ModelBlock")); + } + + TEST_F(AGlslEffect, canParseShaderInputs_CanAssignSemanticToUBO_CameraBlock) + { + const char* vertexShader = R"SHADER( #version 310 es - #extension GL_EXT_geometry_shader : enable - layout(points) in; - layout(points, max_vertices = 1) out; - void main() { - gl_Position = vec4(0.0); - EmitVertex(); - } - )SHADER"; + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 projMat; + mat4 viewMat; + vec3 cameraPos; + } uniformBuffer1; + + void main(void) + { + })SHADER"; - GlslEffect ge(vertexShader, fragmentShader, geometryShader, emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::CameraBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_TRUE(res); - EXPECT_EQ(EDrawMode::Points, res->getGeometryShaderInputType()); + const EffectInputInformationVector& uniforms = res->getUniformInputs(); - EXPECT_TRUE(res); + ASSERT_EQ(4u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("uniformBuffer1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::CameraBlock, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 140u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.projMat", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.viewMat", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 64u }), uniforms[2]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.cameraPos", 1, ramses::internal::EDataType::Vector3F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 12u }, UniformBufferFieldOffset{ 128u }), uniforms[3]); } - TEST_F(AGlslEffect, doesNotAcceptMixedES2VertexAndES3FragmentShaders) + TEST_F(AGlslEffect, failsCreatingEffectIfUboSemanticInvalid_WrongTypeInCameraBlock) { - const char* vertexShader = - "#version 100\n" - "attribute lowp vec3 a_position;\n" - "varying lowp vec3 v_position;\n" - "void main(void)\n" - "{\n" - " v_position = a_position;\n" - " gl_Position = vec4(a_position, 1.0);\n" - "}\n"; - const char* fragmentShader = - "#version 300 es\n" - "in lowp vec3 v_position;\n" - "out lowp vec4 color;\n" - "void main(void)\n" - "{\n" - " color = vec4(v_position, 1.0);\n" - "}\n"; + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat3 projMat; //wrong type + mat4 viewMat; + vec3 cameraPos; + } uniformBuffer1; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + void main(void) + { + })SHADER"; - EXPECT_FALSE(res); + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::CameraBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: is a uniform buffer that does not have correct format for semantic :EFixedSemantics::CameraBlock")); } - TEST_F(AGlslEffect, doesNotAcceptMixedES3VertexAndES2FragmentShaders) + TEST_F(AGlslEffect, failsCreatingEffectIfUboSemanticInvalid_WrongFormatInCameraBlock) { - const char* vertexShader = - "#version 300 es\n" - "in lowp vec3 a_position;\n" - "out lowp vec3 v_position;\n" - "void main(void)\n" - "{\n" - " v_position = a_position;\n" - " gl_Position = vec4(a_position, 1.0);\n" - "}\n"; - const char* fragmentShader = - "#version 100\n" - "varying lowp vec3 v_position;\n" - "void main(void)\n" - "{\n" - " gl_FragColor = vec4(v_position, 1.0);\n" - "}\n"; + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 modelMat; + vec3 posOutOfPos; + mat4 someOtherMatrixIDecidedLooksCoolHere; + } uniformBuffer1; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + void main(void) + { + })SHADER"; - EXPECT_FALSE(res); + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::CameraBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: is a uniform buffer that does not have correct format for semantic :EFixedSemantics::CameraBlock")); } - TEST_F(AGlslEffect, canParseShaderInputs) + TEST_F(AGlslEffect, canParseShaderInputs_CanAssignSemanticToUBO_ModelCameraBlock) { const char* vertexShader = R"SHADER( - #version 320 es + #version 310 es precision highp float; - uniform bool uniformBool1; - uniform mat4 uniformWithSemantic; - uniform mat3 matrix3x3; - uniform mat2 matrix2x2; - in vec3 attributeWithSemantic; - in float attributeFloat; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 mvpMat; + mat4 mvMat; + mat4 normalMat; + } uniformBuffer1; + void main(void) { - gl_Position = vec4(0.0); })SHADER"; - const char* fragmentShader = R"SHADER( - #version 320 es + + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::ModelCameraBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_TRUE(res); + + const EffectInputInformationVector& uniforms = res->getUniformInputs(); + + ASSERT_EQ(4u, uniforms.size()); + EXPECT_EQ(EffectInputInformation("uniformBuffer1", 1, ramses::internal::EDataType::UniformBuffer, EFixedSemantics::ModelCameraBlock, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 192u }, UniformBufferFieldOffset{}), uniforms[0]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.mvpMat", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 0u }), uniforms[1]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.mvMat", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 64u }), uniforms[2]); + EXPECT_EQ(EffectInputInformation("uniformBuffer1.normalMat", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 64u }, UniformBufferFieldOffset{ 128u }), uniforms[3]); + } + + TEST_F(AGlslEffect, failsCreatingEffectIfUboSemanticInvalid_WrongTypeInModelCameraBlock) + { + const char* vertexShader = R"SHADER( + #version 310 es precision highp float; - uniform bool uniformBool2; - uniform sampler2D uniformSampler; - uniform vec4 uniformVec; - out vec4 colorOut; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat3 mvpMat; // wrong type + mat4 mvMat; + mat4 normalMat; + } uniformBuffer1; + void main(void) { - colorOut = vec4(0.0); })SHADER"; - const std::string geometryShader = R"SHADER( - #version 320 es - precision highp float; - layout(points) in; - layout(points, max_vertices = 1) out; - out vec4 g_colorOut; - uniform bool uniformBool3; - uniform float uniformGeomFloat; - uniform vec4 uniformGeomVec; - uniform sampler2D uniformGeomSampler; - void main() { - gl_Position = uniformGeomVec + vec4(uniformGeomFloat); - g_colorOut = texture(uniformGeomSampler, vec2(0.0)); - EmitVertex(); - } - )SHADER"; - - HashMap semantics; - semantics.put("uniformWithSemantic", EFixedSemantics::ModelViewProjectionMatrix); - semantics.put("attributeWithSemantic", EFixedSemantics::CameraWorldPosition); - GlslEffect ge(vertexShader, fragmentShader, geometryShader, emptyCompilerDefines, semantics, ""); - std::unique_ptr res(ge.createEffectResource()); - ASSERT_TRUE(res); + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::ModelCameraBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: is a uniform buffer that does not have correct format for semantic :EFixedSemantics::ModelCameraBlock")); + } - const EffectInputInformationVector& uniforms = res->getUniformInputs(); - const EffectInputInformationVector& attributes = res->getAttributeInputs(); + TEST_F(AGlslEffect, failsCreatingEffectIfUboSemanticInvalid_WrongFormatInModelCameraBlock) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 mvpMat; + mat4 mvMat; + mat4 normalMat; + int wrongElement; + } uniformBuffer1; - ASSERT_EQ(11u, uniforms.size()); - EXPECT_EQ(EffectInputInformation("uniformBool1", 1, ramses::internal::EDataType::Bool, EFixedSemantics::Invalid), uniforms[0]); - EXPECT_EQ(EffectInputInformation("uniformWithSemantic", 1, ramses::internal::EDataType::Matrix44F, EFixedSemantics::ModelViewProjectionMatrix), uniforms[1]); - EXPECT_EQ(EffectInputInformation("matrix3x3", 1, ramses::internal::EDataType::Matrix33F, EFixedSemantics::Invalid), uniforms[2]); - EXPECT_EQ(EffectInputInformation("matrix2x2", 1, ramses::internal::EDataType::Matrix22F, EFixedSemantics::Invalid), uniforms[3]); - EXPECT_EQ(EffectInputInformation("uniformBool2", 1, ramses::internal::EDataType::Bool, EFixedSemantics::Invalid), uniforms[4]); - EXPECT_EQ(EffectInputInformation("uniformSampler", 1, ramses::internal::EDataType::TextureSampler2D, EFixedSemantics::Invalid), uniforms[5]); - EXPECT_EQ(EffectInputInformation("uniformVec", 1, ramses::internal::EDataType::Vector4F, EFixedSemantics::Invalid), uniforms[6]); - EXPECT_EQ(EffectInputInformation("uniformBool3", 1, ramses::internal::EDataType::Bool, EFixedSemantics::Invalid), uniforms[7]); - EXPECT_EQ(EffectInputInformation("uniformGeomFloat", 1, ramses::internal::EDataType::Float, EFixedSemantics::Invalid), uniforms[8]); - EXPECT_EQ(EffectInputInformation("uniformGeomVec", 1, ramses::internal::EDataType::Vector4F, EFixedSemantics::Invalid), uniforms[9]); - EXPECT_EQ(EffectInputInformation("uniformGeomSampler", 1, ramses::internal::EDataType::TextureSampler2D, EFixedSemantics::Invalid), uniforms[10]); + void main(void) + { + })SHADER"; - ASSERT_EQ(2u, attributes.size()); - EXPECT_EQ(EffectInputInformation("attributeWithSemantic", 1, ramses::internal::EDataType::Vector3Buffer, EFixedSemantics::CameraWorldPosition), attributes[0]); - EXPECT_EQ(EffectInputInformation("attributeFloat", 1, ramses::internal::EDataType::FloatBuffer, EFixedSemantics::Invalid), attributes[1]); + const SemanticsMap semanticsMap{ {"uniformBuffer1", EFixedSemantics::ModelCameraBlock} }; + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, semanticsMap, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_02)); + ASSERT_FALSE(res); + EXPECT_THAT(ge.getEffectErrorMessages(), + ::testing::HasSubstr("uniformBuffer1: is a uniform buffer that does not have correct format for semantic :EFixedSemantics::ModelCameraBlock")); } TEST_F(AGlslEffect, canParseSamplerInputsGLSLES2) @@ -447,8 +1634,8 @@ namespace ramses::internal "{\n" " gl_FragColor = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); @@ -485,8 +1672,8 @@ namespace ramses::internal "{\n" " color = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); @@ -524,8 +1711,8 @@ namespace ramses::internal "{\n" " color = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); @@ -559,8 +1746,8 @@ namespace ramses::internal "{\n" " gl_FragColor = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); @@ -590,11 +1777,10 @@ namespace ramses::internal " gl_FragColor = vec4(0.0);\n" "}\n"; - HashMap semantics; - semantics.put("uniformWithWrongSemantic", EFixedSemantics::ModelViewProjectionMatrix); + const SemanticsMap semantics{ {"uniformWithWrongSemantic", EFixedSemantics::ModelViewProjectionMatrix} }; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, semantics, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, semantics, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } @@ -617,8 +1803,8 @@ namespace ramses::internal "{\n" " gl_FragColor = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(0u, res->getUniformInputs().size()); @@ -643,8 +1829,8 @@ namespace ramses::internal "{\n" " gl_FragColor = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(2u, res->getUniformInputs().size()); @@ -670,8 +1856,8 @@ namespace ramses::internal "{\n" " gl_FragColor = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(8u, res->getUniformInputs().size()); @@ -710,8 +1896,8 @@ namespace ramses::internal "{\n" " gl_FragColor = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(3u, res->getUniformInputs().size()); @@ -744,8 +1930,8 @@ namespace ramses::internal "{\n" " gl_FragColor = vec4(0.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(20u, res->getUniformInputs().size()); @@ -782,12 +1968,12 @@ namespace ramses::internal void run() override { const std::vector defs; - const ramses::internal::HashMap sems; + const SemanticsMap sems; const char* v = "void main(){gl_Position=vec4(0);}"; const char* f = "void main(){gl_FragColor=vec4(0);}"; - GlslEffect eff(v, f, "", defs, sems, "myname"); - std::unique_ptr resource(eff.createEffectResource()); + GlslEffect eff(v, f, "", defs, sems, ERenderBackendCompatibility::OpenGL, "myname"); + std::unique_ptr resource(eff.createEffectResource(EFeatureLevel_Latest)); createdSuccessfully = static_cast(resource); } @@ -824,16 +2010,16 @@ namespace ramses::internal gl_FragColor = vec4(0.0); })SHADER"; - GlslEffect ge(basicVertexShader_v100, basicFragmentShader_v100, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader_v100, basicFragmentShader_v100, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(100u, ge.getShadingLanguageVersion()); } TEST_F(AGlslEffect, isAbleToParseShadersWithVersionString) { - GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); } @@ -854,8 +2040,8 @@ namespace ramses::internal return; })SHADER"; - GlslEffect ge(vertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_TRUE(res); } @@ -874,8 +2060,8 @@ namespace ramses::internal gl_Position = vec4(0.0); })SHADER"; - GlslEffect ge(vertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_TRUE(res); } @@ -902,8 +2088,8 @@ namespace ramses::internal " gl_FragColor = texture2D(tex, texCoord);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_TRUE(res); } @@ -931,8 +2117,8 @@ namespace ramses::internal " gl_FragColor = vec4(vec3(color*255), 1.0);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } @@ -959,8 +2145,8 @@ namespace ramses::internal " gl_FragColor = texture3D(tex, texCoord);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } @@ -979,8 +2165,8 @@ namespace ramses::internal " gl_FragColor = dummy;\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - const std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + const std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_TRUE(res); EXPECT_EQ(1u, res->getUniformInputs().size()); @@ -1001,8 +2187,8 @@ namespace ramses::internal " gl_FragColor = vec4(0.0, 0.0, 0.0, dummy);\n" "}\n"; - GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - const std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, fragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + const std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } @@ -1021,8 +2207,8 @@ namespace ramses::internal { gl_FragColor = vec4(0.0); })SHADER"; - GlslEffect ge(basicVertexShader_v100, basicFragmentShader_v100, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(basicVertexShader_v100, basicFragmentShader_v100, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); EXPECT_FALSE(res); } @@ -1035,8 +2221,8 @@ namespace ramses::internal { gl_Position = vec4(0.0) })SHADER"; - GlslEffect ge(vertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ""); - std::unique_ptr res(ge.createEffectResource()); + GlslEffect ge(vertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::OpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); ASSERT_FALSE(res); using namespace ::testing; EXPECT_THAT(ge.getEffectErrorMessages(), @@ -1047,4 +2233,66 @@ namespace ramses::internal "ERROR: 2:5: '' : syntax error, unexpected RIGHT_BRACE, expecting COMMA or SEMICOLON\n" "ERROR: 1 compilation errors. No code generated.\n\n\n"))); } + + TEST_F(AGlslEffect, failsToCreateEffectIfUsingUBOAndLowFeatureLevel) + { + const char* vertexShader = R"SHADER( + #version 310 es + precision highp float; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 ubo1Mat1; + float ubo1Float1[10]; + mat3 ubo1Mat2; + }; + + void main(void) + { + gl_Position = ubo1Mat1 * vec4(0.0); + })SHADER"; + + { + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + EXPECT_FALSE(ge.createEffectResource(EFeatureLevel_01)); + EXPECT_EQ(ge.getEffectErrorMessages(), "Uniform buffer objects are supported only with feature level 02 or higher"); + } + + { + GlslEffect ge(vertexShader, basicFragmentShader310, {}, emptyCompilerDefines, {}, ERenderBackendCompatibility::OpenGL, ""); + EXPECT_TRUE(ge.createEffectResource(EFeatureLevel_02)); + EXPECT_TRUE(ge.getEffectErrorMessages().empty()); + } + } + + TEST_F(AGlslEffect, canCreateEffectWithVulkanAndOpenGLCompatibility) + { + GlslEffect ge(basicVertexShader, basicFragmentShader, "", emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::VulkanAndOpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + EXPECT_NE(0u, res->getVertexShaderSPIRVSize()); + EXPECT_NE(0u, res->getFragmentShaderSPIRVSize()); + EXPECT_EQ(0u, res->getGeometryShaderSPIRVSize()); // no geometry shader + EXPECT_NE(nullptr, res->getVertexShaderSPIRV()); + EXPECT_NE(nullptr, res->getFragmentShaderSPIRV()); + + CheckSPIRVShaderSanity(res->getVertexShaderSPIRV()); + CheckSPIRVShaderSanity(res->getFragmentShaderSPIRV()); + } + + TEST_F(AGlslEffect, canCreateEffectWithVulkanAndOpenGLCompatibility_WithGeometryShader) + { + GlslEffect ge(basicVertexShader, basicFragmentShader, basicGeometryShader, emptyCompilerDefines, emptySemanticInputs, ERenderBackendCompatibility::VulkanAndOpenGL, ""); + std::unique_ptr res(ge.createEffectResource(EFeatureLevel_Latest)); + ASSERT_TRUE(res); + EXPECT_NE(0u, res->getVertexShaderSPIRVSize()); + EXPECT_NE(0u, res->getFragmentShaderSPIRVSize()); + EXPECT_NE(0u, res->getGeometryShaderSPIRVSize()); + EXPECT_NE(nullptr, res->getVertexShaderSPIRV()); + EXPECT_NE(nullptr, res->getFragmentShaderSPIRV()); + EXPECT_NE(nullptr, res->getGeometryShaderSPIRV()); + + CheckSPIRVShaderSanity(res->getVertexShaderSPIRV()); + CheckSPIRVShaderSanity(res->getFragmentShaderSPIRV()); + CheckSPIRVShaderSanity(res->getGeometryShaderSPIRV()); + } } diff --git a/tests/unittests/client/GlslParserTest.cpp b/tests/unittests/client/GlslParserTest.cpp index f2272e346..019c8eade 100644 --- a/tests/unittests/client/GlslParserTest.cpp +++ b/tests/unittests/client/GlslParserTest.cpp @@ -318,7 +318,7 @@ namespace ramses::internal EXPECT_EQ(0u, warnings.size()); } - TEST_F(AGlslParser, warnVertexLocationNotFoundButNameMatches) + TEST_F(AGlslParser, doesNotWarnVertexLocationNotFoundButNameMatches) { const auto vertexShader = R"SHADER( #version 320 es @@ -348,10 +348,7 @@ namespace ramses::internal EXPECT_TRUE(parser->valid()); EXPECT_EQ("", parser->getErrors()); auto warnings = parser->generateWarnings(); - EXPECT_EQ(1u, warnings.size()); - EXPECT_EQ(warnings[0].stage, EShaderStage::Fragment); - EXPECT_EQ(warnings[0].category, EShaderWarningCategory::InterfaceMismatch); - EXPECT_EQ(warnings[0].msg, "Fragment shader input 'layout(location = 0) foo0' is not output in vertex shader"); + EXPECT_EQ(0u, warnings.size()); } TEST_F(AGlslParser, warnFragmentLocationNotFoundButNameMatches) @@ -390,7 +387,7 @@ namespace ramses::internal EXPECT_EQ(warnings[0].msg, "Vertex shader output 'layout(location = 0) foo0' is not input in fragment shader"); } - TEST_F(AGlslParser, warnTypeMismatch) + TEST_F(AGlslParser, failsParsingIfTypesMismatch) { const auto vertexShader = R"SHADER( #version 320 es @@ -413,14 +410,10 @@ namespace ramses::internal })SHADER"; auto parser = MakeParser(vertexShader, fragmentShader); - EXPECT_TRUE(parser->valid()); - ASSERT_EQ("", parser->getErrors()); + EXPECT_FALSE(parser->valid()); + EXPECT_THAT(parser->getErrors(), ::testing::HasSubstr("ERROR: Linking vertex and fragment stages: Types must match")); auto warnings = parser->generateWarnings(); - EXPECT_EQ(1u, warnings.size()); - ASSERT_LE(1u, warnings.size()); - EXPECT_EQ(warnings[0].stage, EShaderStage::Vertex); - EXPECT_EQ(warnings[0].category, EShaderWarningCategory::InterfaceMismatch); - EXPECT_EQ(warnings[0].msg, "Type mismatch: 'foo0'. (Vertex: smooth out highp 2-component vector of float, Fragment: smooth in highp float)"); + EXPECT_EQ(0u, warnings.size()); } TEST_F(AGlslParser, warnPrecisionMismatch) @@ -483,18 +476,10 @@ namespace ramses::internal })SHADER"; auto parser = MakeParser(vertexShader, fragmentShader); - EXPECT_TRUE(parser->getProgram() != nullptr); - ASSERT_TRUE(parser->getErrors().empty()); + EXPECT_FALSE(parser->getProgram()); + EXPECT_THAT(parser->getErrors(), ::testing::HasSubstr("ERROR: Linking unknown stage and fragment stages: Precision qualifiers must match")); auto warnings = parser->generateWarnings(); - EXPECT_EQ(2u, warnings.size()); - ASSERT_LE(2u, warnings.size()); - std::sort(warnings.begin(), warnings.end(), [](const auto& w1, const auto& w2) { return w1.msg < w2.msg; }); // order might be unstable - EXPECT_EQ(warnings[0].stage, EShaderStage::Vertex); - EXPECT_EQ(warnings[0].category, EShaderWarningCategory::PrecisionMismatch); - EXPECT_EQ(warnings[0].msg, "Precision mismatch: 'foo0'. (Vertex: smooth out mediump float, Fragment: smooth in highp float)"); - EXPECT_EQ(warnings[1].stage, EShaderStage::Vertex); - EXPECT_EQ(warnings[1].category, EShaderWarningCategory::PrecisionMismatch); - EXPECT_EQ(warnings[1].msg, "Precision mismatch: 'u_bar'. (Vertex: uniform mediump 2-component vector of float, Fragment: uniform highp 2-component vector of float)"); + EXPECT_EQ(0u, warnings.size()); } TEST_F(AGlslParser, shadersFromParts) diff --git a/tests/unittests/client/NodeTransformationTest.cpp b/tests/unittests/client/NodeTransformationTest.cpp index 992a11327..3087bc322 100644 --- a/tests/unittests/client/NodeTransformationTest.cpp +++ b/tests/unittests/client/NodeTransformationTest.cpp @@ -174,7 +174,7 @@ namespace ramses::internal void SetUp() override { const ramses::internal::IScene& iscene = this->m_scene.impl().getIScene(); - ramses::internal::SceneInfo info(iscene.getSceneId(), iscene.getName()); + ramses::internal::SceneInfo info{ iscene.getSceneId(), iscene.getName() }; EXPECT_CALL(this->sceneActionsCollector, handleNewSceneAvailable(info, _)); EXPECT_CALL(this->sceneActionsCollector, handleInitializeScene(info, _)); EXPECT_TRUE(m_scene.publish(EScenePublicationMode::LocalOnly)); diff --git a/tests/unittests/client/RamsesClientTest.cpp b/tests/unittests/client/RamsesClientTest.cpp index 53755e4c3..19da6895e 100644 --- a/tests/unittests/client/RamsesClientTest.cpp +++ b/tests/unittests/client/RamsesClientTest.cpp @@ -225,7 +225,7 @@ namespace ramses::internal using ramses::internal::SceneInfo; ramses::internal::SceneId internalSceneId(sceneId.getValue()); - EXPECT_CALL(sceneActionsCollector, handleNewSceneAvailable(SceneInfo(internalSceneId, scene->getName()), _)); + EXPECT_CALL(sceneActionsCollector, handleNewSceneAvailable(SceneInfo{ internalSceneId, "" }, _)); EXPECT_CALL(sceneActionsCollector, handleInitializeScene(_, _)); EXPECT_CALL(sceneActionsCollector, handleSceneUpdate_rvr(ramses::internal::SceneId(sceneId.getValue()), _, _)); EXPECT_CALL(sceneActionsCollector, handleSceneBecameUnavailable(internalSceneId, _)); @@ -245,6 +245,10 @@ namespace ramses::internal EXPECT_EQ(client.impl().findSceneReference(sceneId_t{ 123 }, sceneId_t{ 456 }), nullptr); } +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif TEST_F(ALocalRamsesClient, returnsNullptrOnFindSceneReferenceIfWrongReferencedSceneIdIsProvided) { auto scene = client.createScene(sceneId_t{ 123 }); @@ -425,6 +429,9 @@ namespace ramses::internal testing::StrictMock handler; client.dispatchEvents(handler); } +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif TEST(ARamsesFrameworkImplInAClientLib, canCreateAClient) { diff --git a/tests/unittests/client/RamsesObjectValidationTest.cpp b/tests/unittests/client/RamsesObjectValidationTest.cpp index 0f612b7ce..91b9472ec 100644 --- a/tests/unittests/client/RamsesObjectValidationTest.cpp +++ b/tests/unittests/client/RamsesObjectValidationTest.cpp @@ -6,6 +6,19 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- +#include "ClientTestUtils.h" +#include "CreationHelper.h" +#include "ramses/client/RenderBuffer.h" +#include "ramses/client/RenderGroup.h" +#include "ramses/client/RenderPass.h" +#include "ramses/client/logic/AppearanceBinding.h" +#include "ramses/client/logic/CameraBinding.h" +#include "ramses/client/logic/MeshNodeBinding.h" +#include "ramses/client/logic/NodeBinding.h" +#include "ramses/client/logic/RenderBufferBinding.h" +#include "ramses/client/logic/RenderGroupBinding.h" +#include "ramses/client/logic/RenderGroupBindingElements.h" +#include "ramses/client/logic/RenderPassBinding.h" #include "ramses/framework/ValidationReport.h" #include "ramses/framework/RamsesObject.h" #include "impl/RamsesObjectImpl.h" @@ -149,4 +162,238 @@ namespace ramses::internal EXPECT_EQ(4u, report.getIssues().size()); } + + class ASceneObjectBindingValidation : public LocalTestClientWithScene, public ::testing::Test + { + protected: + LogicEngine* le{ m_scene.createLogicEngine() }; + }; + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfAppearanceBindingBoundMoreThanOnce) + { + auto& obj = createObject(""); + le->createAppearanceBinding(obj); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidBinding = le->createAppearanceBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfCameraBindingBoundMoreThanOnce) + { + auto& obj = createObject(""); + SetValidPerspectiveCameraParameters(obj); + le->createCameraBinding(obj); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidBinding = le->createCameraBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfMeshNodeBindingBoundMoreThanOnce) + { + auto& obj = createValidMeshNode(); + le->createMeshNodeBinding(obj); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidBinding = le->createMeshNodeBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfNodeBindingBoundMoreThanOnce) + { + auto& obj = createObject(""); + le->createNodeBinding(obj); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidBinding = le->createNodeBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfRenderBufferBindingBoundMoreThanOnce) + { + auto& obj = createObject(""); + le->createRenderBufferBinding(obj); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidBinding = le->createRenderBufferBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfRenderGroupBindingBoundMoreThanOnce) + { + auto& renderGroup = createObject(""); + MeshNode& mesh = createValidMeshNode(); + EXPECT_TRUE(renderGroup.addMeshNode(mesh, 3)); + RenderGroupBindingElements elements; + EXPECT_TRUE(elements.addElement(mesh, "Mesh Node")); + + le->createRenderGroupBinding(renderGroup, elements); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidBinding = le->createRenderGroupBinding(renderGroup, elements); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfRenderPassBindingBoundMoreThanOnce) + { + auto& renderPass = createObject(""); + le->createRenderPassBinding(renderPass); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidBinding = le->createRenderPassBinding(renderPass); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, reportsErrorIfBindingBoundMoreThanOnceInDifferentLogicEngines) + { + auto& meshnode = createValidMeshNode(); + auto* binding = le->createMeshNodeBinding(meshnode); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + LogicEngine* le2{ m_scene.createLogicEngine() }; + le2->createMeshNodeBinding(meshnode); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*binding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, validateCameraBindingAndNodeBindingToSameCameraObject) + { + auto& obj = createObject(""); + SetValidPerspectiveCameraParameters(obj); + le->createCameraBinding(obj); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + le->createNodeBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidNodeBinding = le->createNodeBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidNodeBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidCamBinding = le->createCameraBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidCamBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } + + TEST_F(ASceneObjectBindingValidation, validateMeshNodeBindingAndNodeBindingToSameMeshNodeObject) + { + auto& obj = createValidMeshNode(); + le->createMeshNodeBinding(obj); + ValidationReport report; + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + le->createNodeBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidNodeBinding = le->createNodeBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidNodeBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + + auto* invalidMeshNodeBinding = le->createMeshNodeBinding(obj); + report.clear(); + m_scene.validate(report); + EXPECT_TRUE(report.hasError()); + + le->destroy(*invalidMeshNodeBinding); + report.clear(); + m_scene.validate(report); + EXPECT_FALSE(report.hasError()); + } } diff --git a/tests/unittests/client/RamsesVersionTest.cpp b/tests/unittests/client/RamsesVersionTest.cpp index eb6bd24ae..6c892c0de 100644 --- a/tests/unittests/client/RamsesVersionTest.cpp +++ b/tests/unittests/client/RamsesVersionTest.cpp @@ -299,46 +299,6 @@ namespace ramses::internal EXPECT_FALSE(RamsesVersion::ReadFromStream(in, info, featureLevel)); } - TEST_F(ARamsesVersion, MatchesCurrentMajorMinorMatchesCurrentExactVersion) - { - RamsesVersion::VersionInfo vi; - vi.major = ::ramses_sdk::RAMSES_SDK_PROJECT_VERSION_MAJOR_INT; - vi.minor = ::ramses_sdk::RAMSES_SDK_PROJECT_VERSION_MINOR_INT; - EXPECT_TRUE(RamsesVersion::MatchesMajorMinor(::ramses_sdk::RAMSES_SDK_PROJECT_VERSION_MAJOR_INT, ::ramses_sdk::RAMSES_SDK_PROJECT_VERSION_MINOR_INT, vi)); - } - - TEST_F(ARamsesVersion, AcceptsMasterVersionZeroZeroAlways) - { - RamsesVersion::VersionInfo vi; - vi.major = 0; - vi.minor = 0; - EXPECT_TRUE(RamsesVersion::MatchesMajorMinor(0, 0, vi)); - } - - TEST_F(ARamsesVersion, AcceptsAnyFileVersionWithMasterZeroZero) - { - RamsesVersion::VersionInfo vi; - vi.major = 1; - vi.minor = 2; - EXPECT_TRUE(RamsesVersion::MatchesMajorMinor(0, 0, vi)); - } - - TEST_F(ARamsesVersion, MatchesCurrentMajorMinorFailsIfMajorDiffers) - { - RamsesVersion::VersionInfo vi; - vi.major = 55 + 1; - vi.minor = 66; - EXPECT_FALSE(RamsesVersion::MatchesMajorMinor(55, 66, vi)); - } - - TEST_F(ARamsesVersion, MatchesCurrentMajorMinorFailsIfMinorDiffers) - { - RamsesVersion::VersionInfo vi; - vi.major = 55; - vi.minor = 66 + 1; - EXPECT_FALSE(RamsesVersion::MatchesMajorMinor(55, 66, vi)); - } - TEST_F(ARamsesVersion, failsWhenFeatureLevelCompletelyMissing) { { diff --git a/tests/unittests/client/RenderBufferTest.cpp b/tests/unittests/client/RenderBufferTest.cpp index 381602082..ac6890dce 100644 --- a/tests/unittests/client/RenderBufferTest.cpp +++ b/tests/unittests/client/RenderBufferTest.cpp @@ -23,7 +23,7 @@ namespace ramses::internal class RenderBufferTest : public LocalTestClientWithScene, public testing::Test { protected: - void useInRenderPass(const ramses::RenderBuffer& rb) + ramses::RenderPass* useInRenderPass(const ramses::RenderBuffer& rb) { RenderTargetDescription rtDesc; rtDesc.addRenderBuffer(rb); @@ -34,6 +34,7 @@ namespace ramses::internal orthoCam->setViewport(0, 0, 100, 200); rp->setCamera(*orthoCam); rp->setRenderTarget(rt); + return rp; } void useInBlitPassAsSource(const ramses::RenderBuffer& rb) @@ -91,6 +92,9 @@ namespace ramses::internal ValidationReport report; renderBuffer->validate(report); EXPECT_TRUE(report.hasIssue()); + ASSERT_EQ(2, report.getIssues().size()); + EXPECT_THAT(report.getIssues()[0].message, ::testing::HasSubstr("is not set as destination in any RenderPass or BlitPass")); + EXPECT_THAT(report.getIssues()[1].message, ::testing::HasSubstr("is neither used in a TextureSampler for reading nor set as source in a BlitPass")); } TEST_F(RenderBufferTest, reportsWarningIfUsedInRenderPassButNotReferencedByAnySamplerNorUsedAsBlitPassSource) @@ -101,6 +105,8 @@ namespace ramses::internal ValidationReport report; renderBuffer->validate(report); EXPECT_TRUE(report.hasIssue()); + ASSERT_EQ(1, report.getIssues().size()); + EXPECT_THAT(report.getIssues()[0].message, ::testing::HasSubstr("is neither used in a TextureSampler for reading nor set as source in a BlitPass")); } TEST_F(RenderBufferTest, reportsWarningIfReferencedBySamplerButNotUsedInAnyRenderPassNorUsedAsBlitPassDestination) @@ -111,6 +117,22 @@ namespace ramses::internal ValidationReport report; renderBuffer->validate(report); EXPECT_TRUE(report.hasIssue()); + ASSERT_EQ(1, report.getIssues().size()); + EXPECT_THAT(report.getIssues()[0].message, ::testing::HasSubstr("is used in a TextureSampler or BlitPass for reading, but is not set as destination")); + } + + TEST_F(RenderBufferTest, reportsWarningIfReferencedBySamplerButRenderPassDisabled) + { + const ramses::RenderBuffer* renderBuffer = m_scene.createRenderBuffer(400u, 400u, ERenderBufferFormat::RGBA8, ERenderBufferAccessMode::ReadWrite); + ASSERT_TRUE(renderBuffer != nullptr); + auto rp = useInRenderPass(*renderBuffer); + rp->setEnabled(false); + m_scene.createTextureSampler(ETextureAddressMode::Clamp, ETextureAddressMode::Clamp, ETextureSamplingMethod::Nearest, ETextureSamplingMethod::Nearest, *renderBuffer); + ValidationReport report; + renderBuffer->validate(report); + EXPECT_TRUE(report.hasIssue()); + ASSERT_EQ(1, report.getIssues().size()); + EXPECT_THAT(report.getIssues()[0].message, ::testing::HasSubstr("is used in a TextureSampler or BlitPass for reading, but assigned RenderPass is not enabled")); } TEST_F(RenderBufferTest, validatesWhenUsedInRenderPassAndReferencedBySampler) diff --git a/tests/unittests/client/RenderGroupTest.cpp b/tests/unittests/client/RenderGroupTest.cpp index b21cf7c9f..a629175db 100644 --- a/tests/unittests/client/RenderGroupTest.cpp +++ b/tests/unittests/client/RenderGroupTest.cpp @@ -113,54 +113,13 @@ namespace ramses::internal EXPECT_FALSE(report.hasIssue()); } - TEST_F(ARenderGroup, validationGivesWarningIfRenderGroupIsEmpty) - { - ValidationReport report; - renderGroup.validate(report); - EXPECT_TRUE(report.hasIssue()); - } - - TEST_F(ARenderGroup, validationGivesWarningIfNestedRenderGroupIsEmpty) - { - addValidMeshToRenderGroup(); - ValidationReport report; - renderGroup.validate(report); - ASSERT_FALSE(report.hasIssue()); - - renderGroup.addRenderGroup(renderGroup2); - - report.clear(); - renderGroup.validate(report); - EXPECT_TRUE(report.hasIssue()); - } - - TEST_F(ARenderGroup, validatesIfEmptyButNestedRenderGroupIsNot) - { - // empty -> invalid - ValidationReport report; - renderGroup.validate(report); - EXPECT_TRUE(report.hasIssue()); - - // nested group also empty -> invalid - renderGroup.addRenderGroup(renderGroup2); - report.clear(); - renderGroup.validate(report); - EXPECT_TRUE(report.hasIssue()); - - // add mesh to nested group -> valid - EXPECT_TRUE(renderGroup2.addMeshNode(createValidMeshNode(), 3)); - report.clear(); - renderGroup.validate(report); - EXPECT_FALSE(report.hasIssue()); - } - TEST_F(ARenderGroup, validationGivesWarningIfRenderGroupContainsInvalidMesh) { addBrokenMeshToRenderGroup(); ValidationReport report; renderGroup.validate(report); - EXPECT_TRUE(report.hasIssue()); + EXPECT_TRUE(report.hasError()); } TEST_F(ARenderGroup, validationGivesWarningIfNestedRenderGroupContainsInvalidMesh) @@ -179,7 +138,7 @@ namespace ramses::internal report.clear(); renderGroup.validate(report); - EXPECT_TRUE(report.hasIssue()); + EXPECT_TRUE(report.hasError()); } TEST_F(ARenderGroup, canAddMeshNodes) diff --git a/tests/unittests/client/SceneCommandBufferTest.cpp b/tests/unittests/client/SceneCommandBufferTest.cpp index bfb708e98..210468c1e 100644 --- a/tests/unittests/client/SceneCommandBufferTest.cpp +++ b/tests/unittests/client/SceneCommandBufferTest.cpp @@ -20,6 +20,10 @@ namespace ramses::internal class MockSceneCommandVisitor { public: + void operator()(const SceneCommandSetProperty& cmd) + { + handleSceneCommandSetProperty(cmd); + } void operator()(const SceneCommandFlushSceneVersion& cmd) { handleSceneCommandFlushSceneVersion(cmd); @@ -37,6 +41,7 @@ namespace ramses::internal handleSceneCommandLogResourceMemoryUsage(cmd); } + MOCK_METHOD(void, handleSceneCommandSetProperty, (const SceneCommandSetProperty&)); MOCK_METHOD(void, handleSceneCommandFlushSceneVersion, (const SceneCommandFlushSceneVersion&)); MOCK_METHOD(void, handleSceneCommandValidationRequest, (const SceneCommandValidationRequest&)); MOCK_METHOD(void, handleSceneCommandDumpSceneToFile, (const SceneCommandDumpSceneToFile&), (const)); diff --git a/tests/unittests/client/SceneCommandsTest.cpp b/tests/unittests/client/SceneCommandsTest.cpp index 932bee2d0..3fa04c623 100644 --- a/tests/unittests/client/SceneCommandsTest.cpp +++ b/tests/unittests/client/SceneCommandsTest.cpp @@ -8,6 +8,7 @@ #include "ClientTestUtils.h" #include "internal/Core/Utils/File.h" +#include "ramses/client/UniformInput.h" #include @@ -79,4 +80,116 @@ namespace ramses::internal EXPECT_TRUE(getFramework().executeRamshCommand(fmt::format("dumpScene -sendViaDLT -flush {} {}", m_scene.getSceneId(), filename))); EXPECT_TRUE(getSceneDumpFile().exists()); } + + class ASetProperty : public LocalTestClientWithScene, public ::testing::Test + { + protected: + bool ramsh(const std::string& cmd) + { + auto ret = getFramework().executeRamshCommand(cmd); + getScene().flush(); + return ret; + } + MeshNode& m_mesh = createValidMeshNode(); + Appearance* m_appearance = m_mesh.getAppearance(); + }; + + TEST_F(ASetProperty, badParameters) + { + EXPECT_FALSE(ramsh("setprop")); + EXPECT_FALSE(ramsh(fmt::format("setprop {}", m_scene.getSceneId()))); + EXPECT_FALSE(ramsh(fmt::format("setprop notAScene", m_scene.getSceneId()))); + EXPECT_FALSE(ramsh(fmt::format("setprop {} notanobject", m_scene.getSceneId()))); + EXPECT_FALSE(ramsh(fmt::format("setprop {} notanobject", m_scene.getSceneId()))); + EXPECT_FALSE(ramsh(fmt::format("setprop {} {}", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_FALSE(ramsh(fmt::format("setprop {} {} notaproperty", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_FALSE(ramsh(fmt::format("setprop {} {} vis 2 extraparam", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + + EXPECT_FALSE(ramsh(fmt::format("setall {}", m_scene.getSceneId()))); + EXPECT_FALSE(ramsh(fmt::format("setall {} notAType", m_scene.getSceneId()))); + EXPECT_FALSE(ramsh(fmt::format("setall {} notAType prop value", m_scene.getSceneId()))); + EXPECT_FALSE(ramsh(fmt::format("setall {} mesh vis 2 extraparam", m_scene.getSceneId()))); + } + + TEST_F(ASetProperty, nodeVisible) + { + EXPECT_EQ(ramses::EVisibilityMode::Visible, m_mesh.getVisibility()); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} visible 1", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_EQ(ramses::EVisibilityMode::Invisible, m_mesh.getVisibility()); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} visible 2", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_EQ(ramses::EVisibilityMode::Visible, m_mesh.getVisibility()); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} visible 0", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_EQ(ramses::EVisibilityMode::Off, m_mesh.getVisibility()); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} visible invis", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_EQ(ramses::EVisibilityMode::Invisible, m_mesh.getVisibility()); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} visible visi", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_EQ(ramses::EVisibilityMode::Visible, m_mesh.getVisibility()); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} visible off", m_scene.getSceneId(), m_mesh.getSceneObjectId().getValue()))); + EXPECT_EQ(ramses::EVisibilityMode::Off, m_mesh.getVisibility()); + + EXPECT_TRUE(ramsh(fmt::format("setall {} mesh visible vis", m_scene.getSceneId()))); + EXPECT_EQ(ramses::EVisibilityMode::Visible, m_mesh.getVisibility()); + EXPECT_TRUE(ramsh(fmt::format("setall {} meshnode visible 0", m_scene.getSceneId()))); + EXPECT_EQ(ramses::EVisibilityMode::Off, m_mesh.getVisibility()); + } + + TEST_F(ASetProperty, uniform) + { + auto uniform = m_appearance->getEffect().findUniformInput("u_FragColorR"); + float value = -1.f; + ASSERT_TRUE(uniform.has_value()); + EXPECT_TRUE(m_appearance->getInputValue(*uniform, value)); + EXPECT_FLOAT_EQ(0.f, value); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} uniform.u_FragColorR 1", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getInputValue(*uniform, value)); + EXPECT_FLOAT_EQ(1.f, value); + EXPECT_TRUE(ramsh(fmt::format("setall {} appear uniform.u_FragColorR 0.5", m_scene.getSceneId()))); + EXPECT_TRUE(m_appearance->getInputValue(*uniform, value)); + EXPECT_FLOAT_EQ(0.5f, value); + } + + TEST_F(ASetProperty, depth_func) + { + EDepthFunc func = EDepthFunc::Disabled; + EXPECT_TRUE(m_appearance->getDepthFunction(func)); + EXPECT_EQ(EDepthFunc::LessEqual, func); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.func always", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthFunction(func)); + EXPECT_EQ(EDepthFunc::Always, func); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.func disabled", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthFunction(func)); + EXPECT_EQ(EDepthFunc::Disabled, func); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.func less", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthFunction(func)); + EXPECT_EQ(EDepthFunc::Less, func); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.func lessEqual", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthFunction(func)); + EXPECT_EQ(EDepthFunc::LessEqual, func); + EXPECT_TRUE(ramsh(fmt::format("setall {} appear depth.func always", m_scene.getSceneId()))); + EXPECT_TRUE(m_appearance->getDepthFunction(func)); + EXPECT_EQ(EDepthFunc::Always, func); + } + + TEST_F(ASetProperty, depth_write) + { + EDepthWrite depthWrite = EDepthWrite::Disabled; + EXPECT_TRUE(m_appearance->getDepthWriteMode(depthWrite)); + EXPECT_EQ(EDepthWrite::Enabled, depthWrite); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.write 0", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthWriteMode(depthWrite)); + EXPECT_EQ(EDepthWrite::Disabled, depthWrite); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.write 1", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthWriteMode(depthWrite)); + EXPECT_EQ(EDepthWrite::Enabled, depthWrite); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.write off", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthWriteMode(depthWrite)); + EXPECT_EQ(EDepthWrite::Disabled, depthWrite); + EXPECT_TRUE(ramsh(fmt::format("setprop {} {} depth.write on", m_scene.getSceneId(), m_appearance->getSceneObjectId().getValue()))); + EXPECT_TRUE(m_appearance->getDepthWriteMode(depthWrite)); + EXPECT_EQ(EDepthWrite::Enabled, depthWrite); + EXPECT_TRUE(ramsh(fmt::format("setall {} app depth.write off", m_scene.getSceneId()))); + EXPECT_TRUE(m_appearance->getDepthWriteMode(depthWrite)); + EXPECT_EQ(EDepthWrite::Disabled, depthWrite); + } + } diff --git a/tests/unittests/client/SceneDistributionTest.cpp b/tests/unittests/client/SceneDistributionTest.cpp index 9540d265e..87f69d88c 100644 --- a/tests/unittests/client/SceneDistributionTest.cpp +++ b/tests/unittests/client/SceneDistributionTest.cpp @@ -16,10 +16,10 @@ namespace ramses::internal { using namespace testing; - class ADistributedScene : public LocalTestClientWithScene, public ::testing::TestWithParam + class ADistributedScene : public LocalTestClientWithScene, public ::testing::TestWithParam> { public: - ADistributedScene() : LocalTestClientWithScene(GetParam()) + ADistributedScene() : LocalTestClientWithScene{ ramses::EFeatureLevel_Latest, std::get<0>(GetParam()), std::get<1>(GetParam()) } { framework.connect(); } @@ -27,10 +27,10 @@ namespace ramses::internal void publishScene() { const ramses::internal::IScene& iscene = m_scene.impl().getIScene(); - ramses::internal::SceneInfo info(iscene.getSceneId(), iscene.getName()); + ramses::internal::SceneInfo info{ iscene.getSceneId(), iscene.getName(), EScenePublicationMode::LocalOnly, iscene.getRenderBackendCompatibility(), iscene.getVulkanAPIVersion(), iscene.getSPIRVVersion() }; EXPECT_CALL(sceneActionsCollector, handleNewSceneAvailable(info, _)); EXPECT_CALL(sceneActionsCollector, handleInitializeScene(info, _)); - EXPECT_TRUE(m_scene.publish(GetParam())); + EXPECT_TRUE(m_scene.publish(std::get<0>(GetParam()))); } void unpublishScene() @@ -72,7 +72,8 @@ namespace ramses::internal INSTANTIATE_TEST_SUITE_P( ADistributedScene_Suite, ADistributedScene, - ::testing::Values(EScenePublicationMode::LocalOnly, EScenePublicationMode::LocalAndRemote)); + ::testing::Combine(::testing::ValuesIn(std::array{EScenePublicationMode::LocalOnly, EScenePublicationMode::LocalAndRemote}), + ::testing::ValuesIn(std::array{ERenderBackendCompatibility::OpenGL, ERenderBackendCompatibility::VulkanAndOpenGL}))); TEST_P(ADistributedScene, flushProducesSingleActionList) { @@ -107,7 +108,7 @@ namespace ramses::internal doSceneOperations(); publishScene(); - if (GetParam() == EScenePublicationMode::LocalOnly) // in local only case scene has to be flush to send anything + if (std::get<0>(GetParam()) == EScenePublicationMode::LocalOnly) // in local only case scene has to be flush to send anything m_scene.flush(); EXPECT_EQ(1u, sceneActionsCollector.getNumReceivedActionLists()); @@ -140,7 +141,7 @@ namespace ramses::internal ASSERT_TRUE(otherScene != nullptr); const ramses::internal::IScene& otherIScene = otherScene->impl().getIScene(); - ramses::internal::SceneInfo sceneInfo(sceneId, otherIScene.getName()); + ramses::internal::SceneInfo sceneInfo{ sceneId, otherIScene.getName() }; EXPECT_CALL(sceneActionsCollector, handleNewSceneAvailable(sceneInfo, _)); EXPECT_TRUE(otherScene->publish()); diff --git a/tests/unittests/client/SceneFactoryTest.cpp b/tests/unittests/client/SceneFactoryTest.cpp index b94a1f426..ec0bc1092 100644 --- a/tests/unittests/client/SceneFactoryTest.cpp +++ b/tests/unittests/client/SceneFactoryTest.cpp @@ -23,7 +23,7 @@ namespace ramses::internal TEST_F(ASceneFactory, createsAndDeletesScene) { - IScene* scene = factory.createScene(SceneInfo()); + IScene* scene = factory.createScene(SceneInfo(), EFeatureLevel_Latest); ASSERT_TRUE(nullptr != scene); auto sceneOwnPtr = factory.releaseScene(scene->getSceneId()); EXPECT_EQ(scene, sceneOwnPtr.get()); @@ -31,17 +31,17 @@ namespace ramses::internal TEST_F(ASceneFactory, cannotCreateTwoScenesWithTheSameId) { - IScene* scene = factory.createScene(SceneInfo()); + IScene* scene = factory.createScene(SceneInfo(), EFeatureLevel_Latest); ASSERT_TRUE(nullptr != scene); - EXPECT_TRUE(nullptr == factory.createScene(SceneInfo(scene->getSceneId()))); + EXPECT_TRUE(nullptr == factory.createScene(SceneInfo{ scene->getSceneId() }, EFeatureLevel_Latest)); } TEST_F(ASceneFactory, createsSceneWithProvidedOptions) { - const SceneSizeInformation sizeInfo(1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u); + const SceneSizeInformation sizeInfo(1u, 2u, 3u, 4u, 5u, 6u, 7u, 8u, 9u, 10u, 11u, 12u, 13u, 14u, 15u, 16u, 17u, 18u, 19u); const SceneId sceneId(456u); - const SceneInfo sceneInfo(sceneId, "sceneName"); - auto* scene = static_cast(factory.createScene(sceneInfo)); + const SceneInfo sceneInfo{ sceneId, "sceneName" }; + auto* scene = static_cast(factory.createScene(sceneInfo, EFeatureLevel_Latest)); scene->preallocateSceneSize(sizeInfo); ASSERT_TRUE(scene != nullptr); EXPECT_EQ(std::string("sceneName"), scene->getName()); diff --git a/tests/unittests/client/SceneObjectSerializationTest.cpp b/tests/unittests/client/SceneObjectSerializationTest.cpp new file mode 100644 index 000000000..b69b46893 --- /dev/null +++ b/tests/unittests/client/SceneObjectSerializationTest.cpp @@ -0,0 +1,133 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include +#include +#include + +#include "ClientTestUtils.h" +#include "internal/Core/Utils/BinaryInputStream.h" +#include "internal/Core/Utils/BinaryOutputStream.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" +#include "internal/SceneGraph/Scene/ClientScene.h" +#include "ramses/framework/EScenePublicationMode.h" +#include "ramses/framework/RamsesFrameworkTypes.h" +#include "ramses/client/Node.h" +#include "ramses/client/ramses-utils.h" +#include "impl/SerializationContext.h" +#include "impl/SceneImpl.h" +#include "impl/SceneObjectImpl.h" +#include "impl/SaveFileConfigImpl.h" +#include "impl/SerializationHelper.h" + +using namespace testing; + +namespace ramses::internal +{ + class ASceneObjectSerializationTest : public LocalTestClient, public testing::Test + { + public: + const std::string_view name{"TestNode"}; + const NodeHandle nodeHandle{0}; + const sceneObjectId_t sceneObjectId{1}; + const std::pair userId{987u, 654u}; + + void serializeTest(BinaryOutputStream& outStream) + { + SceneConfig config{sceneId_t(123u), EScenePublicationMode::LocalOnly}; + auto * scene = getClient().createScene(config); + ASSERT_NE(nullptr, scene); + + auto* node = scene->createNode(name); + ASSERT_NE(nullptr, node); + + node->setUserId(userId.first, userId.second); + + EXPECT_EQ(nodeHandle, node->impl().getNodeHandle()); + EXPECT_EQ(name, node->impl().getName()); + EXPECT_EQ(sceneObjectId, node->impl().getSceneObjectId()); + EXPECT_EQ(userId, node->impl().getUserId()); + + SaveFileConfigImpl saveFileConfig; + SerializationContext serializationContext(saveFileConfig); + ASSERT_TRUE(node->impl().serialize(outStream, serializationContext)); + + getClient().destroy(*scene); + } + }; + + TEST_F(ASceneObjectSerializationTest, canSerializeAndDeserializeNode) + { + BinaryOutputStream outStream; + serializeTest(outStream); + + SceneConfig config{sceneId_t(123u), EScenePublicationMode::LocalOnly}; + auto * scene = getClient().createScene(config); + ASSERT_NE(nullptr, scene); + + auto* node = scene->createNode(name); + ASSERT_NE(nullptr, node); + + BinaryInputStream inStream(outStream.getData()); + SceneConfigImpl sceneConfig; + DeserializationContext deserializationContext(sceneConfig, nullptr); + deserializationContext.resize(1, 1); + + ObjectIDType objectID = SerializationHelper::DeserializeObjectID(inStream); + EXPECT_NE(DeserializationContext::GetObjectIDNull(), objectID); + ASSERT_TRUE(node->impl().deserialize(inStream, deserializationContext)); + + EXPECT_EQ(nodeHandle, node->impl().getNodeHandle()); + EXPECT_EQ(name, node->impl().getName()); + EXPECT_EQ(sceneObjectId, node->impl().getSceneObjectId()); + EXPECT_EQ(userId, node->impl().getUserId()); + + getClient().destroy(*scene); + } + + TEST_F(ASceneObjectSerializationTest, canSerializeAndDeserializeNodeWithMapping) + { + BinaryOutputStream outStream; + serializeTest(outStream); + + SceneConfig config{sceneId_t(123u), EScenePublicationMode::LocalOnly}; + auto * scene = getClient().createScene(config); + ASSERT_NE(nullptr, scene); + + auto* node = scene->createNode(); + ASSERT_NE(nullptr, node); + + auto* mappedNode = scene->createNode(name); + ASSERT_NE(nullptr, mappedNode); + + BinaryInputStream inStream(outStream.getData()); + SceneConfigImpl sceneConfig; + SceneMergeHandleMapping mapping; + const NodeHandle mappedNodeHandle{1}; + const sceneObjectId_t mappedSceneObjectId{2}; + mapping.addMapping(nodeHandle, mappedNodeHandle); + + DeserializationContext deserializationContext(sceneConfig, &mapping); + deserializationContext.resize(2, 2); + + ObjectIDType objectID = SerializationHelper::DeserializeObjectID(inStream); + EXPECT_NE(DeserializationContext::GetObjectIDNull(), objectID); + ASSERT_TRUE(mappedNode->impl().deserialize(inStream, deserializationContext)); + + EXPECT_EQ(mappedNodeHandle, mappedNode->impl().getNodeHandle()); + EXPECT_EQ(name, mappedNode->impl().getName()); + EXPECT_EQ(mappedSceneObjectId, mappedNode->impl().getSceneObjectId()); + EXPECT_EQ(userId, mappedNode->impl().getUserId()); + + EXPECT_TRUE(mapping.hasMapping(sceneObjectId)); + EXPECT_EQ(mappedSceneObjectId, mapping.getMapping(sceneObjectId)); + + getClient().destroy(*scene); + } +} diff --git a/tests/unittests/client/ScenePersistationTest.cpp b/tests/unittests/client/ScenePersistationTest.cpp index 618b0d0aa..283d77b18 100644 --- a/tests/unittests/client/ScenePersistationTest.cpp +++ b/tests/unittests/client/ScenePersistationTest.cpp @@ -8,6 +8,7 @@ #include +#include "internal/Components/SceneFileHandle.h" #include "internal/PlatformAbstraction/PlatformError.h" #include "ramses/client/MeshNode.h" #include "ramses/client/TextureSampler.h" @@ -36,7 +37,6 @@ #include "ramses/client/logic/TimerNode.h" #include "ramses/client/ramses-utils.h" -#include "ScenePersistationTest.h" #include "impl/CameraNodeImpl.h" #include "impl/AppearanceImpl.h" #include "impl/DataObjectImpl.h" @@ -64,26 +64,40 @@ #include "internal/SceneGraph/Scene/ResourceChanges.h" #include "internal/SceneGraph/Scene/SceneActionApplier.h" +#include "ScenePersistationTest.h" #include "TestEffects.h" #include "FileDescriptorHelper.h" #include "UnsafeTestMemoryHelpers.h" #include "RamsesObjectTestTypes.h" +#include "FeatureLevelTestValues.h" +#include "ramses/framework/EFeatureLevel.h" #include #include #include +#include namespace ramses::internal { using namespace testing; - TEST_F(ASceneLoadedFromFile, canWriteAndReadSceneFromFile) + class ASceneLoadedFromFile : public SceneLoadedFromFile, public ::testing::TestWithParam + { + public: + ASceneLoadedFromFile() + : SceneLoadedFromFile{ GetParam() } + { + } + }; + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(ASceneLoadedFromFile); + + TEST_P(ASceneLoadedFromFile, canWriteAndReadSceneFromFile) { EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); EXPECT_NE(nullptr, m_clientForLoading.loadSceneFromFile("someTemporaryFile.ram", {})); } - TEST_F(ASceneLoadedFromFile, logsExporterMetadata) + TEST_P(ASceneLoadedFromFile, logsExporterMetadata) { ramses::SaveFileConfig config; config.setMetadataString("foo-bar-baz"); @@ -103,17 +117,17 @@ namespace ramses::internal EXPECT_THAT(logs, Contains("R.main: Exporter version: 1.2.3 (file format version 7)")); } - TEST_F(ASceneLoadedFromFile, loadedSceneHasReferenceToClientAndFrameworkAndMatchingFeaturelevel) + TEST_P(ASceneLoadedFromFile, loadedSceneHasReferenceToClientAndFrameworkAndMatchingFeaturelevel) { EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); auto loadedScene = m_clientForLoading.loadSceneFromFile("someTemporaryFile.ram", {}); ASSERT_NE(nullptr, loadedScene); EXPECT_EQ(&m_clientForLoading, &loadedScene->getRamsesClient()); EXPECT_EQ(&m_frameworkForLoader, &loadedScene->getRamsesClient().getRamsesFramework()); - EXPECT_EQ(EFeatureLevel_Latest, loadedScene->getRamsesClient().getRamsesFramework().getFeatureLevel()); + EXPECT_EQ(GetParam(), loadedScene->getRamsesClient().getRamsesFramework().getFeatureLevel()); } - TEST_F(ASceneLoadedFromFile, canWriteAndReadSceneFromMemoryWithExplicitDeleter) + TEST_P(ASceneLoadedFromFile, canWriteAndReadSceneFromMemoryWithExplicitDeleter) { EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); @@ -128,7 +142,7 @@ namespace ramses::internal EXPECT_NE(nullptr, m_clientForLoading.loadSceneFromMemory(std::move(data), fileSize, {})); } - TEST_F(ASceneLoadedFromFile, canWriteAndReadSceneFromMemoryWithImplicitDeleter) + TEST_P(ASceneLoadedFromFile, canWriteAndReadSceneFromMemoryWithImplicitDeleter) { EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); @@ -143,7 +157,7 @@ namespace ramses::internal EXPECT_NE(nullptr, RamsesUtils::LoadSceneFromMemory(m_clientForLoading, std::move(data), fileSize, {})); } - TEST_F(ASceneLoadedFromFile, canWriteAndReadSceneFromFileDescriptor) + TEST_P(ASceneLoadedFromFile, canWriteAndReadSceneFromFileDescriptor) { EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); @@ -172,7 +186,7 @@ namespace ramses::internal EXPECT_EQ(123u, scene->getSceneId().getValue()); } - TEST_F(ASceneLoadedFromFile, canReadSceneFromFileDescriptorCustomSceneId) + TEST_P(ASceneLoadedFromFile, canReadSceneFromFileDescriptorCustomSceneId) { const char* filename = "someTemporaryFile.ram"; EXPECT_TRUE(m_scene.saveToFile(filename, {})); @@ -199,7 +213,7 @@ namespace ramses::internal } } - TEST_F(ASceneLoadedFromFile, errorsReadingSceneFromFileDescriptorCustomSceneId) + TEST_P(ASceneLoadedFromFile, errorsReadingSceneFromFileDescriptorCustomSceneId) { const char* filename = "someTemporaryFile.ram"; EXPECT_TRUE(m_scene.saveToFile(filename, {})); @@ -224,7 +238,7 @@ namespace ramses::internal EXPECT_TRUE(invalidFileSize == nullptr); } - TEST_F(ASceneLoadedFromFile, canReadWriteAScene) + TEST_P(ASceneLoadedFromFile, canReadWriteAScene) { EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); @@ -242,7 +256,7 @@ namespace ramses::internal EXPECT_EQ(origSceneSizeInfo, loadedSceneSizeInfo); } - TEST_F(ASceneLoadedFromFile, validationReportSameBeforeSavingAndAfterLoadingFromFile) + TEST_P(ASceneLoadedFromFile, validationReportSameBeforeSavingAndAfterLoadingFromFile) { TestEffects::CreateTestEffectWithAllStages(this->m_scene, "eff"); ValidationReport report1; @@ -257,7 +271,7 @@ namespace ramses::internal EXPECT_EQ(report1.impl().toString(), report2.impl().toString()); } - TEST_F(ASceneLoadedFromFile, validationReportWithWarningsSameBeforeSavingAndAfterLoadingFromFile) + TEST_P(ASceneLoadedFromFile, validationReportWithWarningsSameBeforeSavingAndAfterLoadingFromFile) { TestEffects::CreateTestEffectWithAllStagesWithWarnings(this->m_scene, "eff"); ValidationReport report1; @@ -272,7 +286,7 @@ namespace ramses::internal EXPECT_EQ(report1.impl().toString(), report2.impl().toString()); } - TEST_F(ASceneLoadedFromFile, validationReportWithWarningsSameBeforeSavingAndAfterLoadingFromFileWithCompression) + TEST_P(ASceneLoadedFromFile, validationReportWithWarningsSameBeforeSavingAndAfterLoadingFromFileWithCompression) { TestEffects::CreateTestEffectWithAllStagesWithWarnings(this->m_scene, "eff"); ValidationReport report1; @@ -287,7 +301,7 @@ namespace ramses::internal EXPECT_EQ(report1.impl().toString(), report2.impl().toString()); } - TEST_F(ASceneLoadedFromFile, loadsLogic) + TEST_P(ASceneLoadedFromFile, loadsLogic) { auto* logic = this->m_scene.createLogicEngine("my logic"); auto* timer = logic->createTimerNode("dummy"); @@ -303,7 +317,33 @@ namespace ramses::internal EXPECT_TRUE(m_sceneLoaded->destroy(*loadedLogic)); } - TEST_F(ASceneLoadedFromFile, canReadWriteAPerspectiveCamera) + TEST_P(ASceneLoadedFromFile, canReadWriteASceneWithOpenGLCompatibility) + { + doWriteReadCycle(); + + EXPECT_EQ(ERenderBackendCompatibility::OpenGL, m_sceneLoaded->impl().getIScene().getRenderBackendCompatibility()); + EXPECT_EQ(EVulkanAPIVersion::Invalid, m_sceneLoaded->impl().getIScene().getVulkanAPIVersion()); + EXPECT_EQ(ESPIRVVersion::Invalid, m_sceneLoaded->impl().getIScene().getSPIRVVersion()); + } + + TEST_P(ASceneLoadedFromFile, canReadWriteASceneWithVulkanAndOpenGLCompatibility) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + auto* scene = client.createScene(SceneConfig{ sceneId_t{456u}, EScenePublicationMode::LocalOnly, ERenderBackendCompatibility::VulkanAndOpenGL }); + EXPECT_TRUE(scene->saveToFile("someTemporaryFile.ram", {})); + + CheckSceneFile("someTemporaryFile.ram", scene); + m_sceneLoaded = m_clientForLoading.loadSceneFromFile("someTemporaryFile.ram"); + ASSERT_TRUE(nullptr != m_sceneLoaded); + + EXPECT_EQ(ERenderBackendCompatibility::VulkanAndOpenGL, m_sceneLoaded->impl().getIScene().getRenderBackendCompatibility()); + EXPECT_EQ(TargetVulkanApiVersion, m_sceneLoaded->impl().getIScene().getVulkanAPIVersion()); + EXPECT_EQ(TargetSPIRVVersion, m_sceneLoaded->impl().getIScene().getSPIRVVersion()); + } + + TEST_P(ASceneLoadedFromFile, canReadWriteAPerspectiveCamera) { auto* camera = this->m_scene.createPerspectiveCamera("my cam"); camera->setFrustum(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f); @@ -332,7 +372,7 @@ namespace ramses::internal m_sceneLoaded->destroy(*loadedCamera); } - TEST_F(ASceneLoadedFromFile, canReadWriteAnOrthographicCamera) + TEST_P(ASceneLoadedFromFile, canReadWriteAnOrthographicCamera) { OrthographicCamera* camera = this->m_scene.createOrthographicCamera("my cam"); camera->setFrustum(0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f); @@ -363,7 +403,7 @@ namespace ramses::internal m_sceneLoaded->destroy(*loadedCamera); } - TEST_F(ASceneLoadedFromFile, canReadWriteAnEffect) + TEST_P(ASceneLoadedFromFile, canReadWriteAnEffect) { TestEffects::CreateTestEffectWithAllStages(this->m_scene, "eff"); @@ -422,7 +462,79 @@ namespace ramses::internal EXPECT_EQ(EDrawMode::Lines, gsInputType); } - TEST_F(ASceneLoadedFromFile, canReadWriteAnAppearance) + TEST_P(ASceneLoadedFromFile, canReadWriteAnEffect_withUBO) + { + if (GetParam() < EFeatureLevel_02) + GTEST_SKIP(); + + TestEffects::CreateTestEffectWithUBOSemantics(this->m_scene, { EEffectUniformSemantic::ModelBlock, EEffectUniformSemantic::CameraBlock, EEffectUniformSemantic::ModelCameraBlock }, "eff"); + + doWriteReadCycle(); + + auto loadedEffect = this->getObjectForTesting("eff"); + ASSERT_TRUE(loadedEffect); + + EXPECT_EQ(10u, loadedEffect->getUniformInputCount()); + + const auto uniModel = loadedEffect->getUniformInput(0u); + ASSERT_TRUE(uniModel); + EXPECT_STREQ("modelUBO", uniModel->getName()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, uniModel->getDataType()); + + const auto uniModelField1 = loadedEffect->getUniformInput(1u); + ASSERT_TRUE(uniModelField1); + EXPECT_STREQ("modelUBO.ubModelMat", uniModelField1->getName()); + EXPECT_EQ(ramses::EDataType::Matrix44F, uniModelField1->getDataType()); + EXPECT_EQ(1u, uniModelField1->getElementCount()); + + const auto uniCam = loadedEffect->getUniformInput(2u); + ASSERT_TRUE(uniCam); + EXPECT_STREQ("camUBO", uniCam->getName()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, uniCam->getDataType()); + + const auto uniCamProj = loadedEffect->getUniformInput(3u); + ASSERT_TRUE(uniCamProj); + EXPECT_STREQ("camUBO.projMat", uniCamProj->getName()); + EXPECT_EQ(ramses::EDataType::Matrix44F, uniCamProj->getDataType()); + EXPECT_EQ(1u, uniCamProj->getElementCount()); + + const auto uniCamView = loadedEffect->getUniformInput(4u); + ASSERT_TRUE(uniCamView); + EXPECT_STREQ("camUBO.viewMat", uniCamView->getName()); + EXPECT_EQ(ramses::EDataType::Matrix44F, uniCamView->getDataType()); + EXPECT_EQ(1u, uniCamView->getElementCount()); + + const auto uniCamPos = loadedEffect->getUniformInput(5u); + ASSERT_TRUE(uniCamPos); + EXPECT_STREQ("camUBO.cameraPos", uniCamPos->getName()); + EXPECT_EQ(ramses::EDataType::Vector3F, uniCamPos->getDataType()); + EXPECT_EQ(1u, uniCamPos->getElementCount()); + + const auto uniModelCam = loadedEffect->getUniformInput(6u); + ASSERT_TRUE(uniModelCam); + EXPECT_STREQ("modelCamUBO", uniModelCam->getName()); + EXPECT_EQ(ramses::EDataType::UniformBuffer, uniModelCam->getDataType()); + + const auto uniModelCamMVP = loadedEffect->getUniformInput(7u); + ASSERT_TRUE(uniModelCamMVP); + EXPECT_STREQ("modelCamUBO.mvpMat", uniModelCamMVP->getName()); + EXPECT_EQ(ramses::EDataType::Matrix44F, uniModelCamMVP->getDataType()); + EXPECT_EQ(1u, uniModelCamMVP->getElementCount()); + + const auto uniModelCamMV = loadedEffect->getUniformInput(8u); + ASSERT_TRUE(uniModelCamMV); + EXPECT_STREQ("modelCamUBO.mvMat", uniModelCamMV->getName()); + EXPECT_EQ(ramses::EDataType::Matrix44F, uniModelCamMV->getDataType()); + EXPECT_EQ(1u, uniModelCamMV->getElementCount()); + + const auto uniModelCamN = loadedEffect->getUniformInput(9u); + ASSERT_TRUE(uniModelCamN); + EXPECT_STREQ("modelCamUBO.normalMat", uniModelCamN->getName()); + EXPECT_EQ(ramses::EDataType::Matrix44F, uniModelCamN->getDataType()); + EXPECT_EQ(1u, uniModelCamN->getElementCount()); + } + + TEST_P(ASceneLoadedFromFile, canReadWriteAnAppearance) { Effect* effect = TestEffects::CreateTestEffect(this->m_scene); Appearance* appearance = this->m_scene.createAppearance(*effect, "appearance"); @@ -437,7 +549,7 @@ namespace ramses::internal EXPECT_EQ(appearance->impl().getIScene().getSceneId(), loadedAppearance->impl().getIScene().getSceneId()); } - TEST_F(ASceneLoadedFromFile, canReadWriteAnAppearanceWithGeometryShaderAndRestrictDrawMode) + TEST_P(ASceneLoadedFromFile, canReadWriteAnAppearanceWithGeometryShaderAndRestrictDrawMode) { const Effect* effect = TestEffects::CreateTestEffectWithAllStages(this->m_scene); this->m_scene.createAppearance(*effect, "appearance"); @@ -462,7 +574,7 @@ namespace ramses::internal EXPECT_FALSE(loadedAppearance->setDrawMode(EDrawMode::Points)); } - TEST_F(ASceneLoadedFromFile, canReadWriteAnAppearanceWithGeometryShaderAndRestrictDrawMode_usingSameEffect) + TEST_P(ASceneLoadedFromFile, canReadWriteAnAppearanceWithGeometryShaderAndRestrictDrawMode_usingSameEffect) { const Effect* effect1 = TestEffects::CreateTestEffectWithAllStages(this->m_scene); const Effect* effect2 = TestEffects::CreateTestEffectWithAllStages(this->m_scene); @@ -499,7 +611,7 @@ namespace ramses::internal EXPECT_FALSE(loadedAppearance2->setDrawMode(EDrawMode::Points)); } - TEST_F(ASceneLoadedFromFile, keepingTrackOfsceneObjectIdsAndFindObjectByIdWork) + TEST_P(ASceneLoadedFromFile, keepingTrackOfsceneObjectIdsAndFindObjectByIdWork) { Effect* effect = TestEffects::CreateTestEffect(this->m_scene); @@ -523,7 +635,7 @@ namespace ramses::internal EXPECT_NE(geometryIdBeforeSaveAndLoad, camera->getSceneObjectId()); } - TEST_F(ASceneLoadedFromFile, canReadWriteAnAppearanceWithUniformValuesSetOrBound) + TEST_P(ASceneLoadedFromFile, canReadWriteAnAppearanceWithUniformValuesSetOrBound) { Effect* effect = TestEffects::CreateTestEffect(this->m_scene); Appearance* appearance = this->m_scene.createAppearance(*effect, "appearance"); @@ -556,7 +668,7 @@ namespace ramses::internal EXPECT_EQ(123.f, resultG); } - TEST_F(ASceneLoadedFromFile, multipleAppearancesSharingSameEffectAreCorrectlyWrittenAndLoaded) + TEST_P(ASceneLoadedFromFile, multipleAppearancesSharingSameEffectAreCorrectlyWrittenAndLoaded) { Effect* effect = TestEffects::CreateTestEffect(this->m_scene); const Appearance* appearance1 = m_scene.createAppearance(*effect, "appearance1"); @@ -581,7 +693,7 @@ namespace ramses::internal m_sceneLoaded->destroy(*loadedAppearance1); } - TEST_F(ASceneLoadedFromFile, canReadWriteGeometry) + TEST_P(ASceneLoadedFromFile, canReadWriteGeometry) { static const uint16_t inds[3] = { 0, 1, 2 }; ArrayResource* const indices = this->m_scene.createArrayResource(3u, inds, "indices"); @@ -609,7 +721,7 @@ namespace ramses::internal EXPECT_TRUE(attributeInputOut.has_value()); } - TEST_F(ASceneLoadedFromFile, canReadWriteAMeshNode) + TEST_P(ASceneLoadedFromFile, canReadWriteAMeshNode) { MeshNode* meshNode = this->m_scene.createMeshNode("a meshnode"); @@ -624,7 +736,7 @@ namespace ramses::internal EXPECT_EQ(meshNode->impl().getFlattenedVisibility(), loadedMeshNode->impl().getFlattenedVisibility()); } - TEST_F(ASceneLoadedFromFile, canReadWriteAMeshNode_withVisibilityParent) + TEST_P(ASceneLoadedFromFile, canReadWriteAMeshNode_withVisibilityParent) { MeshNode* meshNode = this->m_scene.createMeshNode("a meshnode"); @@ -643,7 +755,7 @@ namespace ramses::internal EXPECT_EQ(loadedMeshNode->impl().getFlattenedVisibility(), EVisibilityMode::Invisible); } - TEST_F(ASceneLoadedFromFile, canReadWriteAMeshNode_withVisibilityParentOff) + TEST_P(ASceneLoadedFromFile, canReadWriteAMeshNode_withVisibilityParentOff) { MeshNode* meshNode = this->m_scene.createMeshNode("a meshnode"); @@ -662,7 +774,7 @@ namespace ramses::internal EXPECT_EQ(loadedMeshNode->impl().getFlattenedVisibility(), EVisibilityMode::Off); } - TEST_F(ASceneLoadedFromFile, canReadWriteAMeshNode_withValues) + TEST_P(ASceneLoadedFromFile, canReadWriteAMeshNode_withValues) { Effect* effect = TestEffects::CreateTestEffect(this->m_scene); Appearance* appearance = this->m_scene.createAppearance(*effect, "appearance"); @@ -694,7 +806,7 @@ namespace ramses::internal EXPECT_EQ(loadedMeshNode->impl().getFlattenedVisibility(), EVisibilityMode::Off); } - TEST_F(ASceneLoadedFromFile, canReadWriteANodeWithVisibility) + TEST_P(ASceneLoadedFromFile, canReadWriteANodeWithVisibility) { Node* visibilityNode = this->m_scene.createNode("a visibilitynode"); @@ -707,7 +819,7 @@ namespace ramses::internal EXPECT_EQ(loadedVisibilityNode->getVisibility(), EVisibilityMode::Invisible); } - TEST_F(ASceneLoadedFromFile, canReadWriteARenderGroup) + TEST_P(ASceneLoadedFromFile, canReadWriteARenderGroup) { ramses::RenderGroup* renderGroup = this->m_scene.createRenderGroup("a rendergroup"); @@ -737,7 +849,7 @@ namespace ramses::internal EXPECT_EQ(2, ramses::internal::RenderGroupUtils::FindRenderableEntry(meshB->impl().getRenderableHandle(), internalRg)->order); } - TEST_F(ASceneLoadedFromFile, canReadWriteANestedRenderGroup) + TEST_P(ASceneLoadedFromFile, canReadWriteANestedRenderGroup) { ramses::RenderGroup* renderGroup = this->m_scene.createRenderGroup("a rendergroup"); ramses::RenderGroup* nestedRenderGroup = this->m_scene.createRenderGroup("a nested rendergroup"); @@ -780,7 +892,7 @@ namespace ramses::internal EXPECT_EQ(2, ramses::internal::RenderGroupUtils::FindRenderableEntry(meshB->impl().getRenderableHandle(), internalRgNested)->order); } - TEST_F(ASceneLoadedFromFile, canReadWriteABasicRenderPass) + TEST_P(ASceneLoadedFromFile, canReadWriteABasicRenderPass) { const int32_t renderOrder = 1; @@ -800,7 +912,7 @@ namespace ramses::internal EXPECT_TRUE(loadedRenderPass->isRenderOnce()); } - TEST_F(ASceneLoadedFromFile, canReadWriteARenderPassWithACamera) + TEST_P(ASceneLoadedFromFile, canReadWriteARenderPassWithACamera) { ramses::RenderPass* renderPass = this->m_scene.createRenderPass("a renderpass"); @@ -822,7 +934,7 @@ namespace ramses::internal EXPECT_FALSE(report.hasIssue()); } - TEST_F(ASceneLoadedFromFile, canReadWriteARenderPassWhichHasRenderGroups) + TEST_P(ASceneLoadedFromFile, canReadWriteARenderPassWhichHasRenderGroups) { ramses::RenderPass* renderPass = this->m_scene.createRenderPass("a renderpass"); ramses::RenderGroup* groupA = this->m_scene.createRenderGroup("groupA"); @@ -851,7 +963,7 @@ namespace ramses::internal EXPECT_EQ(2, ramses::internal::RenderGroupUtils::FindRenderGroupEntry(groupB->impl().getRenderGroupHandle(), internalRP)->order); } - TEST_F(ASceneLoadedFromFile, canReadWriteBlitPass) + TEST_P(ASceneLoadedFromFile, canReadWriteBlitPass) { const int32_t renderOrder = 1; const ramses::RenderBuffer* srcRenderBuffer = this->m_scene.createRenderBuffer(23, 42, ERenderBufferFormat::Depth32, ERenderBufferAccessMode::WriteOnly, 0u, "src renderBuffer"); @@ -911,7 +1023,7 @@ namespace ramses::internal EXPECT_EQ(dstRenderBuffer->impl().getRenderBufferHandle(), loadedBlitPass->getDestinationRenderBuffer().impl().getRenderBufferHandle()); } - TEST_F(ASceneLoadedFromFile, canReadWritePickableObject) + TEST_P(ASceneLoadedFromFile, canReadWritePickableObject) { const ramses::EDataType geometryBufferDataType = ramses::EDataType::Vector3F; const ArrayBuffer* geometryBuffer = this->m_scene.createArrayBuffer(geometryBufferDataType, 3u, "geometryBuffer"); @@ -951,7 +1063,7 @@ namespace ramses::internal EXPECT_EQ(pickableCamera->impl().getCameraHandle(), loadedPickableObject->getCamera()->impl().getCameraHandle()); } - TEST_F(ASceneLoadedFromFile, canReadWriteRenderBuffer) + TEST_P(ASceneLoadedFromFile, canReadWriteRenderBuffer) { ramses::RenderBuffer* renderBuffer = this->m_scene.createRenderBuffer(23, 42, ERenderBufferFormat::Depth16, ERenderBufferAccessMode::WriteOnly, 4u, "a renderTarget"); @@ -970,7 +1082,7 @@ namespace ramses::internal EXPECT_EQ(renderBuffer->impl().getRenderBufferHandle(), loadedRenderBuffer->impl().getRenderBufferHandle()); } - TEST_F(ASceneLoadedFromFile, canReadWriteARenderPassWithARenderTargetAndCamera) + TEST_P(ASceneLoadedFromFile, canReadWriteARenderPassWithARenderTargetAndCamera) { ramses::RenderPass* renderPass = this->m_scene.createRenderPass("a renderpass"); @@ -1000,7 +1112,7 @@ namespace ramses::internal EXPECT_FALSE(report.hasIssue()) << report.impl().toString(); } - TEST_F(ASceneLoadedFromFile, canReadWriteRenderTarget) + TEST_P(ASceneLoadedFromFile, canReadWriteRenderTarget) { const ramses::RenderBuffer& rb = *m_scene.createRenderBuffer(16u, 8u, ERenderBufferFormat::RGBA8, ERenderBufferAccessMode::ReadWrite); RenderTargetDescription rtDesc; @@ -1020,7 +1132,7 @@ namespace ramses::internal EXPECT_EQ(renderTarget->impl().getRenderTargetHandle(), loadedRenderTarget->impl().getRenderTargetHandle()); } - TEST_F(ASceneLoadedFromFile, canReadWriteIndexDataBuffer) + TEST_P(ASceneLoadedFromFile, canReadWriteIndexDataBuffer) { ArrayBuffer& buffer = *m_scene.createArrayBuffer(ramses::EDataType::UInt32, 6u, "indexDB"); buffer.updateData(3u, 2u, std::array{ {6, 7} }.data()); @@ -1047,7 +1159,7 @@ namespace ramses::internal EXPECT_EQ(7u, bufferDataOut[4]); } - TEST_F(ASceneLoadedFromFile, canReadWriteTexture2DBuffer) + TEST_P(ASceneLoadedFromFile, canReadWriteTexture2DBuffer) { Texture2DBuffer& buffer = *m_scene.createTexture2DBuffer(ETextureFormat::RGBA8, 3, 4, 2, "textureBuffer"); buffer.updateData(0, 0, 0, 2, 2, UnsafeTestMemoryHelpers::ConvertToBytes({12, 23, 34, 56})); @@ -1102,7 +1214,7 @@ namespace ramses::internal EXPECT_EQ(78u, bufferForMip1[0]); } - TEST_F(ASceneLoadedFromFile, canReadWriteANode) + TEST_P(ASceneLoadedFromFile, canReadWriteANode) { //generic node cannot be created, therefore using group node Node* grandParent = this->m_scene.createNode("node1"); @@ -1154,7 +1266,7 @@ namespace ramses::internal EXPECT_FLOAT_EQ(3, scale.z); } - TEST_F(ASceneLoadedFromFile, canReadWriteANodeWithTranslation) + TEST_P(ASceneLoadedFromFile, canReadWriteANodeWithTranslation) { Node* node = this->m_scene.createNode("translate node 1"); Node* child = this->m_scene.createNode("groupnode child"); @@ -1179,7 +1291,7 @@ namespace ramses::internal EXPECT_FLOAT_EQ(3, translation.z); } - TEST_F(ASceneLoadedFromFile, canReadWriteANodeWithRotation) + TEST_P(ASceneLoadedFromFile, canReadWriteANodeWithRotation) { Node* node = this->m_scene.createNode("rotate node 1"); Node* child = this->m_scene.createNode("groupnode child"); @@ -1204,7 +1316,7 @@ namespace ramses::internal EXPECT_EQ(ERotationType::Euler_ZYX, loadedRotateNode->getRotationType()); } - TEST_F(ASceneLoadedFromFile, canReadWriteANodeWithScaling) + TEST_P(ASceneLoadedFromFile, canReadWriteANodeWithScaling) { Node* node = this->m_scene.createNode("scale node"); Node* child = this->m_scene.createNode("groupnode child"); @@ -1228,7 +1340,7 @@ namespace ramses::internal EXPECT_FLOAT_EQ(3, scale.z); } - TEST_F(ASceneLoadedFromFile, canReadWriteATextureSampler) + TEST_P(ASceneLoadedFromFile, canReadWriteATextureSampler) { const ETextureAddressMode wrapUMode = ETextureAddressMode::Mirror; const ETextureAddressMode wrapVMode = ETextureAddressMode::Repeat; @@ -1255,7 +1367,7 @@ namespace ramses::internal EXPECT_EQ(ERamsesObjectType::Texture2D, loadedSampler->impl().getTextureType()); } - TEST_F(ASceneLoadedFromFile, canReadWriteATextureSamplerMS) + TEST_P(ASceneLoadedFromFile, canReadWriteATextureSamplerMS) { ramses::RenderBuffer* renderBuffer = m_scene.createRenderBuffer(4u, 4u, ERenderBufferFormat::RGB8, ERenderBufferAccessMode::ReadWrite, 4u); @@ -1270,7 +1382,7 @@ namespace ramses::internal EXPECT_EQ(ERamsesObjectType::RenderBuffer, loadedSampler->impl().getTextureType()); } - TEST_F(ASceneLoadedFromFile, canReadWriteATextureSamplerExternal) + TEST_P(ASceneLoadedFromFile, canReadWriteATextureSamplerExternal) { TextureSamplerExternal* sampler = this->m_scene.createTextureSamplerExternal(ETextureSamplingMethod::Linear, ETextureSamplingMethod::Linear, "sampler"); ASSERT_TRUE(nullptr != sampler); @@ -1283,7 +1395,7 @@ namespace ramses::internal EXPECT_EQ(ERamsesObjectType::TextureSamplerExternal, loadedSampler->impl().getTextureType()); } - TEST_F(ASceneLoadedFromFile, canReadWriteSceneId) + TEST_P(ASceneLoadedFromFile, canReadWriteSceneId) { const sceneId_t sceneId = ramses::sceneId_t(1ULL << 63); ramses::Scene& mScene(*client.createScene(SceneConfig(sceneId))); @@ -1296,7 +1408,7 @@ namespace ramses::internal EXPECT_EQ(sceneId, m_sceneLoaded->getSceneId()); } - TEST_F(ASceneLoadedFromFile, defaultsToLocalPublicationMode) + TEST_P(ASceneLoadedFromFile, defaultsToLocalPublicationMode) { const sceneId_t sceneId(81); EXPECT_TRUE(client.createScene(SceneConfig(sceneId))->saveToFile("someTempararyFile.ram", {})); @@ -1306,7 +1418,7 @@ namespace ramses::internal EXPECT_EQ(EScenePublicationMode::LocalOnly, m_sceneLoaded->impl().getPublicationModeSetFromSceneConfig()); } - TEST_F(ASceneLoadedFromFile, canOverridePublicationModeForLoadedFiles_savedAsLocalOnly_loadedAsRemote) + TEST_P(ASceneLoadedFromFile, canOverridePublicationModeForLoadedFiles_savedAsLocalOnly_loadedAsRemote) { const sceneId_t sceneId(80); SceneConfig config(sceneId, EScenePublicationMode::LocalOnly); @@ -1319,7 +1431,7 @@ namespace ramses::internal EXPECT_EQ(EScenePublicationMode::LocalAndRemote, m_sceneLoaded->impl().getPublicationModeSetFromSceneConfig()); } - TEST_F(ASceneLoadedFromFile, canOverridePublicationModeForLoadedFiles_savedAsRemote_loadedAsLocalOnly) + TEST_P(ASceneLoadedFromFile, canOverridePublicationModeForLoadedFiles_savedAsRemote_loadedAsLocalOnly) { const sceneId_t sceneId(80); SceneConfig config(sceneId, EScenePublicationMode::LocalAndRemote); @@ -1330,17 +1442,17 @@ namespace ramses::internal EXPECT_EQ(EScenePublicationMode::LocalOnly, m_sceneLoaded->impl().getPublicationModeSetFromSceneConfig()); } - TEST_F(ASceneLoadedFromFile, reportsErrorWhenSavingSceneToFileWithInvalidFileName) + TEST_P(ASceneLoadedFromFile, reportsErrorWhenSavingSceneToFileWithInvalidFileName) { EXPECT_FALSE(m_scene.saveToFile("?Euler_ZYX:/dummyFile", {})); } - TEST_F(ASceneLoadedFromFile, reportsErrorWhenSavingSceneToFileWithNoFileName) + TEST_P(ASceneLoadedFromFile, reportsErrorWhenSavingSceneToFileWithNoFileName) { EXPECT_FALSE(m_scene.saveToFile({}, {})); } - TEST_F(ASceneLoadedFromFile, overwritesExistingFileWhenSavingSceneToIt) + TEST_P(ASceneLoadedFromFile, overwritesExistingFileWhenSavingSceneToIt) { { ramses::internal::File existingFile("dummyFile.dat"); @@ -1359,19 +1471,19 @@ namespace ramses::internal EXPECT_TRUE(ramses::internal::File("dummyFile.dat").remove()); } - TEST_F(ASceneLoadedFromFile, doesNotLoadSceneFromFileWithInvalidFileName) + TEST_P(ASceneLoadedFromFile, doesNotLoadSceneFromFileWithInvalidFileName) { ramses::Scene* scene = client.loadSceneFromFile("?Euler_ZYX:/dummyFile"); EXPECT_TRUE(nullptr == scene); } - TEST_F(ASceneLoadedFromFile, doesNotLoadSceneFromFileWithoutFileName) + TEST_P(ASceneLoadedFromFile, doesNotLoadSceneFromFileWithoutFileName) { EXPECT_EQ(nullptr, client.loadSceneFromFile({})); EXPECT_EQ(nullptr, client.loadSceneFromFile("")); } - TEST_F(ASceneLoadedFromFile, doesNotLoadSceneFromInvalidMemory) + TEST_P(ASceneLoadedFromFile, doesNotLoadSceneFromInvalidMemory) { auto deleter = [](const auto* ptr) { delete[] ptr; }; EXPECT_EQ(nullptr, client.loadSceneFromMemory(std::unique_ptr(nullptr, deleter), 1, {})); @@ -1381,19 +1493,19 @@ namespace ramses::internal EXPECT_EQ(nullptr, RamsesUtils::LoadSceneFromMemory(client, std::unique_ptr(new std::byte[1]), 0, {})); } - TEST_F(ASceneLoadedFromFile, doesNotLoadSceneFromInvalidFileDescriptor) + TEST_P(ASceneLoadedFromFile, doesNotLoadSceneFromInvalidFileDescriptor) { EXPECT_EQ(nullptr, client.loadSceneFromFileDescriptor(-1, 0, 1, {})); EXPECT_EQ(nullptr, client.loadSceneFromFileDescriptor(1, 0, 0, {})); } - TEST_F(ASceneLoadedFromFile, doesNotLoadSceneFromUnexistingFile) + TEST_P(ASceneLoadedFromFile, doesNotLoadSceneFromUnexistingFile) { ramses::Scene* scene = client.loadSceneFromFile("ZEGETWTWAGTGSDGEg_thisfilename_in_this_directory_should_not_exist_DSAFDSFSTEZHDXHB"); EXPECT_TRUE(nullptr == scene); } - TEST_F(ASceneLoadedFromFile, canHandleAllZeroFileOnSceneLoad) + TEST_P(ASceneLoadedFromFile, canHandleAllZeroFileOnSceneLoad) { const char* filename = "allzerofile.dat"; { @@ -1408,7 +1520,7 @@ namespace ramses::internal EXPECT_TRUE(scene == nullptr); } - TEST_F(ASceneLoadedFromFile, cannotLoadSameFileTwice) + TEST_P(ASceneLoadedFromFile, cannotLoadSameFileTwice) { const sceneId_t sceneId = ramses::sceneId_t(1ULL << 63); ramses::Scene* scene = client.createScene(SceneConfig(sceneId)); @@ -1420,7 +1532,7 @@ namespace ramses::internal EXPECT_EQ(nullptr, m_clientForLoading.loadSceneFromFile("someTempararyFile.ram")); } - TEST_F(ASceneLoadedFromFile, cannotLoadScenesWithSameSceneIdTwice) + TEST_P(ASceneLoadedFromFile, cannotLoadScenesWithSameSceneIdTwice) { const sceneId_t sceneId = ramses::sceneId_t(1ULL << 63); @@ -1441,13 +1553,13 @@ namespace ramses::internal EXPECT_EQ(nullptr, m_clientForLoading.loadSceneFromFile("someTempararyFile_2.ram")); } - TEST_F(ASceneLoadedFromFile, cannotLoadSceneWithMismatchingFeatureLevel) + TEST_P(ASceneLoadedFromFile, cannotLoadSceneWithMismatchingFeatureLevel) { SaveSceneWithFeatureLevelToFile(EFeatureLevel(99), "someTemporaryFile.ram"); EXPECT_EQ(nullptr, m_clientForLoading.loadSceneFromFile("someTemporaryFile.ram")); } - TEST_F(ASceneLoadedFromFile, canGetFeatureLevelFromSceneFile) + TEST_P(ASceneLoadedFromFile, canGetFeatureLevelFromSceneFile) { SaveSceneWithFeatureLevelToFile(EFeatureLevel_Latest, "someTemporaryFile.ram"); @@ -1456,7 +1568,7 @@ namespace ramses::internal EXPECT_EQ(EFeatureLevel_Latest, featureLevel); } - TEST_F(ASceneLoadedFromFile, failsToGetFeatureLevelFromFileWithUnknownFeatureLevel) + TEST_P(ASceneLoadedFromFile, failsToGetFeatureLevelFromFileWithUnknownFeatureLevel) { SaveSceneWithFeatureLevelToFile(EFeatureLevel(99), "someTemporaryFile.ram"); @@ -1464,13 +1576,13 @@ namespace ramses::internal EXPECT_FALSE(RamsesClient::GetFeatureLevelFromFile("someTemporaryFile.ram", featureLevel)); } - TEST_F(ASceneLoadedFromFile, failsToGetFeatureLevelFromNonexistingFile) + TEST_P(ASceneLoadedFromFile, failsToGetFeatureLevelFromNonexistingFile) { EFeatureLevel featureLevel = EFeatureLevel_01; EXPECT_FALSE(RamsesClient::GetFeatureLevelFromFile("doesnt.Exist", featureLevel)); } - TEST_F(ASceneLoadedFromFile, canGetFeatureLevelFromSceneFileViaFileDescriptor) + TEST_P(ASceneLoadedFromFile, canGetFeatureLevelFromSceneFileViaFileDescriptor) { SaveSceneWithFeatureLevelToFile(EFeatureLevel_Latest, "someTemporaryFile.ram"); @@ -1499,14 +1611,14 @@ namespace ramses::internal EXPECT_EQ(EFeatureLevel_Latest, featureLevel); } - TEST_F(ASceneLoadedFromFile, failsToGetFeatureLevelFromInvalidFileDescriptor) + TEST_P(ASceneLoadedFromFile, failsToGetFeatureLevelFromInvalidFileDescriptor) { EFeatureLevel featureLevel = EFeatureLevel_01; EXPECT_FALSE(RamsesClient::GetFeatureLevelFromFile(-1, 0u, 10u, featureLevel)); EXPECT_FALSE(RamsesClient::GetFeatureLevelFromFile(1, 0u, 0u, featureLevel)); } - TEST_F(ASceneLoadedFromFile, canReadWriteTransformDataSlot) + TEST_P(ASceneLoadedFromFile, canReadWriteTransformDataSlot) { Node* node = this->m_scene.createNode("node"); @@ -1528,7 +1640,7 @@ namespace ramses::internal EXPECT_EQ(ramses::internal::EDataSlotType::TransformationConsumer, this->m_sceneLoaded->impl().getIScene().getDataSlot(slotHandle).type); } - TEST_F(ASceneLoadedFromFile, canReadWriteDataObject) + TEST_P(ASceneLoadedFromFile, canReadWriteDataObject) { float setValue = 5.0f; auto data = this->m_scene.createDataObject(ramses::EDataType::Float, "floatData"); @@ -1545,7 +1657,11 @@ namespace ramses::internal EXPECT_EQ(setValue, loadedValue); } - TEST_F(ASceneLoadedFromFile, canReadWriteSceneReferences) +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + TEST_P(ASceneLoadedFromFile, canReadWriteSceneReferences) { constexpr ramses::sceneId_t referencedSceneId(444); auto sr1 = this->m_scene.createSceneReference(referencedSceneId, "scene ref"); @@ -1567,8 +1683,11 @@ namespace ramses::internal EXPECT_EQ(referencedSceneId2, loadedSceneRef2->getReferencedSceneId()); EXPECT_EQ(ramses::RendererSceneState::Rendered, loadedSceneRef2->getRequestedState()); } +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif - TEST_F(ASceneLoadedFromFile, savesLLResourceOnlyOnceIfTwoHLResourcesReferToIt) + TEST_P(ASceneLoadedFromFile, savesLLResourceOnlyOnceIfTwoHLResourcesReferToIt) { std::vector inds(300); std::iota(inds.begin(), inds.end(), static_cast(0u)); @@ -1585,65 +1704,7 @@ namespace ramses::internal EXPECT_GT(1600, size) << "scene file size exceeds allowed max size. verify that LL resource is saved only once before adapting this number"; } - template - struct TestHelper - { - static T* create(ASceneLoadedFromFileTemplated* fixture, ramses::RamsesClient& /*unused*/, ramses::Scene& /*unused*/) - { - return &fixture->template createObject("a node"); - } - }; - - TYPED_TEST_SUITE(ASceneLoadedFromFileTemplated, NodeTypes); - TYPED_TEST(ASceneLoadedFromFileTemplated, canReadWriteAllNodes) - { - auto node = TestHelper::create(this, this->client, this->m_scene); - - node->setVisibility(EVisibilityMode::Invisible); - - auto child = &this->template createObject("child"); - auto parent = &this->template createObject("parent"); - - node->setTranslation({1, 2, 3}); - node->setRotation({4, 5, 6}, ERotationType::Euler_XZX); - node->setScaling({7, 8, 9}); - node->addChild(*child); - node->setParent(*parent); - - this->m_scene.flush(); - - this->doWriteReadCycle(); - - const auto loadedSuperNode = this->template getObjectForTesting("a node"); - const auto loadedChild = this->template getObjectForTesting("child"); - const auto loadedParent = this->template getObjectForTesting("parent"); - - ASSERT_TRUE(nullptr != loadedSuperNode); - ASSERT_TRUE(nullptr != loadedChild); - ASSERT_TRUE(nullptr != loadedParent); - - ASSERT_EQ(1u, loadedSuperNode->getChildCount()); - EXPECT_EQ(loadedChild, loadedSuperNode->getChild(0u)); - EXPECT_EQ(loadedParent, loadedSuperNode->getParent()); - vec3f value; - EXPECT_TRUE(loadedSuperNode->getTranslation(value)); - EXPECT_FLOAT_EQ(1, value.x); - EXPECT_FLOAT_EQ(2, value.y); - EXPECT_FLOAT_EQ(3, value.z); - EXPECT_TRUE(loadedSuperNode->getRotation(value)); - EXPECT_FLOAT_EQ(4, value.x); - EXPECT_FLOAT_EQ(5, value.y); - EXPECT_FLOAT_EQ(6, value.z); - EXPECT_EQ(ERotationType::Euler_XZX, loadedSuperNode->getRotationType()); - EXPECT_TRUE(loadedSuperNode->getScaling(value)); - EXPECT_FLOAT_EQ(7, value.x); - EXPECT_FLOAT_EQ(8, value.y); - EXPECT_FLOAT_EQ(9, value.z); - - EXPECT_EQ(loadedSuperNode->getVisibility(), EVisibilityMode::Invisible); - } - - TEST_F(ASceneLoadedFromFile, compressedFileIsSmallerThanUncompressedWhenUsingSaveSceneToFile) + TEST_P(ASceneLoadedFromFile, compressedFileIsSmallerThanUncompressedWhenUsingSaveSceneToFile) { ramses::Scene* scene = client.createScene(SceneConfig(sceneId_t(1))); const std::vector data(1000u, 0u); @@ -1669,7 +1730,7 @@ namespace ramses::internal EXPECT_GT(uncompressedFileSize, compressedFileSize); } - TEST_F(ASceneLoadedFromFile, savedFilesAreConsistent) + TEST_P(ASceneLoadedFromFile, savedFilesAreConsistent) { for (const auto& name : { "ts1.ramscene", "ts2.ramscene", "ts3.ramscene", "ts4.ramscene", "ts5.ramscene", "ts6.ramscene" }) { @@ -1682,27 +1743,190 @@ namespace ramses::internal } } - TEST_F(ASceneLoadedFromFile, closesSceneFileAndLowLevelResourceWhenDestroyed) + TEST_P(ASceneLoadedFromFile, closesSceneFileAndLowLevelResourceWhenDestroyed) + { + EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); + + m_sceneLoaded = m_clientForLoading.loadSceneFromFile("someTemporaryFile.ram", {}); + ASSERT_TRUE(nullptr != m_sceneLoaded); + + auto handles = m_sceneLoaded->impl().getSceneFileHandles(); + for (const auto& handle: handles) + { + EXPECT_TRUE(m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)); + } + m_clientForLoading.destroy(*m_sceneLoaded); + + // scene gets destroyed asynchronously, so we can't just test after the destroy + // unfortunately there is no callback, but I don't want to skip the test + // => wait for it to happen in finite time, we don't test for performance here + uint32_t ticks = 60000u; + for (; ticks > 0 && !handles.empty(); --ticks) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::vector notRemovedHandles; + notRemovedHandles.reserve(handles.size()); + for (const auto& handle: handles) + { + if (m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)) + { + notRemovedHandles.push_back(handle); + } + } + handles.swap(notRemovedHandles); + } + EXPECT_GT(ticks, 0u); + } + + TEST_P(ASceneLoadedFromFile, closesSceneFileAndLowLevelResourceOfMergedSceneWhenDestroyed) + { + EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); + EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile2.ram", {})); + + m_sceneLoaded = m_clientForLoading.loadSceneFromFile("someTemporaryFile.ram", {}); + ASSERT_TRUE(nullptr != m_sceneLoaded); + + bool success = m_clientForLoading.mergeSceneFromFile(*m_sceneLoaded, "someTemporaryFile2.ram"); + // scene merge is supported starting from feature level 02 + if (GetParam() < EFeatureLevel::EFeatureLevel_02) + { + EXPECT_FALSE(success); + return; + } + ASSERT_TRUE(success); + + auto handles = m_sceneLoaded->impl().getSceneFileHandles(); + EXPECT_EQ(2, handles.size()); + + for (const auto& handle: handles) + { + EXPECT_TRUE(m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)); + } + m_clientForLoading.destroy(*m_sceneLoaded); + + // scene gets destroyed asynchronously, so we can't just test after the destroy + // unfortunately there is no callback, but I don't want to skip the test + // => wait for it to happen in finite time, we don't test for performance here + uint32_t ticks = 60000u; + for (; ticks > 0 && !handles.empty(); --ticks) + { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + std::vector notRemovedHandles; + notRemovedHandles.reserve(handles.size()); + for (const auto& handle: handles) + { + if (m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)) + { + notRemovedHandles.push_back(handle); + } + } + handles.swap(notRemovedHandles); + } + EXPECT_GT(ticks, 0u); + } + + TEST_P(ASceneLoadedFromFile, closesSceneFileAndLowLevelResourceOfSameMergedSceneWhenDestroyed) { EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); m_sceneLoaded = m_clientForLoading.loadSceneFromFile("someTemporaryFile.ram", {}); ASSERT_TRUE(nullptr != m_sceneLoaded); - const ramses::internal::SceneFileHandle handle = m_sceneLoaded->impl().getSceneFileHandle(); - EXPECT_TRUE(m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)); + bool success = m_clientForLoading.mergeSceneFromFile(*m_sceneLoaded, "someTemporaryFile.ram"); + // scene merge is supported starting from feature level 02 + if (GetParam() < EFeatureLevel::EFeatureLevel_02) + { + EXPECT_FALSE(success); + return; + } + ASSERT_TRUE(success); + + auto handles = m_sceneLoaded->impl().getSceneFileHandles(); + EXPECT_EQ(2, handles.size()); + + for (const auto& handle: handles) + { + EXPECT_TRUE(m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)); + } m_clientForLoading.destroy(*m_sceneLoaded); // scene gets destroyed asynchronously, so we can't just test after the destroy // unfortunately there is no callback, but I don't want to skip the test // => wait for it to happen in finite time, we don't test for performance here uint32_t ticks = 60000u; - for (; ticks > 0; --ticks) + for (; ticks > 0 && !handles.empty(); --ticks) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); - if (!m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)) - break; + std::vector notRemovedHandles; + notRemovedHandles.reserve(handles.size()); + for (const auto& handle: handles) + { + if (m_clientForLoading.impl().getClientApplication().hasResourceFile(handle)) + { + notRemovedHandles.push_back(handle); + } + } + handles.swap(notRemovedHandles); } EXPECT_GT(ticks, 0u); } + + template + class ASceneLoadedFromFileNodesTest : public SceneLoadedFromFile, public ::testing::Test + { + public: + ASceneLoadedFromFileNodesTest() + : SceneLoadedFromFile{ EFeatureLevel_Latest } + { + } + }; + + TYPED_TEST_SUITE(ASceneLoadedFromFileNodesTest, NodeTypes); + TYPED_TEST(ASceneLoadedFromFileNodesTest, canReadWriteAllNodes) + { + auto node = &this->template createObject("a node"); + + node->setVisibility(EVisibilityMode::Invisible); + + auto child = &this->template createObject("child"); + auto parent = &this->template createObject("parent"); + + node->setTranslation({ 1, 2, 3 }); + node->setRotation({ 4, 5, 6 }, ERotationType::Euler_XZX); + node->setScaling({ 7, 8, 9 }); + node->addChild(*child); + node->setParent(*parent); + + this->m_scene.flush(); + + this->doWriteReadCycle(); + + const auto loadedSuperNode = this->template getObjectForTesting("a node"); + const auto loadedChild = this->template getObjectForTesting("child"); + const auto loadedParent = this->template getObjectForTesting("parent"); + + ASSERT_TRUE(nullptr != loadedSuperNode); + ASSERT_TRUE(nullptr != loadedChild); + ASSERT_TRUE(nullptr != loadedParent); + + ASSERT_EQ(1u, loadedSuperNode->getChildCount()); + EXPECT_EQ(loadedChild, loadedSuperNode->getChild(0u)); + EXPECT_EQ(loadedParent, loadedSuperNode->getParent()); + vec3f value; + EXPECT_TRUE(loadedSuperNode->getTranslation(value)); + EXPECT_FLOAT_EQ(1, value.x); + EXPECT_FLOAT_EQ(2, value.y); + EXPECT_FLOAT_EQ(3, value.z); + EXPECT_TRUE(loadedSuperNode->getRotation(value)); + EXPECT_FLOAT_EQ(4, value.x); + EXPECT_FLOAT_EQ(5, value.y); + EXPECT_FLOAT_EQ(6, value.z); + EXPECT_EQ(ERotationType::Euler_XZX, loadedSuperNode->getRotationType()); + EXPECT_TRUE(loadedSuperNode->getScaling(value)); + EXPECT_FLOAT_EQ(7, value.x); + EXPECT_FLOAT_EQ(8, value.y); + EXPECT_FLOAT_EQ(9, value.z); + + EXPECT_EQ(loadedSuperNode->getVisibility(), EVisibilityMode::Invisible); + } } diff --git a/tests/unittests/client/ScenePersistationTest.h b/tests/unittests/client/ScenePersistationTest.h index bdd157190..89ded5fdb 100644 --- a/tests/unittests/client/ScenePersistationTest.h +++ b/tests/unittests/client/ScenePersistationTest.h @@ -21,11 +21,13 @@ namespace ramses::internal { - class ASceneLoadedFromFile : public LocalTestClientWithScene, public ::testing::Test + class SceneLoadedFromFile : public LocalTestClientWithScene { public: - ASceneLoadedFromFile() - : m_clientForLoading(*m_frameworkForLoader.createClient("client")) + explicit SceneLoadedFromFile(EFeatureLevel featureLevel) + : LocalTestClientWithScene{ featureLevel } + , m_frameworkForLoader{ RamsesFrameworkConfig{featureLevel} } + , m_clientForLoading(*m_frameworkForLoader.createClient("client")) { m_frameworkForLoader.impl().getScenegraphComponent().setSceneRendererHandler(&sceneActionsCollector); } @@ -49,7 +51,6 @@ namespace ramses::internal } } - static void FillObjectTypeHistogramFromScene( ObjectTypeHistogram& counter, const ramses::Scene& scene ) { SceneObjectVector objects; @@ -105,10 +106,11 @@ namespace ramses::internal return wrongHistogramCount; } - void checkSceneFile(const char* filename) + static void CheckSceneFile(const char* filename, ramses::Scene* scene) { + assert(scene != nullptr); std::vector buffer; - EXPECT_TRUE(m_scene.impl().serialize(buffer, {})); + EXPECT_TRUE(scene->impl().serialize(buffer, {})); EXPECT_FALSE(buffer.empty()); ramses::internal::File f(filename); @@ -123,6 +125,11 @@ namespace ramses::internal EXPECT_EQ(buffer, fileBuffer); } + void checkSceneFile(const char* filename) + { + CheckSceneFile(filename, &m_scene); + } + void doWriteReadCycle(bool expectSameSceneSizeInfo = true, bool expectSameTypeHistogram = true, bool withCompression = false) { SaveFileConfig config; @@ -180,18 +187,8 @@ namespace ramses::internal return specificObject; } - ramses::RamsesFramework m_frameworkForLoader{ RamsesFrameworkConfig{EFeatureLevel_Latest} }; + ramses::RamsesFramework m_frameworkForLoader; ramses::RamsesClient& m_clientForLoading; ramses::Scene* m_sceneLoaded{nullptr}; }; - - class ASceneLoadedFromFileWithDefaultRenderPass : public ASceneLoadedFromFile - { - }; - - template - class ASceneLoadedFromFileTemplated : public ASceneLoadedFromFile - { - }; - } diff --git a/tests/unittests/client/ScenePersistationThreadedTest.cpp b/tests/unittests/client/ScenePersistationThreadedTest.cpp index 99b0d6c6a..f3d056667 100644 --- a/tests/unittests/client/ScenePersistationThreadedTest.cpp +++ b/tests/unittests/client/ScenePersistationThreadedTest.cpp @@ -143,8 +143,7 @@ namespace ramses::internal EXPECT_EQ(sceneId_t(123u), loadedScene->getSceneId()); } - // TODO needs to reenabled when the issue is fixed: ABPI-401386 - TEST_F(ARamsesFileLoadedInSeveralThread, DISABLED_asyncLoadSceneFileWithoutEverCallingDispatchDoesNotLeakMemory) + TEST_F(ARamsesFileLoadedInSeveralThread, asyncLoadSceneFileWithoutEverCallingDispatchDoesNotLeakMemory) { EXPECT_TRUE(client.loadSceneFromFileAsync(sceneFile)); // do nothing, scene load will finish before RamsesClient is destructed diff --git a/tests/unittests/client/SceneReferenceTest.cpp b/tests/unittests/client/SceneReferenceTest.cpp index 7aed77fb2..9c16605c8 100644 --- a/tests/unittests/client/SceneReferenceTest.cpp +++ b/tests/unittests/client/SceneReferenceTest.cpp @@ -15,6 +15,11 @@ using namespace testing; +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif + namespace ramses::internal { class ASceneReference : public LocalTestClientWithScene, public ::testing::Test @@ -249,3 +254,7 @@ namespace ramses::internal EXPECT_EQ(consumerId.getValue(), actions[1].consumerId.getValue()); } } + +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif diff --git a/tests/unittests/client/SceneTest.cpp b/tests/unittests/client/SceneTest.cpp index 54d857ae3..c4bd4cb46 100644 --- a/tests/unittests/client/SceneTest.cpp +++ b/tests/unittests/client/SceneTest.cpp @@ -7,7 +7,9 @@ // ------------------------------------------------------------------------- #include +#include "ramses/client/ArrayResource.h" #include "ramses/client/EffectDescription.h" +#include "ramses/client/RamsesClient.h" #include "ramses/client/SceneObjectIterator.h" #include "ramses/client/RenderGroup.h" #include "ramses/client/RenderPass.h" @@ -31,6 +33,9 @@ #include "ramses/client/logic/NodeBinding.h" #include "ramses/client/ramses-utils.h" #include "ramses/framework/EDataType.h" +#include "ramses/framework/EFeatureLevel.h" +#include "ramses/framework/RamsesFramework.h" +#include "ramses/framework/RamsesFrameworkTypes.h" #include "impl/DataObjectImpl.h" #include "impl/RenderGroupImpl.h" @@ -43,7 +48,9 @@ #include "impl/SceneConfigImpl.h" #include "ClientTestUtils.h" #include "SimpleSceneTopology.h" +#include "FileDescriptorHelper.h" #include "internal/Components/FlushTimeInformation.h" +#include "internal/Components/FileInputStreamContainer.h" #include "internal/PlatformAbstraction/PlatformTime.h" using namespace testing; @@ -85,12 +92,15 @@ namespace ramses::internal { SceneConfig config; config.setPublicationMode(EScenePublicationMode::LocalAndRemote); + config.setRenderBackendCompatibility(ERenderBackendCompatibility::VulkanAndOpenGL); SceneConfig configCopy{ config }; EXPECT_EQ(EScenePublicationMode::LocalAndRemote, configCopy.impl().getPublicationMode()); + EXPECT_EQ(ERenderBackendCompatibility::VulkanAndOpenGL, configCopy.impl().getRenderBackendCompatibility()); SceneConfig configMove{ std::move(config) }; EXPECT_EQ(EScenePublicationMode::LocalAndRemote, configMove.impl().getPublicationMode()); + EXPECT_EQ(ERenderBackendCompatibility::VulkanAndOpenGL, configCopy.impl().getRenderBackendCompatibility()); } TEST(ASceneConfig, CanBeCopyAndMoveAssigned) @@ -246,6 +256,33 @@ namespace ramses::internal EXPECT_FALSE(report.hasIssue()); } + TEST_F(AScene, byDefaultSceneHasOpenGLCompatibility) + { + EXPECT_EQ(ERenderBackendCompatibility::OpenGL, m_internalScene.getRenderBackendCompatibility()); + EXPECT_EQ(EVulkanAPIVersion::Invalid, m_internalScene.getVulkanAPIVersion()); + EXPECT_EQ(ESPIRVVersion::Invalid, m_internalScene.getSPIRVVersion()); + } + + TEST_F(AScene, canCreateSceneWithVulkanAndOpenGLCompatibility) + { + const SceneConfig sceneConfig{ sceneId_t{456u}, EScenePublicationMode::LocalOnly, ERenderBackendCompatibility::VulkanAndOpenGL }; + auto* scene = client.createScene(sceneConfig); + ASSERT_NE(nullptr, scene); + const auto& iscene = scene->impl().getIScene(); + EXPECT_EQ(ERenderBackendCompatibility::VulkanAndOpenGL, iscene.getRenderBackendCompatibility()); + EXPECT_EQ(TargetVulkanApiVersion, iscene.getVulkanAPIVersion()); + EXPECT_EQ(TargetSPIRVVersion, iscene.getSPIRVVersion()); + } + + TEST_F(AScene, canNotCreateSceneWithVulkanAndOpenGLCompatibilityWithFeatureLevel01) + { + RamsesFramework fl0Framework(LocalTestClient::GetDefaultFrameworkConfig(EFeatureLevel::EFeatureLevel_01)); + RamsesClient& fl0Client = *fl0Framework.createClient("localTestClient"); + const SceneConfig sceneConfig{ sceneId_t{456u}, EScenePublicationMode::LocalOnly, ERenderBackendCompatibility::VulkanAndOpenGL }; + auto* scene = fl0Client.createScene(sceneConfig); + EXPECT_EQ(nullptr, scene); + } + TEST_F(AScene, failsValidationIfContainsInvalidSceneObject) { ramses::RenderPass* passWithoutCamera = m_scene.createRenderPass(); @@ -1945,4 +1982,194 @@ namespace ramses::internal scene->createNode("{}"); } + + TEST_F(ASceneWithContent, canMergeSceneFromFile) + { + const std::string_view fileName{"tmp.ramses"}; + + ASSERT_TRUE(m_scene.saveToFile(fileName)); + EXPECT_TRUE(client.destroy(m_scene)); + + const sceneId_t sceneId{123u}; + auto* newScene = client.createScene(sceneId); + ASSERT_NE(nullptr, newScene); + auto* node = newScene->createNode(); + ASSERT_NE(nullptr, node); + + ASSERT_TRUE(client.mergeSceneFromFile(*newScene, fileName)); + EXPECT_NE(nullptr, newScene->findObject("mesh1a")); + EXPECT_NE(nullptr, newScene->findObject("mesh1b")); + } + + TEST_F(ASceneWithContent, canMergeSceneFromMemory) + { + const std::string_view fileName{"tmp.ramses"}; + + ASSERT_TRUE(m_scene.saveToFile(fileName)); + EXPECT_TRUE(client.destroy(m_scene)); + + const sceneId_t sceneId{123u}; + auto* newScene = client.createScene(sceneId); + ASSERT_NE(nullptr, newScene); + auto* node = newScene->createNode(); + ASSERT_NE(nullptr, node); + + ramses::internal::File file(fileName); + size_t fileSize = 0; + EXPECT_TRUE(file.getSizeInBytes(fileSize)); + + std::unique_ptr data(new std::byte[fileSize], [](const auto* ptr) { delete[] ptr; }); + size_t numBytesRead = 0; + EXPECT_TRUE(file.open(ramses::internal::File::Mode::ReadOnlyBinary)); + EXPECT_EQ(ramses::internal::EStatus::Ok, file.read(data.get(), fileSize, numBytesRead)); + EXPECT_TRUE(client.mergeSceneFromMemory(*newScene, std::move(data), fileSize)); + + EXPECT_NE(nullptr, newScene->findObject("mesh1a")); + EXPECT_NE(nullptr, newScene->findObject("mesh1b")); + } + + TEST_F(ASceneWithContent, canMergeSceneFromFileDescriptor) + { + EXPECT_TRUE(m_scene.saveToFile("someTemporaryFile.ram", {})); + + size_t fileSize = 0; + { + // write to a file with some offset + ramses::internal::File inFile("someTemporaryFile.ram"); + EXPECT_TRUE(inFile.getSizeInBytes(fileSize)); + std::vector data(fileSize); + size_t numBytesRead = 0; + EXPECT_TRUE(inFile.open(ramses::internal::File::Mode::ReadOnlyBinary)); + EXPECT_EQ(ramses::internal::EStatus::Ok, inFile.read(data.data(), fileSize, numBytesRead)); + + ramses::internal::File outFile("someTemporaryFileWithOffset.ram"); + EXPECT_TRUE(outFile.open(ramses::internal::File::Mode::WriteOverWriteOldBinary)); + + uint32_t zeroData = 0; + EXPECT_TRUE(outFile.write(&zeroData, sizeof(zeroData))); + EXPECT_TRUE(outFile.write(data.data(), data.size())); + EXPECT_TRUE(outFile.write(&zeroData, sizeof(zeroData))); + } + + EXPECT_TRUE(client.destroy(m_scene)); + + const sceneId_t sceneId{123u}; + auto* newScene = client.createScene(sceneId); + ASSERT_NE(nullptr, newScene); + auto* node = newScene->createNode(); + ASSERT_NE(nullptr, node); + + const int fd = ramses::internal::FileDescriptorHelper::OpenFileDescriptorBinary ("someTemporaryFileWithOffset.ram"); + EXPECT_TRUE(client.mergeSceneFromFileDescriptor(*newScene, fd, 4u, fileSize)); + + EXPECT_NE(nullptr, newScene->findObject("mesh1a")); + EXPECT_NE(nullptr, newScene->findObject("mesh1b")); + } + + TEST_F(ASceneWithContent, canMergeSceneFromSceneFileWithDeletedNodeAndRes) + { + const std::string_view fileName{"sceneWithDeletedNodeAndRes.ramses"}; + + // A scene with deleted nodes and resources + const vec2f data[2] = { vec2f{1.f,2.f}, vec2f{3.f,4.f} }; + SceneObjectVector objs; + for (int i = 0; i < 10; ++i) { + objs.push_back(m_scene.createNode("NodeToDelete")); + objs.push_back(m_scene.createArrayResource(2, data, "ResToDelete")); + } + m_scene.createNode("dummyNode1"); + m_scene.createArrayResource(2, data, "dummyRes1"); + for (auto obj : objs) { + ASSERT_NE(nullptr, obj); + m_scene.destroy(*obj); + } + ASSERT_TRUE(m_scene.saveToFile(fileName)); + EXPECT_TRUE(client.destroy(m_scene)); + + const sceneId_t sceneId{123u}; + auto* newScene = client.createScene(sceneId); + ASSERT_NE(nullptr, newScene); + auto* node = newScene->createNode("dummyNode2"); + ASSERT_NE(nullptr, node); + auto* res = newScene->createArrayResource(2, data, "dummyRes2"); + ASSERT_NE(nullptr, res); + + ASSERT_TRUE(client.mergeSceneFromFile(*newScene, fileName)); + EXPECT_NE(nullptr, newScene->findObject("mesh1a")); + EXPECT_NE(nullptr, newScene->findObject("mesh1b")); + EXPECT_EQ(nullptr, newScene->findObject("NodeToDelete")); + EXPECT_EQ(nullptr, newScene->findObject("ResToDelete")); + EXPECT_NE(nullptr, newScene->findObject("dummyNode1")); + EXPECT_NE(nullptr, newScene->findObject("dummyRes1")); + EXPECT_NE(nullptr, newScene->findObject("dummyNode2")); + EXPECT_NE(nullptr, newScene->findObject("dummyRes2")); + } + + class SceneMergeTest : public ::testing::Test + { + protected: + static void RunMergeSceneRenderBackendCompatibilityTest(ERenderBackendCompatibility compatibilityMergeScene, ERenderBackendCompatibility compatibilityMainScene, bool expectSuccess) + { + RamsesFramework framework(LocalTestClient::GetDefaultFrameworkConfig(EFeatureLevel::EFeatureLevel_Latest)); + RamsesClient& client = *framework.createClient("localTestClient"); + + const std::string_view fileName{ "tmp.ramses" }; + { + const sceneId_t mergeSceneId{ 3121u }; + auto* mergeScene = client.createScene(SceneConfig{ mergeSceneId, EScenePublicationMode::LocalOnly, compatibilityMergeScene }); + ASSERT_NE(nullptr, mergeScene); + auto* node = mergeScene->createNode(); + ASSERT_NE(nullptr, node); + ASSERT_TRUE(mergeScene->saveToFile(fileName)); + } + + const sceneId_t sceneId{ 123u }; + auto* newScene = client.createScene(SceneConfig{ sceneId, EScenePublicationMode::LocalOnly, compatibilityMainScene }); + ASSERT_NE(nullptr, newScene); + auto* node = newScene->createNode(); + ASSERT_NE(nullptr, node); + + EXPECT_EQ(expectSuccess, client.mergeSceneFromFile(*newScene, fileName)); + } + }; + + TEST_F(SceneMergeTest, mergeSceneFromFileFailsWithFL01) + { + const std::string_view fileName{"tmp.ramses"}; + { + RamsesFramework framework(LocalTestClient::GetDefaultFrameworkConfig(EFeatureLevel::EFeatureLevel_01)); + RamsesClient& client = *framework.createClient("localTestClient"); + const sceneId_t mergeSceneId{3121u}; + auto* mergeScene = client.createScene(mergeSceneId); + ASSERT_NE(nullptr, mergeScene); + auto* node = mergeScene->createNode(); + ASSERT_NE(nullptr, node); + ASSERT_TRUE(mergeScene->saveToFile(fileName)); + } + + RamsesFramework framework(LocalTestClient::GetDefaultFrameworkConfig(EFeatureLevel::EFeatureLevel_Latest)); + RamsesClient& client = *framework.createClient("localTestClient"); + const sceneId_t sceneId{123u}; + auto* newScene = client.createScene(sceneId); + ASSERT_NE(nullptr, newScene); + auto* node = newScene->createNode(); + ASSERT_NE(nullptr, node); + + EXPECT_FALSE(client.mergeSceneFromFile(*newScene, fileName)); + } + + TEST_F(SceneMergeTest, mergeSceneFromFileFailsWithIncompatibleRenderBackends) + { + RunMergeSceneRenderBackendCompatibilityTest(ERenderBackendCompatibility::OpenGL, ERenderBackendCompatibility::VulkanAndOpenGL, false); + } + + TEST_F(SceneMergeTest, canMergeScenesFromFileWithOpenGLCompatibility) + { + RunMergeSceneRenderBackendCompatibilityTest(ERenderBackendCompatibility::OpenGL, ERenderBackendCompatibility::OpenGL, true); + } + + TEST_F(SceneMergeTest, canMergeScenesFromFileWithVulkanAndOpenGLCompatibility) + { + RunMergeSceneRenderBackendCompatibilityTest(ERenderBackendCompatibility::VulkanAndOpenGL, ERenderBackendCompatibility::VulkanAndOpenGL, true); + } } diff --git a/tests/unittests/client/TestEffectCreator.h b/tests/unittests/client/TestEffectCreator.h deleted file mode 100644 index 892dad8a2..000000000 --- a/tests/unittests/client/TestEffectCreator.h +++ /dev/null @@ -1,142 +0,0 @@ -// ------------------------------------------------------------------------- -// Copyright (C) 2015 BMW Car IT GmbH -// ------------------------------------------------------------------------- -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at https://mozilla.org/MPL/2.0/. -// ------------------------------------------------------------------------- - -#pragma once - -#include - -#include "ramses/client/EffectDescription.h" -#include "ClientTestUtils.h" - -namespace ramses::internal -{ - class TestEffectCreator : public LocalTestClientWithScene - { - public: - explicit TestEffectCreator(bool withSemantics = false, bool withGeometryShader = false) - { - effect = createEffect(m_scene, withSemantics, withGeometryShader); - EXPECT_TRUE(effect != nullptr); - appearance = this->m_scene.createAppearance(*effect); - EXPECT_TRUE(appearance != nullptr); - } - - void recreateAppearence() - { - assert(appearance); - this->m_scene.destroy(*appearance); - appearance = this->m_scene.createAppearance(*effect); - assert(appearance); - } - - ~TestEffectCreator() override - { - EXPECT_TRUE(this->m_scene.destroy(*appearance)); - } - - static Effect* createEffect(ramses::Scene& scene, bool withSemantics, bool withGeometryShader = false) - { - std::string VertexShader( - "#version 320 es\n" - "uniform lowp float floatInput;\n" - "uniform lowp float floatInputArray[3];\n" - - "uniform vec2 vec2fInput;\n" - "uniform vec2 vec2fInputArray[3];\n" - "uniform vec3 vec3fInput;\n" - "uniform vec3 vec3fInputArray[3];\n" - "uniform vec4 vec4fInput;\n" - "uniform vec4 vec4fInputArray[3];\n" - - "uniform mat2 matrix22fInput;\n" - "uniform mat2 matrix22fInputArray[3];\n" - "uniform mat3 matrix33fInput;\n" - "uniform mat3 matrix33fInputArray[3];\n" - "uniform mat4 matrix44fInput;\n" - "uniform mat4 matrix44fInputArray[3];\n" - - "uniform bool boolInput;\n" - "uniform bool boolInputArray[3];\n" - - "uniform lowp int integerInput;\n" - "uniform lowp int integerInputArray[3];\n" - - "uniform ivec2 vec2iInput;\n" - "uniform ivec2 vec2iInputArray[3];\n" - "uniform ivec3 vec3iInput;\n" - "uniform ivec3 vec3iInputArray[3];\n" - "uniform ivec4 vec4iInput;\n" - "uniform ivec4 vec4iInputArray[3];\n" - - "in float floatArrayInput;\n" - "in vec2 vec2fArrayInput;\n" - "in vec3 vec3fArrayInput;\n" - "in vec4 vec4fArrayInput;\n" - - "void main(void)\n" - "{\n" - " lowp vec4 values = vec4(1) * floatInput* vec2fInput.x * vec3fInput.y* vec4fInput.z;\n" - " values[0] = float(integerInput) + floatInputArray[0] + floatInputArray[1];\n" - " values[1] = float(vec2iInput.x)* float(vec3iInput.y)* float(vec4iInput.z);\n" - " values[2] = vec2fArrayInput.x*vec3fArrayInput.y*vec4fArrayInput.z;\n" - " values[3] = floatArrayInput*vec2fArrayInput.x*vec4fArrayInput.z;\n" - " values[0] += floatInputArray[0] + vec2fInputArray[0].x + vec3fInputArray[0].x + vec4fInputArray[0].x;\n" - " values[1] += matrix44fInputArray[0][0].x + float(integerInputArray[0]);\n" - " values[2] += float(vec2iInputArray[0].x + vec3iInputArray[0].x + vec4iInputArray[0].x);\n" - " values[3] += matrix22fInput[0][0] + matrix33fInput[0][0] + matrix22fInputArray[0][0].x + matrix33fInputArray[0][0].x;\n" - " values = matrix44fInput * values;\n" - " if (boolInput || boolInputArray[0] || boolInputArray[1] || boolInputArray[2])\n" - " gl_Position = values;\n" - "}\n"); - - std::string FragmentShader( - "#version 320 es\n" - "precision mediump float;\n" - "uniform sampler2D texture2dInput;\n" - "uniform lowp sampler2DMS texture2dMSInput;\n" - "uniform lowp sampler3D texture3dInput;\n" - "uniform samplerCube textureCubeInput;\n" - "#extension GL_OES_EGL_image_external_essl3 : require\n" - "uniform samplerExternalOES textureExternalInput;\n" - "out vec4 FragColor;" - "void main(void)\n" - "{\n" - " FragColor = vec4(1.0) + texture(texture2dInput, vec2(0,0)) + texelFetch(texture2dMSInput, ivec2(0,0), 0) + texture(texture3dInput, vec3(0, 0, 0)) + texture(textureCubeInput, vec3(0,0,0)) + texture(textureExternalInput, vec2(0,0));\n" - "}\n"); - - EffectDescription effectDesc; - effectDesc.setVertexShader(VertexShader.c_str()); - effectDesc.setFragmentShader(FragmentShader.c_str()); - - if (withGeometryShader) - { - effectDesc.setGeometryShader(R"SHADER( - #version 320 es - layout(lines) in; - layout(points, max_vertices = 1) out; - void main() { - gl_Position = vec4(0.0); - EmitVertex(); - } - )SHADER"); - } - - if (withSemantics) - { - effectDesc.setAttributeSemantic("vec2fArrayInput", EEffectAttributeSemantic::TextPositions); - effectDesc.setUniformSemantic("matrix44fInput", EEffectUniformSemantic::ModelViewMatrix); - effectDesc.setUniformSemantic("texture2dInput", EEffectUniformSemantic::TextTexture); - } - - return scene.createEffect(effectDesc, "input test effect"); - } - - Effect* effect; - Appearance* appearance; - }; -} diff --git a/tests/unittests/client/logic/api/AppearanceBindingTest.cpp b/tests/unittests/client/logic/api/AppearanceBindingTest.cpp index 152e822cc..dc549f197 100644 --- a/tests/unittests/client/logic/api/AppearanceBindingTest.cpp +++ b/tests/unittests/client/logic/api/AppearanceBindingTest.cpp @@ -333,7 +333,7 @@ namespace ramses::internal { protected: const std::string_view m_vertShader_simple = R"( - #version 300 es + #version 310 es uniform highp float floatUniform; @@ -343,7 +343,7 @@ namespace ramses::internal })"; const std::string_view m_vertShader_twoUniforms = R"( - #version 300 es + #version 310 es uniform highp float floatUniform1; uniform highp float floatUniform2; @@ -354,7 +354,7 @@ namespace ramses::internal })"; const std::string_view m_vertShader_allTypes = R"( - #version 300 es + #version 310 es uniform highp float floatUniform; uniform bool boolUniform; @@ -373,6 +373,10 @@ namespace ramses::internal uniform highp ivec4 ivec4Array[2]; uniform highp vec4 vec4Array[2]; uniform highp vec4 vec4Uniform_shouldHaveDefaultValue; + layout(std140,binding=0) uniform someUboType{ + highp vec3 vec3Uniform; + highp vec4 vec4Uniform; + } someUbo; void main() { @@ -380,7 +384,7 @@ namespace ramses::internal })"; const std::string_view m_fragShader_trivial = R"( - #version 300 es + #version 310 es out lowp vec4 color; void main(void) @@ -423,6 +427,7 @@ namespace ramses::internal { auto& appearanceBinding = *m_logicEngine->createAppearanceBinding(*m_appearance, "AppearanceBinding"); EXPECT_EQ(m_appearance, &appearanceBinding.getRamsesAppearance()); + EXPECT_EQ(m_appearance, &appearanceBinding.impl().getBoundObject()); } TEST_F(AAppearanceBinding_WithRamses, HasInputsAfterCreation) @@ -453,7 +458,7 @@ namespace ramses::internal { const std::string_view fragShader_ManyUniformTypes = R"( - #version 300 es + #version 310 es // This is the same uniform like in the vertex shader - that's intended! uniform highp float floatUniform; @@ -528,7 +533,7 @@ namespace ramses::internal ramses::Appearance& appearance = createTestAppearance(createTestEffect(m_vertShader_allTypes, m_fragShader_trivial)); auto& appearanceBinding = *m_logicEngine->createAppearanceBinding(appearance, "AppearanceBinding"); auto inputs = appearanceBinding.getInputs(); - ASSERT_EQ(17u, inputs->getChildCount()); + ASSERT_EQ(19u, inputs->getChildCount()); EXPECT_TRUE(inputs->getChild("floatUniform")->set(42.42f)); EXPECT_TRUE(inputs->getChild("boolUniform")->set(true)); EXPECT_TRUE(inputs->getChild("intUniform")->set(42)); @@ -552,6 +557,9 @@ namespace ramses::internal EXPECT_TRUE(inputs->getChild("ivec4Array")->getChild(1)->set({ 45, 46, 47, 48 })); EXPECT_TRUE(inputs->getChild("vec4Array")->getChild(0)->set({ .41f, .42f, .43f, .44f })); EXPECT_TRUE(inputs->getChild("vec4Array")->getChild(1)->set({ .45f, .46f, .47f, .48f })); + EXPECT_FALSE(inputs->getChild("someUbo")); + EXPECT_TRUE(inputs->getChild("someUbo.vec3Uniform")->set({ .415f, .416f, .417f })); + EXPECT_TRUE(inputs->getChild("someUbo.vec4Uniform")->set({ .415f, .416f, .417f, 0.99f })); EXPECT_EQ(std::nullopt, appearanceBinding.impl().update()); @@ -675,6 +683,21 @@ namespace ramses::internal appearance.getInputValue(*optUniform, 2, result.data()); EXPECT_THAT(result, ::testing::ElementsAre(ramses::vec4f{ .41f, .42f, .43f, .44f }, ramses::vec4f{ .45f, .46f, .47f, .48f })); } + // UBO + { + ramses::vec3f result{ 0.0f, 0.0f, 0.0f }; + optUniform = effect.findUniformInput("someUbo.vec3Uniform"); + ASSERT_TRUE(optUniform.has_value()); + appearance.getInputValue(*optUniform, result); + EXPECT_EQ(result, vec3f(.415f, .416f, .417f)); + } + { + ramses::vec4f result{ 0.0f, 0.0f, 0.0f, 0.0f }; + optUniform = effect.findUniformInput("someUbo.vec4Uniform"); + ASSERT_TRUE(optUniform.has_value()); + appearance.getInputValue(*optUniform, result); + EXPECT_EQ(result, vec4f(.415f, .416f, .417f, 0.99f)); + } } TEST_F(AAppearanceBinding_WithRamses, PropagateItsInputsToRamsesAppearanceOnUpdate_OnlyWhenExplicitlySet) @@ -782,6 +805,8 @@ namespace ramses::internal inputs->getChild("ivec2Array")->getChild(1)->set({ 13, 14 }); inputs->getChild("vec2Array")->getChild(0)->set({ .11f, .12f }); inputs->getChild("vec2Array")->getChild(1)->set({ .13f, .14f }); + inputs->getChild("someUbo.vec3Uniform")->set({ .415f, .416f, .417f }); + inputs->getChild("someUbo.vec4Uniform")->set({ .415f, .416f, .417f, 0.99f }); m_logicEngine->update(); ASSERT_TRUE(saveToFile("logic.bin")); } @@ -793,7 +818,7 @@ namespace ramses::internal EXPECT_EQ(loadedAppearanceBinding->getRamsesAppearance().getSceneObjectId(), appearanceId); const auto& inputs = loadedAppearanceBinding->getInputs(); - ASSERT_EQ(17u, inputs->getChildCount()); + ASSERT_EQ(19u, inputs->getChildCount()); // check order after deserialization for (size_t i = 0; i < inputOrderBeforeSaving.size(); ++i) @@ -836,6 +861,12 @@ namespace ramses::internal EXPECT_EQ(EPropertySemantics::BindingInput, inputs->getChild("vec2Array")->impl().getPropertySemantics()); EXPECT_EQ(*inputs->getChild("vec2Array")->getChild(0)->get(), vec2f(.11f, .12f)); EXPECT_EQ(*inputs->getChild("vec2Array")->getChild(1)->get(), vec2f(.13f, .14f)); + + // UBO + EXPECT_EQ(*inputs->getChild("someUbo.vec3Uniform")->get(), vec3f(.415f, .416f, .417f)); + EXPECT_EQ(EPropertySemantics::BindingInput, inputs->getChild("someUbo.vec3Uniform")->impl().getPropertySemantics()); + EXPECT_EQ(*inputs->getChild("someUbo.vec4Uniform")->get(), vec4f(.415f, .416f, .417f, 0.99f)); + EXPECT_EQ(EPropertySemantics::BindingInput, inputs->getChild("someUbo.vec4Uniform")->impl().getPropertySemantics()); }; expectValues(); diff --git a/tests/unittests/client/logic/api/CameraBindingTest.cpp b/tests/unittests/client/logic/api/CameraBindingTest.cpp index 8da63a57f..2f5acdd5d 100644 --- a/tests/unittests/client/logic/api/CameraBindingTest.cpp +++ b/tests/unittests/client/logic/api/CameraBindingTest.cpp @@ -265,6 +265,7 @@ namespace ramses::internal { CameraBinding& cameraBinding = *m_logicEngine->createCameraBinding(*m_perspectiveCam, ""); EXPECT_EQ(m_perspectiveCam, &cameraBinding.getRamsesCamera()); + EXPECT_EQ(m_perspectiveCam, &cameraBinding.impl().getBoundObject()); } TEST_F(ACameraBinding, HasInputsAfterInitializingWithPerspectiveCamera) @@ -490,13 +491,6 @@ namespace ramses::internal } } - TEST_F(ACameraBinding, ReturnsBoundRamsesCamera) - { - auto* cameraBinding = m_logicEngine->createCameraBinding(*m_perspectiveCam, ""); - - EXPECT_EQ(m_perspectiveCam, &cameraBinding->getRamsesCamera()); - } - TEST_F(ACameraBinding, DoesNotModifyRamsesWithoutUpdateBeingCalledWithPerspectiveCamera) { auto* cameraBinding = m_logicEngine->createCameraBinding(*m_perspectiveCam, ""); diff --git a/tests/unittests/client/logic/api/LogicEngineTest_Factory.cpp b/tests/unittests/client/logic/api/LogicEngineTest_Factory.cpp index 42348d2f9..d39006895 100644 --- a/tests/unittests/client/logic/api/LogicEngineTest_Factory.cpp +++ b/tests/unittests/client/logic/api/LogicEngineTest_Factory.cpp @@ -37,10 +37,7 @@ namespace ramses::internal } }; - INSTANTIATE_TEST_SUITE_P( - ALogicEngine_FactoryTests, - ALogicEngine_Factory, - GetFeatureLevelTestValues()); + RAMSES_INSTANTIATE_LATEST_FEATURELEVEL_ONLY_TEST_SUITE(ALogicEngine_Factory); TEST_P(ALogicEngine_Factory, ProducesErrorWhenCreatingEmptyScript) { diff --git a/tests/unittests/client/logic/api/LogicEngineTest_LogicNodeUpdateStatistics.cpp b/tests/unittests/client/logic/api/LogicEngineTest_LogicNodeUpdateStatistics.cpp index 48110e0ac..1b7f619b6 100644 --- a/tests/unittests/client/logic/api/LogicEngineTest_LogicNodeUpdateStatistics.cpp +++ b/tests/unittests/client/logic/api/LogicEngineTest_LogicNodeUpdateStatistics.cpp @@ -116,6 +116,32 @@ namespace ramses::internal EXPECT_TRUE(m_logMessages[5].find("Slowest nodes [name:time_us]: [test node2:10] [test node1:3]") != std::string::npos); } + TEST_F(ALogicEngine_LogicObjectStatistics, verifyLogsDeletedNodes) + { + LogicNodeUpdateStatistics statistics; + statistics.setLoggingRate(1u); + + for (int i = 0; i < 2; ++i) + { + UpdateReport report; + auto* node = m_logicEngine->createTimerNode(fmt::format("test node{}", i)); + auto& dummyNodes = const_cast(report.getNodesExecuted()); + dummyNodes.emplace_back(&static_cast(node)->impl(), std::chrono::microseconds(100 + i)); + statistics.collect(report, dummyNodes.size()); + m_logicEngine->destroy(*node); + } + + statistics.calculateAndLog(); + + ASSERT_EQ(6u, m_logMessages.size()); + EXPECT_THAT(m_logMessages[0], ::testing::HasSubstr("First Statistics Log")); + EXPECT_THAT(m_logMessages[1], ::testing::HasSubstr("Update Execution time (min/max/avg): 0/0/0 [u]sec")); + EXPECT_THAT(m_logMessages[2], ::testing::HasSubstr("Time between Update calls")); + EXPECT_THAT(m_logMessages[3], ::testing::HasSubstr("Nodes Executed (min/max/avg): 0%/0%/0% (0/0/0) of 1 nodes total")); + EXPECT_THAT(m_logMessages[4], ::testing::HasSubstr("Activated links (min/max/avg): 0/0/0")); + EXPECT_THAT(m_logMessages[5], ::testing::HasSubstr("Slowest nodes [name:time_us]: [test node1:101] [test node0:100]")); + } + TEST_F(ALogicEngine_LogicObjectStatistics, verifyLogsForFiveNodesWithSameTime) { LogicNodeUpdateStatistics statistics; diff --git a/tests/unittests/client/logic/api/LogicEngineTest_Serialization.cpp b/tests/unittests/client/logic/api/LogicEngineTest_Serialization.cpp index 944bf2de8..fd8a8386c 100644 --- a/tests/unittests/client/logic/api/LogicEngineTest_Serialization.cpp +++ b/tests/unittests/client/logic/api/LogicEngineTest_Serialization.cpp @@ -150,10 +150,7 @@ namespace ramses::internal } }; - INSTANTIATE_TEST_SUITE_P( - ALogicEngine_SerializationTests, - ALogicEngine_Serialization, - GetFeatureLevelTestValues()); + RAMSES_INSTANTIATE_LATEST_FEATURELEVEL_ONLY_TEST_SUITE(ALogicEngine_Serialization); TEST_P(ALogicEngine_Serialization, ProducesErrorWhenProvidingAFolderAsTargetForSaving) { diff --git a/tests/unittests/client/logic/api/LogicEngineTest_SerializedSize.cpp b/tests/unittests/client/logic/api/LogicEngineTest_SerializedSize.cpp index 07c4b49fa..f0b843e1d 100644 --- a/tests/unittests/client/logic/api/LogicEngineTest_SerializedSize.cpp +++ b/tests/unittests/client/logic/api/LogicEngineTest_SerializedSize.cpp @@ -102,10 +102,7 @@ namespace ramses::internal static constexpr size_t EmptySerializedSizeTotal{ 172u }; - INSTANTIATE_TEST_SUITE_P( - ALogicEngine_SerializedSizeTests, - ALogicEngine_SerializedSize, - ramses::internal::GetFeatureLevelTestValues()); + RAMSES_INSTANTIATE_LATEST_FEATURELEVEL_ONLY_TEST_SUITE(ALogicEngine_SerializedSize); TEST_P(ALogicEngine_SerializedSize, ChecksSerializedSizeWithoutContent) { diff --git a/tests/unittests/client/logic/api/LuaScriptTest_Serialization.cpp b/tests/unittests/client/logic/api/LuaScriptTest_Serialization.cpp index c51f6f468..8feae9419 100644 --- a/tests/unittests/client/logic/api/LuaScriptTest_Serialization.cpp +++ b/tests/unittests/client/logic/api/LuaScriptTest_Serialization.cpp @@ -62,10 +62,7 @@ namespace ramses::internal DeserializationMap m_deserializationMap{ m_ramses.createScene()->impl() }; }; - INSTANTIATE_TEST_SUITE_P( - ALuaScript_SerializationTests, - ALuaScript_Serialization, - GetFeatureLevelTestValues()); + RAMSES_INSTANTIATE_LATEST_FEATURELEVEL_ONLY_TEST_SUITE(ALuaScript_Serialization); // More unit tests with inputs/outputs declared in LogicNode (base class) serialization tests TEST_P(ALuaScript_Serialization, RemembersBaseClassData) diff --git a/tests/unittests/client/logic/api/MeshNodeBindingTest.cpp b/tests/unittests/client/logic/api/MeshNodeBindingTest.cpp index 0c9f04be2..a4a3a3f0d 100644 --- a/tests/unittests/client/logic/api/MeshNodeBindingTest.cpp +++ b/tests/unittests/client/logic/api/MeshNodeBindingTest.cpp @@ -94,6 +94,7 @@ namespace ramses::internal EXPECT_EQ(m_meshNodeWithGeometry, &mbConst.getRamsesMeshNode()); const auto& mbImplConst = m_meshBinding->impl(); EXPECT_EQ(m_meshNodeWithGeometry, &mbImplConst.getRamsesMeshNode()); + EXPECT_EQ(m_meshNodeWithGeometry, &mbImplConst.getBoundObject()); } TEST_F(AMeshNodeBinding, HasInputPropertiesAndNoOutputs) diff --git a/tests/unittests/client/logic/api/NodeBindingTest.cpp b/tests/unittests/client/logic/api/NodeBindingTest.cpp index 7df99b036..01c28c9c4 100644 --- a/tests/unittests/client/logic/api/NodeBindingTest.cpp +++ b/tests/unittests/client/logic/api/NodeBindingTest.cpp @@ -232,6 +232,7 @@ namespace ramses::internal { NodeBinding& nodeBinding = *m_logicEngine->createNodeBinding(*m_node, ERotationType::Euler_XYZ, ""); EXPECT_EQ(m_node, &nodeBinding.getRamsesNode()); + EXPECT_EQ(m_node, &nodeBinding.impl().getBoundObject()); } TEST_F(ANodeBinding, DoesNotModifyRamsesWithoutUpdateBeingCalled) diff --git a/tests/unittests/client/logic/api/RenderBufferBindingTest.cpp b/tests/unittests/client/logic/api/RenderBufferBindingTest.cpp index a9583623e..db8a03139 100644 --- a/tests/unittests/client/logic/api/RenderBufferBindingTest.cpp +++ b/tests/unittests/client/logic/api/RenderBufferBindingTest.cpp @@ -41,6 +41,7 @@ namespace ramses::internal EXPECT_EQ(m_renderBuffer, &rbConst.getRenderBuffer()); const auto& rbImplConst = m_rbBinding->impl(); EXPECT_EQ(m_renderBuffer, &rbImplConst.getRenderBuffer()); + EXPECT_EQ(m_renderBuffer, &rbImplConst.getBoundObject()); } TEST_F(ARenderBufferBinding, HasInputPropertiesAndNoOutputs) diff --git a/tests/unittests/client/logic/api/RenderGroupBindingTest.cpp b/tests/unittests/client/logic/api/RenderGroupBindingTest.cpp index 63a777ac3..b4772a3c0 100644 --- a/tests/unittests/client/logic/api/RenderGroupBindingTest.cpp +++ b/tests/unittests/client/logic/api/RenderGroupBindingTest.cpp @@ -47,6 +47,7 @@ namespace ramses::internal EXPECT_EQ(m_renderGroup, &rpConst.getRamsesRenderGroup()); const auto& rpImplConst = renderGroupBinding.impl(); EXPECT_EQ(m_renderGroup, &rpImplConst.getRamsesRenderGroup()); + EXPECT_EQ(m_renderGroup, &rpImplConst.getBoundObject()); } TEST_F(ARenderGroupBinding, HasInputsAfterCreationWithCorrectNamesAndValues) diff --git a/tests/unittests/client/logic/api/RenderPassBindingTest.cpp b/tests/unittests/client/logic/api/RenderPassBindingTest.cpp index 0eed7bcbc..7f01ea99f 100644 --- a/tests/unittests/client/logic/api/RenderPassBindingTest.cpp +++ b/tests/unittests/client/logic/api/RenderPassBindingTest.cpp @@ -46,6 +46,7 @@ namespace ramses::internal EXPECT_EQ(m_renderPass, &rpConst.getRamsesRenderPass()); const auto& rpImplConst = renderPassBinding.impl(); EXPECT_EQ(m_renderPass, &rpImplConst.getRamsesRenderPass()); + EXPECT_EQ(m_renderPass, &rpImplConst.getBoundObject()); } TEST_F(ARenderPassBinding, HasInputsAfterCreation) diff --git a/tests/unittests/client/logic/api/SkinBindingTest.cpp b/tests/unittests/client/logic/api/SkinBindingTest.cpp index 6f78f44c5..1a1c66416 100644 --- a/tests/unittests/client/logic/api/SkinBindingTest.cpp +++ b/tests/unittests/client/logic/api/SkinBindingTest.cpp @@ -27,7 +27,7 @@ namespace ramses::internal { public: ASkinBinding() - : m_appearance{ m_scene->createAppearance(createTestEffect()) } + : m_appearance{ m_scene->createAppearance(createTestEffect(), "skinAppearance") } { m_uniform = m_appearance->getEffect().findUniformInput("jointMat"); @@ -95,6 +95,7 @@ namespace ramses::internal EXPECT_EQ(m_appearanceBinding, &skinConst.getAppearanceBinding()); const auto& skinImplConst = m_skin->impl(); EXPECT_EQ(&m_appearanceBinding->impl(), &skinImplConst.getAppearanceBinding()); + EXPECT_EQ(&m_appearanceBinding->impl().getBoundObject(), &skinImplConst.getBoundObject()); EXPECT_EQ(EDataType::Matrix44F, m_skin->getAppearanceUniformInput().getDataType()); EXPECT_EQ(2u, m_skin->getAppearanceUniformInput().getElementCount()); @@ -162,6 +163,105 @@ namespace ramses::internal EXPECT_NEAR(expectedMat2[i/4][i%4], mat2[i/4][i%4], 1e-4f) << i; } + TEST_F(ASkinBinding, UpdatesBoundUniformOnNodeBindingChange) + { + // This is the same setup as regular tests, only recreated locally, since with the regular setup (by chance) the nodes are ordered differently. + // If there is no binding dependency between node binding and skin binding, node binding created after skin binding might appear after skin binding + // in update list, resulting in the changes to node binding not being propagated to skin binding and skin binding using old values during update. + auto appearance = m_scene->createAppearance(createTestEffect(), "skinAppearance2"); + auto uniform = appearance->getEffect().findUniformInput("jointMat"); + std::vector jointNodes{ m_scene->createNode(), m_scene->createNode() }; + AppearanceBinding* appearanceBinding{ m_logicEngine->createAppearanceBinding(*appearance) }; + std::vector joints{ m_logicEngine->createNodeBinding(*jointNodes[0]), m_logicEngine->createNodeBinding(*jointNodes[1]) }; + + // add some transformations to the joints before calculating inverse mats and creating skin + jointNodes[0]->setTranslation({1.f, 2.f, 3.f}); + jointNodes[1]->setRotation({10.f, 20.f, 30.f}, ERotationType::Euler_XYZ); + + std::vector inverseMats; + inverseMats.resize(2u); + + jointNodes[0]->getInverseModelMatrix(inverseMats[0]); + jointNodes[1]->getInverseModelMatrix(inverseMats[1]); + + auto skin = m_logicEngine->createSkinBinding(joints, inverseMats, *appearanceBinding, *uniform, "skin2"); + + jointNodes[0]->setRotation({-1.f, -2.f, -3.f}, ERotationType::Euler_XYZ); + jointNodes[1]->setTranslation({-1.f, -2.f, -3.f}); + + // The crutial part of this test is having this binding created after other logic nodes to make it appear last in node update topology. + NodeBinding& nodeBinding = *m_logicEngine->createNodeBinding(*jointNodes[0], ERotationType::Euler_XYZ, "NodeBinding"); + auto inputs = nodeBinding.getInputs(); + inputs->getChild("translation")->set(vec3f{2.1f, 2.2f, 2.3f}); + + EXPECT_TRUE(m_logicEngine->update()); + + const matrix44f expectedMat1 = { + 0.998f, -0.0523f, 0.0349f, 0.f, + 0.0529f, 0.9984f, -0.0174f, 0.f, + -0.0339f, 0.01925f, 0.9992f, 0.f, + 1.0979, 0.1976f, -0.6977f, 1.f + }; + const matrix44f expectedMat2 = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -1.f, -2.f, -3.f, 1.f + }; + + std::array uniformData{}; + appearance->getInputValue(skin->getAppearanceUniformInput(), 2u, uniformData.data()); + const matrix44f mat1 = uniformData[0]; + const matrix44f mat2 = uniformData[1]; + + for (glm::length_t i = 0u; i < 16; ++i) + EXPECT_NEAR(expectedMat1[i/4][i%4], mat1[i/4][i%4], 1e-4f) << i; + + for (glm::length_t i = 0u; i < 16; ++i) + EXPECT_NEAR(expectedMat2[i/4][i%4], mat2[i/4][i%4], 1e-4f) << i; + } + + TEST_F(ASkinBinding, CalculatesSameValuesAfterLoadingFromFile) + { + withTempDirectory(); + + m_jointNodes[0]->setRotation({ -1.f, -2.f, -3.f }, ERotationType::Euler_XYZ); + m_jointNodes[1]->setTranslation({ -1.f, -2.f, -3.f }); + EXPECT_TRUE(m_logicEngine->update()); + EXPECT_TRUE(m_scene->saveToFile("tmp.ramses")); + + ASSERT_TRUE(recreateFromFile("tmp.ramses")); + m_appearance = m_scene->findObject("skinAppearance"); + ASSERT_TRUE(m_appearance); + m_uniform = m_appearance->getEffect().findUniformInput("jointMat"); + ASSERT_TRUE(m_uniform); + EXPECT_TRUE(m_logicEngine->update()); + + const matrix44f expectedMat1 = { + 0.998f, -0.0523f, 0.0349f, 0.f, + 0.0529f, 0.9984f, -0.0174f, 0.f, + -0.0339f, 0.01925f, 0.9992f, 0.f, + -0.00209f, -0.00235f, 0.00227f, 1.f + }; + const matrix44f expectedMat2 = { + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -1.f, -2.f, -3.f, 1.f + }; + + std::array uniformData{}; + m_appearance->getInputValue(*m_uniform, 2u, uniformData.data()); + const matrix44f mat1 = uniformData[0]; + const matrix44f mat2 = uniformData[1]; + + for (glm::length_t i = 0u; i < 16; ++i) + EXPECT_NEAR(expectedMat1[i / 4][i % 4], mat1[i / 4][i % 4], 1e-4f) << i; + + for (glm::length_t i = 0u; i < 16; ++i) + EXPECT_NEAR(expectedMat2[i / 4][i % 4], mat2[i / 4][i % 4], 1e-4f) << i; + } + class ASkinBinding_SerializationLifecycle : public ASkinBinding { protected: diff --git a/tests/unittests/client/logic/internal/ApiObjectsTest.cpp b/tests/unittests/client/logic/internal/ApiObjectsTest.cpp index 8269e5234..661f73be5 100644 --- a/tests/unittests/client/logic/internal/ApiObjectsTest.cpp +++ b/tests/unittests/client/logic/internal/ApiObjectsTest.cpp @@ -179,11 +179,7 @@ namespace ramses::internal size_t m_emptySerializedSizeTotal{164u}; }; - - INSTANTIATE_TEST_SUITE_P( - AnApiObjectsTests, - AnApiObjects, - GetFeatureLevelTestValues()); + RAMSES_INSTANTIATE_LATEST_FEATURELEVEL_ONLY_TEST_SUITE(AnApiObjects); TEST_P(AnApiObjects, CreatesScriptFromValidLuaWithoutErrors) { @@ -1272,10 +1268,7 @@ namespace ramses::internal { }; - INSTANTIATE_TEST_SUITE_P( - AnApiObjects_SerializationTests, - AnApiObjects_Serialization, - GetFeatureLevelTestValues()); + RAMSES_INSTANTIATE_LATEST_FEATURELEVEL_ONLY_TEST_SUITE(AnApiObjects_Serialization); TEST_P(AnApiObjects_Serialization, AlwaysCreatesEmptyFlatbuffersContainers_WhenNoObjectsPresent) { diff --git a/tests/unittests/client/logic/internal/RamsesObjectResolverTest.cpp b/tests/unittests/client/logic/internal/RamsesObjectResolverTest.cpp index 76e209497..97f1e7ba0 100644 --- a/tests/unittests/client/logic/internal/RamsesObjectResolverTest.cpp +++ b/tests/unittests/client/logic/internal/RamsesObjectResolverTest.cpp @@ -8,8 +8,10 @@ #include "gtest/gtest.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" #include "internal/logic/RamsesObjectResolver.h" #include "impl/ErrorReporting.h" +#include "impl/SceneImpl.h" #include "impl/logic/NodeBindingImpl.h" #include "RamsesTestUtils.h" @@ -26,7 +28,7 @@ namespace ramses::internal RamsesTestSetup m_ramsesTestSetup; ramses::Scene* m_scene { m_ramsesTestSetup.createScene() }; ErrorReporting m_errors; - RamsesObjectResolver m_resolver {m_errors, m_scene->impl() }; + RamsesObjectResolver m_resolver {m_errors, m_scene->impl(), nullptr }; }; TEST_F(ARamsesObjectResolver, FindsSceneNodeByItsId) @@ -63,7 +65,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesNodeInScene("some logic node", fakeNodeId)); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42) which couldn't be found in the provided scene!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42|42) which couldn't be found in the provided scene!", m_errors.getError()->message); } TEST_F(ARamsesObjectResolver, ReportsErrorWhenAppearanceWithGivenIdDoesNotExist) @@ -72,7 +74,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesAppearanceInScene("some logic node", fakeAppearanceId)); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42) which couldn't be found in the provided scene!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42|42) which couldn't be found in the provided scene!", m_errors.getError()->message); } TEST_F(ARamsesObjectResolver, ReportsErrorWhenCameraWithGivenIdDoesNotExist) @@ -81,7 +83,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesCameraInScene("some logic node", fakeCameraId)); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42) which couldn't be found in the provided scene!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42|42) which couldn't be found in the provided scene!", m_errors.getError()->message); } TEST_F(ARamsesObjectResolver, ReportsErrorWhenRenderPassWithGivenIdDoesNotExist) @@ -90,7 +92,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesRenderPassInScene("some logic node", fakeRenderPassId)); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42) which couldn't be found in the provided scene!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42|42) which couldn't be found in the provided scene!", m_errors.getError()->message); } TEST_F(ARamsesObjectResolver, ReportsErrorWhenObjectWithGivenIdExists_ButIsNotANode) @@ -99,7 +101,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesNodeInScene("some logic node", appearance.getSceneObjectId())); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 2) which is not of the same type!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 2|2) which is not of the same type!", m_errors.getError()->message); } TEST_F(ARamsesObjectResolver, ReportsErrorWhenResolvedObjectExists_ButIsNotCamera) @@ -108,7 +110,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesCameraInScene("some logic node", node->getSceneObjectId())); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 1) which is not of the same type!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 1|1) which is not of the same type!", m_errors.getError()->message); } TEST_F(ARamsesObjectResolver, ReportsErrorWhenResolvedObjectExists_ButIsNotAppearance) @@ -117,7 +119,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesAppearanceInScene("some logic node", node->getSceneObjectId())); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 1) which is not of the same type!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 1|1) which is not of the same type!", m_errors.getError()->message); } TEST_F(ARamsesObjectResolver, ReportsErrorWhenResolvedObjectExists_ButIsNotRenderPass) @@ -126,7 +128,7 @@ namespace ramses::internal EXPECT_FALSE(m_resolver.findRamsesRenderPassInScene("some logic node", node->getSceneObjectId())); ASSERT_TRUE(m_errors.getError().has_value()); - EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 1) which is not of the same type!", m_errors.getError()->message); + EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 1|1) which is not of the same type!", m_errors.getError()->message); } // Special case (ramses Camera is also a Node) - test that it works as expected when resolved by Id @@ -137,4 +139,50 @@ namespace ramses::internal EXPECT_EQ(camera, m_resolver.findRamsesNodeInScene("some logic node", camera->getSceneObjectId())); EXPECT_FALSE(m_errors.getError().has_value()); } + + + class ARamsesObjectResolverMapped : public ::testing::Test + { + protected: + RamsesTestSetup m_ramsesTestSetup; + ramses::Scene* m_scene { m_ramsesTestSetup.createScene() }; + ErrorReporting m_errors; + SceneMergeHandleMapping m_mapping; + RamsesObjectResolver m_resolver {m_errors, m_scene->impl(), &m_mapping }; + }; + + TEST_F(ARamsesObjectResolverMapped, FindsSceneNodeByItsId) + { + ramses::Node* node = m_scene->createNode(); + const ramses::sceneObjectId_t mappedObjectId{ 99 }; + EXPECT_EQ(nullptr, m_resolver.findRamsesNodeInScene("some logic node", mappedObjectId)); + ASSERT_TRUE(m_errors.getError().has_value()); + m_errors.reset(); + m_mapping.addMapping(mappedObjectId, node->getSceneObjectId()); + EXPECT_EQ(node, m_resolver.findRamsesNodeInScene("some logic node", mappedObjectId)); + EXPECT_FALSE(m_errors.getError().has_value()); + } + + TEST_F(ARamsesObjectResolverMapped, ReportsErrorWhenNodeWithGivenIdDoesNotExist) + { + const ramses::sceneObjectId_t fakeNodeId{ 42 }; + const ramses::sceneObjectId_t fakeMappedNodeId{ 99 }; + + m_mapping.addMapping(fakeNodeId, fakeMappedNodeId); + + EXPECT_FALSE(m_resolver.findRamsesNodeInScene("some logic node", fakeNodeId)); + ASSERT_TRUE(m_errors.getError().has_value()); + EXPECT_EQ("Fatal error during loading from file! Serialized Ramses Logic object 'some logic node' points to a Ramses object (id: 42|99) which couldn't be found in the provided scene!", m_errors.getError()->message); + } + + TEST_F(ARamsesObjectResolverMapped, ReportsErrorWhenResolvedObjectExists_ButIsNotRenderPass) + { + ramses::Node* node = m_scene->createNode(); + const ramses::sceneObjectId_t mappedObjectId{ 99 }; + m_mapping.addMapping(mappedObjectId, node->getSceneObjectId()); + + EXPECT_FALSE(m_resolver.findRamsesRenderPassInScene("some logic node", mappedObjectId)); + ASSERT_TRUE(m_errors.getError().has_value()); + EXPECT_EQ("Fatal error during loading from file! Ramses binding 'some logic node' points to a Ramses scene object (id: 99|1) which is not of the same type!", m_errors.getError()->message); + } } diff --git a/tests/unittests/client/res/testScene_01.ramses b/tests/unittests/client/res/testScene_01.ramses index 427038dd3..bb5f74d9e 100644 Binary files a/tests/unittests/client/res/testScene_01.ramses and b/tests/unittests/client/res/testScene_01.ramses differ diff --git a/tests/unittests/client/res/testScene_02.ramses b/tests/unittests/client/res/testScene_02.ramses new file mode 100644 index 000000000..22adb300e Binary files /dev/null and b/tests/unittests/client/res/testScene_02.ramses differ diff --git a/tests/unittests/client/ClientEventHandlerMock.cpp b/tests/unittests/client/utils/ClientEventHandlerMock.cpp similarity index 100% rename from tests/unittests/client/ClientEventHandlerMock.cpp rename to tests/unittests/client/utils/ClientEventHandlerMock.cpp diff --git a/tests/unittests/client/ClientEventHandlerMock.h b/tests/unittests/client/utils/ClientEventHandlerMock.h similarity index 100% rename from tests/unittests/client/ClientEventHandlerMock.h rename to tests/unittests/client/utils/ClientEventHandlerMock.h diff --git a/tests/unittests/client/ClientTestUtils.cpp b/tests/unittests/client/utils/ClientTestUtils.cpp similarity index 100% rename from tests/unittests/client/ClientTestUtils.cpp rename to tests/unittests/client/utils/ClientTestUtils.cpp diff --git a/tests/unittests/client/ClientTestUtils.h b/tests/unittests/client/utils/ClientTestUtils.h similarity index 86% rename from tests/unittests/client/ClientTestUtils.h rename to tests/unittests/client/utils/ClientTestUtils.h index 823bb0e2e..8147db4d4 100644 --- a/tests/unittests/client/ClientTestUtils.h +++ b/tests/unittests/client/utils/ClientTestUtils.h @@ -38,12 +38,12 @@ namespace ramses::internal class LocalTestClient { public: - LocalTestClient() - : framework{ GetDefaultFrameworkConfig() } + explicit LocalTestClient(ramses::EFeatureLevel featureLevel = ramses::EFeatureLevel_Latest) + : framework{ GetDefaultFrameworkConfig(featureLevel) } , client(*framework.createClient("localTestClient")) , m_creationHelper(nullptr, &client) { - EXPECT_EQ(EFeatureLevel_Latest, framework.getFeatureLevel()); + EXPECT_EQ(featureLevel, framework.getFeatureLevel()); sceneActionsCollector.init(framework.impl().getScenegraphComponent()); framework.impl().getScenegraphComponent().setSceneRendererHandler(&sceneActionsCollector); } @@ -64,11 +64,11 @@ namespace ramses::internal return framework; } - static const RamsesFrameworkConfig& GetDefaultFrameworkConfig() + static RamsesFrameworkConfig GetDefaultFrameworkConfig(ramses::EFeatureLevel featureLevel = ramses::EFeatureLevel_Latest) { //disabling the periodic logs is important as otherwise race conditions can occur in the tests that check //that the statistic counters are updated (periodic logger resets the counters) - static RamsesFrameworkConfig config{EFeatureLevel_Latest}; + RamsesFrameworkConfig config{ featureLevel }; config.setLogLevel(ELogLevel::Off); config.setConnectionSystem(EConnectionSystem::Off); config.setPeriodicLogInterval(std::chrono::seconds(0)); @@ -85,8 +85,9 @@ namespace ramses::internal class LocalTestClientWithScene : public LocalTestClient { public: - explicit LocalTestClientWithScene(EScenePublicationMode publicationMode = EScenePublicationMode::LocalOnly) - : m_scene(CreateScene(client, publicationMode)) + explicit LocalTestClientWithScene(ramses::EFeatureLevel featureLevel = ramses::EFeatureLevel_Latest, EScenePublicationMode publicationMode = EScenePublicationMode::LocalOnly, ERenderBackendCompatibility compatibility = ERenderBackendCompatibility::OpenGL) + : LocalTestClient{ featureLevel } + , m_scene(CreateScene(client, publicationMode, compatibility)) , m_constRefToScene(m_scene) , m_internalScene(m_scene.impl().getIScene()) { @@ -99,9 +100,9 @@ namespace ramses::internal client.destroy(m_scene); } - static ramses::Scene& CreateScene(RamsesClient& client, EScenePublicationMode publicationMode) + static ramses::Scene& CreateScene(RamsesClient& client, EScenePublicationMode publicationMode, ERenderBackendCompatibility compatibility) { - SceneConfig config{sceneId_t(123u), publicationMode}; + SceneConfig config{sceneId_t(123u), publicationMode, compatibility}; return *client.createScene(config); } diff --git a/tests/unittests/client/CreationHelper.cpp b/tests/unittests/client/utils/CreationHelper.cpp similarity index 98% rename from tests/unittests/client/CreationHelper.cpp rename to tests/unittests/client/utils/CreationHelper.cpp index 2242463a3..a6bf2117d 100644 --- a/tests/unittests/client/CreationHelper.cpp +++ b/tests/unittests/client/utils/CreationHelper.cpp @@ -226,6 +226,13 @@ namespace ramses::internal { // SceneReference cannot refer to same sceneID, create a different one every time ++m_lastReferencedSceneId.getReference(); +#ifndef _MSC_VER +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif return m_scene->createSceneReference(m_lastReferencedSceneId, name); +#ifndef _MSC_VER +#pragma GCC diagnostic pop +#endif } } diff --git a/tests/unittests/client/CreationHelper.h b/tests/unittests/client/utils/CreationHelper.h similarity index 100% rename from tests/unittests/client/CreationHelper.h rename to tests/unittests/client/utils/CreationHelper.h diff --git a/tests/unittests/client/logic/shared/LogicEngineTestWithCreationHelper.h b/tests/unittests/client/utils/LogicEngineTestWithCreationHelper.h similarity index 100% rename from tests/unittests/client/logic/shared/LogicEngineTestWithCreationHelper.h rename to tests/unittests/client/utils/LogicEngineTestWithCreationHelper.h diff --git a/tests/unittests/client/logic/shared/LogicEngineTest_Base.h b/tests/unittests/client/utils/LogicEngineTest_Base.h similarity index 100% rename from tests/unittests/client/logic/shared/LogicEngineTest_Base.h rename to tests/unittests/client/utils/LogicEngineTest_Base.h diff --git a/tests/unittests/client/logic/shared/LogicNodeDummy.h b/tests/unittests/client/utils/LogicNodeDummy.h similarity index 93% rename from tests/unittests/client/logic/shared/LogicNodeDummy.h rename to tests/unittests/client/utils/LogicNodeDummy.h index 48c839034..671755648 100644 --- a/tests/unittests/client/logic/shared/LogicNodeDummy.h +++ b/tests/unittests/client/utils/LogicNodeDummy.h @@ -8,12 +8,14 @@ #pragma once +#include "impl/SceneImpl.h" #include "impl/logic/LogicNodeImpl.h" #include "impl/logic/PropertyImpl.h" #include "impl/logic/RamsesBindingImpl.h" #include "ramses/client/logic/LogicNode.h" #include "ramses/client/logic/Property.h" +#include "ramses/client/Node.h" namespace ramses::internal { @@ -72,7 +74,8 @@ namespace ramses::internal class RamsesBindingDummyImpl : public RamsesBindingImpl { public: - explicit RamsesBindingDummyImpl(SceneImpl& scene) : RamsesBindingImpl{ scene, "dummybinding", sceneObjectId_t{1u} } + explicit RamsesBindingDummyImpl(SceneImpl& scene) + : RamsesBindingImpl{ scene, "dummybinding", sceneObjectId_t{1u}, *scene.createNode("") } { } diff --git a/tests/unittests/client/logic/shared/LuaScriptTest_Base.h b/tests/unittests/client/utils/LuaScriptTest_Base.h similarity index 100% rename from tests/unittests/client/logic/shared/LuaScriptTest_Base.h rename to tests/unittests/client/utils/LuaScriptTest_Base.h diff --git a/tests/unittests/client/MockActionCollector.h b/tests/unittests/client/utils/MockActionCollector.h similarity index 99% rename from tests/unittests/client/MockActionCollector.h rename to tests/unittests/client/utils/MockActionCollector.h index 1885957c9..a44dd54e0 100644 --- a/tests/unittests/client/MockActionCollector.h +++ b/tests/unittests/client/utils/MockActionCollector.h @@ -14,6 +14,7 @@ #include "internal/SceneGraph/Scene/SceneActionCollection.h" #include "SceneRendererHandlerMock.h" #include "internal/Components/SceneUpdate.h" +#include "TestEqualHelper.h" namespace ramses::internal { diff --git a/tests/unittests/client/logic/shared/PropertyLinkTestUtils.h b/tests/unittests/client/utils/PropertyLinkTestUtils.h similarity index 100% rename from tests/unittests/client/logic/shared/PropertyLinkTestUtils.h rename to tests/unittests/client/utils/PropertyLinkTestUtils.h diff --git a/tests/unittests/client/logic/shared/RamsesObjectResolverMock.h b/tests/unittests/client/utils/RamsesObjectResolverMock.h similarity index 100% rename from tests/unittests/client/logic/shared/RamsesObjectResolverMock.h rename to tests/unittests/client/utils/RamsesObjectResolverMock.h diff --git a/tests/unittests/client/RamsesObjectTestTypes.h b/tests/unittests/client/utils/RamsesObjectTestTypes.h similarity index 100% rename from tests/unittests/client/RamsesObjectTestTypes.h rename to tests/unittests/client/utils/RamsesObjectTestTypes.h diff --git a/tests/unittests/client/logic/shared/RamsesTestUtils.h b/tests/unittests/client/utils/RamsesTestUtils.h similarity index 100% rename from tests/unittests/client/logic/shared/RamsesTestUtils.h rename to tests/unittests/client/utils/RamsesTestUtils.h diff --git a/tests/unittests/client/logic/shared/SerializationTestUtils.h b/tests/unittests/client/utils/SerializationTestUtils.h similarity index 100% rename from tests/unittests/client/logic/shared/SerializationTestUtils.h rename to tests/unittests/client/utils/SerializationTestUtils.h diff --git a/tests/unittests/client/SimpleSceneTopology.h b/tests/unittests/client/utils/SimpleSceneTopology.h similarity index 100% rename from tests/unittests/client/SimpleSceneTopology.h rename to tests/unittests/client/utils/SimpleSceneTopology.h diff --git a/tests/unittests/client/utils/TestEffectCreator.cpp b/tests/unittests/client/utils/TestEffectCreator.cpp new file mode 100644 index 000000000..d0d673563 --- /dev/null +++ b/tests/unittests/client/utils/TestEffectCreator.cpp @@ -0,0 +1,156 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + + +#include +#include "TestEffectCreator.h" +#include "ramses/client/EffectDescription.h" + +namespace ramses::internal +{ + Effect* TestEffectCreator::CreateEffect(ramses::Scene& scene, bool withGeometryShader, EFeatureLevel featureLevel) + { + std::string VertexShader(R"SHADER( + #version 320 es + uniform lowp float floatInput; + uniform lowp float floatInputArray[3]; + + uniform vec2 vec2fInput; + uniform vec2 vec2fInputArray[3]; + uniform vec3 vec3fInput; + uniform vec3 vec3fInputArray[3]; + uniform vec4 vec4fInput; + uniform vec4 vec4fInputArray[3]; + + uniform mat2 matrix22fInput; + uniform mat2 matrix22fInputArray[3]; + uniform mat3 matrix33fInput; + uniform mat3 matrix33fInputArray[3]; + uniform mat4 matrix44fInput; + uniform mat4 matrix44fInputArray[3]; + + uniform bool boolInput; + uniform bool boolInputArray[3]; + + uniform lowp int integerInput; + uniform lowp int integerInputArray[3]; + + uniform ivec2 vec2iInput; + uniform ivec2 vec2iInputArray[3]; + uniform ivec3 vec3iInput; + uniform ivec3 vec3iInputArray[3]; + uniform ivec4 vec4iInput; + uniform ivec4 vec4iInputArray[3]; + + //__UBO__DECLARATION + + uniform mat4 mvMatrix; + + in float floatArrayInput; + in vec2 vec2fArrayInput; + in vec3 vec3fArrayInput; + in vec4 vec4fArrayInput; + + void main(void) + { + lowp vec4 values = vec4(1) * floatInput* vec2fInput.x * vec3fInput.y* vec4fInput.z; + values[0] = float(integerInput) + floatInputArray[0] + floatInputArray[1]; + values[1] = float(vec2iInput.x)* float(vec3iInput.y)* float(vec4iInput.z); + values[2] = vec2fArrayInput.x*vec3fArrayInput.y*vec4fArrayInput.z; + values[3] = floatArrayInput*vec2fArrayInput.x*vec4fArrayInput.z; + values[0] += floatInputArray[0] + vec2fInputArray[0].x + vec3fInputArray[0].x + vec4fInputArray[0].x; + values[1] += matrix44fInputArray[0][0].x + float(integerInputArray[0]); + values[2] += float(vec2iInputArray[0].x + vec3iInputArray[0].x + vec4iInputArray[0].x); + values[3] += matrix22fInput[0][0] + matrix33fInput[0][0] + matrix22fInputArray[0][0].x + matrix33fInputArray[0][0].x; + //__UBO__USAGE + values = matrix44fInput * mvMatrix * values; + if (boolInput || boolInputArray[0] || boolInputArray[1] || boolInputArray[2]) + gl_Position = values; + } + )SHADER"); + + static_assert(EFeatureLevel_Latest != EFeatureLevel_01, "Remove all this and make UBO declaration/usage always part of test shader"); + if (featureLevel >= EFeatureLevel_02) + { + const std::string_view UBODecl(R"UBODecl( + layout(std140,binding=1) uniform uniformBlock_t + { + mat4 ubMat44; + float ubFloat[3]; + mat3 ubMat33; + } uniformBlock; + + //anonymous uniform block + layout(std140,binding=2) uniform uniformBlock_t2 + { + bool ubBool; + mat3 ubMat33; + mat2 ubMat22; + ivec4 ubIVec4; + vec2 ubVec2; + int ubInt; + }; + + // uniform block with semantics + layout(std140,binding=3) uniform uniformBlock_t3 + { + mat4 ubModelMat; + } ubWithSemantics; + )UBODecl"); + const std::string_view UBOUsage("values[0] += uniformBlock.ubFloat[0] + ubVec2.x + ubMat22[0][0] + ubMat33[0][0] + ubWithSemantics.ubModelMat[0][0];"); + + auto replaceStr = [](std::string& str, std::string_view from, std::string_view to) { str.replace(str.find(from), from.length(), to); }; + replaceStr(VertexShader, "//__UBO__DECLARATION", UBODecl); + replaceStr(VertexShader, "//__UBO__USAGE", UBOUsage); + } + + const std::string_view FragmentShader(R"SHADER( + #version 320 es + precision mediump float; + uniform sampler2D texture2dInput; + uniform lowp sampler2DMS texture2dMSInput; + uniform lowp sampler3D texture3dInput; + uniform samplerCube textureCubeInput; + #extension GL_OES_EGL_image_external_essl3 : require + uniform samplerExternalOES textureExternalInput; + out vec4 FragColor; + void main(void) + { + FragColor = vec4(1.0) + texture(texture2dInput, vec2(0,0)) + texelFetch(texture2dMSInput, ivec2(0,0), 0) + texture(texture3dInput, vec3(0, 0, 0)) + texture(textureCubeInput, vec3(0,0,0)) + texture(textureExternalInput, vec2(0,0)); + } + )SHADER"); + + EffectDescription effectDesc; + effectDesc.setVertexShader(VertexShader); + effectDesc.setFragmentShader(FragmentShader); + + if (withGeometryShader) + { + effectDesc.setGeometryShader(R"SHADER( + #version 320 es + layout(lines) in; + layout(points, max_vertices = 1) out; + void main() { + gl_Position = vec4(0.0); + EmitVertex(); + } + )SHADER"); + } + + effectDesc.setAttributeSemantic("vec2fArrayInput", EEffectAttributeSemantic::TextPositions); + effectDesc.setUniformSemantic("mvMatrix", EEffectUniformSemantic::ModelViewMatrix); + effectDesc.setUniformSemantic("texture2dInput", EEffectUniformSemantic::TextTexture); + effectDesc.setUniformSemantic(3u, EEffectUniformSemantic::ModelBlock); + + auto effect = scene.createEffect(effectDesc, "input test effect"); + EXPECT_TRUE(effect) << scene.getLastEffectErrorMessages(); + return effect; + } + + std::array, ramses::EFeatureLevel_Latest> TestWithSharedEffectPerFeatureLevel::effectCreators; +} diff --git a/tests/unittests/client/utils/TestEffectCreator.h b/tests/unittests/client/utils/TestEffectCreator.h new file mode 100644 index 000000000..020f82758 --- /dev/null +++ b/tests/unittests/client/utils/TestEffectCreator.h @@ -0,0 +1,82 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2015 BMW Car IT GmbH +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include +#include "ClientTestUtils.h" + +namespace ramses::internal +{ + class TestEffectCreator : public LocalTestClientWithScene + { + public: + explicit TestEffectCreator(ramses::EFeatureLevel featureLevel = EFeatureLevel_Latest, bool withGeometryShader = false) + : LocalTestClientWithScene{ featureLevel } + { + effect = CreateEffect(m_scene, withGeometryShader, featureLevel); + EXPECT_TRUE(effect != nullptr); + appearance = this->m_scene.createAppearance(*effect); + EXPECT_TRUE(appearance != nullptr); + } + + Appearance& recreateAppearence() + { + assert(appearance); + this->m_scene.destroy(*appearance); + appearance = this->m_scene.createAppearance(*effect); + assert(appearance); + + return *appearance; + } + + ~TestEffectCreator() override + { + EXPECT_TRUE(this->m_scene.destroy(*appearance)); + } + + static Effect* CreateEffect(ramses::Scene& scene, bool withGeometryShader = false, EFeatureLevel featureLevel = EFeatureLevel_Latest); + + Effect* effect = nullptr; + Appearance* appearance = nullptr; + }; + + // Helper class to provide effect creator in static fashion (to be shared across test cases) while supporting feature level. + // Usage: derive test class from this and use m_sharedTestState. + // Tip: use with RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE to instantiate templated test suite. + class TestWithSharedEffectPerFeatureLevel : public ::testing::TestWithParam + { + public: + explicit TestWithSharedEffectPerFeatureLevel(bool withGeometryShader = false) + : m_withGeometryShader{ withGeometryShader } + { + } + + static TestEffectCreator& GetEffectCreator(ramses::EFeatureLevel featureLevel, bool withGeometryShader = false) + { + assert(featureLevel > 0 && featureLevel <= ramses::EFeatureLevel_Latest); + const size_t idx = featureLevel - 1; + if (!effectCreators[idx]) + effectCreators[idx] = std::make_unique(featureLevel, withGeometryShader); + return *effectCreators[idx]; + } + + static void TearDownTestSuite() + { + for (auto& c : effectCreators) + c.reset(); + } + + protected: + bool m_withGeometryShader = false; + TestEffectCreator& m_sharedTestState = GetEffectCreator(GetParam(), m_withGeometryShader); + + private: + static std::array, ramses::EFeatureLevel_Latest> effectCreators; + }; +} diff --git a/tests/unittests/client/TestEffects.h b/tests/unittests/client/utils/TestEffects.h similarity index 76% rename from tests/unittests/client/TestEffects.h rename to tests/unittests/client/utils/TestEffects.h index ba857a356..c540a0d40 100644 --- a/tests/unittests/client/TestEffects.h +++ b/tests/unittests/client/utils/TestEffects.h @@ -175,5 +175,50 @@ namespace ramses::internal assert(effect != nullptr); return effect; } + + static Effect* CreateTestEffectWithUBOSemantics(ramses::Scene& scene, const std::unordered_set& semantics, std::string_view name = {}) + { + EffectDescription effectDesc; + effectDesc.setVertexShader(R"SHADER( + #version 320 es + layout(std140,binding=0) uniform uniformBlock_t3 + { + mat4 ubModelMat; + } modelUBO; + layout(std140,binding=1) uniform uniformBuffer_t + { + mat4 projMat; + mat4 viewMat; + vec3 cameraPos; + } camUBO; + layout(std140,binding=2) uniform uniformBuffer_t2 + { + mat4 mvpMat; + mat4 mvMat; + mat4 normalMat; + } modelCamUBO; + void main() + { + gl_Position = modelUBO.ubModelMat * camUBO.projMat * camUBO.viewMat * modelCamUBO.mvpMat * vec4(0.0); + })SHADER"); + effectDesc.setFragmentShader(R"SHADER( + #version 320 es + precision mediump float; + out vec4 FragColor; + void main(void) + { + FragColor = vec4(0.0); + })SHADER"); + + if (semantics.count(EEffectUniformSemantic::ModelBlock) != 0u) + effectDesc.setUniformSemantic(0, EEffectUniformSemantic::ModelBlock); + if (semantics.count(EEffectUniformSemantic::CameraBlock) != 0u) + effectDesc.setUniformSemantic(1, EEffectUniformSemantic::CameraBlock); + if (semantics.count(EEffectUniformSemantic::ModelCameraBlock) != 0u) + effectDesc.setUniformSemantic(2, EEffectUniformSemantic::ModelCameraBlock); + Effect* effect = scene.createEffect(effectDesc, name); + assert(effect != nullptr); + return effect; + } }; } diff --git a/tests/unittests/client/logic/shared/WithTempDirectory.h b/tests/unittests/client/utils/WithTempDirectory.h similarity index 95% rename from tests/unittests/client/logic/shared/WithTempDirectory.h rename to tests/unittests/client/utils/WithTempDirectory.h index 3ce68d7ae..0b1f06374 100644 --- a/tests/unittests/client/logic/shared/WithTempDirectory.h +++ b/tests/unittests/client/utils/WithTempDirectory.h @@ -8,7 +8,9 @@ #pragma once -#include "internal/logic/StdFilesystemWrapper.h" +#include + +namespace fs = std::filesystem; namespace ramses::internal { diff --git a/tests/unittests/framework-test-utils/include/FeatureLevelTestValues.h b/tests/unittests/framework-test-utils/include/FeatureLevelTestValues.h new file mode 100644 index 000000000..41dd50eff --- /dev/null +++ b/tests/unittests/framework-test-utils/include/FeatureLevelTestValues.h @@ -0,0 +1,48 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2022 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "gtest/gtest.h" +#include "ramses/framework/EFeatureLevel.h" + +namespace ramses::internal +{ + // List of test values for all supported feature levels. + // Usage: derive test class from ::testing::TestWithParam + // and use RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE below to instantiate them + [[nodiscard]] inline ::testing::internal::ValueArray + GetFeatureLevelTestValues() + { + static_assert(ramses::EFeatureLevel_Latest == ramses::EFeatureLevel_02, "Update this list!"); + return ::testing::Values(ramses::EFeatureLevel_01, ramses::EFeatureLevel_02); + } + + // List of test values for feature level templated tests but containing only the latest feature level. + // This is meant to speed up test runtime for tests which are templated for feature level testing + // but there is no need to test all of them because feature levels do not affect their tested classes' behavior. + [[nodiscard]] inline ::testing::internal::ValueArray + GetLatestFeatureLevelOnlyTestValues() + { + return ::testing::Values(ramses::EFeatureLevel_Latest); + } + +#define RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(_testName) \ + INSTANTIATE_TEST_SUITE_P( \ + _testName ## Tests, \ + _testName, \ + ramses::internal::GetFeatureLevelTestValues()); \ + static_assert(ramses::EFeatureLevel_Latest == ramses::EFeatureLevel_02, "Re-evaluate which tests need to be instantiated for all feature levels"); + +#define RAMSES_INSTANTIATE_LATEST_FEATURELEVEL_ONLY_TEST_SUITE(_testName) \ + INSTANTIATE_TEST_SUITE_P( \ + _testName ## Tests, \ + _testName, \ + ramses::internal::GetLatestFeatureLevelOnlyTestValues()); \ + static_assert(ramses::EFeatureLevel_Latest == ramses::EFeatureLevel_02, "Re-evaluate which tests need to be instantiated for all feature levels"); +} diff --git a/tests/unittests/framework-test-utils/include/ServiceHandlerMocks.h b/tests/unittests/framework-test-utils/include/ServiceHandlerMocks.h index 333760bb5..7813209d1 100644 --- a/tests/unittests/framework-test-utils/include/ServiceHandlerMocks.h +++ b/tests/unittests/framework-test-utils/include/ServiceHandlerMocks.h @@ -13,6 +13,7 @@ #include "internal/SceneReferencing/SceneReferenceEvent.h" #include "internal/Communication/TransportCommon/ServiceHandlerInterfaces.h" #include "internal/Components/ISceneProviderEventConsumer.h" +#include "TestEqualHelper.h" namespace ramses::internal { diff --git a/tests/unittests/framework-test-utils/include/TestEqualHelper.h b/tests/unittests/framework-test-utils/include/TestEqualHelper.h index f78aab906..56ecc92cb 100644 --- a/tests/unittests/framework-test-utils/include/TestEqualHelper.h +++ b/tests/unittests/framework-test-utils/include/TestEqualHelper.h @@ -10,6 +10,7 @@ #include "gtest/gtest.h" #include "glm/mat2x2.hpp" +#include "internal/SceneGraph/SceneAPI/SceneId.h" namespace ramses::internal { @@ -25,4 +26,7 @@ namespace ramses::internal } } } + + bool operator==(const SceneInfo& a, const SceneInfo& b); + bool operator!=(const SceneInfo& a, const SceneInfo& b); } diff --git a/tests/unittests/framework/SceneGraph/Scene/TestingScene.h b/tests/unittests/framework-test-utils/include/TestingScene.h similarity index 80% rename from tests/unittests/framework/SceneGraph/Scene/TestingScene.h rename to tests/unittests/framework-test-utils/include/TestingScene.h index 2247a5342..2afe346a9 100644 --- a/tests/unittests/framework/SceneGraph/Scene/TestingScene.h +++ b/tests/unittests/framework-test-utils/include/TestingScene.h @@ -9,15 +9,19 @@ #pragma once +#include "internal/Core/Common/TypedMemoryHandle.h" #include "internal/SceneGraph/Scene/Scene.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" #include "internal/SceneGraph/SceneAPI/TextureEnums.h" #include "internal/SceneGraph/SceneAPI/RenderBuffer.h" #include "internal/SceneGraph/SceneAPI/RenderGroupUtils.h" +#include "ramses/framework/EFeatureLevel.h" #include "glm/gtx/transform.hpp" #include "glm/gtx/matrix_transform_2d.hpp" #include #include +#include namespace ramses::internal { @@ -27,11 +31,11 @@ namespace ramses::internal return {std::byte(std::forward(args))...}; } - template class TestingScene { public: - explicit TestingScene() + TestingScene(IScene& scene, EFeatureLevel featureLevel) + : m_featureLevel{ featureLevel } { scene.allocateNode(0u, parent); scene.allocateNode(0u, child); @@ -61,6 +65,14 @@ namespace ramses::internal scene.setRotation (t3, t3Rotation, ERotationType::Quaternion); scene.setScaling (t3, t3Scaling ); + if (featureLevel >= EFeatureLevel_02) + { + scene.allocateUniformBuffer(10u, uniformBuffer); + + scene.updateUniformBuffer(uniformBuffer, 3u, 3u, std::array{ std::byte{1u}, std::byte{11u}, std::byte{111u} }.data()); + scene.updateUniformBuffer(uniformBuffer, 8u, 2u, std::array{ std::byte{2u}, std::byte{22u} }.data()); + } + scene.allocateRenderState(renderState); scene.setRenderStateBlendFactors(renderState, EBlendFactor::One, EBlendFactor::SrcAlpha, EBlendFactor::OneMinusSrcAlpha, EBlendFactor::DstAlpha); scene.setRenderStateBlendOperations(renderState, EBlendOperation::Add, EBlendOperation::Subtract); @@ -82,7 +94,6 @@ namespace ramses::internal scene.setRenderableVisibility(renderable, EVisibilityMode::Invisible); scene.setRenderableInstanceCount(renderable, renderableInstanceCount); scene.setRenderableStartVertex(renderable, startVertex); - scene.allocateRenderable(child, renderable2); DataFieldInfoVector uniformLayoutDataFields{ @@ -94,7 +105,8 @@ namespace ramses::internal DataFieldInfo(EDataType::DataReference), DataFieldInfo(EDataType::TextureSamplerExternal), DataFieldInfo(EDataType::Bool), - DataFieldInfo(EDataType::Bool) + DataFieldInfo(EDataType::Bool), + DataFieldInfo(EDataType::UniformBuffer, 1u, EFixedSemantics::Invalid) }; scene.allocateDataLayout(uniformLayoutDataFields, effectHash, uniformLayout); @@ -106,14 +118,17 @@ namespace ramses::internal }; scene.allocateDataLayout(geometryLayoutDataFields, effectHash, vertexLayout); - scene.allocateDataInstance(scene.allocateDataLayout({ DataFieldInfo{ramses::internal::EDataType::Vector2I}, DataFieldInfo{ramses::internal::EDataType::Vector2I} }, - ResourceContentHash::Invalid(), {}), cameraDataInstance); + scene.allocateDataLayout({ DataFieldInfo{ramses::internal::EDataType::Vector2I}, DataFieldInfo{ramses::internal::EDataType::Vector2I} }, + ResourceContentHash::Invalid(), cameraDataLayout); + scene.allocateDataInstance(cameraDataLayout, cameraDataInstance); scene.allocateTextureSampler({ samplerStates, textureHash }, samplerWithTextureResource); scene.allocateTextureSampler({ samplerStates, renderBuffer }, samplerWithRenderBuffer); scene.allocateTextureSampler({ samplerStates, texture2DBuffer }, samplerWithTextureBuffer); scene.allocateTextureSampler({ samplerStates, TextureSampler::ContentType::ExternalTexture, ResourceContentHash::Invalid(), InvalidMemoryHandle }, samplerWithExternalTexture); + scene.allocateDataInstance(uniformLayout, dataRef); + scene.allocateDataInstance(uniformLayout, uniformData); scene.setDataSingleFloat(uniformData, DataFieldHandle(0u), 0.5f); const std::array dataVec4fArray = { glm::vec4(0.0f, 1.0f, 2.0f, 3.0f), glm::vec4(4.0f, 5.0f, 6.0f, 7.0f) }; @@ -125,6 +140,8 @@ namespace ramses::internal scene.setDataTextureSamplerHandle(uniformData, DataFieldHandle(6), samplerWithExternalTexture); scene.setDataSingleBoolean(uniformData, DataFieldHandle(7), true); scene.setDataSingleBoolean(uniformData, DataFieldHandle(8), false); + if (featureLevel >= EFeatureLevel_02) + scene.setDataUniformBuffer(uniformData, DataFieldHandle(9), uniformBuffer); scene.allocateDataInstance(vertexLayout, geometryData); scene.setDataResource(geometryData, DataFieldHandle(0u), indexArrayHash, DataBufferHandle::Invalid(), indexArrayDivisor, 0u, 0u); @@ -142,6 +159,8 @@ namespace ramses::internal scene.setRenderBufferProperties(renderBuffer, 23u, 42u, 3u); scene.addRenderTargetRenderBuffer(renderTarget, renderBuffer); + scene.allocateRenderBuffer({ 1u, 2u, EPixelStorageFormat::RGBA8, ERenderBufferAccessMode::ReadWrite, 0u }, renderBuffer2); + scene.allocateRenderGroup(0u, 0u, renderGroup); scene.addRenderableToRenderGroup(renderGroup, renderable, 15); scene.addRenderableToRenderGroup(renderGroup, renderable2, 5); @@ -196,35 +215,42 @@ namespace ramses::internal scene.setSceneReferenceRenderOrder(sceneRef, -13); } - const SCENE& getScene() const + void VerifyContent(const IScene& otherScene) const { - return scene; + CheckNodesEquivalentTo(otherScene); + CheckTransformsEquivalentTo(otherScene); + CheckRenderablesEquivalentTo(otherScene); + CheckStatesEquivalentTo(otherScene); + CheckDataLayoutsEquivalentTo(otherScene); + CheckDataInstancesEquivalentTo(otherScene); + CheckTextureSamplersEquivalentTo(otherScene); + CheckCamerasEquivalentTo(otherScene); + CheckRenderGroupsEquivalentTo(otherScene); + CheckRenderPassesEquivalentTo(otherScene); + CheckBlitPassesEquivalentTo(otherScene); + CheckRenderBuffersAndTargetsEquivalentTo(otherScene); + CheckDataBuffersEquivalentTo(otherScene); + CheckTextureBuffersEquivalentTo(otherScene); + CheckDataSlotsEquivalentTo(otherScene); + CheckPickableObjectsEquivalentTo(otherScene); + CheckSceneReferencesEquivalentTo(otherScene); + if (m_featureLevel >= EFeatureLevel_02) + CheckSceneUniformBuffersEquivalentTo(otherScene); } - template - void CheckEquivalentTo(const OTHERSCENE& otherScene) const + void setMapping(const SceneMergeHandleMapping* mapping) { - CheckNodesEquivalentTo(otherScene); - CheckTransformsEquivalentTo(otherScene); - CheckRenderablesEquivalentTo(otherScene); - CheckStatesEquivalentTo(otherScene); - CheckDataLayoutsEquivalentTo(otherScene); - CheckDataInstancesEquivalentTo(otherScene); - CheckTextureSamplersEquivalentTo(otherScene); - CheckCamerasEquivalentTo(otherScene); - CheckRenderGroupsEquivalentTo(otherScene); - CheckRenderPassesEquivalentTo(otherScene); - CheckBlitPassesEquivalentTo(otherScene); - CheckRenderBuffersAndTargetsEquivalentTo(otherScene); - CheckDataBuffersEquivalentTo(otherScene); - CheckTextureBuffersEquivalentTo(otherScene); - CheckDataSlotsEquivalentTo(otherScene); - CheckPickableObjectsEquivalentTo(otherScene); - CheckSceneReferencesEquivalentTo(otherScene); + m_mapping = mapping; } - template - void CheckNodesEquivalentTo(const OTHERSCENE& otherScene) const + private: + template + [[nodiscard]] TypedMemoryHandle getMappedHandle(TypedMemoryHandle handle) const + { + return m_mapping ? m_mapping->getMapping(handle) : handle; + } + + void CheckNodesEquivalentTo(const IScene& otherScene) const { EXPECT_TRUE(otherScene.isNodeAllocated(parent)); EXPECT_TRUE(otherScene.isNodeAllocated(child)); @@ -238,14 +264,13 @@ namespace ramses::internal EXPECT_TRUE(otherScene.getParent(childChild2).isValid()); EXPECT_TRUE(otherScene.getParent(childChild3).isValid()); - EXPECT_EQ(parent, otherScene.getParent(child)); - EXPECT_EQ(child, otherScene.getParent(childChild1)); - EXPECT_EQ(child, otherScene.getParent(childChild2)); - EXPECT_EQ(child, otherScene.getParent(childChild3)); + EXPECT_EQ(getMappedHandle(parent), otherScene.getParent(child)); + EXPECT_EQ(getMappedHandle(child), otherScene.getParent(childChild1)); + EXPECT_EQ(getMappedHandle(child), otherScene.getParent(childChild2)); + EXPECT_EQ(getMappedHandle(child), otherScene.getParent(childChild3)); } - template - void CheckTransformsEquivalentTo(const OTHERSCENE& otherScene) const + void CheckTransformsEquivalentTo(const IScene& otherScene) const { EXPECT_TRUE(otherScene.isTransformAllocated(t1)); EXPECT_TRUE(otherScene.isTransformAllocated(t2)); @@ -255,9 +280,9 @@ namespace ramses::internal EXPECT_TRUE(otherScene.getTransformNode(t2).isValid()); EXPECT_TRUE(otherScene.getTransformNode(t3).isValid()); - EXPECT_EQ(childChild1, otherScene.getTransformNode(t1)); - EXPECT_EQ(childChild2, otherScene.getTransformNode(t2)); - EXPECT_EQ(childChild3, otherScene.getTransformNode(t3)); + EXPECT_EQ(getMappedHandle(childChild1), otherScene.getTransformNode(t1)); + EXPECT_EQ(getMappedHandle(childChild2), otherScene.getTransformNode(t2)); + EXPECT_EQ(getMappedHandle(childChild3), otherScene.getTransformNode(t3)); EXPECT_EQ(t1Translation, otherScene.getTranslation (t1)); EXPECT_EQ(t1Scaling , otherScene.getScaling (t1)); @@ -274,24 +299,22 @@ namespace ramses::internal EXPECT_EQ(ERotationType::Quaternion, otherScene.getRotationType(t3)); } - template - void CheckRenderablesEquivalentTo(const OTHERSCENE& otherScene) const + void CheckRenderablesEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isRenderableAllocated(renderable)); const Renderable& renderableData = otherScene.getRenderable(renderable); - EXPECT_EQ(childChild2, renderableData.node); + EXPECT_EQ(getMappedHandle(childChild2), renderableData.node); EXPECT_EQ(startIndex, renderableData.startIndex); EXPECT_EQ(indexCount, renderableData.indexCount); - EXPECT_EQ(uniformData, renderableData.dataInstances[ERenderableDataSlotType_Uniforms]); - EXPECT_EQ(geometryData, renderableData.dataInstances[ERenderableDataSlotType_Geometry]); - EXPECT_EQ(renderState, renderableData.renderState); + EXPECT_EQ(getMappedHandle(uniformData), renderableData.dataInstances[ERenderableDataSlotType_Uniforms]); + EXPECT_EQ(getMappedHandle(geometryData), renderableData.dataInstances[ERenderableDataSlotType_Geometry]); + EXPECT_EQ(getMappedHandle(renderState), renderableData.renderState); EXPECT_EQ(EVisibilityMode::Invisible, renderableData.visibilityMode); EXPECT_EQ(renderableInstanceCount, renderableData.instanceCount); EXPECT_EQ(startVertex, renderableData.startVertex); } - template - void CheckStatesEquivalentTo(const OTHERSCENE& otherScene) const + void CheckStatesEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isRenderStateAllocated(renderState)); const RenderState& rs = otherScene.getRenderState(renderState); @@ -321,13 +344,12 @@ namespace ramses::internal EXPECT_EQ(EStencilOp::Decrement , rs.stencilOpDepthPass); } - template - void CheckDataLayoutsEquivalentTo(const OTHERSCENE& otherScene) const + void CheckDataLayoutsEquivalentTo(const IScene& otherScene) const { // check counts EXPECT_TRUE(otherScene.isDataLayoutAllocated(uniformLayout)); EXPECT_TRUE(otherScene.isDataLayoutAllocated(vertexLayout)); - EXPECT_EQ(9u, otherScene.getDataLayout(uniformLayout).getFieldCount()); + EXPECT_EQ(10u, otherScene.getDataLayout(uniformLayout).getFieldCount()); EXPECT_EQ(4u, otherScene.getDataLayout(vertexLayout).getFieldCount()); // check types EXPECT_EQ(EDataType::Float, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(0)).dataType); @@ -339,6 +361,7 @@ namespace ramses::internal EXPECT_EQ(EDataType::TextureSamplerExternal, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(6)).dataType); EXPECT_EQ(EDataType::Bool, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(7)).dataType); EXPECT_EQ(EDataType::Bool, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(8)).dataType); + EXPECT_EQ(EDataType::UniformBuffer, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(9)).dataType); EXPECT_EQ(effectHash, otherScene.getDataLayout(uniformLayout).getEffectHash()); EXPECT_EQ(EDataType::Indices, otherScene.getDataLayout(vertexLayout).getField(DataFieldHandle(0)).dataType); EXPECT_EQ(EDataType::Vector4Buffer, otherScene.getDataLayout(vertexLayout).getField(DataFieldHandle(1)).dataType); @@ -355,6 +378,7 @@ namespace ramses::internal EXPECT_EQ(1u, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(6)).elementCount); EXPECT_EQ(1u, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(7)).elementCount); EXPECT_EQ(1u, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(8)).elementCount); + EXPECT_EQ(1u, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(9)).elementCount); EXPECT_EQ(1u, otherScene.getDataLayout(vertexLayout).getField(DataFieldHandle(0)).elementCount); EXPECT_EQ(1u, otherScene.getDataLayout(vertexLayout).getField(DataFieldHandle(1)).elementCount); EXPECT_EQ(1u, otherScene.getDataLayout(vertexLayout).getField(DataFieldHandle(2)).elementCount); @@ -362,8 +386,7 @@ namespace ramses::internal EXPECT_EQ(EFixedSemantics::ModelViewMatrix33, otherScene.getDataLayout(uniformLayout).getField(DataFieldHandle(2)).semantics); } - template - void CheckDataInstancesEquivalentTo(const OTHERSCENE& otherScene) const + void CheckDataInstancesEquivalentTo(const IScene& otherScene) const { EXPECT_TRUE(otherScene.isDataInstanceAllocated(geometryData)); EXPECT_TRUE(otherScene.isDataInstanceAllocated(uniformData)); @@ -387,7 +410,7 @@ namespace ramses::internal { const ResourceField& dataResource = otherScene.getDataResource(geometryData, DataFieldHandle(2u)); EXPECT_EQ(ResourceContentHash::Invalid(), dataResource.hash); - EXPECT_EQ(vertexDataBuffer, dataResource.dataBuffer); + EXPECT_EQ(getMappedHandle(vertexDataBuffer), dataResource.dataBuffer); EXPECT_EQ(vertexArrayDivisor, dataResource.instancingDivisor); EXPECT_EQ(222u, dataResource.offsetWithinElementInBytes); EXPECT_EQ(72u, dataResource.stride); @@ -403,6 +426,10 @@ namespace ramses::internal EXPECT_EQ(0.5f, otherScene.getDataSingleFloat(uniformData, DataFieldHandle(0u))); EXPECT_EQ(true, otherScene.getDataSingleBoolean(uniformData, DataFieldHandle(7u))); EXPECT_EQ(false, otherScene.getDataSingleBoolean(uniformData, DataFieldHandle(8u))); + if (m_featureLevel >= EFeatureLevel_02) + { + EXPECT_EQ(getMappedHandle(uniformBuffer), otherScene.getDataUniformBuffer(uniformData, DataFieldHandle(9u))); + } // array check const glm::vec4* dataVec4fArray = otherScene.getDataVector4fArray(uniformData, DataFieldHandle(1u)); @@ -411,14 +438,13 @@ namespace ramses::internal EXPECT_EQ(glm::rotate(glm::mat3(1.f), glm::radians(5.0f)), otherScene.getDataSingleMatrix33f(uniformData, DataFieldHandle(2u))); EXPECT_EQ(glm::translate(glm::vec3{ 5.0f, 4.0f, 3.0f }), otherScene.getDataSingleMatrix44f(uniformData, DataFieldHandle(3u))); - EXPECT_EQ(samplerWithTextureResource, otherScene.getDataTextureSamplerHandle(uniformData, DataFieldHandle(4u))); - EXPECT_EQ(dataRef, otherScene.getDataReference(uniformData, DataFieldHandle(5u))); - EXPECT_EQ(samplerWithExternalTexture, otherScene.getDataTextureSamplerHandle(uniformData, DataFieldHandle(6u))); + EXPECT_EQ(getMappedHandle(samplerWithTextureResource), otherScene.getDataTextureSamplerHandle(uniformData, DataFieldHandle(4u))); + EXPECT_EQ(getMappedHandle(dataRef), otherScene.getDataReference(uniformData, DataFieldHandle(5u))); + EXPECT_EQ(getMappedHandle(samplerWithExternalTexture), otherScene.getDataTextureSamplerHandle(uniformData, DataFieldHandle(6u))); EXPECT_EQ(TextureSampler::ContentType::ExternalTexture, otherScene.getTextureSampler(samplerWithExternalTexture).contentType); } - template - void CheckTextureSamplersEquivalentTo(const OTHERSCENE& otherScene) const + void CheckTextureSamplersEquivalentTo(const IScene& otherScene) const { EXPECT_TRUE(otherScene.isTextureSamplerAllocated(samplerWithTextureResource)); EXPECT_TRUE(otherScene.isTextureSamplerAllocated(samplerWithRenderBuffer)); @@ -431,35 +457,33 @@ namespace ramses::internal EXPECT_EQ(samplerStates.m_anisotropyLevel, otherScene.getTextureSampler(samplerWithTextureResource).states.m_anisotropyLevel); EXPECT_EQ(textureHash, otherScene.getTextureSampler(samplerWithTextureResource).textureResource); - EXPECT_EQ(renderBuffer.asMemoryHandle(), otherScene.getTextureSampler(samplerWithRenderBuffer).contentHandle); - EXPECT_EQ(texture2DBuffer.asMemoryHandle(), otherScene.getTextureSampler(samplerWithTextureBuffer).contentHandle); + EXPECT_EQ(getMappedHandle(renderBuffer).asMemoryHandle(), otherScene.getTextureSampler(samplerWithRenderBuffer).contentHandle); + EXPECT_EQ(getMappedHandle(texture2DBuffer).asMemoryHandle(), otherScene.getTextureSampler(samplerWithTextureBuffer).contentHandle); EXPECT_EQ(TextureSampler::ContentType::ClientTexture, otherScene.getTextureSampler(samplerWithTextureResource).contentType); EXPECT_EQ(TextureSampler::ContentType::RenderBuffer, otherScene.getTextureSampler(samplerWithRenderBuffer).contentType); EXPECT_EQ(TextureSampler::ContentType::TextureBuffer, otherScene.getTextureSampler(samplerWithTextureBuffer).contentType); } - template - void CheckCamerasEquivalentTo(const OTHERSCENE& otherScene) const + void CheckCamerasEquivalentTo(const IScene& otherScene) const { const Camera& camData = otherScene.getCamera(camera); EXPECT_EQ(ECameraProjectionType::Perspective, camData.projectionType); - EXPECT_EQ(cameraNode, camData.node); - EXPECT_EQ(cameraDataInstance, camData.dataInstance); + EXPECT_EQ(getMappedHandle(cameraNode), camData.node); + EXPECT_EQ(getMappedHandle(cameraDataInstance), camData.dataInstance); const Camera& orthoCamData = otherScene.getCamera(orthographicCamera); EXPECT_EQ(ECameraProjectionType::Orthographic, orthoCamData.projectionType); - EXPECT_EQ(cameraNode, orthoCamData.node); + EXPECT_EQ(getMappedHandle(cameraNode), orthoCamData.node); } - template - void CheckRenderGroupsEquivalentTo(const OTHERSCENE& otherScene) const + void CheckRenderGroupsEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isRenderGroupAllocated(renderGroup)); const RenderGroup& rg = otherScene.getRenderGroup(renderGroup); - EXPECT_TRUE(RenderGroupUtils::ContainsRenderable(renderable, rg)); - EXPECT_FALSE(RenderGroupUtils::ContainsRenderable(renderable2, rg)); + EXPECT_TRUE(RenderGroupUtils::ContainsRenderable(getMappedHandle(renderable), rg)); + EXPECT_FALSE(RenderGroupUtils::ContainsRenderable(getMappedHandle(renderable2), rg)); ASSERT_EQ(1u, rg.renderables.size()); - EXPECT_EQ(renderable, rg.renderables[0].renderable); + EXPECT_EQ(getMappedHandle(renderable), rg.renderables[0].renderable); EXPECT_EQ(15, rg.renderables[0].order); ASSERT_TRUE(otherScene.isRenderGroupAllocated(nestedRenderGroupParent)); @@ -467,42 +491,40 @@ namespace ramses::internal const RenderGroup& rgParent = otherScene.getRenderGroup(nestedRenderGroupParent); const RenderGroup& rgChild = otherScene.getRenderGroup(nestedRenderGroupChild); - EXPECT_TRUE(RenderGroupUtils::ContainsRenderGroup(nestedRenderGroupChild, rgParent)); - EXPECT_TRUE(RenderGroupUtils::ContainsRenderable(renderable2, rgChild)); + EXPECT_TRUE(RenderGroupUtils::ContainsRenderGroup(getMappedHandle(nestedRenderGroupChild), rgParent)); + EXPECT_TRUE(RenderGroupUtils::ContainsRenderable(getMappedHandle(renderable2), rgChild)); ASSERT_EQ(1u, rgChild.renderables.size()); - EXPECT_EQ(renderable2, rgChild.renderables[0].renderable); + EXPECT_EQ(getMappedHandle(renderable2), rgChild.renderables[0].renderable); EXPECT_EQ(21, rgChild.renderables[0].order); ASSERT_EQ(1u, rgParent.renderGroups.size()); - EXPECT_EQ(nestedRenderGroupChild, rgParent.renderGroups[0].renderGroup); + EXPECT_EQ(getMappedHandle(nestedRenderGroupChild), rgParent.renderGroups[0].renderGroup); EXPECT_EQ(22, rgParent.renderGroups[0].order); } - template - void CheckRenderPassesEquivalentTo(const OTHERSCENE& otherScene) const + void CheckRenderPassesEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isRenderPassAllocated(renderPass)); const RenderPass& rp = otherScene.getRenderPass(renderPass); - EXPECT_EQ(camera, rp.camera); - EXPECT_EQ(renderTarget, rp.renderTarget); + EXPECT_EQ(getMappedHandle(camera), rp.camera); + EXPECT_EQ(getMappedHandle(renderTarget), rp.renderTarget); EXPECT_EQ(1, rp.renderOrder); EXPECT_EQ(glm::vec4(0.5f, 0.0f, 1.f, 0.25f), rp.clearColor); EXPECT_EQ(EClearFlag::None, rp.clearFlags); EXPECT_FALSE(rp.isEnabled); EXPECT_TRUE(rp.isRenderOnce); - ASSERT_TRUE(RenderGroupUtils::ContainsRenderGroup(renderGroup, rp)); - EXPECT_FALSE(RenderGroupUtils::ContainsRenderGroup(renderGroup2, rp)); - EXPECT_EQ(renderGroup, rp.renderGroups[0].renderGroup); + ASSERT_TRUE(RenderGroupUtils::ContainsRenderGroup(getMappedHandle(renderGroup), rp)); + EXPECT_FALSE(RenderGroupUtils::ContainsRenderGroup(getMappedHandle(renderGroup2), rp)); + EXPECT_EQ(getMappedHandle(renderGroup), rp.renderGroups[0].renderGroup); EXPECT_EQ(15, rp.renderGroups[0].order); } - template - void CheckBlitPassesEquivalentTo(const OTHERSCENE& otherScene) const + void CheckBlitPassesEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isBlitPassAllocated(blitPass)); const BlitPass& blitPassData = otherScene.getBlitPass(blitPass); - EXPECT_EQ(renderBuffer, blitPassData.sourceRenderBuffer); - EXPECT_EQ(renderBuffer2, blitPassData.destinationRenderBuffer); + EXPECT_EQ(getMappedHandle(renderBuffer), blitPassData.sourceRenderBuffer); + EXPECT_EQ(getMappedHandle(renderBuffer2), blitPassData.destinationRenderBuffer); EXPECT_EQ(blitPassSourceRectangle.x, blitPassData.sourceRegion.x); EXPECT_EQ(blitPassSourceRectangle.y, blitPassData.sourceRegion.y); @@ -515,8 +537,7 @@ namespace ramses::internal EXPECT_EQ(blitPassDestinationRectangle.height, blitPassData.destinationRegion.height); } - template - void CheckRenderBuffersAndTargetsEquivalentTo(const OTHERSCENE& otherScene) const + void CheckRenderBuffersAndTargetsEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isRenderTargetAllocated(renderTarget)); ASSERT_TRUE(otherScene.isRenderBufferAllocated(renderBuffer)); @@ -529,11 +550,10 @@ namespace ramses::internal EXPECT_EQ(3u, renderBufferData.sampleCount); EXPECT_EQ(1u, otherScene.getRenderTargetRenderBufferCount(renderTarget)); - EXPECT_EQ(renderBuffer, otherScene.getRenderTargetRenderBuffer(renderTarget, 0u)); + EXPECT_EQ(getMappedHandle(renderBuffer), otherScene.getRenderTargetRenderBuffer(renderTarget, 0u)); } - template - void CheckDataBuffersEquivalentTo(const OTHERSCENE& otherScene) const + void CheckDataBuffersEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isDataBufferAllocated(indexDataBuffer)); EXPECT_TRUE(otherScene.isDataBufferAllocated(vertexDataBuffer)); @@ -556,8 +576,7 @@ namespace ramses::internal EXPECT_EQ(std::byte{0x2C}, vertexData.data[2]); } - template - void CheckTextureBuffersEquivalentTo(const OTHERSCENE& otherScene) const + void CheckTextureBuffersEquivalentTo(const IScene& otherScene) const { ASSERT_TRUE(otherScene.isTextureBufferAllocated(texture2DBuffer)); const TextureBuffer& texBuffer = otherScene.getTextureBuffer(texture2DBuffer); @@ -588,33 +607,30 @@ namespace ramses::internal EXPECT_EQ(Quad(0, 0, 2, 2), texBuffer.mipMaps[2].usedRegion); } - template - void CheckDataSlotsEquivalentTo(const OTHERSCENE& otherScene) const + void CheckDataSlotsEquivalentTo(const IScene& otherScene) const { EXPECT_TRUE(otherScene.isDataSlotAllocated(transformDataSlot)); const DataSlot& dataSlot = otherScene.getDataSlot(transformDataSlot); EXPECT_EQ(EDataSlotType::TransformationConsumer, dataSlot.type); EXPECT_EQ(dataSlotId, dataSlot.id); - EXPECT_EQ(parent, dataSlot.attachedNode); - EXPECT_EQ(dataRef, dataSlot.attachedDataReference); + EXPECT_EQ(getMappedHandle(parent), dataSlot.attachedNode); + EXPECT_EQ(getMappedHandle(dataRef), dataSlot.attachedDataReference); EXPECT_EQ(textureHash, dataSlot.attachedTexture); - EXPECT_EQ(samplerWithTextureResource, dataSlot.attachedTextureSampler); + EXPECT_EQ(getMappedHandle(samplerWithTextureResource), dataSlot.attachedTextureSampler); } - template - void CheckPickableObjectsEquivalentTo(const OTHERSCENE& otherScene) const + void CheckPickableObjectsEquivalentTo(const IScene& otherScene) const { EXPECT_TRUE(otherScene.isPickableObjectAllocated(pickableHandle)); const PickableObject& pickableObject = otherScene.getPickableObject(pickableHandle); - EXPECT_EQ(vertexDataBuffer, pickableObject.geometryHandle); - EXPECT_EQ(child, pickableObject.nodeHandle); - EXPECT_EQ(camera, pickableObject.cameraHandle); + EXPECT_EQ(getMappedHandle(vertexDataBuffer), pickableObject.geometryHandle); + EXPECT_EQ(getMappedHandle(child), pickableObject.nodeHandle); + EXPECT_EQ(getMappedHandle(camera), pickableObject.cameraHandle); EXPECT_EQ(pickableId, pickableObject.id); EXPECT_FALSE(pickableObject.isEnabled); } - template - void CheckSceneReferencesEquivalentTo(const OTHERSCENE& otherScene) const + void CheckSceneReferencesEquivalentTo(const IScene& otherScene) const { EXPECT_TRUE(otherScene.isSceneReferenceAllocated(sceneRef)); const auto& sr = otherScene.getSceneReference(sceneRef); @@ -624,7 +640,13 @@ namespace ramses::internal EXPECT_TRUE(sr.flushNotifications); } - SCENE scene; + void CheckSceneUniformBuffersEquivalentTo(const IScene& otherScene) const + { + const std::vector expectedUniformBufferData( { + std::byte{0u}, std::byte{0u}, std::byte{0u}, std::byte{1u}, std::byte{11u}, + std::byte{111u}, std::byte{0u}, std::byte{0u}, std::byte{2u}, std::byte{22u}}); + EXPECT_EQ(expectedUniformBufferData, otherScene.getUniformBuffer(uniformBuffer).data); + } const ResourceContentHash indexArrayHash {111u, 0}; const ResourceContentHash vertexArrayHash {222u, 0}; @@ -658,6 +680,7 @@ namespace ramses::internal const NodeHandle childChild2 {21u}; const NodeHandle childChild3 {31u}; const NodeHandle cameraNode {23u}; + const DataLayoutHandle cameraDataLayout {23u}; const DataInstanceHandle cameraDataInstance {23u}; const TransformHandle t1 {35u}; const TransformHandle t2 {39u}; @@ -678,6 +701,7 @@ namespace ramses::internal const TextureSamplerHandle samplerWithRenderBuffer {58u}; const TextureSamplerHandle samplerWithTextureBuffer {60u}; const TextureSamplerHandle samplerWithExternalTexture {61u}; + const UniformBufferHandle uniformBuffer {641u}; const DataSlotHandle transformDataSlot {58u}; const RenderGroupHandle renderGroup {59u}; const RenderGroupHandle renderGroup2 {60u}; @@ -694,5 +718,8 @@ namespace ramses::internal const PickableObjectId pickableId { 69u }; const SceneReferenceHandle sceneRef { 70u }; const SceneId sceneRefSceneId { 123 }; + + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; + const SceneMergeHandleMapping* m_mapping = nullptr; }; } diff --git a/tests/unittests/framework-test-utils/src/TestEqualHelper.cpp b/tests/unittests/framework-test-utils/src/TestEqualHelper.cpp new file mode 100644 index 000000000..f3f766b2f --- /dev/null +++ b/tests/unittests/framework-test-utils/src/TestEqualHelper.cpp @@ -0,0 +1,26 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "TestEqualHelper.h" + +namespace ramses::internal +{ + bool operator==(const SceneInfo& a, const SceneInfo& b) + { + return a.sceneID == b.sceneID + && a.friendlyName == b.friendlyName + && a.renderBackendCompatibility == b.renderBackendCompatibility + && a.vulkanAPIVersion == b.vulkanAPIVersion + && a.spirvVersion == b.spirvVersion; + } + + bool operator!=(const SceneInfo& a, const SceneInfo& b) + { + return !(a == b); + } +} diff --git a/tests/unittests/framework/Communication/TransportCommon/CommunicationSystemTest.cpp b/tests/unittests/framework/Communication/TransportCommon/CommunicationSystemTest.cpp index c6577c823..691062ebb 100644 --- a/tests/unittests/framework/Communication/TransportCommon/CommunicationSystemTest.cpp +++ b/tests/unittests/framework/Communication/TransportCommon/CommunicationSystemTest.cpp @@ -43,7 +43,7 @@ namespace ramses::internal EXPECT_FALSE(csw->commSystem->sendSubscribeScene(to, SceneId(123))); EXPECT_FALSE(csw->commSystem->sendUnsubscribeScene(to, SceneId(123))); EXPECT_FALSE(csw->commSystem->sendInitializeScene(to, SceneId())); - EXPECT_FALSE(csw->commSystem->sendSceneUpdate(to, SceneId(123), SceneUpdateSerializer(SceneUpdate(), sceneStatistics))); + EXPECT_FALSE(csw->commSystem->sendSceneUpdate(to, SceneId(123), SceneUpdateSerializer(SceneUpdate(), sceneStatistics, EFeatureLevel_Latest))); } TEST_P(ACommunicationSystem, sendFunctionsFailAfterCallingDisconnect) @@ -60,7 +60,7 @@ namespace ramses::internal EXPECT_FALSE(csw->commSystem->sendSubscribeScene(to, SceneId(123))); EXPECT_FALSE(csw->commSystem->sendUnsubscribeScene(to, SceneId(123))); EXPECT_FALSE(csw->commSystem->sendInitializeScene(to, SceneId())); - EXPECT_FALSE(csw->commSystem->sendSceneUpdate(to, SceneId(123), SceneUpdateSerializer(SceneUpdate(), sceneStatistics))); + EXPECT_FALSE(csw->commSystem->sendSceneUpdate(to, SceneId(123), SceneUpdateSerializer(SceneUpdate(), sceneStatistics, EFeatureLevel_Latest))); } TEST_P(ACommunicationSystemWithDaemon, canConnectAndDisconnectWithoutBlocking) @@ -245,7 +245,7 @@ namespace ramses::internal SceneId sceneId; SceneInfoVector unavailableScenes; - unavailableScenes.push_back(SceneInfo(sceneId)); + unavailableScenes.push_back(SceneInfo{ sceneId }); EXPECT_CALL(handler_1, handleScenesBecameUnavailable(unavailableScenes, sender->id)).WillOnce(InvokeWithoutArgs([&](){ state->sendEvent(); })); EXPECT_CALL(handler_2, handleScenesBecameUnavailable(unavailableScenes, sender->id)).WillOnce(InvokeWithoutArgs([&](){ state->sendEvent(); })); sender->commSystem->broadcastScenesBecameUnavailable(unavailableScenes); diff --git a/tests/unittests/framework/Communication/TransportCommon/FlushInformationSerializationHelperTest.cpp b/tests/unittests/framework/Communication/TransportCommon/FlushInformationSerializationHelperTest.cpp index 431117599..18a9e740f 100644 --- a/tests/unittests/framework/Communication/TransportCommon/FlushInformationSerializationHelperTest.cpp +++ b/tests/unittests/framework/Communication/TransportCommon/FlushInformationSerializationHelperTest.cpp @@ -17,8 +17,8 @@ namespace ramses::internal public: FlushInformation SerializeDeserialize(const FlushInformation& flushInfos) { - const absl::Span infos = FlushInformationSerialization::SerializeInfos(flushInfos, workingMem); - return FlushInformationSerialization::Deserialize(infos); + const absl::Span infos = FlushInformationSerialization::SerializeInfos(flushInfos, workingMem, EFeatureLevel_Latest); + return FlushInformationSerialization::Deserialize(infos, EFeatureLevel_Latest); } std::vector workingMem; @@ -27,7 +27,7 @@ namespace ramses::internal TEST_F(AFlushInformationSerialization, minimumSizeIsSizeOfEmptyFlushInfoSerialized) { - const absl::Span infos = FlushInformationSerialization::SerializeInfos(in, workingMem); + const absl::Span infos = FlushInformationSerialization::SerializeInfos(in, workingMem, EFeatureLevel_Latest); ASSERT_EQ(FlushInformation::getMinimumSize(), infos.size()); } @@ -50,7 +50,7 @@ namespace ramses::internal in.resourceChanges.m_sceneResourceActions.push_back(std::move(action)); SceneReferenceAction refAction{ SceneReferenceActionType::LinkData, SceneReferenceHandle{ 1 }, DataSlotId{ 1 }, SceneReferenceHandle{ 2 }, DataSlotId{ 2 } }; in.sceneReferences.push_back(refAction); - in.sizeInfo = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}; + in.sizeInfo = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18, 19}; in.versionTag = SceneVersionTag(2); EXPECT_EQ(in, SerializeDeserialize(in)); } @@ -105,13 +105,13 @@ namespace ramses::internal in.resourceChanges.m_sceneResourceActions.push_back(std::move(action)); SceneReferenceAction refAction{ SceneReferenceActionType::LinkData, SceneReferenceHandle{ 1 }, DataSlotId{ 1 }, SceneReferenceHandle{ 2 }, DataSlotId{ 2 } }; in.sceneReferences.push_back(refAction); - in.sizeInfo = { 1,2,3,4,5,6,7,8,9,10,11,12,13,15,16,18,19, 20 }; + in.sizeInfo = { 1,2,3,4,5,6,7, 21, 8,9,10,11,12,13,15,16,18,19, 20 }; in.versionTag = SceneVersionTag(2); EXPECT_EQ(fmt::to_string(in), "FlushInformation:[valid:true;flushcounter:14;version:2;" "resChanges[+:1;-:1;resActions:1];refActions:1;time[0;sync:1;exp:12345;int:54321];" - "sizeInfo:[node=1 camera=2 transform=3 renderable=4 state=5 datalayout=6 datainstance=7 renderGroup=8 renderPass=9 blitPass=10 renderTarget=11 renderBuffer=12 textureSampler=13 dataSlot=15 " + "sizeInfo:[node=1 camera=2 transform=3 renderable=4 state=5 datalayout=6 datainstance=7 uniformBuffer=21 renderGroup=8 renderPass=9 blitPass=10 renderTarget=11 renderBuffer=12 textureSampler=13 dataSlot=15 " "dataBuffer=16 textureBuffer=18 pickableObjectCount=19 sceneReferenceCount=20]]"); } diff --git a/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationHelperTest.cpp b/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationHelperTest.cpp index b9e116526..4c9c3bdf8 100644 --- a/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationHelperTest.cpp +++ b/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationHelperTest.cpp @@ -52,7 +52,7 @@ namespace ramses::internal { const absl::Span desc = ResourceSerialization::SerializeDescription(resource, workingMem); const absl::Span data = ResourceSerialization::SerializeData(resource); - return ResourceSerialization::Deserialize(desc, data); + return ResourceSerialization::Deserialize(desc, data, EFeatureLevel_Latest); } std::vector workingMem; @@ -112,7 +112,7 @@ namespace ramses::internal const absl::Span data = ResourceSerialization::SerializeData(*res); ASSERT_GT(data.size(), 0u); - std::unique_ptr deserRes(ResourceSerialization::Deserialize(desc, data.subspan(1))); + std::unique_ptr deserRes(ResourceSerialization::Deserialize(desc, data.subspan(1), EFeatureLevel_Latest)); ASSERT_FALSE(deserRes); } } diff --git a/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationTest.cpp b/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationTest.cpp index 4f4c93dc8..d40d92dd8 100644 --- a/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationTest.cpp +++ b/tests/unittests/framework/Communication/TransportCommon/SceneUpdateSerializationTest.cpp @@ -26,7 +26,7 @@ namespace ramses::internal public: bool serialize(size_t pktSize) { - SceneUpdateSerializer sus(update, sceneStatistics); + SceneUpdateSerializer sus(update, sceneStatistics, EFeatureLevel_Latest); std::vector vec(pktSize); return sus.writeToPackets({vec.data(), vec.size()}, [&](size_t s) { data.push_back(vec); @@ -58,7 +58,7 @@ namespace ramses::internal update.flushInfos.resourceChanges.m_sceneResourceActions.push_back(std::move(action)); SceneReferenceAction refAction; update.flushInfos.sceneReferences.push_back(refAction); - update.flushInfos.sizeInfo = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18}; + update.flushInfos.sizeInfo = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18, 19}; update.flushInfos.versionTag = SceneVersionTag(2); } @@ -103,7 +103,7 @@ namespace ramses::internal compare(result); } - SceneUpdateStreamDeserializer deser; + SceneUpdateStreamDeserializer deser{ EFeatureLevel_Latest }; ResourceDeleterCallingCallback deleterMock; SceneUpdate update; StatisticCollectionScene sceneStatistics; @@ -205,7 +205,7 @@ namespace ramses::internal TEST_F(ASceneUpdateSerialization, failsSerializeWhenWriteFunctionFailsOnFirstPacket) { - SceneUpdateSerializer sus(update, sceneStatistics); + SceneUpdateSerializer sus(update, sceneStatistics, EFeatureLevel_Latest); std::vector vec(60); EXPECT_FALSE(sus.writeToPackets({vec.data(), vec.size()}, [&](size_t) { return false; @@ -215,7 +215,7 @@ namespace ramses::internal TEST_F(ASceneUpdateSerialization, failsSerializeWhenWriteFunctionFailsOnLaterPacketInResource) { update.resources.push_back(CreateTestResource(2500)); - SceneUpdateSerializer sus(update, sceneStatistics); + SceneUpdateSerializer sus(update, sceneStatistics, EFeatureLevel_Latest); std::vector vec(60); int cnt = 0; EXPECT_FALSE(sus.writeToPackets({vec.data(), vec.size()}, [&](size_t) { @@ -229,7 +229,7 @@ namespace ramses::internal { for (size_t i = 0; i < 100; ++i) addTestActions(); - SceneUpdateSerializer sus(update, sceneStatistics); + SceneUpdateSerializer sus(update, sceneStatistics, EFeatureLevel_Latest); std::vector vec(60); int cnt = 0; EXPECT_FALSE(sus.writeToPackets({vec.data(), vec.size()}, [&](size_t) { @@ -351,7 +351,7 @@ namespace ramses::internal SCOPED_TRACE(i); std::vector vec = data[0]; vec.resize(i); - SceneUpdateStreamDeserializer localDeser; + SceneUpdateStreamDeserializer localDeser{ EFeatureLevel_Latest }; EXPECT_EQ(SceneUpdateStreamDeserializer::ResultType::Failed, localDeser.processData(vec).result); } } diff --git a/tests/unittests/framework/Components/ClientSceneLogicTest.cpp b/tests/unittests/framework/Components/ClientSceneLogicTest.cpp index e70a750a8..5f56cb8b8 100644 --- a/tests/unittests/framework/Components/ClientSceneLogicTest.cpp +++ b/tests/unittests/framework/Components/ClientSceneLogicTest.cpp @@ -19,6 +19,7 @@ #include "internal/SceneGraph/Resource/ArrayResource.h" #include "internal/SceneGraph/Resource/TextureResource.h" #include "internal/SceneGraph/Resource/EffectResource.h" +#include "TestEqualHelper.h" namespace ramses::internal { @@ -78,9 +79,9 @@ class SceneGraphSenderMock : public ISceneGraphSender public: SceneGraphSenderMock() = default; ~SceneGraphSenderMock() override = default; - MOCK_METHOD(void, sendPublishScene, (SceneId sceneId, EScenePublicationMode publicationMode, std::string_view name), (override)); + MOCK_METHOD(void, sendPublishScene, (const SceneInfo& sceneInfo), (override)); MOCK_METHOD(void, sendUnpublishScene, (SceneId sceneId, EScenePublicationMode publicationMode), (override)); - MOCK_METHOD(void, sendCreateScene, (const Guid& to, const SceneId& sceneId, EScenePublicationMode publicationMode), (override)); + MOCK_METHOD(void, sendCreateScene, (const Guid& to, const SceneInfo& sceneInfo), (override)); MOCK_METHOD(void, sendSceneUpdate_rvr, (const std::vector& to, const SceneUpdate & sceneAction, SceneId sceneId, EScenePublicationMode publicationMode, StatisticCollectionScene& sceneStatistics)); void sendSceneUpdate(const std::vector& to, SceneUpdate&& update, SceneId sceneId, EScenePublicationMode publicationMode, StatisticCollectionScene& sceneStatistics) override @@ -97,11 +98,12 @@ class AClientSceneLogic_All : public ::testing::Test AClientSceneLogic_All() : m_myID(765) , m_sceneId(33u) - , m_scene(SceneInfo(m_sceneId)) - , m_sceneLogic(m_sceneGraphProviderComponent, m_scene, m_resourceComponent, m_myID) + , m_sceneInfo{ m_sceneId, "sceneName", EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::VulkanAndOpenGL, TargetVulkanApiVersion, TargetSPIRVVersion} + , m_scene(m_sceneInfo) + , m_sceneLogic(m_sceneGraphProviderComponent, m_scene, m_resourceComponent, m_myID, EFeatureLevel_Latest) , m_rendererID(1337) , m_arrayResourceRaw(new ArrayResource(EResourceType::IndexArray, 1, EDataType::UInt16, nullptr, {})) - , m_effectResourceRaw(new EffectResource("foo", {}, {}, {}, {}, {}, {})) + , m_effectResourceRaw(new EffectResource("foo", {}, {}, {}, {}, {}, {}, {}, EFeatureLevel_Latest)) , m_textureResourceRaw(new TextureResource(EResourceType::Texture2D, TextureMetaInfo(1u, 1u, 1u, EPixelStorageFormat::R8, false, {}, { 1u }), {})) , m_arrayResource(m_arrayResourceRaw) , m_effectResource(m_effectResourceRaw) @@ -118,8 +120,7 @@ class AClientSceneLogic_All : public ::testing::Test protected: void publish() { - std::string_view name{m_scene.getName()}; - EXPECT_CALL(m_sceneGraphProviderComponent, sendPublishScene(m_sceneId, EScenePublicationMode::LocalAndRemote, name)); + EXPECT_CALL(m_sceneGraphProviderComponent, sendPublishScene(this->m_sceneInfo)); m_sceneLogic.publish(EScenePublicationMode::LocalAndRemote); } @@ -147,7 +148,7 @@ class AClientSceneLogic_All : public ::testing::Test SceneUpdate createFlushSceneActionList(bool expectSendSize = true, uint64_t flushIdx = 1) { SceneUpdate update; - SceneActionCollectionCreator creator(update.actions); + SceneActionCollectionCreator creator(update.actions, EFeatureLevel_Latest); update.flushInfos.hasSizeInfo = expectSendSize; update.flushInfos.flushCounter = flushIdx; return update; @@ -170,7 +171,7 @@ class AClientSceneLogic_All : public ::testing::Test void expectSceneSend() { - EXPECT_CALL(m_sceneGraphProviderComponent, sendCreateScene(m_rendererID, m_sceneId, _)); + EXPECT_CALL(m_sceneGraphProviderComponent, sendCreateScene(m_rendererID, this->m_sceneInfo)); } void expectSceneUnpublish() @@ -230,6 +231,7 @@ class AClientSceneLogic_All : public ::testing::Test Guid m_myID; SceneId m_sceneId; + SceneInfo m_sceneInfo; ClientScene m_scene; StrictMock m_resourceComponent; StrictMock m_sceneGraphProviderComponent; @@ -336,7 +338,7 @@ TYPED_TEST(AClientSceneLogic_All, doesNotSendSceneOutIfSceneDistributedWithNoSub TYPED_TEST(AClientSceneLogic_All, sendsPublishOnlyOnce) { std::string_view name{this->m_scene.getName()}; - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendPublishScene(this->m_sceneId, EScenePublicationMode::LocalAndRemote, name)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendPublishScene(this->m_sceneInfo)); this->m_sceneLogic.publish(EScenePublicationMode::LocalAndRemote); this->m_sceneLogic.publish(EScenePublicationMode::LocalAndRemote); @@ -590,7 +592,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, doesNotClearPendingActionsIfWaitingSubscrib this->m_scene.allocateNode(0, {}); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); this->expectFlushSceneActionList(); this->m_sceneLogic.addSubscriber(newRendererID); @@ -620,7 +622,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, doesNotClearPendingActionsIfSubscriberRemov this->publishAndAddSubscriberWithoutPendingActions(); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); this->expectFlushSceneActionList(); this->m_sceneLogic.addSubscriber(newRendererID); @@ -876,7 +878,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, canSubscribeToSceneEvenWithPendingActions) this->m_scene.allocateNode(0, {}); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); this->expectFlushSceneActionList(); this->m_sceneLogic.addSubscriber(newRendererID); @@ -893,7 +895,7 @@ TEST_F(AClientSceneLogic_Direct, canSubscribeToSceneEvenWithPendingActions) const Guid newRendererID("12345678-1234-5678-0000-123456789012"); SceneUpdate update; - SceneActionCollectionCreator creator(update.actions); + SceneActionCollectionCreator creator(update.actions, EFeatureLevel_Latest); creator.allocateNode(0, handle); update.flushInfos.hasSizeInfo = true; update.flushInfos.flushCounter = 2; @@ -901,7 +903,7 @@ TEST_F(AClientSceneLogic_Direct, canSubscribeToSceneEvenWithPendingActions) EXPECT_CALL(m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ this->m_rendererID }, ContainsSceneUpdate(update), _, _, _)); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); EXPECT_CALL(m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ newRendererID }, ContainsSceneUpdate(update), _, _, _)); this->m_sceneLogic.addSubscriber(newRendererID); @@ -918,7 +920,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, SendCleanSceneToNewSubscriber) const Guid newRendererID("12345678-1234-5678-0000-123456789012"); // expect direct scene send to new renderer - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); this->expectFlushSceneActionList(); this->m_sceneLogic.addSubscriber(newRendererID); @@ -934,7 +936,7 @@ TEST_F(AClientSceneLogic_Direct, SendCleanSceneToNewSubscriber) const Guid newRendererID("12345678-1234-5678-0000-123456789012"); // expect direct scene send to new renderer - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); this->m_sceneLogic.addSubscriber(newRendererID); EXPECT_CALL(m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{newRendererID}, ContainsSceneUpdate(createFlushSceneActionList(true, 2)), _, _, _)); @@ -1256,7 +1258,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, sendsSceneToNewlySubscribedRendererAfterFlu this->m_scene.allocateRenderable(node, RenderableHandle(2)); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); // expect newly flushed actions to new renderer EXPECT_CALL(this->m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ newRendererID }, _, this->m_sceneId, _, _)).WillOnce([&](const auto& /*unused*/, const auto& update, auto /*unused*/, auto /*unused*/, auto& /*unused*/) { @@ -1294,7 +1296,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, sendsSceneToNewlySubscribedRendererWithNewR this->m_scene.allocateNode(0, {}); // action not flushed const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _)); EXPECT_CALL(this->m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ newRendererID }, _, this->m_sceneId, _, _)).WillOnce([&](const auto& /*unused*/, const auto& update, auto /*unused*/, auto /*unused*/, auto& /*unused*/) { ASSERT_EQ(4u, update.actions.numberOfActions()); @@ -1320,7 +1322,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, sendsSceneToNewlySubscribedRendererWithVali this->m_sceneLogic.flushSceneActions(ftiIn, versionTagIn); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _)); EXPECT_CALL(this->m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ newRendererID }, _, this->m_sceneId, _, _)).WillOnce([&](const auto& /*unused*/, const auto& update, auto /*unused*/, auto /*unused*/, auto& /*unused*/) { ASSERT_EQ(0u, update.actions.numberOfActions()); @@ -1346,7 +1348,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, sendsSceneToNewlySubscribedRendererWithLast this->m_sceneLogic.flushSceneActions(ftiIn2, versionTagIn2); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _)); EXPECT_CALL(this->m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ newRendererID }, _, this->m_sceneId, _, _)).WillOnce([&](const auto& /*unused*/, const auto& update, auto /*unused*/, auto /*unused*/, auto& /*unused*/) { ASSERT_EQ(0u, update.actions.numberOfActions()); @@ -1375,7 +1377,7 @@ TEST_F(AClientSceneLogic_Direct, sendsSceneToNewlySubscribedRendererWithNewResou const Guid newRendererID("12345678-1234-5678-0000-123456789012"); this->m_sceneLogic.addSubscriber(newRendererID); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _)); EXPECT_CALL(this->m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ newRendererID }, _, this->m_sceneId, _, _)).WillOnce([&](const auto& /*unused*/, const auto& update, auto /*unused*/, auto /*unused*/, auto& /*unused*/) { ASSERT_EQ(5u, update.actions.numberOfActions()); @@ -1399,7 +1401,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, doesNotSendSceneUpdatesToNewSubscriberThatU this->m_scene.allocateNode(0, {}); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneId, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, this->m_sceneInfo)); this->expectFlushSceneActionList(); this->m_sceneLogic.addSubscriber(newRendererID); @@ -1422,7 +1424,7 @@ TEST_F(AClientSceneLogic_Direct, doesNotSendAnythingToNewSubscriberThatUnsubscri this->m_scene.allocateNode(0, {}); const Guid newRendererID("12345678-1234-5678-0000-123456789012"); - const SceneInfo sceneInfo(this->m_sceneId, this->m_scene.getName()); + const SceneInfo sceneInfo{ this->m_sceneId, this->m_scene.getName() }; this->m_sceneLogic.addSubscriber(newRendererID); this->m_scene.allocateNode(0, {}); @@ -1443,7 +1445,7 @@ TYPED_TEST(AClientSceneLogic_All, sceneReferenceActionsAreNotSentToNewlySubscrib const Guid newRendererID("12345678-1234-5678-0000-123456789012"); this->m_sceneLogic.addSubscriber(newRendererID); - EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _, _)); + EXPECT_CALL(this->m_sceneGraphProviderComponent, sendCreateScene(newRendererID, _)); EXPECT_CALL(this->m_sceneGraphProviderComponent, sendSceneUpdate_rvr(std::vector{ newRendererID }, _, this->m_sceneId, _, _)).WillOnce([&](const auto& /*unused*/, const auto& update, auto /*unused*/, auto /*unused*/, auto& /*unused*/) { auto& sceneReferenceActions = update.flushInfos.sceneReferences; @@ -1531,7 +1533,7 @@ TYPED_TEST(AClientSceneLogic_All, doesSendSceneToSubscriberAfterFlush) // for checking SceneUpdate update; update.actions = (this->m_scene.getSceneActionCollection().copy()); - SceneActionCollectionCreator creator(update.actions); + SceneActionCollectionCreator creator(update.actions, EFeatureLevel_Latest); update.flushInfos.hasSizeInfo = true; update.flushInfos.flushCounter = 1; update.flushInfos.sizeInfo = this->m_scene.getSceneSizeInformation(); @@ -1554,7 +1556,7 @@ TEST_F(AClientSceneLogic_ShadowCopy, doesSendSceneAfterFlushToLateSubscribers) // for checking SceneUpdate update; update.actions = this->m_scene.getSceneActionCollection().copy(); - SceneActionCollectionCreator creator(update.actions); + SceneActionCollectionCreator creator(update.actions, EFeatureLevel_Latest); update.flushInfos.hasSizeInfo = true; update.flushInfos.flushCounter = 1; update.flushInfos.sizeInfo = this->m_scene.getSceneSizeInformation(); @@ -1582,7 +1584,7 @@ TEST_F(AClientSceneLogic_Direct, doesSendSceneAfterFlushToLateSubscribers) // for checking SceneUpdate expectedUpdate; expectedUpdate.actions = (this->m_scene.getSceneActionCollection().copy()); - SceneActionCollectionCreator creator(expectedUpdate.actions); + SceneActionCollectionCreator creator(expectedUpdate.actions, EFeatureLevel_Latest); expectedUpdate.flushInfos.hasSizeInfo = true; expectedUpdate.flushInfos.flushCounter = 1; expectedUpdate.flushInfos.sizeInfo = this->m_scene.getSceneSizeInformation(); @@ -1968,7 +1970,7 @@ TYPED_TEST(AClientSceneLogic_All, updatesResourceStatisticsIfEffectAddedAndRemov this->expectStatistics(EResourceStatisticIndex_Effect, { 1, 6, 6 }); this->expectStatistics(EResourceStatisticIndex_Texture, { 0, 0, 0 }); - ManagedResource newManRes(new EffectResource("f00", "bar", {}, {}, {}, {}, {})); + ManagedResource newManRes(new EffectResource("f00", "bar", {}, {}, {}, {}, {}, {}, EFeatureLevel_Latest)); this->expectResourceQueries({ newManRes }, { this->m_effectResource, newManRes }); this->m_scene.allocateDataSlot({EDataSlotType::TextureProvider, DataSlotId(1u), {}, {}, newManRes->getHash(), {}}, {}); diff --git a/tests/unittests/framework/Components/ResourceComponentTest.cpp b/tests/unittests/framework/Components/ResourceComponentTest.cpp index 251927ab7..53ede4468 100644 --- a/tests/unittests/framework/Components/ResourceComponentTest.cpp +++ b/tests/unittests/framework/Components/ResourceComponentTest.cpp @@ -125,7 +125,7 @@ namespace ramses::internal std::vector> serializeResources(const ManagedResourceVector& resVec, uint32_t chunkSize = 100000) { SceneUpdate update{SceneActionCollection(), resVec, {}}; - return TestSerializeSceneUpdateToVectorChunked(SceneUpdateSerializer(update, sceneStatistics), chunkSize); + return TestSerializeSceneUpdateToVectorChunked(SceneUpdateSerializer(update, sceneStatistics, EFeatureLevel_Latest), chunkSize); } protected: @@ -141,7 +141,7 @@ namespace ramses::internal { public: AResourceComponentTest() - : localResourceComponent(statistics, frameworkLock) + : localResourceComponent(statistics, frameworkLock, EFeatureLevel_Latest) {} ResourceComponent& getResourceComponent() override @@ -177,7 +177,7 @@ namespace ramses::internal { public: AResourceComponentWithThreadedTaskExecutorTest() - : localResourceComponent(statistics, frameworkLock) + : localResourceComponent(statistics, frameworkLock, EFeatureLevel_Latest) {} ResourceComponent& getResourceComponent() override diff --git a/tests/unittests/framework/Components/ResourcePersistationTest.cpp b/tests/unittests/framework/Components/ResourcePersistationTest.cpp index 7307c6c13..cdbe66e11 100644 --- a/tests/unittests/framework/Components/ResourcePersistationTest.cpp +++ b/tests/unittests/framework/Components/ResourcePersistationTest.cpp @@ -21,6 +21,7 @@ #include "ResourceMock.h" #include "InputStreamMock.h" #include "UnsafeTestMemoryHelpers.h" +#include "ResourceSerializationTestHelper.h" #include using namespace testing; @@ -35,7 +36,7 @@ namespace ramses::internal { } - static std::unique_ptr ReadWriteResource(const ManagedResource& inResource) + static std::unique_ptr ReadWriteResource(const ManagedResource& inResource, EFeatureLevel featureLevel = EFeatureLevel_Latest) { std::unique_ptr loaded; @@ -48,7 +49,7 @@ namespace ramses::internal { File file("filename"); BinaryFileInputStream stream(file); - loaded = ResourcePersistation::ReadOneResourceFromStream(stream, inResource->getHash()); + loaded = ResourcePersistation::ReadOneResourceFromStream(stream, inResource->getHash(), featureLevel); } EXPECT_TRUE(loaded); @@ -57,15 +58,71 @@ namespace ramses::internal } template - std::unique_ptr createLoadedResource(const IResource& res, const EResourceType resourceType) + std::unique_ptr createLoadedResource(const IResource& res, const EResourceType resourceType, EFeatureLevel featureLevel = EFeatureLevel_Latest) { ManagedResource managedRes{ &res, m_deleterMock }; - std::unique_ptr loadedResource = ReadWriteResource(managedRes); + std::unique_ptr loadedResource = ReadWriteResource(managedRes, featureLevel); EXPECT_EQ(res.getResourceData().span(), loadedResource->getResourceData().span()); - EXPECT_EQ(resourceType, loadedResource->getTypeID()); - return std::unique_ptr(static_cast(loadedResource.release())); + // save and load resource second time - this can reveal discrepencies between deserialize and serialize code (in this order) + ManagedResource managedRes2{ loadedResource.get(), m_deleterMock }; + std::unique_ptr loadedResource2 = ReadWriteResource(managedRes2, featureLevel); + EXPECT_EQ(res.getResourceData().span(), loadedResource2->getResourceData().span()); + EXPECT_EQ(resourceType, loadedResource2->getTypeID()); + + return std::unique_ptr(static_cast(loadedResource2.release())); + } + + static EffectResource CreateTestEffect(EFeatureLevel featureLevel) + { + const std::string customVertexShader(R"SHADER( + #version 310 es + layout(location=11) uniform vec2 u_myVec2; + layout(location=5) uniform sampler2D u_mySampler1; + layout(std140,binding=1) uniform MyUbo_t + { + vec2 u_myVec2; + } myUbo; + layout(location=23) uniform vec3 u_myVec3; + layout(location=7) uniform sampler2D u_mySampler2; + + void main(void) + { + gl_Position = texture(u_mySampler1, u_myVec2)+ texture(u_mySampler2, myUbo.u_myVec2) * u_myVec3.x; + } + )SHADER"); + const std::string customFragmentShader(R"SHADER( + #version 310 es + out highp vec4 fragColor; + void main(void) + { + fragColor = vec4(1.0); + } + )SHADER"); + + EffectInputInformationVector uniformInputs; + uniformInputs.push_back(EffectInputInformation("u_myVec2", 1, EDataType::Vector2F, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("u_mySampler1", 1, EDataType::TextureSampler2D, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("myUbo", 1, EDataType::UniformBuffer, EFixedSemantics::Invalid, UniformBufferBinding{ 1u })); + uniformInputs.push_back(EffectInputInformation("myUbo.u_myVec2", 1, EDataType::Vector2F, EFixedSemantics::Invalid, UniformBufferBinding{ 1u }, UniformBufferElementSize{ 8u }, UniformBufferFieldOffset{ 0u })); + uniformInputs.push_back(EffectInputInformation("u_myVec3", 1, EDataType::Vector3F, EFixedSemantics::Invalid)); + uniformInputs.push_back(EffectInputInformation("u_mySampler2", 1, EDataType::TextureSampler2D, EFixedSemantics::Invalid)); + + SPIRVShaders dummySpirvShaders{ + SPIRVShaderBlob{ 1u, 2u, 3u, 4u }, + SPIRVShaderBlob{ 5u, 6u, 7u, 8u, 9u }, + SPIRVShaderBlob{ 10u, 11u, 12u} }; + + return EffectResource( + customVertexShader, + customFragmentShader, + "geometryFoo", + featureLevel >= EFeatureLevel_02 ? dummySpirvShaders : SPIRVShaders{}, + EDrawMode::Lines, + uniformInputs, + {}, + "test effect", featureLevel); } private: @@ -183,15 +240,28 @@ namespace ramses::internal TEST_F(AResourcePersistation, WriteRead_EffectResource) { - EffectResource effectResource("vertexBla", "fragmentFoo", "geometryFoo", EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), "effect name"); + const auto effectResource = CreateTestEffect(EFeatureLevel_Latest); auto loadedEffectResource = createLoadedResource(effectResource, EResourceType::Effect); + ResourceSerializationTestHelper::CompareTypedResources(effectResource, *loadedEffectResource); + } + + TEST_F(AResourcePersistation, WriteRead_EffectResource_FL01) + { + static_assert(EFeatureLevel_Latest != EFeatureLevel_01, "Remove test when feature levels flattened"); + const auto effectResource = CreateTestEffect(EFeatureLevel_01); + + auto loadedEffectResource = createLoadedResource(effectResource, EResourceType::Effect, EFeatureLevel_01); EXPECT_STREQ(effectResource.getVertexShader(), loadedEffectResource->getVertexShader()); EXPECT_STREQ(effectResource.getFragmentShader(), loadedEffectResource->getFragmentShader()); EXPECT_STREQ(effectResource.getGeometryShader(), loadedEffectResource->getGeometryShader()); - EXPECT_EQ(std::string("effect name"), loadedEffectResource->getName()); + EXPECT_EQ(std::string("test effect"), loadedEffectResource->getName()); EXPECT_EQ(EDrawMode::Lines, loadedEffectResource->getGeometryShaderInputType()); + + EXPECT_EQ(0u, loadedEffectResource->getVertexShaderSPIRVSize()); + EXPECT_EQ(0u, loadedEffectResource->getFragmentShaderSPIRVSize()); + EXPECT_EQ(0u, loadedEffectResource->getGeometryShaderSPIRVSize()); } TEST(ResourcePersistation, sandwich_writeThreeResources_ReadOneBackBasedTableOfContentsInformation) @@ -217,7 +287,7 @@ namespace ramses::internal ManagedResource managedRes2{ &res2, dummyManagedResourceCallback }; const ResourceContentHash hash2 = managedRes2->getHash(); - EffectResource res3("foo", "bar", "qux", EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), "Some effect with a name"); + EffectResource res3("foo", "bar", "qux", {}, EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), "Some effect with a name", EFeatureLevel_Latest); ManagedResource managedRes3{ &res3, dummyManagedResourceCallback }; const ResourceContentHash hash3 = managedRes3->getHash(); @@ -237,21 +307,21 @@ namespace ramses::internal { ASSERT_TRUE(loadedTOC.containsResource(hash)); - auto loadedResource = ResourcePersistation::RetrieveResourceFromStream(instream, loadedTOC.getEntryForHash(hash)); + auto loadedResource = ResourcePersistation::RetrieveResourceFromStream(instream, loadedTOC.getEntryForHash(hash), EFeatureLevel_Latest); ASSERT_TRUE(UnsafeTestMemoryHelpers::CompareMemoryBlobToSpan(dataA, sizeof(dataA), loadedResource->getResourceData().span())); EXPECT_EQ(std::string("res1"), loadedResource->getName()); } { ASSERT_TRUE(loadedTOC.containsResource(hash2)); - auto loadedResource = ResourcePersistation::RetrieveResourceFromStream(instream, loadedTOC.getEntryForHash(hash2)); + auto loadedResource = ResourcePersistation::RetrieveResourceFromStream(instream, loadedTOC.getEntryForHash(hash2), EFeatureLevel_Latest); ASSERT_TRUE(UnsafeTestMemoryHelpers::CompareMemoryBlobToSpan(dataB, sizeof(dataB), loadedResource->getResourceData().span())); EXPECT_EQ(std::string("res2"), loadedResource->getName()); } { ASSERT_TRUE(loadedTOC.containsResource(hash3)); - auto loadedResource = ResourcePersistation::RetrieveResourceFromStream(instream, loadedTOC.getEntryForHash(hash3)); + auto loadedResource = ResourcePersistation::RetrieveResourceFromStream(instream, loadedTOC.getEntryForHash(hash3), EFeatureLevel_Latest); EXPECT_STREQ(res3.getVertexShader(), loadedResource->convertTo()->getVertexShader()); EXPECT_STREQ(res3.getFragmentShader(), loadedResource->convertTo()->getFragmentShader()); EXPECT_EQ(std::string("Some effect with a name"), loadedResource->getName()); @@ -261,7 +331,7 @@ namespace ramses::internal static std::pair, ResourceFileEntry> getDummyResourceData() { BinaryOutputStream outStream; - EffectResource res("foo", "bar", "qux", EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), "Some effect with a name"); + EffectResource res("foo", "bar", "qux", {}, EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), "Some effect with a name", EFeatureLevel_Latest); NiceMock managedResourceDeleter; ResourceDeleterCallingCallback dummyManagedResourceCallback(managedResourceDeleter); ManagedResource managedRes{ &res, dummyManagedResourceCallback }; @@ -292,7 +362,7 @@ namespace ramses::internal resStream.read(data, size); return stream; }); - EXPECT_TRUE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second)); + EXPECT_TRUE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second, EFeatureLevel_Latest)); } TEST(ResourcePersistation, retrieveResourceFromStreamCanHandleSeekErrors) @@ -301,7 +371,7 @@ namespace ramses::internal InputStreamMock stream; BinaryInputStream resStream(dummyResource.first.data()); EXPECT_CALL(stream, seek(_, _)).WillRepeatedly(Return(EStatus::Error)); - EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second)); + EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second, EFeatureLevel_Latest)); } TEST(ResourcePersistation, retrieveResourceFromStreamCanHandleGetPosErrors) @@ -320,7 +390,7 @@ namespace ramses::internal resStream.read(data, size); return stream; }); - EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second)); + EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second, EFeatureLevel_Latest)); } TEST(ResourcePersistation, retrieveResourceFromStreamCanHandleGetPosWrongData) @@ -343,7 +413,7 @@ namespace ramses::internal resStream.read(data, size); return stream; }); - EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second)); + EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second, EFeatureLevel_Latest)); } TEST(ResourcePersistation, retrieveResourceFromStreamCanHandleGetStateErrors) @@ -359,7 +429,7 @@ namespace ramses::internal resStream.read(data, size); return stream; }); - EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second)); + EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second, EFeatureLevel_Latest)); } TEST(ResourcePersistation, retrieveResourceFromStreamCanHandleZeroReader) @@ -375,6 +445,6 @@ namespace ramses::internal std::memset(data, 0, size); return stream; }); - EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second)); + EXPECT_FALSE(ResourcePersistation::RetrieveResourceFromStream(stream, dummyResource.second, EFeatureLevel_Latest)); } } diff --git a/tests/unittests/framework/Components/ResourceSerializationTestHelper.h b/tests/unittests/framework/Components/ResourceSerializationTestHelper.h index 144e41005..c75752db5 100644 --- a/tests/unittests/framework/Components/ResourceSerializationTestHelper.h +++ b/tests/unittests/framework/Components/ResourceSerializationTestHelper.h @@ -122,16 +122,51 @@ namespace ramses::internal frag[i] = 'b'; geom[i] = 'c'; } - auto* resource = new EffectResource(vert, frag, geom, EDrawMode::Points, EffectInputInformationVector(), EffectInputInformationVector(), "effect name"); + auto* resource = new EffectResource(vert, frag, geom, {}, EDrawMode::Points, EffectInputInformationVector(), EffectInputInformationVector(), "effect name", EFeatureLevel_Latest); return resource; } template <> inline void ResourceSerializationTestHelper::CompareTypedResources(const EffectResource& a, const EffectResource& b) { + EXPECT_EQ(a.getName(), b.getName()); + EXPECT_EQ(a.getGeometryShaderInputType(), b.getGeometryShaderInputType()); + EXPECT_STREQ(a.getVertexShader(), b.getVertexShader()); EXPECT_STREQ(a.getFragmentShader(), b.getFragmentShader()); EXPECT_STREQ(a.getGeometryShader(), b.getGeometryShader()); EXPECT_EQ(a.getGeometryShaderInputType(), b.getGeometryShaderInputType()); + + ASSERT_EQ(a.getVertexShaderSPIRVSize(), b.getVertexShaderSPIRVSize()); + ASSERT_EQ(a.getFragmentShaderSPIRVSize(), b.getFragmentShaderSPIRVSize()); + ASSERT_EQ(a.getGeometryShaderSPIRVSize(), b.getGeometryShaderSPIRVSize()); + + if (a.getVertexShaderSPIRVSize() == 0) + { + // No SPIRV in effect + return; + } + + // check alignment + EXPECT_EQ(0u, uintptr_t(a.getVertexShaderSPIRV()) % sizeof(uint32_t)); + EXPECT_EQ(0u, uintptr_t(a.getFragmentShaderSPIRV()) % sizeof(uint32_t)); + EXPECT_EQ(0u, uintptr_t(a.getGeometryShaderSPIRV()) % sizeof(uint32_t)); + + EXPECT_EQ(0u, uintptr_t(b.getVertexShaderSPIRV()) % sizeof(uint32_t)); + EXPECT_EQ(0u, uintptr_t(b.getFragmentShaderSPIRV()) % sizeof(uint32_t)); + EXPECT_EQ(0u, uintptr_t(b.getGeometryShaderSPIRV()) % sizeof(uint32_t)); + + // check contents + auto checkSPIRVContents = [](const uint32_t* aSpirv, const uint32_t* bSpirv, std::size_t sizeInBytes) { + if (sizeInBytes == 0u) + return; + const SPIRVShaderBlob aSpirvBlob(aSpirv, aSpirv + sizeInBytes / sizeof(uint32_t)); + const SPIRVShaderBlob bSpirvBlob(bSpirv, bSpirv + sizeInBytes / sizeof(uint32_t)); + EXPECT_EQ(aSpirvBlob, bSpirvBlob); + }; + + checkSPIRVContents(a.getVertexShaderSPIRV(), b.getVertexShaderSPIRV(), a.getVertexShaderSPIRVSize()); + checkSPIRVContents(a.getFragmentShaderSPIRV(), b.getFragmentShaderSPIRV(), a.getFragmentShaderSPIRVSize()); + checkSPIRVContents(a.getGeometryShaderSPIRV(), b.getGeometryShaderSPIRV(), a.getGeometryShaderSPIRVSize()); } } diff --git a/tests/unittests/framework/Components/SceneGraphComponentTest.cpp b/tests/unittests/framework/Components/SceneGraphComponentTest.cpp index 733fbd5b9..5a4fedf01 100644 --- a/tests/unittests/framework/Components/SceneGraphComponentTest.cpp +++ b/tests/unittests/framework/Components/SceneGraphComponentTest.cpp @@ -32,9 +32,9 @@ class ASceneGraphComponentBase : public ::testing::Test , remoteParticipantID(12) , sceneGraphComponent(localParticipantID, communicationSystem, connectionStatusUpdateNotifier, resourceComponent, frameworkLock, ramses::EFeatureLevel_Latest) { - localSceneIdInfo = SceneInfo(localSceneId, "sceneName", EScenePublicationMode::LocalOnly); + localSceneIdInfo = SceneInfo{ localSceneId, "sceneName", EScenePublicationMode::LocalOnly, ERenderBackendCompatibility::VulkanAndOpenGL, EVulkanAPIVersion::Version_1_1, ESPIRVVersion::Version_1_2 }; localSceneIdInfoVector.push_back(localSceneIdInfo); - localAndRemoteSceneIdInfo = SceneInfo(localSceneId, "sceneName", EScenePublicationMode::LocalAndRemote); + localAndRemoteSceneIdInfo = SceneInfo{ localSceneId, "sceneName", EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::VulkanAndOpenGL, EVulkanAPIVersion::Version_1_1, ESPIRVVersion::Version_1_2 }; localAndRemoteSceneIdInfoVector.push_back(localAndRemoteSceneIdInfo); } @@ -51,7 +51,7 @@ class ASceneGraphComponentBase : public ::testing::Test std::vector> actionsToChunks(const SceneActionCollection& actions, uint32_t chunkSize = 100000, const ManagedResourceVector& resources = {}, const FlushInformation& flushinfo = {}) { SceneUpdate update{actions.copy(), resources, flushinfo.copy()}; - return TestSerializeSceneUpdateToVectorChunked(SceneUpdateSerializer(update, sceneStatistics), chunkSize); + return TestSerializeSceneUpdateToVectorChunked(SceneUpdateSerializer(update, sceneStatistics, EFeatureLevel_Latest), chunkSize); } void expectSendSceneActionsToNetwork(Guid remote, SceneId sceneId, const SceneActionCollection& expectedActions) @@ -64,13 +64,13 @@ class ASceneGraphComponentBase : public ::testing::Test }); } - void publishScene(uint32_t sceneId, std::string_view name, EScenePublicationMode pubMode) + void publishScene(uint32_t sceneId, std::string name, EScenePublicationMode pubMode) { - SceneInfo info(SceneId(sceneId), name, pubMode); + SceneInfo info{ SceneId(sceneId), std::move(name), pubMode }; EXPECT_CALL(consumer, handleNewSceneAvailable(info, _)); if (pubMode != EScenePublicationMode::LocalOnly) EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(SceneInfoVector{info}, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(SceneId(sceneId), pubMode, name); + sceneGraphComponent.sendPublishScene(info); } protected: @@ -111,20 +111,20 @@ TEST_F(ASceneGraphComponent, sendsSceneToLocalConsumer) sceneGraphComponent.setSceneRendererHandler(&consumer); EXPECT_CALL(consumer, handleInitializeScene(_, _)).Times(1); - sceneGraphComponent.sendCreateScene(localParticipantID, SceneId(666u), EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(localParticipantID, SceneInfo{ SceneId(666u), "", EScenePublicationMode::LocalAndRemote }); } TEST_F(ASceneGraphComponent, doesntSendSceneIfLocalConsumerIsntSet) { EXPECT_CALL(consumer, handleInitializeScene(_, localParticipantID)).Times(0); - sceneGraphComponent.sendCreateScene(localParticipantID, SceneId(666u), EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(localParticipantID, SceneInfo{ SceneId(666u), "", EScenePublicationMode::LocalAndRemote }); } TEST_F(ASceneGraphComponent, sendsSceneToRemoteProvider) { EXPECT_CALL(communicationSystem, sendInitializeScene(remoteParticipantID, SceneId(666u))); - sceneGraphComponent.sendCreateScene(remoteParticipantID, SceneId(666u), EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(remoteParticipantID, SceneInfo{ SceneId(666u), "", EScenePublicationMode::LocalAndRemote }); } TEST_F(ASceneGraphComponent, publishesSceneAtLocalConsumerInLocalAndRemoteMode) @@ -133,7 +133,7 @@ TEST_F(ASceneGraphComponent, publishesSceneAtLocalConsumerInLocalAndRemoteMode) EXPECT_CALL(consumer, handleNewSceneAvailable(localAndRemoteSceneIdInfo, _)); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(localAndRemoteSceneIdInfoVector, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(localAndRemoteSceneIdInfo); } TEST_F(ASceneGraphComponentNotConnected, publishesSceneAtLocalConsumerInLocalAndRemoteMode) @@ -142,7 +142,7 @@ TEST_F(ASceneGraphComponentNotConnected, publishesSceneAtLocalConsumerInLocalAnd { EXPECT_CALL(consumer, handleNewSceneAvailable(localAndRemoteSceneIdInfo, _)); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(_, ramses::EFeatureLevel_Latest)).Times(0); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(localAndRemoteSceneIdInfo); } { EXPECT_CALL(consumer, handleSceneBecameUnavailable(localAndRemoteSceneIdInfo.sceneID, _)); @@ -156,19 +156,19 @@ TEST_F(ASceneGraphComponent, publishesSceneAtLocalConsumerInLocalOnlyMode) sceneGraphComponent.setSceneRendererHandler(&consumer); EXPECT_CALL(consumer, handleNewSceneAvailable(localSceneIdInfo, _)); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(localSceneIdInfo); } TEST_F(ASceneGraphComponent, doesntPublishSceneIfLocalConsumerIsntSet) { EXPECT_CALL(consumer, handleNewSceneAvailable(localAndRemoteSceneIdInfo, _)).Times(0); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(localSceneIdInfoVector, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(localAndRemoteSceneIdInfo); } TEST_F(ASceneGraphComponent, doesNotPublishSceneToRemoteProviderInLocalOnlyMode) { - sceneGraphComponent.sendPublishScene(remoteSceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(localSceneIdInfo); // no expect needed, StrictMock on communicationSystem checks it already } @@ -176,14 +176,14 @@ TEST_F(ASceneGraphComponent, publishesSceneAtRemoteProvider) { sceneGraphComponent.newParticipantHasConnected(Guid(33)); - SceneInfoVector newScenes(1, SceneInfo(remoteSceneId, "sceneName")); + SceneInfoVector newScenes(1, SceneInfo{ remoteSceneId, "sceneName" }); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(newScenes, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(remoteSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(SceneInfo{ remoteSceneId, "sceneName", EScenePublicationMode::LocalAndRemote }); } TEST_F(ASceneGraphComponent, alreadyPublishedSceneGetsRepublishedWhenLocalConsumerIsSet) { - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(localSceneIdInfo); EXPECT_CALL(consumer, handleNewSceneAvailable(localSceneIdInfo, _)); sceneGraphComponent.setSceneRendererHandler(&consumer); @@ -194,7 +194,7 @@ TEST_F(ASceneGraphComponent, locallySubscribedScenesGetUnsubscibedWhenLocalConsu sceneGraphComponent.setSceneRendererHandler(&consumer); SceneId sceneId(1); - SceneInfo sceneInfo(SceneInfo(sceneId, "foo")); + SceneInfo sceneInfo{ sceneId, "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.handleCreateScene(scene, false, eventConsumer); @@ -219,9 +219,9 @@ TEST_F(ASceneGraphComponent, unpublishesSceneAtLocalConsumer) const SceneId sceneId(999); sceneGraphComponent.setSceneRendererHandler(&consumer); - SceneInfoVector newScenes(1, SceneInfo(sceneId, "sceneName")); - EXPECT_CALL(consumer, handleNewSceneAvailable(SceneInfo(sceneId, "sceneName", EScenePublicationMode::LocalOnly), _)); - sceneGraphComponent.sendPublishScene(sceneId, EScenePublicationMode::LocalOnly, "sceneName"); + SceneInfoVector newScenes(1, SceneInfo{ sceneId, "sceneName" }); + EXPECT_CALL(consumer, handleNewSceneAvailable(SceneInfo{ sceneId, "sceneName", EScenePublicationMode::LocalOnly }, _)); + sceneGraphComponent.sendPublishScene(SceneInfo{ sceneId, "sceneName", EScenePublicationMode::LocalOnly }); EXPECT_CALL(consumer, handleSceneBecameUnavailable(sceneId, _)); sceneGraphComponent.sendUnpublishScene(sceneId, EScenePublicationMode::LocalOnly); @@ -232,14 +232,14 @@ TEST_F(ASceneGraphComponent, doesntUnpublishSceneIfLocalConsumerIsntSet) EXPECT_CALL(consumer, handleSceneBecameUnavailable(_, _)).Times(0); const SceneId sceneId(1ull << 63); - sceneGraphComponent.sendPublishScene(sceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(SceneInfo{ sceneId, "sceneName", EScenePublicationMode::LocalOnly }); sceneGraphComponent.sendUnpublishScene(sceneId, EScenePublicationMode::LocalOnly); } TEST_F(ASceneGraphComponent, doesNotUnpublishesSceneAtRemoteProviderIfSceneWasPublishedLocalOnly) { const SceneId sceneId(1ull << 63); - sceneGraphComponent.sendPublishScene(sceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(SceneInfo{ sceneId, "sceneName", EScenePublicationMode::LocalOnly }); sceneGraphComponent.sendUnpublishScene(sceneId, EScenePublicationMode::LocalOnly); // expect noting on remote, checked by strict mock } @@ -249,18 +249,18 @@ TEST_F(ASceneGraphComponent, unpublishesSceneAtRemoteProvider) const SceneId sceneId(1ull << 63); sceneGraphComponent.newParticipantHasConnected(Guid(33)); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(_, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(sceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(SceneInfo{ sceneId, "sceneName", EScenePublicationMode::LocalAndRemote }); - SceneInfoVector unavailableScenes(1, SceneInfo(sceneId, "sceneName")); + SceneInfoVector unavailableScenes(1, SceneInfo{ sceneId, "sceneName" }); EXPECT_CALL(communicationSystem, broadcastScenesBecameUnavailable(unavailableScenes)); sceneGraphComponent.sendUnpublishScene(sceneId, EScenePublicationMode::LocalAndRemote); } TEST_F(ASceneGraphComponent, sendsAvailableScenesToNewParticipant) { - SceneInfoVector newScenes(1, SceneInfo(remoteSceneId, "sceneName")); + SceneInfoVector newScenes(1, SceneInfo{ remoteSceneId, "sceneName" }); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(newScenes, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(remoteSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(SceneInfo{ remoteSceneId, "sceneName", EScenePublicationMode::LocalAndRemote }); Guid id(33); EXPECT_CALL(communicationSystem, sendScenesAvailable(id, newScenes, ramses::EFeatureLevel_Latest)); @@ -269,8 +269,8 @@ TEST_F(ASceneGraphComponent, sendsAvailableScenesToNewParticipant) TEST_F(ASceneGraphComponentNotConnected, sendsAvailableScenesToNewParticipant) { - SceneInfoVector newScenes(1, SceneInfo(remoteSceneId, "sceneName")); - sceneGraphComponent.sendPublishScene(remoteSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + SceneInfoVector newScenes(1, SceneInfo{ remoteSceneId, "sceneName" }); + sceneGraphComponent.sendPublishScene(SceneInfo{ remoteSceneId, "sceneName", EScenePublicationMode::LocalAndRemote }); Guid id(33); EXPECT_CALL(communicationSystem, sendScenesAvailable(id, newScenes, ramses::EFeatureLevel_Latest)); @@ -279,8 +279,8 @@ TEST_F(ASceneGraphComponentNotConnected, sendsAvailableScenesToNewParticipant) TEST_F(ASceneGraphComponent, doesNotSendAvailableSceneToNewParticipantIfLocalOnlyScene) { - SceneInfoVector newScenes(1, SceneInfo(remoteSceneId, "sceneName")); - sceneGraphComponent.sendPublishScene(remoteSceneId, EScenePublicationMode::LocalOnly, "sceneName"); + SceneInfoVector newScenes(1, SceneInfo{ remoteSceneId, "sceneName" }); + sceneGraphComponent.sendPublishScene(SceneInfo{ remoteSceneId, "sceneName", EScenePublicationMode::LocalOnly }); Guid id(33); EXPECT_CALL(communicationSystem, sendScenesAvailable(id, newScenes, ramses::EFeatureLevel_Latest)).Times(0); @@ -346,7 +346,7 @@ TEST_F(ASceneGraphComponent, sendsResourcesCompressedToRemoteProvider) { SceneId sceneId; EXPECT_CALL(communicationSystem, sendInitializeScene(_, _)).Times(1); - sceneGraphComponent.sendCreateScene(remoteParticipantID, sceneId, EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(remoteParticipantID, SceneInfo{ sceneId, "", EScenePublicationMode::LocalAndRemote }); ResourceBlob blob(1024 * EnumToSize(EDataType::Float)); std::generate(blob.data(), blob.data() + blob.size(), [](){ static uint8_t i{9}; return std::byte(++i); }); @@ -380,7 +380,7 @@ TEST_F(ASceneGraphComponent, sendsSceneActionToRemoteProvider) { SceneId sceneId; EXPECT_CALL(communicationSystem, sendInitializeScene(_, _)).Times(1); - sceneGraphComponent.sendCreateScene(remoteParticipantID, sceneId, EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(remoteParticipantID, SceneInfo{ sceneId, "", EScenePublicationMode::LocalAndRemote }); SceneActionCollection list(CreateFakeSceneActionCollectionFromTypes({ ESceneActionId::TestAction })); expectSendSceneActionsToNetwork(remoteParticipantID, sceneId, list); @@ -393,7 +393,7 @@ TEST_F(ASceneGraphComponent, sendsAllSceneActionsAtOnceToRemoteProvider) { SceneId sceneId(1); EXPECT_CALL(communicationSystem, sendInitializeScene(_, _)).Times(1); - sceneGraphComponent.sendCreateScene(remoteParticipantID, sceneId, EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(remoteParticipantID, SceneInfo{ sceneId, "", EScenePublicationMode::LocalAndRemote }); SceneActionCollection list(CreateFakeSceneActionCollectionFromTypes({ ESceneActionId::TestAction, ESceneActionId::SetDataVector2fArray, ESceneActionId::AllocateNode })); expectSendSceneActionsToNetwork(remoteParticipantID, sceneId, list); @@ -405,7 +405,7 @@ TEST_F(ASceneGraphComponent, sendsAllSceneActionsAtOnceToRemoteProvider) TEST_F(ASceneGraphComponent, doesNotsendSceneUpdateToRemoteIfSceneWasPublishedLocalOnly) { const SceneId sceneId(111); - sceneGraphComponent.sendPublishScene(sceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(SceneInfo{ sceneId, "sceneName", EScenePublicationMode::LocalOnly }); SceneActionCollection list(CreateFakeSceneActionCollectionFromTypes({ ESceneActionId::TestAction })); SceneUpdate update; @@ -421,7 +421,7 @@ TEST_F(ASceneGraphComponent, canSendSceneActionsToLocalAndRemote) const SceneId sceneId(456); EXPECT_CALL(communicationSystem, sendInitializeScene(_, _)).Times(1); - sceneGraphComponent.sendCreateScene(remoteParticipantID, sceneId, EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(remoteParticipantID, SceneInfo{ sceneId, "", EScenePublicationMode::LocalAndRemote }); SceneActionCollection list(CreateFakeSceneActionCollectionFromTypes({ ESceneActionId::TestAction })); InSequence seq; @@ -441,7 +441,7 @@ TEST_F(ASceneGraphComponent, canRepublishALocalOnlySceneToBeDistributedRemotely) // publish LocalOnly EXPECT_CALL(consumer, handleNewSceneAvailable(localSceneIdInfo, _)); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(localSceneIdInfo); Mock::VerifyAndClearExpectations(&communicationSystem); // unpublish @@ -451,10 +451,10 @@ TEST_F(ASceneGraphComponent, canRepublishALocalOnlySceneToBeDistributedRemotely) Mock::VerifyAndClearExpectations(&consumer); // publish LocalAndRemote - SceneInfoVector newScenes(1, SceneInfo(localSceneId, "sceneName")); + SceneInfoVector newScenes(1, localAndRemoteSceneIdInfo); EXPECT_CALL(consumer, handleNewSceneAvailable(localAndRemoteSceneIdInfo, localParticipantID)); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(newScenes, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(localAndRemoteSceneIdInfo); } TEST_F(ASceneGraphComponent, canRepublishARemoteSceneToBeLocalOnly) @@ -465,7 +465,7 @@ TEST_F(ASceneGraphComponent, canRepublishARemoteSceneToBeLocalOnly) // publish LocalAndRemote EXPECT_CALL(consumer, handleNewSceneAvailable(localAndRemoteSceneIdInfo, localParticipantID)); EXPECT_CALL(communicationSystem, broadcastNewScenesAvailable(localAndRemoteSceneIdInfoVector, ramses::EFeatureLevel_Latest)); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalAndRemote, "sceneName"); + sceneGraphComponent.sendPublishScene(localAndRemoteSceneIdInfo); Mock::VerifyAndClearExpectations(&communicationSystem); Mock::VerifyAndClearExpectations(&consumer); @@ -478,7 +478,7 @@ TEST_F(ASceneGraphComponent, canRepublishARemoteSceneToBeLocalOnly) // publish LocalOnly EXPECT_CALL(consumer, handleNewSceneAvailable(_, _)); - sceneGraphComponent.sendPublishScene(localSceneId, EScenePublicationMode::LocalOnly, "sceneName"); + sceneGraphComponent.sendPublishScene(localSceneIdInfo); Mock::VerifyAndClearExpectations(&communicationSystem); } @@ -486,7 +486,7 @@ TEST_F(ASceneGraphComponent, disconnectFromNetworkBroadcastsScenesUnavailableOnN { sceneGraphComponent.setSceneRendererHandler(&consumer); publishScene(1, "name", EScenePublicationMode::LocalAndRemote); - EXPECT_CALL(communicationSystem, broadcastScenesBecameUnavailable(SceneInfoVector{ SceneInfo(SceneId(1), "name") })); + EXPECT_CALL(communicationSystem, broadcastScenesBecameUnavailable(SceneInfoVector{ SceneInfo{ SceneId(1), "name" } })); sceneGraphComponent.disconnectFromNetwork(); } @@ -502,24 +502,24 @@ TEST_F(ASceneGraphComponent, disconnectFromNetworkBroadcastsScenesUnavailableOnN sceneGraphComponent.disconnectFromNetwork(); ASSERT_EQ(2u, unpubScenes.size()); - EXPECT_TRUE(contains_c(unpubScenes, SceneInfo(SceneId(1), "name1"))); - EXPECT_TRUE(contains_c(unpubScenes, SceneInfo(SceneId(3), "name3"))); + EXPECT_TRUE(contains_c(unpubScenes, SceneInfo{ SceneId(1), "name1" })); + EXPECT_TRUE(contains_c(unpubScenes, SceneInfo{ SceneId(3), "name3" })); } TEST_F(ASceneGraphComponent, sendsPublishForNewParticipantsAfterDisconnect) { sceneGraphComponent.setSceneRendererHandler(&consumer); publishScene(1, "name", EScenePublicationMode::LocalAndRemote); - EXPECT_CALL(communicationSystem, broadcastScenesBecameUnavailable(SceneInfoVector{ SceneInfo(SceneId(1), "name") })); + EXPECT_CALL(communicationSystem, broadcastScenesBecameUnavailable(SceneInfoVector{ SceneInfo{ SceneId(1), "name" } })); sceneGraphComponent.disconnectFromNetwork(); - EXPECT_CALL(communicationSystem, sendScenesAvailable(remoteParticipantID, SceneInfoVector{ SceneInfo(SceneId(1), "name") }, ramses::EFeatureLevel_Latest)); + EXPECT_CALL(communicationSystem, sendScenesAvailable(remoteParticipantID, SceneInfoVector{ SceneInfo{ SceneId(1), "name" } }, ramses::EFeatureLevel_Latest)); sceneGraphComponent.newParticipantHasConnected(remoteParticipantID); } TEST_F(ASceneGraphComponent, disconnectDoesNotAffectLocalScenesAtAllButUnpublishesRemoteScenes) { - SceneInfo sceneInfo(SceneInfo(SceneId(1), "foo")); + SceneInfo sceneInfo{ SceneId(1), "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.setSceneRendererHandler(&consumer); @@ -584,10 +584,10 @@ TEST_F(ASceneGraphComponent, disconnectDoesNotAffectLocalScenesAtAllButUnpublish event1.sceneid = SceneId{ 123 }; ResourceAvailabilityEvent event2; event2.sceneid = SceneId{ 10000 }; - SceneInfo sceneInfo1(SceneInfo(SceneId{ 123 }, "foo")); + SceneInfo sceneInfo1{ SceneId{ 123 }, "foo" }; ClientScene scene1(sceneInfo1); sceneGraphComponent.handleCreateScene(scene1, false, eventConsumer); - SceneInfo sceneInfo2(SceneInfo(SceneId{ 10000 }, "bar")); + SceneInfo sceneInfo2{ SceneId{ 10000 }, "bar" }; ClientScene scene2(sceneInfo2); sceneGraphComponent.handleCreateScene(scene2, false, scene2Consumer); @@ -646,7 +646,7 @@ TEST_F(ASceneGraphComponent, sendResourceAvailabilityEventViaCommSystemForRemote TEST_F(ASceneGraphComponent, sendSceneReferenceEventForLocalParticipantCallsHandlerDirectly) { SceneReferenceEvent event(SceneId{ 123 }); - SceneInfo sceneInfo(SceneInfo(SceneId{ 123 }, "foo")); + SceneInfo sceneInfo{ SceneId{ 123 }, "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.handleCreateScene(scene, false, eventConsumer); event.type = SceneReferenceEventType::SceneFlushed; @@ -665,7 +665,7 @@ TEST_F(ASceneGraphComponent, sendSceneReferenceEventForLocalParticipantCallsHand TEST_F(ASceneGraphComponent, sendResourceAvailabilityEventForLocalParticipantCallsHandlerDirectly) { SceneReferenceEvent event(SceneId { 123 }); - SceneInfo sceneInfo(SceneInfo(SceneId{ 123 }, "foo")); + SceneInfo sceneInfo{ SceneId{ 123 }, "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.handleCreateScene(scene, false, eventConsumer); event.type = SceneReferenceEventType::SceneFlushed; @@ -696,7 +696,7 @@ TEST_F(ASceneGraphComponent, doesNotSendResourceAvailabilityEventForLocalPartici TEST_F(ASceneGraphComponent, unpacksRendererEventToSceneReferenceEventAndForwardsToHandler) { SceneReferenceEvent event(SceneId{ 123 }); - SceneInfo sceneInfo(SceneInfo(SceneId{ 123 }, "foo")); + SceneInfo sceneInfo{ SceneId{ 123 }, "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.handleCreateScene(scene, false, eventConsumer); event.type = SceneReferenceEventType::SceneFlushed; @@ -718,7 +718,7 @@ TEST_F(ASceneGraphComponent, unpacksRendererEventToResourceAvailabilityEventAndF { ResourceAvailabilityEvent event; event.sceneid = SceneId { 123 }; - SceneInfo sceneInfo(SceneInfo(SceneId{ 123 }, "foo")); + SceneInfo sceneInfo{ SceneId{ 123 }, "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.handleCreateScene(scene, false, eventConsumer); event.availableResources.emplace_back(1, 2); @@ -755,10 +755,10 @@ TEST_F(ASceneGraphComponent, forwardsEventsToCorrectHandler) SceneReferenceEvent event1(SceneId{ 123 }); SceneReferenceEvent event2(SceneId{ 10000 }); - SceneInfo sceneInfo1(SceneInfo(SceneId{ 123 }, "foo")); + SceneInfo sceneInfo1{ SceneId{ 123 }, "foo" }; ClientScene scene1(sceneInfo1); sceneGraphComponent.handleCreateScene(scene1, false, eventConsumer); - SceneInfo sceneInfo2(SceneInfo(SceneId{ 10000 }, "bar")); + SceneInfo sceneInfo2{ SceneId{ 10000 }, "bar" }; ClientScene scene2(sceneInfo2); sceneGraphComponent.handleCreateScene(scene2, false, scene2Consumer); @@ -791,8 +791,8 @@ TEST_F(ASceneGraphComponent, forwardsPublishFromRemoteToConsumer) sceneGraphComponent.newParticipantHasConnected(Guid(33)); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_33(SceneId(1), "", EScenePublicationMode::LocalAndRemote); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_33{ SceneId(1), "", EScenePublicationMode::LocalAndRemote }; + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_33, Guid(33))); sceneGraphComponent.handleNewScenesAvailable({info_33}, Guid(33), ramses::EFeatureLevel_Latest); @@ -807,8 +807,8 @@ TEST_F(ASceneGraphComponent, forwardsUnpublishFromRemoteToConsumer) sceneGraphComponent.newParticipantHasConnected(Guid(33)); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_33(SceneId(1), "", EScenePublicationMode::LocalAndRemote); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_33{ SceneId(1), "", EScenePublicationMode::LocalAndRemote }; + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_33, Guid(33))); sceneGraphComponent.handleNewScenesAvailable({info_33}, Guid(33), ramses::EFeatureLevel_Latest); @@ -826,8 +826,8 @@ TEST_F(ASceneGraphComponent, unpublishesRemoteScenesToConsumerOnParticipantDisco sceneGraphComponent.newParticipantHasConnected(Guid(33)); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_33(SceneId(1), "", EScenePublicationMode::LocalAndRemote); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_33{ SceneId(1), "", EScenePublicationMode::LocalAndRemote }; + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_33, _)); sceneGraphComponent.handleNewScenesAvailable({info_33}, Guid(33), ramses::EFeatureLevel_Latest); @@ -845,7 +845,7 @@ TEST_F(ASceneGraphComponent, ignoresDuplicatePublishFromOtherRemote) sceneGraphComponent.newParticipantHasConnected(Guid(22)); sceneGraphComponent.newParticipantHasConnected(Guid(33)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -857,7 +857,7 @@ TEST_F(ASceneGraphComponent, unpublishesFirstOnDuplicatePublishFromSameRemote) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -872,7 +872,7 @@ TEST_F(ASceneGraphComponent, ignoresPublishOfMismatchedFeatureLevelSceneFromRemo sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(_, _)).Times(0); sceneGraphComponent.handleNewScenesAvailable({ info_22 }, Guid(22), static_cast(99)); @@ -883,7 +883,7 @@ TEST_F(ASceneGraphComponent, ignoresDuplicateUnpublishFromRemote) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -897,7 +897,7 @@ TEST_F(ASceneGraphComponent, forwardsInitializeSceneToConsumer) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -919,7 +919,7 @@ TEST_F(ASceneGraphComponent, ignoresInitializeSceneFromWrongProvider) sceneGraphComponent.newParticipantHasConnected(Guid(22)); sceneGraphComponent.newParticipantHasConnected(Guid(33)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -931,7 +931,7 @@ TEST_F(ASceneGraphComponent, forwardsSceneActionListFromRemote) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -967,7 +967,7 @@ TEST_F(ASceneGraphComponent, ignoreSceneActionsFromRemoteWithoutInitializeScene) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -981,7 +981,7 @@ TEST_F(ASceneGraphComponent, ignoreSceneActionsFromRemoteFromWrongProvider) sceneGraphComponent.newParticipantHasConnected(Guid(22)); sceneGraphComponent.newParticipantHasConnected(Guid(33)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -997,7 +997,7 @@ TEST_F(ASceneGraphComponent, ignoreSceneActionsFromRemoteWithEmptyData) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -1012,7 +1012,7 @@ TEST_F(ASceneGraphComponent, stopsDeserilizationFromRemotAfterInvalidPacket) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -1039,7 +1039,7 @@ TEST_F(ASceneGraphComponent, brokenActionDeserilizeFromRemoteIsClearOnNextInitia sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -1065,7 +1065,7 @@ TEST_F(ASceneGraphComponent, canHandleSceneActionFromRemoteSplitInMultipleChunks sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({info_22}, Guid(22), ramses::EFeatureLevel_Latest); @@ -1091,7 +1091,7 @@ TEST_F(ASceneGraphComponent, deserializesAndForwardsFlushInformationFromRemote) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({ info_22 }, Guid(22), ramses::EFeatureLevel_Latest); @@ -1141,7 +1141,7 @@ TEST_F(ASceneGraphComponent, deserializesResourcesFromRemote) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({ info_22 }, Guid(22), ramses::EFeatureLevel_Latest); @@ -1180,7 +1180,7 @@ TEST_F(ASceneGraphComponent, deserializesResourcesFromRemote_SmallChunks) sceneGraphComponent.setSceneRendererHandler(&consumer); sceneGraphComponent.newParticipantHasConnected(Guid(22)); - SceneInfo info_22(SceneId(2), "", EScenePublicationMode::LocalAndRemote); + SceneInfo info_22{ SceneId(2), "", EScenePublicationMode::LocalAndRemote }; EXPECT_CALL(consumer, handleNewSceneAvailable(info_22, Guid(22))); sceneGraphComponent.handleNewScenesAvailable({ info_22 }, Guid(22), ramses::EFeatureLevel_Latest); @@ -1219,7 +1219,7 @@ TEST_F(ASceneGraphComponent, deserializesResourcesFromRemote_SmallChunks) TEST_F(ASceneGraphComponent, returnsFalseForFlushOnWrongResolvedResourceNumber_Shadow) { const SceneId sceneId(1u); - SceneInfo sceneInfo(SceneInfo(sceneId, "foo")); + SceneInfo sceneInfo{ sceneId, "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.setSceneRendererHandler(&consumer); @@ -1245,7 +1245,7 @@ TEST_F(ASceneGraphComponent, returnsFalseForFlushOnWrongResolvedResourceNumber_S TEST_F(ASceneGraphComponent, returnsFalseForFlushOnWrongResolvedResourceNumber_Direct) { const SceneId sceneId(1u); - SceneInfo sceneInfo(SceneInfo(sceneId, "foo")); + SceneInfo sceneInfo{ sceneId, "foo" }; ClientScene scene(sceneInfo); sceneGraphComponent.setSceneRendererHandler(&consumer); @@ -1271,7 +1271,7 @@ TEST_F(ASceneGraphComponent, sendSceneUpdatePassesSceneStatisticsToSerializer) { SceneId sceneId; EXPECT_CALL(communicationSystem, sendInitializeScene(_, _)).Times(1); - sceneGraphComponent.sendCreateScene(remoteParticipantID, sceneId, EScenePublicationMode::LocalAndRemote); + sceneGraphComponent.sendCreateScene(remoteParticipantID, SceneInfo{ localSceneId, "", EScenePublicationMode::LocalAndRemote }); EXPECT_CALL(communicationSystem, sendSceneUpdate(remoteParticipantID, sceneId, _)).WillOnce([&](auto /*unused*/, auto /*unused*/, auto& serializer) { const auto& stats = static_cast(serializer).getStatisticCollection(); diff --git a/tests/unittests/framework/Components/SceneGraphProtocolSenderAndReceiverTest.cpp b/tests/unittests/framework/Components/SceneGraphProtocolSenderAndReceiverTest.cpp index 34561ec8a..0484c64cb 100644 --- a/tests/unittests/framework/Components/SceneGraphProtocolSenderAndReceiverTest.cpp +++ b/tests/unittests/framework/Components/SceneGraphProtocolSenderAndReceiverTest.cpp @@ -45,7 +45,7 @@ namespace ramses::internal const SceneId sceneId(55u); const std::string name("sceneName"); SceneInfoVector newScenes; - newScenes.push_back(SceneInfo(sceneId, name)); + newScenes.push_back(SceneInfo{ sceneId, name }); { PlatformGuard g(receiverExpectCallLock); @@ -72,7 +72,7 @@ namespace ramses::internal { const SceneId sceneId(1ull << 63); SceneInfoVector unavailableScenes; - unavailableScenes.push_back(SceneInfo(sceneId)); + unavailableScenes.push_back(SceneInfo{ sceneId }); { PlatformGuard g(receiverExpectCallLock); @@ -93,7 +93,7 @@ namespace ramses::internal TEST_P(ASceneGraphProtocolSenderAndReceiverTest, sendScenesAvailable) { SceneInfoVector newScenes; - newScenes.push_back(SceneInfo(SceneId(55u), "sceneName")); + newScenes.push_back(SceneInfo{ SceneId(55u), "sceneName" }); { PlatformGuard g(receiverExpectCallLock); diff --git a/tests/unittests/framework/Components/SingleResourceSerializationTest.cpp b/tests/unittests/framework/Components/SingleResourceSerializationTest.cpp index df99edcee..58b10fd96 100644 --- a/tests/unittests/framework/Components/SingleResourceSerializationTest.cpp +++ b/tests/unittests/framework/Components/SingleResourceSerializationTest.cpp @@ -23,7 +23,7 @@ namespace ramses::internal SingleResourceSerialization::SerializeResource(outStream, res); BinaryInputStream inStream(outStream.getData()); - return std::unique_ptr(SingleResourceSerialization::DeserializeResource(inStream, hash)); + return std::unique_ptr(SingleResourceSerialization::DeserializeResource(inStream, hash, EFeatureLevel_Latest)); } } diff --git a/tests/unittests/framework/Core/TaskFramework/test/MockITask.h b/tests/unittests/framework/Core/TaskFramework/MockITask.h similarity index 100% rename from tests/unittests/framework/Core/TaskFramework/test/MockITask.h rename to tests/unittests/framework/Core/TaskFramework/MockITask.h diff --git a/tests/unittests/framework/Core/TaskFramework/test/MockTaskFinishHandler.h b/tests/unittests/framework/Core/TaskFramework/MockTaskFinishHandler.h similarity index 100% rename from tests/unittests/framework/Core/TaskFramework/test/MockTaskFinishHandler.h rename to tests/unittests/framework/Core/TaskFramework/MockTaskFinishHandler.h diff --git a/tests/unittests/framework/Core/TaskFramework/test/MockTaskQueue.h b/tests/unittests/framework/Core/TaskFramework/MockTaskQueue.h similarity index 100% rename from tests/unittests/framework/Core/TaskFramework/test/MockTaskQueue.h rename to tests/unittests/framework/Core/TaskFramework/MockTaskQueue.h diff --git a/tests/unittests/framework/Core/TaskFramework/test/ProcessingTaskQueueTest.cpp b/tests/unittests/framework/Core/TaskFramework/ProcessingTaskQueueTest.cpp similarity index 100% rename from tests/unittests/framework/Core/TaskFramework/test/ProcessingTaskQueueTest.cpp rename to tests/unittests/framework/Core/TaskFramework/ProcessingTaskQueueTest.cpp diff --git a/tests/unittests/framework/Core/TaskFramework/test/TaskExecutingThreadTest.cpp b/tests/unittests/framework/Core/TaskFramework/TaskExecutingThreadTest.cpp similarity index 98% rename from tests/unittests/framework/Core/TaskFramework/test/TaskExecutingThreadTest.cpp rename to tests/unittests/framework/Core/TaskFramework/TaskExecutingThreadTest.cpp index edc594b23..ae71953de 100644 --- a/tests/unittests/framework/Core/TaskFramework/test/TaskExecutingThreadTest.cpp +++ b/tests/unittests/framework/Core/TaskFramework/TaskExecutingThreadTest.cpp @@ -10,7 +10,7 @@ #include "gmock/gmock.h" #include "internal/Core/TaskFramework/ProcessingTaskQueue.h" #include "internal/PlatformAbstraction/PlatformEvent.h" -#include "Watchdog/ThreadAliveNotifierMock.h" +#include "internal/Watchdog/ThreadAliveNotifierMock.h" #include #include diff --git a/tests/unittests/framework/Core/TaskFramework/test/TaskFinishHandlerDecoratorTest.cpp b/tests/unittests/framework/Core/TaskFramework/TaskFinishHandlerDecoratorTest.cpp similarity index 100% rename from tests/unittests/framework/Core/TaskFramework/test/TaskFinishHandlerDecoratorTest.cpp rename to tests/unittests/framework/Core/TaskFramework/TaskFinishHandlerDecoratorTest.cpp diff --git a/tests/unittests/framework/Core/TaskFramework/test/TaskFinishHandlerDecoratorTest.h b/tests/unittests/framework/Core/TaskFramework/TaskFinishHandlerDecoratorTest.h similarity index 100% rename from tests/unittests/framework/Core/TaskFramework/test/TaskFinishHandlerDecoratorTest.h rename to tests/unittests/framework/Core/TaskFramework/TaskFinishHandlerDecoratorTest.h diff --git a/tests/unittests/framework/Core/TaskFramework/test/TaskForwardingQueueTest.cpp b/tests/unittests/framework/Core/TaskFramework/TaskForwardingQueueTest.cpp similarity index 100% rename from tests/unittests/framework/Core/TaskFramework/test/TaskForwardingQueueTest.cpp rename to tests/unittests/framework/Core/TaskFramework/TaskForwardingQueueTest.cpp diff --git a/tests/unittests/framework/Core/TaskFramework/test/ThreadedTaskExecutorTest.cpp b/tests/unittests/framework/Core/TaskFramework/ThreadedTaskExecutorTest.cpp similarity index 92% rename from tests/unittests/framework/Core/TaskFramework/test/ThreadedTaskExecutorTest.cpp rename to tests/unittests/framework/Core/TaskFramework/ThreadedTaskExecutorTest.cpp index 97ea18ef4..d768cc8c7 100644 --- a/tests/unittests/framework/Core/TaskFramework/test/ThreadedTaskExecutorTest.cpp +++ b/tests/unittests/framework/Core/TaskFramework/ThreadedTaskExecutorTest.cpp @@ -9,7 +9,7 @@ #include "internal/Core/TaskFramework/ThreadedTaskExecutor.h" #include "internal/PlatformAbstraction/PlatformThread.h" #include "internal/Core/TaskFramework/EnqueueOnlyOneAtATimeQueue.h" -#include "ThreadWatchdogConfig.h" +#include "impl/ThreadWatchdogConfig.h" #include "PlatformWatchDogMock.h" #include "internal/PlatformAbstraction/PlatformEvent.h" #include "internal/Core/Utils/ThreadBarrier.h" @@ -68,17 +68,25 @@ namespace ramses::internal PlatformEvent& m_blockedExecutionStateEvent; }; - TEST(AThreadedTaskExecutor, reportsToWatchDogNotifierWhenAllThreadsReportAlive) + class AThreadedTaskExecutorParam : public ::testing::TestWithParam + { + }; + // Notification interval 0 is not expected to notify (forbidden by RamsesFrameworkConfig) + INSTANTIATE_TEST_SUITE_P(AThreadedTaskExecutorParam_TestInstances, AThreadedTaskExecutorParam, ::testing::Values(1, 2, 100)); + + TEST_P(AThreadedTaskExecutorParam, reportsToWatchDogNotifierWhenAllThreadsReportAlive) { PlatformEvent syncWaiter; PlatformWatchdogMockCallback mockCallback; EXPECT_CALL(mockCallback, registerThread(ERamsesThreadIdentifier::Workers)); ThreadWatchdogConfig config; config.setThreadWatchDogCallback(&mockCallback); - config.setWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers, 100); + config.setWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers, GetParam()); EXPECT_CALL(mockCallback, notifyThread(ERamsesThreadIdentifier::Workers)) - .Times(AtLeast(1)) + .Times(AtLeast(3)) + .WillOnce(InvokeWithoutArgs([&]() {})) + .WillOnce(InvokeWithoutArgs([&]() {})) .WillRepeatedly(InvokeWithoutArgs([&]() { syncWaiter.signal(); })); ThreadedTaskExecutor ex(2, config); @@ -91,7 +99,7 @@ namespace ramses::internal { std::atomic notifyCounter(0); NiceMock mockCallback; - ON_CALL(mockCallback, notifyThread(_)).WillByDefault([&](auto) { notifyCounter++; }); + ON_CALL(mockCallback, notifyThread(_)).WillByDefault([&](auto /*unused*/) { notifyCounter++; }); std::atomic fastTasksCounter(0); NiceMock fastTask; diff --git a/tests/unittests/framework/PlatformAbstraction/PlatformThreadTest.cpp b/tests/unittests/framework/PlatformAbstraction/PlatformThreadTest.cpp index 59ca3cd79..248d796ff 100644 --- a/tests/unittests/framework/PlatformAbstraction/PlatformThreadTest.cpp +++ b/tests/unittests/framework/PlatformAbstraction/PlatformThreadTest.cpp @@ -194,7 +194,7 @@ namespace ramses::internal // logging prefix name tests work with static thread_local variables, each test case needs to run in own thread to not affect other test cases std::thread t([&] { - RamsesLogger::SetPrefixes("instName", ""); + RamsesLoggerPrefixes::SetRamsesLoggerPrefixes("instName", ""); LoggingRunnable runnable; diff --git a/tests/unittests/framework/SceneGraph/Resource/EffectResourceTest.cpp b/tests/unittests/framework/SceneGraph/Resource/EffectResourceTest.cpp index 6c4968f61..9778e0d49 100644 --- a/tests/unittests/framework/SceneGraph/Resource/EffectResourceTest.cpp +++ b/tests/unittests/framework/SceneGraph/Resource/EffectResourceTest.cpp @@ -6,7 +6,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "gtest/gtest.h" +#include "gmock/gmock.h" #include "internal/SceneGraph/Resource/EffectResource.h" #include "internal/Core/Utils/BinaryOutputStream.h" #include "internal/Core/Utils/BinaryInputStream.h" @@ -19,16 +19,10 @@ namespace ramses::internal public: AEffectResource() { - EffectInputInformation uniformA; - uniformA.inputName = "uni A"; - uniformInputs.push_back(uniformA); - EffectInputInformation uniformB; - uniformB.inputName = "uni B"; - uniformInputs.push_back(uniformB); - - EffectInputInformation attributeA; - attributeA.inputName = "attr A"; - attributeInputs.push_back(attributeA); + uniformInputs.emplace_back("uni A", 10u, EDataType::Bool, EFixedSemantics::CameraWorldPosition); + uniformInputs.emplace_back("uni B", 1u, EDataType::Float, EFixedSemantics::Invalid, UniformBufferBinding{11u}, UniformBufferElementSize{12u}, UniformBufferFieldOffset{13u} ); + + attributeInputs.emplace_back("attr A", 1u, EDataType::ByteBlob, EFixedSemantics::Invalid); } static std::unique_ptr SerializeDeserialize(const EffectResource& effectResource, std::string_view name) @@ -36,7 +30,7 @@ namespace ramses::internal BinaryOutputStream outStream; effectResource.serializeResourceMetadataToStream(outStream); BinaryInputStream inStream(outStream.getData()); - std::unique_ptr resource = EffectResource::CreateResourceFromMetadataStream(inStream, name); + std::unique_ptr resource = EffectResource::CreateResourceFromMetadataStream(inStream, name, EFeatureLevel_Latest); if (!resource) { return nullptr; @@ -46,29 +40,80 @@ namespace ramses::internal return std::unique_ptr(static_cast(resource.release())); } + void checkSpirvShaders(const EffectResource& effectRes, bool withGeometryShader = true) + { + ASSERT_EQ(effectRes.getVertexShaderSPIRVSize(), dummySpirvShaders.m_vertexSPIRVBlob.size() * sizeof(uint32_t)); + ASSERT_EQ(effectRes.getFragmentShaderSPIRVSize(), dummySpirvShaders.m_fragmentSPIRVBlob.size() * sizeof(uint32_t)); + ASSERT_EQ(effectRes.getGeometryShaderSPIRVSize(), withGeometryShader ? dummySpirvShaders.m_geometrySPIRVBlob.size() * sizeof(uint32_t) : 0u); + + // check alignment + EXPECT_EQ(0u, uintptr_t(effectRes.getVertexShaderSPIRV()) % sizeof(uint32_t)); + EXPECT_EQ(0u, uintptr_t(effectRes.getFragmentShaderSPIRV()) % sizeof(uint32_t)); + + // check contents + const SPIRVShaderBlob effectVertexSPIRV(effectRes.getVertexShaderSPIRV(), effectRes.getVertexShaderSPIRV() + effectRes.getVertexShaderSPIRVSize() / sizeof(uint32_t)); + const SPIRVShaderBlob effectFragmentSPIRV(effectRes.getFragmentShaderSPIRV(), effectRes.getFragmentShaderSPIRV() + effectRes.getFragmentShaderSPIRVSize() / sizeof(uint32_t)); + EXPECT_EQ(dummySpirvShaders.m_vertexSPIRVBlob, effectVertexSPIRV); + EXPECT_EQ(dummySpirvShaders.m_fragmentSPIRVBlob, effectFragmentSPIRV); + + if(withGeometryShader) + { + EXPECT_EQ(0u, uintptr_t(effectRes.getGeometryShaderSPIRV()) % sizeof(uint32_t)); + const SPIRVShaderBlob effectGeometrySPIRV(effectRes.getGeometryShaderSPIRV(), effectRes.getGeometryShaderSPIRV() + effectRes.getGeometryShaderSPIRVSize() / sizeof(uint32_t)); + EXPECT_EQ(dummySpirvShaders.m_geometrySPIRVBlob, effectGeometrySPIRV); + } + } + EffectInputInformationVector uniformInputs; EffectInputInformationVector attributeInputs; + SPIRVShaders dummySpirvShaders{ + SPIRVShaderBlob{ 1u, 2u, 3u, 4u }, + SPIRVShaderBlob{ 5u, 6u, 7u, 8u, 9u }, + SPIRVShaderBlob{ 10u, 11u, 12u} }; }; TEST_F(AEffectResource, canBeCreatedWithName) { - EffectResource effect("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), "myname"); + EffectResource effect("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "myname", EFeatureLevel_Latest); EXPECT_EQ(std::string{"myname"}, effect.getName()); EXPECT_FALSE(effect.getGeometryShaderInputType().has_value()); } TEST_F(AEffectResource, canBeCreatedWithShaders) { - EffectResource effect("verttext", "fragtext", "geomtext", EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource effect("verttext", "fragtext", "geomtext", {}, EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); EXPECT_STREQ("verttext", effect.getVertexShader()); EXPECT_STREQ("fragtext", effect.getFragmentShader()); EXPECT_STREQ("geomtext", effect.getGeometryShader()); EXPECT_EQ(EDrawMode::Lines, effect.getGeometryShaderInputType()); } + TEST_F(AEffectResource, canBeCreatedWithSPIRVShaders) + { + EffectResource effect("verttext", "fragtext", "geomtext", dummySpirvShaders, EDrawMode::Lines, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); + EXPECT_STREQ("verttext", effect.getVertexShader()); + EXPECT_STREQ("fragtext", effect.getFragmentShader()); + EXPECT_STREQ("geomtext", effect.getGeometryShader()); + EXPECT_EQ(EDrawMode::Lines, effect.getGeometryShaderInputType()); + + checkSpirvShaders(effect); + } + + TEST_F(AEffectResource, canBeCreatedWithoutGeometryWithSPIRVShaders) + { + SPIRVShaders dummySpirvWithGeom{ dummySpirvShaders.m_vertexSPIRVBlob, dummySpirvShaders.m_fragmentSPIRVBlob, SPIRVShaderBlob{} }; + EffectResource effect("verttext", "fragtext", "", dummySpirvWithGeom, std::nullopt, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); + EXPECT_STREQ("verttext", effect.getVertexShader()); + EXPECT_STREQ("fragtext", effect.getFragmentShader()); + EXPECT_STREQ("", effect.getGeometryShader()); + EXPECT_FALSE(effect.getGeometryShaderInputType().has_value()); + + checkSpirvShaders(effect, false); + } + TEST_F(AEffectResource, canBeCreatedWithInputs) { - EffectResource effect("", "", "", {}, uniformInputs, attributeInputs, ""); + EffectResource effect("", "", "", {}, {}, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); EXPECT_EQ(uniformInputs, effect.getUniformInputs()); EXPECT_EQ(attributeInputs, effect.getAttributeInputs()); EXPECT_FALSE(effect.getGeometryShaderInputType().has_value()); @@ -76,7 +121,7 @@ namespace ramses::internal TEST_F(AEffectResource, canGetInputsByName) { - EffectResource effect("", "", "", {}, uniformInputs, attributeInputs, ""); + EffectResource effect("", "", "", {}, {}, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); EXPECT_EQ(DataFieldHandle(1), effect.getUniformDataFieldHandleByName("uni B")); EXPECT_EQ(DataFieldHandle::Invalid(), effect.getUniformDataFieldHandleByName("does not exist")); @@ -87,50 +132,77 @@ namespace ramses::internal TEST_F(AEffectResource, sameParametersGiveSameHash) { - EffectResource effect1("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); - EffectResource effect2("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); + EffectResource effect1("asd", "def", "xyz", dummySpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "xyz", dummySpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); EXPECT_EQ(effect1.getHash(), effect2.getHash()); } TEST_F(AEffectResource, differentVertexShaderResultsInDifferentHash) { - EffectResource effect1("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); - EffectResource effect2("XXX", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); + EffectResource effect1("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("XXX", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); EXPECT_NE(effect1.getHash(), effect2.getHash()); } TEST_F(AEffectResource, differentFragmentShaderResultsInDifferentHash) { - EffectResource effect1("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); - EffectResource effect2("asd", "XXX", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); + EffectResource effect1("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "XXX", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); EXPECT_NE(effect1.getHash(), effect2.getHash()); } TEST_F(AEffectResource, differentGeometryShaderResultsInDifferentHash) { - EffectResource effect1("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); - EffectResource effect2("asd", "def", "XXX", EDrawMode::Lines, uniformInputs, attributeInputs, ""); + EffectResource effect1("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "XXX", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); EXPECT_NE(effect1.getHash(), effect2.getHash()); } TEST_F(AEffectResource, differentUniformInputResultsInDifferentHash) { - EffectResource effect1("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); - EffectResource effect2("asd", "def", "xyz", EDrawMode::Lines, EffectInputInformationVector(), attributeInputs, ""); + EffectResource effect1("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "xyz", {}, EDrawMode::Lines, EffectInputInformationVector(), attributeInputs, "", EFeatureLevel_Latest); EXPECT_NE(effect1.getHash(), effect2.getHash()); } TEST_F(AEffectResource, differentAttributeInputResultsInDifferentHash) { - EffectResource effect1("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); - EffectResource effect2("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, EffectInputInformationVector(), ""); + EffectResource effect1("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, EffectInputInformationVector(), "", EFeatureLevel_Latest); + EXPECT_NE(effect1.getHash(), effect2.getHash()); + } + + TEST_F(AEffectResource, differentVertexShaderSPIRVResultsInDifferentHash) + { + SPIRVShaders otherSpirvShaders = dummySpirvShaders; + otherSpirvShaders.m_vertexSPIRVBlob = SPIRVShaderBlob(9u, 9u); + EffectResource effect1("asd", "def", "xyz", dummySpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "xyz", otherSpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EXPECT_NE(effect1.getHash(), effect2.getHash()); + } + + TEST_F(AEffectResource, differentFragmentShaderSPIRVResultsInDifferentHash) + { + SPIRVShaders otherSpirvShaders = dummySpirvShaders; + otherSpirvShaders.m_fragmentSPIRVBlob = SPIRVShaderBlob(9u, 9u); + EffectResource effect1("asd", "def", "xyz", dummySpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "xyz", otherSpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EXPECT_NE(effect1.getHash(), effect2.getHash()); + } + + TEST_F(AEffectResource, differentGeometryShaderSPIRVResultsInDifferentHash) + { + SPIRVShaders otherSpirvShaders = dummySpirvShaders; + otherSpirvShaders.m_geometrySPIRVBlob = SPIRVShaderBlob(9u, 9u); + EffectResource effect1("asd", "def", "xyz", dummySpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "xyz", otherSpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); EXPECT_NE(effect1.getHash(), effect2.getHash()); } TEST_F(AEffectResource, differentNameDoesNotChangeHash) { - EffectResource effect1("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, "some name"); - EffectResource effect2("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, "different name"); + EffectResource effect1("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "some name", EFeatureLevel_Latest); + EffectResource effect2("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "different name", EFeatureLevel_Latest); EXPECT_EQ(effect1.getHash(), effect2.getHash()); } @@ -138,7 +210,7 @@ namespace ramses::internal TEST_F(AEffectResource, hasCorrectTypeAfterSerializeAndDeserialize) { - EffectResource effectBefore("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); + EffectResource effectBefore("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); std::unique_ptr effectAfter(SerializeDeserialize(effectBefore, "")); ASSERT_TRUE(effectAfter); @@ -147,7 +219,7 @@ namespace ramses::internal TEST_F(AEffectResource, isEqualAfterSerializeAndDeserialize) { - EffectResource effectBefore("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, ""); + EffectResource effectBefore("asd", "def", "xyz", dummySpirvShaders, EDrawMode::Lines, uniformInputs, attributeInputs, "", EFeatureLevel_Latest); std::unique_ptr effectAfter(SerializeDeserialize(effectBefore, "")); ASSERT_TRUE(effectAfter); @@ -158,11 +230,13 @@ namespace ramses::internal EXPECT_EQ(effectBefore.getGeometryShaderInputType(), effectAfter->getGeometryShaderInputType()); EXPECT_EQ(effectBefore.getUniformInputs(), effectAfter->getUniformInputs()); EXPECT_EQ(effectBefore.getAttributeInputs(), effectAfter->getAttributeInputs()); + + checkSpirvShaders(*effectAfter); } - TEST_F(AEffectResource, isEqualAfterSerializeAndDeserializeNoGeometryShader) + TEST_F(AEffectResource, isEqualAfterSerializeAndDeserializeNoGeometryShaderOrSPIRV) { - EffectResource effectBefore("asd", "def", {}, {}, uniformInputs, attributeInputs, {}); + EffectResource effectBefore("asd", "def", "", {}, {}, uniformInputs, attributeInputs, {}, EFeatureLevel_Latest); std::unique_ptr effectAfter(SerializeDeserialize(effectBefore, "")); ASSERT_TRUE(effectAfter); @@ -177,7 +251,7 @@ namespace ramses::internal TEST_F(AEffectResource, hasNameProvidedToSerializeAfterSerializeAndDeserialize) { - EffectResource effectBefore("asd", "def", "xyz", EDrawMode::Lines, uniformInputs, attributeInputs, "some name"); + EffectResource effectBefore("asd", "def", "xyz", {}, EDrawMode::Lines, uniformInputs, attributeInputs, "some name", EFeatureLevel_Latest); std::unique_ptr effectAfter(SerializeDeserialize(effectBefore, "different name")); ASSERT_TRUE(effectAfter); diff --git a/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.cpp b/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.cpp index 895d1f283..d456bbe17 100644 --- a/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.cpp @@ -11,8 +11,10 @@ namespace ramses::internal { - ActionTestScene::ActionTestScene(const SceneInfo& sceneInfo) - : m_scene(sceneInfo) + ActionTestScene::ActionTestScene(const SceneInfo& sceneInfo, EFeatureLevel featureLevel) + : m_scene{ sceneInfo } + , m_actionCollector{ sceneInfo, featureLevel } + , m_featureLevel{ featureLevel } { } @@ -26,6 +28,21 @@ namespace ramses::internal return m_scene.getSceneId(); } + ERenderBackendCompatibility ActionTestScene::getRenderBackendCompatibility() const + { + return m_scene.getRenderBackendCompatibility(); + } + + EVulkanAPIVersion ActionTestScene::getVulkanAPIVersion() const + { + return m_scene.getVulkanAPIVersion(); + } + + ESPIRVVersion ActionTestScene::getSPIRVVersion() const + { + return m_scene.getSPIRVVersion(); + } + void ActionTestScene::setEffectTimeSync(FlushTime::Clock::time_point /*t*/) { // not set by a scene action @@ -471,6 +488,11 @@ namespace ramses::internal return m_scene.getDataReference(containerHandle, field); } + UniformBufferHandle ActionTestScene::getDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle field) const + { + return m_scene.getDataUniformBuffer(containerHandle, field); + } + float ActionTestScene::getDataSingleFloat(DataInstanceHandle containerHandle, DataFieldHandle field) const { return m_scene.getDataSingleFloat(containerHandle, field); @@ -621,6 +643,12 @@ namespace ramses::internal flushPendingSceneActions(); } + void ActionTestScene::setDataUniformBuffer(DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) + { + m_actionCollector.setDataUniformBuffer(containerHandle, field, uniformBufferHandle); + flushPendingSceneActions(); + } + void ActionTestScene::setDataSingleFloat(DataInstanceHandle containerHandle, DataFieldHandle field, float data) { m_actionCollector.setDataSingleFloat(containerHandle, field, data); @@ -904,6 +932,40 @@ namespace ramses::internal return m_scene.getDataBuffer(handle); } + UniformBufferHandle ActionTestScene::allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) + { + const auto actualHandle = m_actionCollector.allocateUniformBuffer(size, handle); + flushPendingSceneActions(); + return actualHandle; + } + + void ActionTestScene::releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) + { + m_actionCollector.releaseUniformBuffer(uniformBufferHandle); + flushPendingSceneActions(); + } + + void ActionTestScene::updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) + { + m_actionCollector.updateUniformBuffer(uniformBufferHandle, offset, size, data); + flushPendingSceneActions(); + } + + bool ActionTestScene::isUniformBufferAllocated(UniformBufferHandle uniformBufferHandle) const + { + return m_scene.isUniformBufferAllocated(uniformBufferHandle); + } + + uint32_t ActionTestScene::getUniformBufferCount() const + { + return m_scene.getUniformBufferCount(); + } + + const UniformBuffer& ActionTestScene::getUniformBuffer(UniformBufferHandle uniformBufferHandle) const + { + return m_scene.getUniformBuffer(uniformBufferHandle); + } + TextureBufferHandle ActionTestScene::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) { const TextureBufferHandle actualHandle = m_actionCollector.allocateTextureBuffer(textureFormat, mipMapDimensions, handle); @@ -1188,7 +1250,7 @@ namespace ramses::internal void ActionTestScene::flushPendingSceneActions() { SceneActionCollection& actionCollection = m_actionCollector.getSceneActionCollection(); - SceneActionApplier::ApplyActionsOnScene(const_cast(m_scene), actionCollection); + SceneActionApplier::ApplyActionsOnScene(const_cast(m_scene), actionCollection, m_featureLevel); m_actionCollector.getSceneActionCollection().clear(); } diff --git a/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.h b/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.h index 2293cf4ab..5ce9c7a1a 100644 --- a/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.h +++ b/tests/unittests/framework/SceneGraph/Scene/ActionTestScene.h @@ -22,10 +22,13 @@ namespace ramses::internal class ActionTestScene : public IScene { public: - explicit ActionTestScene(const SceneInfo& sceneInfo = SceneInfo()); + explicit ActionTestScene(const SceneInfo& sceneInfo = SceneInfo(), EFeatureLevel featureLevel = EFeatureLevel_Latest); [[nodiscard]] const std::string& getName () const override; [[nodiscard]] SceneId getSceneId () const override; + [[nodiscard]] ERenderBackendCompatibility getRenderBackendCompatibility () const override; + [[nodiscard]] EVulkanAPIVersion getVulkanAPIVersion () const override; + [[nodiscard]] ESPIRVVersion getSPIRVVersion () const override; void setEffectTimeSync(FlushTime::Clock::time_point t) override; [[nodiscard]] FlushTime::Clock::time_point getEffectTimeSync() const override; @@ -42,7 +45,7 @@ namespace ramses::internal void setRenderableVisibility (RenderableHandle renderableHandle, EVisibilityMode visible) override; void setRenderableInstanceCount (RenderableHandle renderableHandle, uint32_t instanceCount) override; void setRenderableStartVertex (RenderableHandle renderableHandle, uint32_t startVertex) override; - [[nodiscard]] const Renderable& getRenderable (RenderableHandle renderableHandle) const override; + [[nodiscard]] const Renderable& getRenderable (RenderableHandle renderableHandle) const override; // Render state RenderStateHandle allocateRenderState (RenderStateHandle stateHandle) override; @@ -125,6 +128,7 @@ namespace ramses::internal [[nodiscard]] const ResourceField& getDataResource (DataInstanceHandle containerHandle, DataFieldHandle field) const override; [[nodiscard]] TextureSamplerHandle getDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field) const override; [[nodiscard]] DataInstanceHandle getDataReference (DataInstanceHandle containerHandle, DataFieldHandle field) const override; + [[nodiscard]] UniformBufferHandle getDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field) const override; void setDataFloatArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const float* data) override; void setDataVector2fArray (DataInstanceHandle containerHandle, DataFieldHandle field, uint32_t elementCount, const glm::vec2* data) override; @@ -141,6 +145,7 @@ namespace ramses::internal void setDataResource (DataInstanceHandle containerHandle, DataFieldHandle field, const ResourceContentHash& hash, DataBufferHandle dataBuffer, uint32_t instancingDivisor, uint16_t offsetWithinElementInBytes, uint16_t stride) override; void setDataTextureSamplerHandle (DataInstanceHandle containerHandle, DataFieldHandle field, TextureSamplerHandle samplerHandle) override; void setDataReference (DataInstanceHandle containerHandle, DataFieldHandle field, DataInstanceHandle dataRef) override; + void setDataUniformBuffer (DataInstanceHandle containerHandle, DataFieldHandle field, UniformBufferHandle uniformBufferHandle) override; // get/setData*Array wrappers for elementCount == 1 [[nodiscard]] float getDataSingleFloat (DataInstanceHandle containerHandle, DataFieldHandle field) const override; @@ -249,6 +254,14 @@ namespace ramses::internal [[nodiscard]] bool isDataBufferAllocated (DataBufferHandle handle) const override; [[nodiscard]] const GeometryDataBuffer& getDataBuffer (DataBufferHandle handle) const override; + // Uniform buffers + UniformBufferHandle allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) override; + void releaseUniformBuffer(UniformBufferHandle uniformBufferHandle) override; + void updateUniformBuffer(UniformBufferHandle uniformBufferHandle, uint32_t offset, uint32_t size, const std::byte* data) override; + [[nodiscard]] bool isUniformBufferAllocated(UniformBufferHandle uniformBufferHandle) const override; + [[nodiscard]] uint32_t getUniformBufferCount() const override; + [[nodiscard]] const UniformBuffer& getUniformBuffer(UniformBufferHandle uniformBufferHandle) const override; + //Texture buffers TextureBufferHandle allocateTextureBuffer (EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle) override; void releaseTextureBuffer (TextureBufferHandle handle) override; @@ -283,6 +296,8 @@ namespace ramses::internal const Scene m_scene; // Converts IScene calls to actions, collects them and applies to m_actionApplier, which applies them on m_scene ActionCollectingScene m_actionCollector; + + EFeatureLevel m_featureLevel = EFeatureLevel_Latest; }; } diff --git a/tests/unittests/framework/SceneGraph/Scene/AllocationHelper.cpp b/tests/unittests/framework/SceneGraph/Scene/AllocationHelper.cpp new file mode 100644 index 000000000..9f8ee13aa --- /dev/null +++ b/tests/unittests/framework/SceneGraph/Scene/AllocationHelper.cpp @@ -0,0 +1,155 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "AllocationHelper.h" +#include "internal/Core/Utils/LogMacros.h" +#include "internal/SceneGraph/SceneAPI/DataFieldInfo.h" +#include "internal/SceneGraph/SceneAPI/EDataType.h" +#include "internal/SceneGraph/SceneAPI/EFixedSemantics.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/SceneGraph/SceneAPI/MipMapSize.h" +#include "internal/SceneGraph/SceneAPI/RenderBuffer.h" +#include "internal/SceneGraph/SceneAPI/SceneId.h" +#include "internal/SceneGraph/SceneAPI/SceneSizeInformation.h" +#include "internal/SceneGraph/SceneAPI/TextureSampler.h" + +namespace ramses::internal +{ + const DataFieldInfoVector AllocationHelper::DATA_FIELD_INFOS{ + DataFieldInfo{EDataType::Vector2F, 1}}; + const TextureSampler AllocationHelper::TEXTURE_SAMPLER{{}, TEXTURE_HASH}; + const RenderBuffer AllocationHelper::RENDER_BUFFER{}; + const MipMapDimensions AllocationHelper::MIP_MAP_DIMENSIONS{}; + + const SceneSizeInformation AllocationHelper::SCENE_SIZE_INFO{ + 42u, //nodes, + 42u, //cameras, + 42u, //transforms, + 42u, //renderables, + 42u, //states, + 42u, //datalayouts, + 42u, //datainstances, + 42u, //uniformBuffers, + 42u, //renderGroups, + 42u, //renderPasses, + 42u, //blitPasses, + 42u, //renderTargets, + 42u, //renderBuffers, + 42u, //textureSamplers, + 42u, //dataSlots, + 42u, //dataBuffers, + 42u, //textureBuffers, + 42u, //pickableObjects, + 42u, //sceneReferences + }; + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateRenderable(NODE_HANDLE, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateRenderState(handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateCamera(CAMERA_TYPE, NODE_HANDLE, DATA_INSTANCE_HANDLE, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateNode(CHILDREN_COUNT, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateTransform(NODE_HANDLE, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateDataLayout(DATA_FIELD_INFOS, EFFECT_HASH, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateDataInstance(DATA_LAYOUT_HANDLE, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateUniformBuffer(UNIFORM_BUFFER_SIZE, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateTextureSampler(TEXTURE_SAMPLER, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateRenderGroup(RENDERABLE_COUNT, NESTED_GROUP_COUNT, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateRenderPass(RENDERABLE_COUNT, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateBlitPass(SOURCE_RENDER_BUFFER_HANDLE, DESTINATION_RENDER_BUFFER_HANDLE, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocatePickableObject(GEOMETRY_HANDLE, NODE_HANDLE, PICKABLE_OBJECT_ID, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateRenderTarget(handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateRenderBuffer(RENDER_BUFFER, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateDataBuffer(DATA_BUFFER_TYPE, DATA_TYPE,MAX_SIZE, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateTextureBuffer(TEXTURE_FORMAT, MIP_MAP_DIMENSIONS, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateDataSlot(DATA_SLOT, handle); + } + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle) + { + return scene.allocateSceneReference(SCENE_ID, handle); + } + + template <> void AllocationHelper::setupPrerequisits(IScene& scene) + { + scene.allocateNode(0u, AllocationHelper::NODE_HANDLE); + } + + template <> void AllocationHelper::setupPrerequisits(IScene& scene) + { + scene.allocateDataLayout(AllocationHelper::DATA_FIELD_INFOS, AllocationHelper::EFFECT_HASH, AllocationHelper::DATA_LAYOUT_HANDLE); + } +} diff --git a/tests/unittests/framework/SceneGraph/Scene/AllocationHelper.h b/tests/unittests/framework/SceneGraph/Scene/AllocationHelper.h new file mode 100644 index 000000000..9c87402fa --- /dev/null +++ b/tests/unittests/framework/SceneGraph/Scene/AllocationHelper.h @@ -0,0 +1,101 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + + +#include "internal/Core/Common/TypedMemoryHandle.h" +#include "internal/SceneGraph/SceneAPI/DataFieldInfo.h" +#include "internal/SceneGraph/SceneAPI/DataSlot.h" +#include "internal/SceneGraph/SceneAPI/ECameraProjectionType.h" +#include "internal/SceneGraph/SceneAPI/EDataBufferType.h" +#include "internal/SceneGraph/SceneAPI/EDataSlotType.h" +#include "internal/SceneGraph/SceneAPI/EDataType.h" +#include "internal/SceneGraph/SceneAPI/GeometryDataBuffer.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/SceneGraph/SceneAPI/RenderBuffer.h" +#include "internal/SceneGraph/SceneAPI/RenderState.h" +#include "internal/SceneGraph/SceneAPI/SceneSizeInformation.h" +#include "internal/SceneGraph/SceneAPI/SceneTypes.h" +#include "internal/SceneGraph/SceneAPI/TextureSampler.h" +#include "gtest/gtest.h" +#include +#include +#include "ActionTestScene.h" +#include "ramses/framework/TextureEnums.h" + + +namespace ramses::internal +{ + class AllocationHelper + { + public: + static constexpr NodeHandle NODE_HANDLE{12u}; + static constexpr ECameraProjectionType CAMERA_TYPE{ECameraProjectionType::Perspective}; + static constexpr DataInstanceHandle DATA_INSTANCE_HANDLE{321u}; + static constexpr uint32_t CHILDREN_COUNT{0u}; + static constexpr ResourceContentHash EFFECT_HASH{876u, 543u}; + static constexpr ResourceContentHash TEXTURE_HASH{9876u, 543u}; + static constexpr DataLayoutHandle DATA_LAYOUT_HANDLE{3u}; + static const DataFieldInfoVector DATA_FIELD_INFOS; + static constexpr EDataBufferType DATA_BUFFER_TYPE{EDataBufferType::IndexBuffer}; + static constexpr EDataType DATA_TYPE{EDataType::Vector3F}; + static constexpr uint32_t MAX_SIZE{12u}; + static const TextureSampler TEXTURE_SAMPLER; + static constexpr EPixelStorageFormat TEXTURE_FORMAT{EPixelStorageFormat::RGBA8}; + static const MipMapDimensions MIP_MAP_DIMENSIONS; + static constexpr uint32_t RENDERABLE_COUNT{7u}; + static constexpr uint32_t NESTED_GROUP_COUNT{0u}; + static constexpr RenderBufferHandle SOURCE_RENDER_BUFFER_HANDLE{234u}; + static constexpr RenderBufferHandle DESTINATION_RENDER_BUFFER_HANDLE{345u}; + static constexpr DataBufferHandle GEOMETRY_HANDLE{96u}; + static constexpr PickableObjectId PICKABLE_OBJECT_ID{66}; + static const RenderBuffer RENDER_BUFFER; + static constexpr SceneId SCENE_ID{12345}; + static constexpr DataSlot DATA_SLOT{EDataSlotType::DataConsumer, {}, {}, {}, {}, {}}; + static constexpr uint32_t UNIFORM_BUFFER_SIZE{12u}; + + static const SceneSizeInformation SCENE_SIZE_INFO; + + template + static TypedMemoryHandle allocate([[maybe_unused]] IScene& scene, [[maybe_unused]] TypedMemoryHandle handle) + { + assert(false); + return TypedMemoryHandle::Invalid(); + } + + template + static void setupPrerequisits([[maybe_unused]] IScene& scene) + { + // nothing to do for most types + } + }; + + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + template <> TypedMemoryHandle AllocationHelper::allocate(IScene& scene, TypedMemoryHandle handle); + + template <> void AllocationHelper::setupPrerequisits(IScene& scene); + template <> void AllocationHelper::setupPrerequisits(IScene& scene); +} diff --git a/tests/unittests/framework/SceneGraph/Scene/DataLayoutCachedSceneTest.cpp b/tests/unittests/framework/SceneGraph/Scene/DataLayoutCachedSceneTest.cpp index e6ebb9afa..7ec3b4331 100644 --- a/tests/unittests/framework/SceneGraph/Scene/DataLayoutCachedSceneTest.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/DataLayoutCachedSceneTest.cpp @@ -17,7 +17,7 @@ namespace ramses::internal { public: ADataLayoutCachedScene() - : scene(SceneInfo()) + : scene(SceneInfo(), EFeatureLevel_Latest) { } diff --git a/tests/unittests/framework/SceneGraph/Scene/MergeSceneTest.cpp b/tests/unittests/framework/SceneGraph/Scene/MergeSceneTest.cpp new file mode 100644 index 000000000..7a35b2e4d --- /dev/null +++ b/tests/unittests/framework/SceneGraph/Scene/MergeSceneTest.cpp @@ -0,0 +1,140 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "AllocationHelper.h" +#include "internal/SceneGraph/Scene/DataLayoutCachedScene.h" +#include "internal/SceneGraph/Scene/MergeScene.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" +#include "internal/SceneGraph/SceneAPI/DataFieldInfo.h" +#include "internal/SceneGraph/SceneAPI/EDataType.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "TestingScene.h" +#include "internal/SceneGraph/SceneAPI/ResourceContentHash.h" +#include "ramses/framework/EFeatureLevel.h" + +using namespace testing; + +namespace ramses::internal +{ + template + class AMergeSceneTest : public ::testing::Test + { + public: + void setupPrerequisits(MergeScene& scene) + { + AllocationHelper::setupPrerequisits(scene); + } + + ActionCollectingScene createOriginalScene() + { + return ActionCollectingScene(); + } + }; + + using HandleTypes = ::testing::Types< + RenderableHandle, + RenderStateHandle, + CameraHandle, + NodeHandle, + TransformHandle, + DataLayoutHandle, + DataInstanceHandle, + UniformBufferHandle, + TextureSamplerHandle, + RenderGroupHandle, + RenderPassHandle, + BlitPassHandle, + PickableObjectHandle, + RenderTargetHandle, + RenderBufferHandle, + DataBufferHandle, + TextureBufferHandle, + DataSlotHandle, + SceneReferenceHandle>; + + TYPED_TEST_SUITE(AMergeSceneTest, HandleTypes); + + + TYPED_TEST(AMergeSceneTest, canAllocateAndBuildMapping) + { + auto originalScene = this->createOriginalScene(); + originalScene.preallocateSceneSize(AllocationHelper::SCENE_SIZE_INFO); + SceneMergeHandleMapping mapping; + MergeScene scene(originalScene, mapping); + this->setupPrerequisits(scene); + + const TypeParam handle{3u}; + const TypeParam expectedHandle = handle + 42u; + const auto handleAllocated = AllocationHelper::allocate(scene, handle); + EXPECT_EQ(expectedHandle, handleAllocated); + + EXPECT_TRUE(mapping.hasMapping(handle)); + const auto handleMapped = mapping.getMapping(handle); + EXPECT_EQ(expectedHandle, handleMapped); + } + + class MergeSceneTest : public ::testing::Test + { + }; + + TEST_F(MergeSceneTest, canMergeScenes) + { + DataLayoutCachedScene originalScene; + SceneMergeHandleMapping mapping; + + TestingScene testingScene(originalScene, EFeatureLevel_Latest); + testingScene.VerifyContent(originalScene); + + MergeScene scene(originalScene, mapping); + TestingScene testingSceneMerged(scene, EFeatureLevel_Latest); + + // verify original content + testingSceneMerged.VerifyContent(originalScene); + + // verify merged content using mapping + testingSceneMerged.setMapping(&mapping); + testingSceneMerged.VerifyContent(scene); + } + + TEST_F(MergeSceneTest, canAllocateSameDataLayoutMultipleTimes) + { + DataLayoutCachedScene originalScene; + SceneMergeHandleMapping mapping; + ResourceContentHash effectHash {7, 12}; + + DataFieldInfoVector dataFields; + dataFields.emplace_back(DataFieldInfo(EDataType::Vector3F)); + + const DataLayoutHandle originalHandle {0u}; + auto handle1 = originalScene.allocateDataLayout(dataFields, effectHash, originalHandle); + ASSERT_EQ(originalHandle, handle1); + + MergeScene scene(originalScene, mapping); + + auto handle2 = scene.allocateDataLayout(dataFields, effectHash, originalHandle); + + EXPECT_EQ(originalHandle, handle2); + + // SceneDescriber will create allocateDataLayout actions for each reference to the same data layout + auto handle3 = scene.allocateDataLayout(dataFields, effectHash, originalHandle); + + EXPECT_EQ(originalHandle, handle3); + + // now also test for previously unused handle + const DataLayoutHandle newHandle {1u}; + auto handle4 = scene.allocateDataLayout(dataFields, effectHash, newHandle); + + EXPECT_EQ(originalHandle, handle4); + + auto handle5 = scene.allocateDataLayout(dataFields, effectHash, newHandle); + + EXPECT_EQ(originalHandle, handle5); + } +} diff --git a/tests/unittests/framework/SceneGraph/Scene/ResourceChangeCollectingSceneTest.cpp b/tests/unittests/framework/SceneGraph/Scene/ResourceChangeCollectingSceneTest.cpp index c0d04d626..0d9cb2904 100644 --- a/tests/unittests/framework/SceneGraph/Scene/ResourceChangeCollectingSceneTest.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/ResourceChangeCollectingSceneTest.cpp @@ -285,6 +285,61 @@ namespace ramses::internal EXPECT_EQ(0u, sceneResourceActions.size()); } + TEST_F(AResourceChangeCollectingScene, createdUniformBufferIsTracked) + { + const auto handle = scene.allocateUniformBuffer(10u, {}); + ASSERT_EQ(1u, sceneResourceActions.size()); + EXPECT_EQ(handle, sceneResourceActions[0].handle); + EXPECT_EQ(ESceneResourceAction_CreateUniformBuffer, sceneResourceActions[0].action); + + scene.resetResourceChanges(); + EXPECT_EQ(0u, sceneResourceActions.size()); + } + + TEST_F(AResourceChangeCollectingScene, createdAndUpdatedUniformBufferIsTrackedAndSameAsExtractedFromScene) + { + const auto handle = scene.allocateUniformBuffer(10u, {}); + scene.updateUniformBuffer(handle, 0, 0, nullptr); + ASSERT_EQ(2u, sceneResourceActions.size()); + EXPECT_EQ(handle, sceneResourceActions[0].handle); + EXPECT_EQ(ESceneResourceAction_CreateUniformBuffer, sceneResourceActions[0].action); + EXPECT_EQ(handle, sceneResourceActions[1].handle); + EXPECT_EQ(ESceneResourceAction_UpdateUniformBuffer, sceneResourceActions[1].action); + expectSameSceneResourceChangesWhenExtractedFromScene(10u); + + scene.resetResourceChanges(); + EXPECT_EQ(0u, sceneResourceActions.size()); + } + + TEST_F(AResourceChangeCollectingScene, destroyedUniformBufferIsTracked) + { + const auto handle = scene.allocateUniformBuffer(10u, {}); + scene.resetResourceChanges(); + + scene.releaseUniformBuffer(handle); + ASSERT_EQ(1u, sceneResourceActions.size()); + EXPECT_EQ(handle, sceneResourceActions[0].handle); + EXPECT_EQ(ESceneResourceAction_DestroyUniformBuffer, sceneResourceActions[0].action); + + scene.resetResourceChanges(); + EXPECT_EQ(0u, sceneResourceActions.size()); + } + + TEST_F(AResourceChangeCollectingScene, updatedUniformBufferIsTracked) + { + const auto handle = scene.allocateUniformBuffer(10u, {}); + scene.resetResourceChanges(); + + const std::byte dummyData[2] = { std::byte{0} }; + scene.updateUniformBuffer(handle, 2u, 2u, dummyData); + ASSERT_EQ(1u, sceneResourceActions.size()); + EXPECT_EQ(handle, sceneResourceActions[0].handle); + EXPECT_EQ(ESceneResourceAction_UpdateUniformBuffer, sceneResourceActions[0].action); + + scene.resetResourceChanges(); + EXPECT_EQ(0u, sceneResourceActions.size()); + } + TEST_F(AResourceChangeCollectingScene, hasClientResourcesNotDirtyOnCreation) { EXPECT_FALSE(scene.haveResourcesChanged()); diff --git a/tests/unittests/framework/SceneGraph/Scene/ResourceUtilsTest.cpp b/tests/unittests/framework/SceneGraph/Scene/ResourceUtilsTest.cpp index 23bec39ee..8dd1579bc 100644 --- a/tests/unittests/framework/SceneGraph/Scene/ResourceUtilsTest.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/ResourceUtilsTest.cpp @@ -27,7 +27,7 @@ namespace ramses::internal // preallocate mempools for scene with explicit mempools SceneSizeInformation sizeInfo{ MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, - MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed }; + MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed, MaxHandlesUsed }; scene.preallocateSceneSize(sizeInfo); } diff --git a/tests/unittests/framework/SceneGraph/Scene/SceneActionCollectionCreatorAndApplierTest.cpp b/tests/unittests/framework/SceneGraph/Scene/SceneActionCollectionCreatorAndApplierTest.cpp index 3575099ec..8a1d31223 100644 --- a/tests/unittests/framework/SceneGraph/Scene/SceneActionCollectionCreatorAndApplierTest.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/SceneActionCollectionCreatorAndApplierTest.cpp @@ -18,7 +18,7 @@ namespace ramses::internal { public: ASceneActionCollectionCreatorAndApplier() - : creator(collection) + : creator(collection, EFeatureLevel_Latest) { } diff --git a/tests/unittests/framework/SceneGraph/Scene/SceneActionHelperAndApplierTest.cpp b/tests/unittests/framework/SceneGraph/Scene/SceneActionHelperAndApplierTest.cpp index 826763335..d08e841cb 100644 --- a/tests/unittests/framework/SceneGraph/Scene/SceneActionHelperAndApplierTest.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/SceneActionHelperAndApplierTest.cpp @@ -52,7 +52,7 @@ namespace ramses::internal { public: ASceneActionCreatorAndApplier() - : creator(collection) + : creator(collection, EFeatureLevel_Latest) {} StrictMock scene; @@ -84,7 +84,8 @@ namespace ramses::internal + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(DataInstanceHandle) - + sizeof(DataInstanceHandle)); + + sizeof(DataInstanceHandle) + ); creator.compoundRenderable(renderableHandle, renderable); @@ -100,7 +101,7 @@ namespace ramses::internal EXPECT_CALL(scene, setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Geometry, renderable.dataInstances[ERenderableDataSlotType_Geometry])); EXPECT_CALL(scene, setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Uniforms, renderable.dataInstances[ERenderableDataSlotType_Uniforms])); - SceneActionApplier::ApplyActionsOnScene(scene, collection); + SceneActionApplier::ApplyActionsOnScene(scene, collection, EFeatureLevel_Latest); } @@ -127,13 +128,14 @@ namespace ramses::internal + sizeof(uint32_t) + sizeof(uint32_t) + sizeof(DataInstanceHandle) - + sizeof(DataInstanceHandle)); + + sizeof(DataInstanceHandle) + ); creator.compoundRenderable(renderableHandle, renderable); ASSERT_EQ(sizeOfActionData, collection.collectionData().size()); - // default values will not be serialized + // default values will not be applied EXPECT_CALL(scene, allocateRenderable(renderable.node, renderableHandle)).WillOnce(Return(renderableHandle)); EXPECT_CALL(scene, setRenderableStartIndex(renderableHandle, _)).Times(0); EXPECT_CALL(scene, setRenderableIndexCount(renderableHandle, renderable.indexCount)); @@ -144,7 +146,7 @@ namespace ramses::internal EXPECT_CALL(scene, setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Geometry, renderable.dataInstances[ERenderableDataSlotType_Geometry])); EXPECT_CALL(scene, setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Uniforms, renderable.dataInstances[ERenderableDataSlotType_Uniforms])); - SceneActionApplier::ApplyActionsOnScene(scene, collection); + SceneActionApplier::ApplyActionsOnScene(scene, collection, EFeatureLevel_Latest); } TEST_F(ASceneActionCreatorAndApplier, CanSerializeCompoundRenderableEffectDataWithDefaultValues) @@ -164,7 +166,7 @@ namespace ramses::internal EXPECT_CALL(scene, setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformInstanceHandle)); EXPECT_CALL(scene, setRenderableRenderState(renderable, stateHandle)); - SceneActionApplier::ApplyActionsOnScene(scene, collection); + SceneActionApplier::ApplyActionsOnScene(scene, collection, EFeatureLevel_Latest); } TEST_F(ASceneActionCreatorAndApplier, CanSerializeCompoundState) @@ -210,6 +212,6 @@ namespace ramses::internal EXPECT_CALL(scene, setRenderStateStencilOps(state, rs.stencilOpFail, rs.stencilOpDepthFail, rs.stencilOpDepthPass)); EXPECT_CALL(scene, setRenderStateColorWriteMask(state, rs.colorWriteMask)); - SceneActionApplier::ApplyActionsOnScene(scene, collection); + SceneActionApplier::ApplyActionsOnScene(scene, collection, EFeatureLevel_Latest); } } diff --git a/tests/unittests/framework/SceneGraph/Scene/SceneDescriberTest.cpp b/tests/unittests/framework/SceneGraph/Scene/SceneDescriberTest.cpp index a76d1b900..304d8a5d4 100644 --- a/tests/unittests/framework/SceneGraph/Scene/SceneDescriberTest.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/SceneDescriberTest.cpp @@ -7,6 +7,7 @@ // ------------------------------------------------------------------------- #include "gmock/gmock.h" +#include "internal/SceneGraph/Scene/SceneActionCollection.h" #include "internal/SceneGraph/Scene/SceneDescriber.h" #include "internal/SceneGraph/Scene/ClientScene.h" #include "SceneActionUtils.h" @@ -14,6 +15,9 @@ #include "internal/SceneGraph/Scene/SceneActionApplier.h" #include "TestEqualHelper.h" #include "internal/Core/Utils/MemoryUtils.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" +#include "internal/SceneGraph/SceneAPI/PixelRectangle.h" +#include "internal/SceneGraph/SceneAPI/RenderBuffer.h" using namespace testing; @@ -23,7 +27,7 @@ namespace ramses::internal { protected: SceneDescriberTest() - : creator(actions) + : creator(actions, EFeatureLevel_Latest) {} static void ExpectAllocateNodeAction(SceneActionCollection::SceneActionReader action, NodeHandle handle, uint32_t expectedChildrenCount) @@ -48,6 +52,113 @@ namespace ramses::internal EXPECT_EQ(child, actualChild); } + static void ExpectAllocateRenderBufferAction(SceneActionCollection::SceneActionReader action, RenderBufferHandle handle, const RenderBuffer& renderBuffer) + { + ASSERT_EQ(ESceneActionId::AllocateRenderBuffer, action.type()); + + RenderBufferHandle actualHandle; + RenderBuffer actualRenderBuffer; + uint32_t enumInt = 0; + + action.read(actualRenderBuffer.width); + action.read(actualRenderBuffer.height); + action.read(actualHandle); + action.read(enumInt); + actualRenderBuffer.format = static_cast(enumInt); + action.read(enumInt); + actualRenderBuffer.accessMode = static_cast(enumInt); + action.read(actualRenderBuffer.sampleCount); + + EXPECT_EQ(actualHandle, handle); + EXPECT_EQ(actualRenderBuffer.width, renderBuffer.width); + EXPECT_EQ(actualRenderBuffer.height, renderBuffer.height); + EXPECT_EQ(actualRenderBuffer.format, renderBuffer.format); + EXPECT_EQ(actualRenderBuffer.accessMode, renderBuffer.accessMode); + EXPECT_EQ(actualRenderBuffer.sampleCount, renderBuffer.sampleCount); + + EXPECT_TRUE(action.isFullyRead()); + } + + static void ExpectAllocateBlitPassAction(SceneActionCollection::SceneActionReader action, BlitPassHandle handle, RenderBufferHandle sourceRenderBufferHandle, RenderBufferHandle destinationRenderbufferHandle) + { + ASSERT_EQ(ESceneActionId::AllocateBlitPass, action.type()); + + BlitPassHandle actualHandle; + RenderBufferHandle actualSourceRenderbufferHandle; + RenderBufferHandle actualDestinationRenderbufferHandle; + + action.read(actualSourceRenderbufferHandle); + action.read(actualDestinationRenderbufferHandle); + action.read(actualHandle); + + EXPECT_EQ(actualHandle, handle); + EXPECT_EQ(actualSourceRenderbufferHandle, sourceRenderBufferHandle); + EXPECT_EQ(actualDestinationRenderbufferHandle, destinationRenderbufferHandle); + + EXPECT_TRUE(action.isFullyRead()); + } + + static void ExpectSetBlitPassRegionsAction(SceneActionCollection::SceneActionReader action, BlitPassHandle handle, const PixelRectangle& sourceRegion, const PixelRectangle& destinationRegion) + { + ASSERT_EQ(ESceneActionId::SetBlitPassRegions, action.type()); + + BlitPassHandle actualHandle; + PixelRectangle actualSourceRegion; + PixelRectangle actualDestinationRegion; + + action.read(actualHandle); + action.read(actualSourceRegion.x); + action.read(actualSourceRegion.y); + action.read(actualSourceRegion.width); + action.read(actualSourceRegion.height); + action.read(actualDestinationRegion.x); + action.read(actualDestinationRegion.y); + action.read(actualDestinationRegion.width); + action.read(actualDestinationRegion.height); + + EXPECT_EQ(handle, actualHandle); + EXPECT_EQ(sourceRegion.x, actualSourceRegion.x); + EXPECT_EQ(sourceRegion.y, actualSourceRegion.y); + EXPECT_EQ(sourceRegion.width, actualSourceRegion.width); + EXPECT_EQ(sourceRegion.height, actualSourceRegion.height); + EXPECT_EQ(destinationRegion.x, actualDestinationRegion.x); + EXPECT_EQ(destinationRegion.y, actualDestinationRegion.y); + EXPECT_EQ(destinationRegion.width, actualDestinationRegion.width); + EXPECT_EQ(destinationRegion.height, actualDestinationRegion.height); + + EXPECT_TRUE(action.isFullyRead()); + } + + static void ExpectSetBlitPassRenderOrderAction(SceneActionCollection::SceneActionReader action, BlitPassHandle handle, int32_t renderOrder) + { + ASSERT_EQ(ESceneActionId::SetBlitPassRenderOrder, action.type()); + + BlitPassHandle actualHandle; + int32_t actualRenderOrder {}; + action.read(actualHandle); + action.read(actualRenderOrder); + + EXPECT_EQ(handle, actualHandle); + EXPECT_EQ(renderOrder, actualRenderOrder); + + EXPECT_TRUE(action.isFullyRead()); + }; + + static void ExpectSetBlitPassEnabledAction(SceneActionCollection::SceneActionReader action, BlitPassHandle handle, bool enabled) + { + ASSERT_EQ(ESceneActionId::SetBlitPassEnabled, action.type()); + + BlitPassHandle actualHandle; + bool actualEnabled {}; + action.read(actualHandle); + action.read(actualEnabled); + + EXPECT_EQ(handle, actualHandle); + EXPECT_EQ(enabled, actualEnabled); + + EXPECT_TRUE(action.isFullyRead()); + }; + struct RenderableCreationData { RenderableCreationData() {} // NOLINT(modernize-use-equals-default): build issues with clang-12 @@ -64,8 +175,8 @@ namespace ramses::internal void createRenderable(const RenderableCreationData& data = RenderableCreationData{}) { - const NodeHandle node = m_scene.allocateNode(0, {}); - const RenderableHandle renderable = m_scene.allocateRenderable(node, {}); + const NodeHandle node = m_scene.allocateNode(0, {}); + const RenderableHandle renderable = m_scene.allocateRenderable(node, {}); m_scene.setRenderableStartIndex(renderable, data.startIndex); m_scene.setRenderableIndexCount(renderable, data.indexCount); m_scene.setRenderableRenderState(renderable, data.state); @@ -179,7 +290,7 @@ namespace ramses::internal // no actions for setting the zeroed data types Scene newScene; - SceneActionApplier::ApplyActionsOnScene(newScene, actions); + SceneActionApplier::ApplyActionsOnScene(newScene, actions, EFeatureLevel_Latest); // validate skipped actions still result in nulled data EXPECT_TRUE(MemoryUtils::AreAllBytesZero(newScene.getDataIntegerArray(dataInstance, DataFieldHandle(0u)), dataFieldElementCount)); @@ -251,4 +362,46 @@ namespace ramses::internal ASSERT_EQ(3u, actions.numberOfActions()); EXPECT_EQ(3u, SceneActionCollectionUtils::CountNumberOfActionsOfType(actions, ESceneActionId::AllocateDataLayout)); } + + TEST_F(SceneDescriberTest, checksDescriptionActionsForBlitPassesAndRenderBuffers) + { + const ramses::internal::RenderBuffer renderBuffer { + 120u, + 240u, + EPixelStorageFormat::RGBA8, + ERenderBufferAccessMode::ReadWrite, + 1 + }; + const PixelRectangle sourceRegion { + 12, 21, 123, 321 + }; + const PixelRectangle destinationRegion { + 23, 32, 234, 432 + }; + const int32_t renderOrder = 7; + const bool blitPassEnabled = true; + + const auto renderBufferSourceHandle = m_scene.allocateRenderBuffer(renderBuffer, {}); + const auto renderBufferDestinationHandle = m_scene.allocateRenderBuffer(renderBuffer, {}); + + const auto blitPassHandle = m_scene.allocateBlitPass(renderBufferSourceHandle, renderBufferDestinationHandle, {}); + m_scene.setBlitPassRegions(blitPassHandle, sourceRegion, destinationRegion); + m_scene.setBlitPassRenderOrder(blitPassHandle, renderOrder); + m_scene.setBlitPassEnabled(blitPassHandle, blitPassEnabled); + + SceneDescriber::describeScene(m_scene, creator); + + ASSERT_EQ(6u, actions.numberOfActions()); + uint32_t actionIdx = 0u; + + // order of actions is curcial + // first we need to allocate render buffers + // then allocate blit passes + ExpectAllocateRenderBufferAction(actions[actionIdx++], renderBufferSourceHandle, renderBuffer); + ExpectAllocateRenderBufferAction(actions[actionIdx++], renderBufferDestinationHandle, renderBuffer); + ExpectAllocateBlitPassAction(actions[actionIdx++], blitPassHandle, renderBufferSourceHandle, renderBufferDestinationHandle); + ExpectSetBlitPassRegionsAction(actions[actionIdx++], blitPassHandle, sourceRegion, destinationRegion); + ExpectSetBlitPassRenderOrderAction(actions[actionIdx++], blitPassHandle, renderOrder); + ExpectSetBlitPassEnabledAction(actions[actionIdx++], blitPassHandle, blitPassEnabled); + } } diff --git a/tests/unittests/framework/SceneGraph/Scene/SceneMergeHandleMappingTest.cpp b/tests/unittests/framework/SceneGraph/Scene/SceneMergeHandleMappingTest.cpp new file mode 100644 index 000000000..766cfa19d --- /dev/null +++ b/tests/unittests/framework/SceneGraph/Scene/SceneMergeHandleMappingTest.cpp @@ -0,0 +1,80 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "gtest/gtest.h" +#include "gmock/gmock.h" +#include "internal/SceneGraph/Scene/SceneMergeHandleMapping.h" +#include "internal/SceneGraph/SceneAPI/Handles.h" + +using namespace testing; + +namespace ramses::internal +{ + template + class SceneMergeHandleMappingTest : public ::testing::Test + { + }; + + using HandleTypes = ::testing::Types< + RenderableHandle, + RenderStateHandle, + CameraHandle, + NodeHandle, + TransformHandle, + DataLayoutHandle, + DataInstanceHandle, + UniformBufferHandle, + TextureSamplerHandle, + RenderGroupHandle, + RenderPassHandle, + BlitPassHandle, + PickableObjectHandle, + RenderTargetHandle, + RenderBufferHandle, + DataBufferHandle, + TextureBufferHandle, + DataSlotHandle, + SceneReferenceHandle, + sceneObjectId_t>; + + TYPED_TEST_SUITE(SceneMergeHandleMappingTest, HandleTypes); + + TYPED_TEST(SceneMergeHandleMappingTest, returnsMappedHandle) + { + SceneMergeHandleMapping mapping; + TypeParam handle(42u); + TypeParam mappedHandle(49u); + + mapping.addMapping(handle, mappedHandle); + auto returnedHandle = mapping.getMapping(handle); + + EXPECT_EQ(returnedHandle, mappedHandle); + } + + TYPED_TEST(SceneMergeHandleMappingTest, returnsHasMapping) + { + SceneMergeHandleMapping mapping; + TypeParam handle(42u); + TypeParam mappedHandle(49u); + + EXPECT_FALSE(mapping.hasMapping(handle)); + EXPECT_FALSE(mapping.hasMapping(TypeParam::Invalid())); + + mapping.addMapping(handle, mappedHandle); + EXPECT_TRUE(mapping.hasMapping(handle)); + } + + TYPED_TEST(SceneMergeHandleMappingTest, returnsInvalidHandleWhenNotMapped) + { + SceneMergeHandleMapping mapping; + TypeParam handle(42u); + + auto returnedHandle = mapping.getMapping(handle); + EXPECT_FALSE(returnedHandle.isValid()); + } +} diff --git a/tests/unittests/framework/SceneGraph/Scene/ScenePersistationTest.cpp b/tests/unittests/framework/SceneGraph/Scene/ScenePersistationTest.cpp index a7673f4c7..a5085f19f 100644 --- a/tests/unittests/framework/SceneGraph/Scene/ScenePersistationTest.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/ScenePersistationTest.cpp @@ -10,33 +10,41 @@ #include "internal/SceneGraph/Scene/ScenePersistation.h" #include "internal/SceneGraph/Scene/ClientScene.h" #include "TestingScene.h" +#include "FeatureLevelTestValues.h" using namespace testing; namespace ramses::internal { - TEST(AScenePersistation, canReadWrite) + class AScenePersistation : public ::testing::TestWithParam + { + }; + + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(AScenePersistation); + + TEST_P(AScenePersistation, canReadWrite) { ClientScene scene; NodeHandle parentNodeHandle = scene.allocateNode(0, {}); NodeHandle childNodeHandle = scene.allocateNode(0, {}); scene.addChildToNode(parentNodeHandle, childNodeHandle); - ScenePersistation::WriteSceneToFile("testfile", scene); + ScenePersistation::WriteSceneToFile("testfile", scene, GetParam()); Scene loadedScene; - ScenePersistation::ReadSceneFromFile("testfile", loadedScene); + ScenePersistation::ReadSceneFromFile("testfile", loadedScene, GetParam(), nullptr); ASSERT_EQ(2u, loadedScene.getNodeCount()); ASSERT_EQ(parentNodeHandle, loadedScene.getParent(childNodeHandle)); } - TEST(AScenePersistation, canReadWriteMockScene) + TEST_P(AScenePersistation, canReadWriteTestingScene) { - TestingScene scene; - ScenePersistation::WriteSceneToFile("testfile", scene.getScene()); + ClientScene scene; + TestingScene testingScene{ scene, GetParam() }; + ScenePersistation::WriteSceneToFile("testfile", scene, GetParam()); Scene loadedScene; SceneActionCollection dummyCollection; - ScenePersistation::ReadSceneFromFile("testfile", loadedScene); - scene.CheckEquivalentTo(loadedScene); + ScenePersistation::ReadSceneFromFile("testfile", loadedScene, GetParam(), nullptr); + testingScene.VerifyContent(loadedScene); } } diff --git a/tests/unittests/framework/SceneGraph/Scene/SceneTest_Generic.cpp b/tests/unittests/framework/SceneGraph/Scene/SceneTest_Generic.cpp index c49e7e2c4..bd9f00a0e 100644 --- a/tests/unittests/framework/SceneGraph/Scene/SceneTest_Generic.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/SceneTest_Generic.cpp @@ -17,7 +17,7 @@ namespace ramses::internal TYPED_TEST(AScene, PreallocatesMemoryPoolsBasedOnSizeInformation) { - const SceneSizeInformation sizeInfo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18); + const SceneSizeInformation sizeInfo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19); const SceneInfo sceneInfo; TypeParam preallocatedScene(sceneInfo); @@ -41,6 +41,7 @@ namespace ramses::internal EXPECT_EQ(sizeInfo.dataBufferCount, preallocatedScene.getDataBufferCount()); EXPECT_EQ(sizeInfo.pickableObjectCount, preallocatedScene.getPickableObjectCount()); EXPECT_EQ(sizeInfo.sceneReferenceCount, preallocatedScene.getSceneReferenceCount()); + EXPECT_EQ(sizeInfo.uniformBufferCount, preallocatedScene.getUniformBufferCount()); } TYPED_TEST(AScene, MemoryPoolSizesInUseStayZeroUponCreation) @@ -53,13 +54,13 @@ namespace ramses::internal TYPED_TEST(AScene, PreallocatesMemoryPoolsBasedOnSizeInformationNeverShrink) { - const SceneSizeInformation sizeInfo(21, 22, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18); + const SceneSizeInformation sizeInfo(21, 22, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19); const SceneInfo sceneInfo; TypeParam preallocatedScene(sceneInfo); preallocatedScene.preallocateSceneSize(sizeInfo); EXPECT_EQ(sizeInfo, preallocatedScene.getSceneSizeInformation()); - const SceneSizeInformation smallerSizeInfo(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); + const SceneSizeInformation smallerSizeInfo(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); preallocatedScene.preallocateSceneSize(smallerSizeInfo); EXPECT_EQ(sizeInfo, preallocatedScene.getSceneSizeInformation()); @@ -79,14 +80,44 @@ namespace ramses::internal EXPECT_EQ(sizeInfo.dataSlotCount, preallocatedScene.getDataSlotCount()); EXPECT_EQ(sizeInfo.dataBufferCount, preallocatedScene.getDataBufferCount()); EXPECT_EQ(sizeInfo.sceneReferenceCount, preallocatedScene.getSceneReferenceCount()); + EXPECT_EQ(sizeInfo.uniformBufferCount, preallocatedScene.getUniformBufferCount()); } TYPED_TEST(AScene, InitializesCorrectly) { - const SceneInfo sceneInfo(SceneId(537u), "TestScene"); + const SceneInfo sceneInfo{ SceneId(537u), "TestScene" }; TypeParam scene(sceneInfo); EXPECT_EQ(sceneInfo.sceneID, scene.getSceneId()); EXPECT_EQ(sceneInfo.friendlyName, scene.getName()); } + + TEST(ASceneUBO, SkipsUBOPoolPreallocationInFL01) + { + static_assert(EFeatureLevel_Latest != EFeatureLevel_01, "Remove test when feature levels flattened"); + ActionTestScene preallocatedScene{ {}, EFeatureLevel_01 }; + + const SceneSizeInformation sizeInfo{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 }; + preallocatedScene.preallocateSceneSize(sizeInfo); + + EXPECT_FALSE(sizeInfo == preallocatedScene.getSceneSizeInformation()); + EXPECT_EQ(sizeInfo.nodeCount, preallocatedScene.getNodeCount()); + EXPECT_EQ(sizeInfo.cameraCount, preallocatedScene.getCameraCount()); + EXPECT_EQ(sizeInfo.transformCount, preallocatedScene.getTransformCount()); + EXPECT_EQ(sizeInfo.renderableCount, preallocatedScene.getRenderableCount()); + EXPECT_EQ(sizeInfo.renderStateCount, preallocatedScene.getRenderStateCount()); + EXPECT_EQ(sizeInfo.datalayoutCount, preallocatedScene.getDataLayoutCount()); + EXPECT_EQ(sizeInfo.datainstanceCount, preallocatedScene.getDataInstanceCount()); + EXPECT_EQ(sizeInfo.renderGroupCount, preallocatedScene.getRenderGroupCount()); + EXPECT_EQ(sizeInfo.renderPassCount, preallocatedScene.getRenderPassCount()); + EXPECT_EQ(sizeInfo.blitPassCount, preallocatedScene.getBlitPassCount()); + EXPECT_EQ(sizeInfo.renderTargetCount, preallocatedScene.getRenderTargetCount()); + EXPECT_EQ(sizeInfo.renderBufferCount, preallocatedScene.getRenderBufferCount()); + EXPECT_EQ(sizeInfo.textureSamplerCount, preallocatedScene.getTextureSamplerCount()); + EXPECT_EQ(sizeInfo.dataSlotCount, preallocatedScene.getDataSlotCount()); + EXPECT_EQ(sizeInfo.dataBufferCount, preallocatedScene.getDataBufferCount()); + EXPECT_EQ(sizeInfo.pickableObjectCount, preallocatedScene.getPickableObjectCount()); + EXPECT_EQ(sizeInfo.sceneReferenceCount, preallocatedScene.getSceneReferenceCount()); + EXPECT_EQ(0u, preallocatedScene.getUniformBufferCount()); + } } diff --git a/tests/unittests/framework/SceneGraph/Scene/SceneTest_IteratableMemoryPools.cpp b/tests/unittests/framework/SceneGraph/Scene/SceneTest_IteratableMemoryPools.cpp index 5fa672501..d274d60e3 100644 --- a/tests/unittests/framework/SceneGraph/Scene/SceneTest_IteratableMemoryPools.cpp +++ b/tests/unittests/framework/SceneGraph/Scene/SceneTest_IteratableMemoryPools.cpp @@ -73,7 +73,7 @@ namespace ramses::internal TYPED_TEST(AnIteratableScene, CanIterateOverRenderables) { - auto allocateF = [scene = &this->m_scene] { return scene->allocateRenderable(NodeHandle{}, RenderableHandle{}); }; + auto allocateF = [scene = &this->m_scene]{ return scene->allocateRenderable(NodeHandle{}, RenderableHandle{}); }; auto releaseF = [scene = &this->m_scene](RenderableHandle renderable) { scene->releaseRenderable(renderable); }; this->runTest(allocateF, releaseF, this->m_scene.getRenderables()); } @@ -87,7 +87,7 @@ namespace ramses::internal TYPED_TEST(AnIteratableScene, CanIterateOverCameras) { - auto allocateF = [scene = &this->m_scene] { return scene->allocateCamera(ECameraProjectionType::Orthographic, NodeHandle{}, DataInstanceHandle{}, CameraHandle{}); }; + auto allocateF = [scene = &this->m_scene]{ return scene->allocateCamera(ECameraProjectionType::Orthographic, NodeHandle{}, DataInstanceHandle{}, CameraHandle{}); }; auto releaseF = [scene = &this->m_scene](CameraHandle camera) { scene->releaseCamera(camera); }; this->runTest(allocateF, releaseF, this->m_scene.getCameras()); } diff --git a/tests/unittests/framework/SceneGraph/Scene/TestingScene.cpp b/tests/unittests/framework/SceneGraph/Scene/TestingScene.cpp new file mode 100644 index 000000000..da443c319 --- /dev/null +++ b/tests/unittests/framework/SceneGraph/Scene/TestingScene.cpp @@ -0,0 +1,34 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "gtest/gtest.h" +#include "TestingScene.h" +#include "SceneTest.h" + +using namespace testing; + +namespace ramses::internal +{ + template + class ATestingScene : public testing::Test + { + }; + + TYPED_TEST_SUITE(ATestingScene, SceneTypes); + + TYPED_TEST(ATestingScene, generateAndCheckContent) + { + // no easy way in GTest to test combinations of template parameters, so using simply for loop here + for (EFeatureLevel featureLevel = EFeatureLevel_01; featureLevel <= EFeatureLevel_Latest; featureLevel = EFeatureLevel{ featureLevel + 1 }) + { + TypeParam scene; + TestingScene testingScene{ scene, featureLevel }; + testingScene.VerifyContent(scene); + } + } +} diff --git a/tests/unittests/framework/SceneGraph/SceneAPI/ResourceContentHashTest.cpp b/tests/unittests/framework/SceneGraph/SceneAPI/ResourceContentHashTest.cpp index 16fdef7e8..c7c725626 100644 --- a/tests/unittests/framework/SceneGraph/SceneAPI/ResourceContentHashTest.cpp +++ b/tests/unittests/framework/SceneGraph/SceneAPI/ResourceContentHashTest.cpp @@ -10,7 +10,6 @@ #include "internal/Core/Utils/BinaryOutputStream.h" #include "internal/Core/Utils/BinaryInputStream.h" #include "internal/PlatformAbstraction/Collections/HashSet.h" -#include "internal/PlatformAbstraction/Collections/StringOutputStream.h" #include "gtest/gtest.h" #include diff --git a/tests/unittests/framework/Watchdog/PlatformWatchDogTest.cpp b/tests/unittests/framework/Watchdog/PlatformWatchDogTest.cpp index 918d7c2cc..b4e7fae37 100644 --- a/tests/unittests/framework/Watchdog/PlatformWatchDogTest.cpp +++ b/tests/unittests/framework/Watchdog/PlatformWatchDogTest.cpp @@ -90,13 +90,13 @@ namespace ramses::internal EXPECT_CALL(callback, unregisterThread(ERamsesThreadIdentifier::Workers)); EXPECT_CALL(callback, notifyThread(ERamsesThreadIdentifier::Workers)).Times(6); - EXPECT_EQ(0ms, watchdogNotifer.calculateTimeout()); + EXPECT_EQ(1ms, watchdogNotifer.calculateTimeout()); // timeout of 0ms would block (e.g. BlockingQueue::pop()) watchdogNotifer.notifyWatchdog(); - EXPECT_EQ(0ms, watchdogNotifer.calculateTimeout()); + EXPECT_EQ(1ms, watchdogNotifer.calculateTimeout()); watchdogNotifer.notifyWatchdog(); - EXPECT_EQ(0ms, watchdogNotifer.calculateTimeout()); + EXPECT_EQ(1ms, watchdogNotifer.calculateTimeout()); watchdogNotifer.notifyWatchdog(); - EXPECT_EQ(0ms, watchdogNotifer.calculateTimeout()); + EXPECT_EQ(1ms, watchdogNotifer.calculateTimeout()); watchdogNotifer.notifyWatchdog(); watchdogNotifer.notifyWatchdog(); watchdogNotifer.notifyWatchdog(); diff --git a/tests/unittests/framework/ramses-framework/RamsesFrameworkConfigTest.cpp b/tests/unittests/framework/ramses-framework/RamsesFrameworkConfigTest.cpp index 7fd714123..845de2da7 100644 --- a/tests/unittests/framework/ramses-framework/RamsesFrameworkConfigTest.cpp +++ b/tests/unittests/framework/ramses-framework/RamsesFrameworkConfigTest.cpp @@ -209,4 +209,15 @@ namespace ramses::internal EXPECT_EQ(std::chrono::milliseconds(250), frameworkConfig.impl().m_tcpConfig.getAliveInterval()); EXPECT_EQ(std::chrono::milliseconds(9000), frameworkConfig.impl().m_tcpConfig.getAliveTimeout()); } + + TEST_F(ARamsesFrameworkConfig, CanSetWatchdogInterval) + { + EXPECT_EQ(1000u, frameworkConfig.impl().m_watchdogConfig.getWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers)); + EXPECT_FALSE(frameworkConfig.setWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers, 0)); + EXPECT_EQ(1000u, frameworkConfig.impl().m_watchdogConfig.getWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers)); + EXPECT_TRUE(frameworkConfig.setWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers, 1)); + EXPECT_EQ(1u, frameworkConfig.impl().m_watchdogConfig.getWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers)); + EXPECT_TRUE(frameworkConfig.setWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers, 100)); + EXPECT_EQ(100u, frameworkConfig.impl().m_watchdogConfig.getWatchdogNotificationInterval(ERamsesThreadIdentifier::Workers)); + } } diff --git a/tests/unittests/framework/ramses-framework/RamsesFrameworkTest.cpp b/tests/unittests/framework/ramses-framework/RamsesFrameworkTest.cpp index 169d91b8b..408c60b88 100644 --- a/tests/unittests/framework/ramses-framework/RamsesFrameworkTest.cpp +++ b/tests/unittests/framework/ramses-framework/RamsesFrameworkTest.cpp @@ -242,7 +242,7 @@ TEST_F(ARamsesFrameworkLogging, SetLoggingPrefix) LOG_ERROR(CONTEXT_FRAMEWORK, "test"); EXPECT_EQ("R.main: test", m_logMessage); - RamsesLogger::SetPrefixes("I", "T", "A"); + RamsesLoggerPrefixes::SetRamsesLoggerPrefixes("I", "T", "A"); LOG_INFO(CONTEXT_FRAMEWORK, "test"); EXPECT_EQ("I.T.A: test", m_logMessage); LOG_WARN(CONTEXT_FRAMEWORK, "test"); diff --git a/tests/unittests/glslang-init-gtest-env/CMakeLists.txt b/tests/unittests/glslang-init-gtest-env/CMakeLists.txt new file mode 100644 index 000000000..d912f45d1 --- /dev/null +++ b/tests/unittests/glslang-init-gtest-env/CMakeLists.txt @@ -0,0 +1,23 @@ +# ------------------------------------------------------------------------- +# Copyright (C) 2024 BMW AG +# ------------------------------------------------------------------------- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# ------------------------------------------------------------------------- + +# This target is designed to automatically add gtest environment +# that initializes glslang, to avoid having glslang initialized +# for every test +# NOTE: this target must be added as a DIRECT dependency +# to the cmake module that needs this functionality + +createModule( + NAME glslang-init-gtest-env + TYPE OBJECT + INCLUDE_PATHS . + SRC_FILES *.h + *.cpp + DEPENDENCIES ramses-client + ramses-gmock +) diff --git a/tests/unittests/glslang-init-gtest-env/GlslangInitializerTestEnivornment.cpp b/tests/unittests/glslang-init-gtest-env/GlslangInitializerTestEnivornment.cpp new file mode 100644 index 000000000..667788f68 --- /dev/null +++ b/tests/unittests/glslang-init-gtest-env/GlslangInitializerTestEnivornment.cpp @@ -0,0 +1,42 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "internal/glslEffectBlock/GlslangInitializer.h" +#include "GlslangInitializerTestEnivornment.h" +#include "gtest/gtest.h" + +namespace ramses::internal +{ + // gtest's Environment gets setup before RUN_ALL_TESTS, and gets torn down right after + // this should be a safe way to init and deinit glslang once per test run + class GlslangInitializerTestEnivornment : public ::testing::Environment { + public: + void SetUp() override + { + m_glslangInitializer = std::make_unique(); + } + + void TearDown() override + { + m_glslangInitializer.reset(); + } + + private: + std::unique_ptr m_glslangInitializer; + }; + + GlslangInitializerTestEnivornmentSetter::GlslangInitializerTestEnivornmentSetter() + { + // gtest takes ownership of the passed Environment, i.e., delete should not be called + AddGlobalTestEnvironment(new GlslangInitializerTestEnivornment); + } + + // This static var only has a constructor (no destructor), since it relies on gtest + // Environment doing proper cleanup + static GlslangInitializerTestEnivornmentSetter GlslangInitializerTestEnivornmentSetterInstance; +} diff --git a/tests/unittests/glslang-init-gtest-env/GlslangInitializerTestEnivornment.h b/tests/unittests/glslang-init-gtest-env/GlslangInitializerTestEnivornment.h new file mode 100644 index 000000000..a139d0c4b --- /dev/null +++ b/tests/unittests/glslang-init-gtest-env/GlslangInitializerTestEnivornment.h @@ -0,0 +1,19 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +namespace ramses::internal +{ + // This makes sure that glslang init/deinit is called maximum once per test run to reduce execution time + class GlslangInitializerTestEnivornmentSetter + { + public: + GlslangInitializerTestEnivornmentSetter(); + }; +} diff --git a/tests/unittests/renderer/CMakeLists.txt b/tests/unittests/renderer/CMakeLists.txt index e108315e3..9af5c6412 100644 --- a/tests/unittests/renderer/CMakeLists.txt +++ b/tests/unittests/renderer/CMakeLists.txt @@ -8,6 +8,7 @@ add_subdirectory(renderer-test-common) add_subdirectory(renderer-lib) +add_subdirectory(PlatformFactoryFake) add_subdirectory(ramses-renderer) if(ramses-sdk_ENABLE_WINDOW_TYPE_WINDOWS) diff --git a/tests/unittests/renderer/PlatformFactoryFake/CMakeLists.txt b/tests/unittests/renderer/PlatformFactoryFake/CMakeLists.txt new file mode 100644 index 000000000..3db67b6e0 --- /dev/null +++ b/tests/unittests/renderer/PlatformFactoryFake/CMakeLists.txt @@ -0,0 +1,21 @@ +# ------------------------------------------------------------------------- +# Copyright (C) 2024 BMW AG +# ------------------------------------------------------------------------- +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at https://mozilla.org/MPL/2.0/. +# ------------------------------------------------------------------------- + +# This library solves the problem of allowing ramses-renderer to have +# dependency on Platform, while still allowing unit testing +# of ramses-renderer without that depdendency on Platform +# The library allows unit test to link to ramses-renderer-impl +# without producing linker error + +createModule( + NAME PlatformFactoryFake + TYPE STATIC_LIBRARY + SRC_FILES *.h + *.cpp + DEPENDENCIES ramses-renderer-internal +) diff --git a/tests/unittests/renderer/PlatformFactoryFake/PlatformFactoryFake.cpp b/tests/unittests/renderer/PlatformFactoryFake/PlatformFactoryFake.cpp new file mode 100644 index 000000000..e8b424d69 --- /dev/null +++ b/tests/unittests/renderer/PlatformFactoryFake/PlatformFactoryFake.cpp @@ -0,0 +1,23 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "internal/Platform/PlatformFactory.h" +#include + +namespace ramses::internal +{ + // This is a fake implementation of PlatformFactory, that basically does nothing, but allows + // the tests to link and build without error + // It is needed in order to allow unit testing of ramses-renderer + // without dependency on Platform + std::unique_ptr PlatformFactory::createPlatform([[maybe_unused]] const RendererConfigData& rendererConfig, [[maybe_unused]] const DisplayConfigData& displayConfig) + { + assert(false); + return {}; + } +} diff --git a/tests/unittests/renderer/embedded-compositor-wayland/EmbeddedCompositor_Wayland_Test.cpp b/tests/unittests/renderer/embedded-compositor-wayland/EmbeddedCompositor_Wayland_Test.cpp index c9779fa4b..112c0a43a 100644 --- a/tests/unittests/renderer/embedded-compositor-wayland/EmbeddedCompositor_Wayland_Test.cpp +++ b/tests/unittests/renderer/embedded-compositor-wayland/EmbeddedCompositor_Wayland_Test.cpp @@ -8,8 +8,8 @@ #include "gmock/gmock.h" #include "TestWithWaylandEnvironment.h" -#include "internal/RendererLib/RendererConfig.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/RendererConfigData.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Platform/Wayland/EmbeddedCompositor/EmbeddedCompositor_Wayland.h" #include "ContextMock.h" #include "PlatformMock.h" @@ -166,7 +166,7 @@ namespace ramses::internal WaylandEnvironmentUtils::UnsetVariable(WaylandEnvironmentVariable::XDGRuntimeDir); } - DisplayConfig displayConfig; + DisplayConfigData displayConfig; displayConfig.setWaylandEmbeddedCompositingSocketName(ecSocketName); displayConfig.setWaylandEmbeddedCompositingSocketGroup(ecSocketGroup); displayConfig.setWaylandEmbeddedCompositingSocketFD(ecSocketFD); diff --git a/tests/unittests/renderer/embedded-compositor-wayland/WaylandResourceLifecycleTest.cpp b/tests/unittests/renderer/embedded-compositor-wayland/WaylandResourceLifecycleTest.cpp index 08376e53d..39b24e9d5 100644 --- a/tests/unittests/renderer/embedded-compositor-wayland/WaylandResourceLifecycleTest.cpp +++ b/tests/unittests/renderer/embedded-compositor-wayland/WaylandResourceLifecycleTest.cpp @@ -27,8 +27,8 @@ #include "internal/Platform/Wayland/EmbeddedCompositor/WaylandOutputConnection.h" #include "internal/Platform/Wayland/EmbeddedCompositor/LinuxDmabufConnection.h" -#include "internal/RendererLib/RendererConfig.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/RendererConfigData.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "gtest/gtest.h" diff --git a/tests/unittests/renderer/ramses-renderer/CMakeLists.txt b/tests/unittests/renderer/ramses-renderer/CMakeLists.txt index 1368335b1..5dcc13193 100644 --- a/tests/unittests/renderer/ramses-renderer/CMakeLists.txt +++ b/tests/unittests/renderer/ramses-renderer/CMakeLists.txt @@ -12,7 +12,8 @@ createModule( SRC_FILES *.h *.cpp DEPENDENCIES ramses-client - ramses-renderer + ramses-renderer-impl + PlatformFactoryFake ramses-gmock-main renderer-test-common ) diff --git a/tests/unittests/renderer/ramses-renderer/DisplayConfigTest.cpp b/tests/unittests/renderer/ramses-renderer/DisplayConfigTest.cpp index 2ca1b3f9a..f415dc1fc 100644 --- a/tests/unittests/renderer/ramses-renderer/DisplayConfigTest.cpp +++ b/tests/unittests/renderer/ramses-renderer/DisplayConfigTest.cpp @@ -17,13 +17,28 @@ namespace ramses::internal class ADisplayConfig : public ::testing::Test { protected: + void expectDisplayConfigValid() + { + ramses::ValidationReport report; + config.validate(report); + EXPECT_FALSE(report.hasIssue()); + } + + void expectDisplayConfigInvalid(std::string_view expectedError) + { + ramses::ValidationReport report; + config.validate(report); + EXPECT_TRUE(report.hasError()); + EXPECT_THAT(report.impl().toString(), ::testing::HasSubstr(expectedError)); + } + ramses::DisplayConfig config; }; TEST_F(ADisplayConfig, hasDefaultValuesUponConstruction) { - const ramses::internal::DisplayConfig defaultDisplayConfig; - const ramses::internal::DisplayConfig& displayConfig = config.impl().getInternalDisplayConfig(); + const ramses::internal::DisplayConfigData defaultDisplayConfig; + const auto& displayConfig = config.impl().getInternalDisplayConfig(); EXPECT_EQ(defaultDisplayConfig.getWindowPositionX(), displayConfig.getWindowPositionX()); EXPECT_EQ(defaultDisplayConfig.getWindowPositionY(), displayConfig.getWindowPositionY()); @@ -64,6 +79,12 @@ namespace ramses::internal EXPECT_EQ(ramses::EWindowType::Wayland_IVI, config.impl().getInternalDisplayConfig().getWindowType()); } + TEST_F(ADisplayConfig, setsWindowTitle) + { + EXPECT_TRUE(config.setWindowTitle("window title")); + EXPECT_EQ("window title", config.impl().getInternalDisplayConfig().getWindowTitle()); + } + TEST_F(ADisplayConfig, setsFullscreenState) { EXPECT_TRUE(config.setWindowFullscreen(true)); @@ -162,36 +183,47 @@ namespace ramses::internal TEST_F(ADisplayConfig, IsValidUponConstruction) { - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); } TEST_F(ADisplayConfig, IsValidIfWindowTypeWindowsAndDeviceTypeNotGLES30) { config.setWindowType(ramses::EWindowType::Windows); config.setDeviceType(ramses::EDeviceType::GL_4_5); - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); + } + + TEST_F(ADisplayConfig, IsValidIfSupportedWindowTypeUsedWithVulkan) + { + config.setDeviceType(ramses::EDeviceType::Vulkan); + config.setAsyncEffectUploadEnabled(false); + + config.setWindowType(ramses::EWindowType::Windows); + expectDisplayConfigValid(); + config.setWindowType(ramses::EWindowType::X11); + expectDisplayConfigValid(); + } + + TEST_F(ADisplayConfig, IsNotValidIfAsyncUploadEnabledWithVulkanDevice) + { + config.setDeviceType(ramses::EDeviceType::Vulkan); + config.setAsyncEffectUploadEnabled(true); + + expectDisplayConfigInvalid("Vulkan does not support async shader upload"); } TEST_F(ADisplayConfig, IsValidIfWindowTypeAndroidAndDeviceTypeGLES30) { config.setWindowType(ramses::EWindowType::Android); config.setDeviceType(ramses::EDeviceType::GLES_3_0); - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); } TEST_F(ADisplayConfig, IsValidIfWindowTypeIOSAndDeviceTypeGLES30) { config.setWindowType(ramses::EWindowType::iOS); config.setDeviceType(ramses::EDeviceType::GLES_3_0); - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); } TEST_F(ADisplayConfig, IsValidIfWindowTypeAndroidAndExternalAndroidWindowHandleProvided) @@ -199,9 +231,7 @@ namespace ramses::internal std::uintptr_t dummyVoidPointer{ 1u }; config.setAndroidNativeWindow(reinterpret_cast(dummyVoidPointer)); config.setWindowType(ramses::EWindowType::Android); - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); } TEST_F(ADisplayConfig, IsValidIfWindowTypeIOSAndExternalIOSWindowHandleProvided) @@ -209,9 +239,7 @@ namespace ramses::internal std::uintptr_t dummyVoidPointer{ 1u }; config.setIOSNativeWindow(ramses::IOSNativeWindowPtr{ reinterpret_cast(dummyVoidPointer) }); config.setWindowType(ramses::EWindowType::iOS); - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); } TEST_F(ADisplayConfig, IsValidIfWindowTypeWindowsAndExternalWindowsWindowHandleProvided) @@ -219,9 +247,7 @@ namespace ramses::internal std::uintptr_t dummyVoidPointer{ 1u }; config.setWindowsWindowHandle(reinterpret_cast(dummyVoidPointer)); config.setWindowType(ramses::EWindowType::Windows); - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); } TEST_F(ADisplayConfig, IsValidIfWindowTypeX11AndExternalX11WindowHandleProvided) @@ -229,9 +255,7 @@ namespace ramses::internal ramses::X11WindowHandle dummyX11Window{ 1u }; config.setX11WindowHandle(dummyX11Window); config.setWindowType(ramses::EWindowType::X11); - ramses::ValidationReport report; - config.validate(report); - EXPECT_FALSE(report.hasIssue()); + expectDisplayConfigValid(); } TEST_F(ADisplayConfig, ValidationWarningIfCompositorEmbeddedCompositorDisplsayAndSocketFdAreSet) @@ -249,10 +273,7 @@ namespace ramses::internal { config.setWindowType(ramses::EWindowType::Android); config.setDeviceType(ramses::EDeviceType::GL_4_2); - ramses::ValidationReport report; - config.validate(report); - EXPECT_TRUE(report.hasError()); - EXPECT_THAT(report.impl().toString(), ::testing::HasSubstr("ERROR: Selected window type supports only GL ES 3.0 device type")); + expectDisplayConfigInvalid("ERROR: Selected window type does not support device type"); } TEST_F(ADisplayConfig, ValidationErrorIfExternalHandleWindowsSetAndTypeNotWindows) @@ -260,10 +281,7 @@ namespace ramses::internal std::uintptr_t dummyVoidPointer{ 1u }; config.setWindowsWindowHandle(reinterpret_cast(dummyVoidPointer)); config.setWindowType(ramses::EWindowType::X11); - ramses::ValidationReport report; - config.validate(report); - EXPECT_TRUE(report.hasError()); - EXPECT_THAT(report.impl().toString(), ::testing::HasSubstr("ERROR: External Windows window handle is set and selected window type is not Windows")); + expectDisplayConfigInvalid("ERROR: External Windows window handle is set and selected window type is not Windows"); } TEST_F(ADisplayConfig, ValidationErrorIfExternalHandleAndroidSetAndTypeNotAndroid) @@ -271,10 +289,7 @@ namespace ramses::internal std::uintptr_t dummyVoidPointer{ 1u }; config.setAndroidNativeWindow(reinterpret_cast(dummyVoidPointer)); config.setWindowType(ramses::EWindowType::X11); - ramses::ValidationReport report; - config.validate(report); - EXPECT_TRUE(report.hasError()); - EXPECT_THAT(report.impl().toString(), ::testing::HasSubstr("ERROR: External Android window handle is set and selected window type is not Android")); + expectDisplayConfigInvalid("ERROR: External Android window handle is set and selected window type is not Android"); } TEST_F(ADisplayConfig, ValidationErrorIfExternalHandleIOSSetAndTypeNotIOS) @@ -282,20 +297,14 @@ namespace ramses::internal std::uintptr_t dummyVoidPointer{ 1u }; config.setIOSNativeWindow(ramses::IOSNativeWindowPtr{ reinterpret_cast(dummyVoidPointer) }); config.setWindowType(ramses::EWindowType::X11); - ramses::ValidationReport report; - config.validate(report); - EXPECT_TRUE(report.hasError()); - EXPECT_THAT(report.impl().toString(), ::testing::HasSubstr("ERROR: External iOS window handle is set and selected window type is not iOS")); + expectDisplayConfigInvalid("ERROR: External iOS window handle is set and selected window type is not iOS"); } TEST_F(ADisplayConfig, ValidationErrorIfExternalHandleX11SetAndTypeNotX11) { config.setX11WindowHandle(ramses::X11WindowHandle(123u)); config.setWindowType(ramses::EWindowType::Android); - ramses::ValidationReport report; - config.validate(report); - EXPECT_TRUE(report.hasError()); - EXPECT_THAT(report.impl().toString(), ::testing::HasSubstr("ERROR: External X11 window handle is set and selected window type is not X11")); + expectDisplayConfigInvalid("ERROR: External X11 window handle is set and selected window type is not X11"); } TEST_F(ADisplayConfig, CanBeCopyAndMoveConstructed) diff --git a/tests/unittests/renderer/ramses-renderer/RamsesRendererTest.cpp b/tests/unittests/renderer/ramses-renderer/RamsesRendererTest.cpp index e02b73248..216117f43 100644 --- a/tests/unittests/renderer/ramses-renderer/RamsesRendererTest.cpp +++ b/tests/unittests/renderer/ramses-renderer/RamsesRendererTest.cpp @@ -126,7 +126,10 @@ namespace ramses::internal static ramses::RendererConfig CreateRendererConfigWithSystemCompositor() { ramses::RendererConfig config; +WARNINGS_PUSH +WARNING_DISABLE_LINUX(-Wdeprecated-declarations) config.enableSystemCompositorControl(); +WARNINGS_POP return config; } }; @@ -450,6 +453,8 @@ namespace ramses::internal /* * SystemCompositorControl */ +WARNINGS_PUSH +WARNING_DISABLE_LINUX(-Wdeprecated-declarations) TEST_F(ARamsesRenderer, createsNoCommandForSystemCompositorControllerIfNotEnabledFromConfig) { EXPECT_FALSE(renderer.setSurfaceVisibility(0, true)); @@ -501,6 +506,7 @@ namespace ramses::internal EXPECT_CALL(cmdVisitor, systemCompositorScreenshot(std::string_view{"name"}, -1)); cmdVisitor.visit(commandBuffer); } +WARNINGS_POP /* * Threading and thread sanitizer tests @@ -560,12 +566,15 @@ namespace ramses::internal renderer.destroyOffscreenBuffer(displayId, ob); renderer.flush(); +WARNINGS_PUSH +WARNING_DISABLE_LINUX(-Wdeprecated-declarations) renderer.setSurfaceVisibility(0u, true); renderer.setSurfaceOpacity(0u, 1.0f); renderer.setSurfaceRectangle(0u, 0, 0, 0, 0); renderer.takeSystemCompositorScreenshot("", -1); renderer.setFrameTimerLimits(10001u, 10000u, 10000u); renderer.setLayerVisibility(0u, true); +WARNINGS_POP renderer.flush(); renderer.dispatchEvents(eventHandler); diff --git a/tests/unittests/renderer/ramses-renderer/RendererConfigTest.cpp b/tests/unittests/renderer/ramses-renderer/RendererConfigTest.cpp index d9d835950..5982cc923 100644 --- a/tests/unittests/renderer/ramses-renderer/RendererConfigTest.cpp +++ b/tests/unittests/renderer/ramses-renderer/RendererConfigTest.cpp @@ -15,11 +15,11 @@ namespace ramses::internal { TEST(ARendererConfig, hasDefaultValuesUponConstruction) { - const ramses::internal::RendererConfig defaultConfig; + const RendererConfigData defaultConfig; ramses::RendererConfig config; EXPECT_EQ(nullptr, config.impl().getBinaryShaderCache()); - const ramses::internal::RendererConfig& internalConfig = config.impl().getInternalRendererConfig(); + const auto& internalConfig = config.impl().getInternalRendererConfig(); EXPECT_EQ(defaultConfig.getFrameCallbackMaxPollTime(), internalConfig.getFrameCallbackMaxPollTime()); EXPECT_EQ(defaultConfig.getRenderThreadLoopTimingReportingPeriod(), internalConfig.getRenderThreadLoopTimingReportingPeriod()); @@ -29,8 +29,11 @@ namespace ramses::internal TEST(ARendererConfig, canEnableSystemCompositor) { ramses::RendererConfig config; +WARNINGS_PUSH +WARNING_DISABLE_LINUX(-Wdeprecated-declarations) EXPECT_TRUE(config.enableSystemCompositorControl()); EXPECT_TRUE(config.impl().getInternalRendererConfig().getSystemCompositorControlEnabled()); +WARNINGS_POP } TEST(ARendererConfig, CanBeCopyAndMoveConstructed) @@ -91,9 +94,12 @@ namespace ramses::internal TEST(ARendererConfig, setsAndGetsWaylandDisplay) { ramses::RendererConfig config; +WARNINGS_PUSH +WARNING_DISABLE_LINUX(-Wdeprecated-declarations) EXPECT_TRUE(config.setSystemCompositorWaylandDisplay("xxx")); EXPECT_EQ("xxx", config.getSystemCompositorWaylandDisplay()); EXPECT_EQ("xxx", config.impl().getInternalRendererConfig().getWaylandDisplayForSystemCompositorController()); +WARNINGS_POP } TEST(ARendererConfig, setsAndGetsLoopCountPeriod) diff --git a/tests/unittests/renderer/renderer-lib/RendererFramework/RendererFrameworkLogicTest.cpp b/tests/unittests/renderer/renderer-lib/RendererFramework/RendererFrameworkLogicTest.cpp index cd48d04d0..63c7e4888 100644 --- a/tests/unittests/renderer/renderer-lib/RendererFramework/RendererFrameworkLogicTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererFramework/RendererFrameworkLogicTest.cpp @@ -57,8 +57,9 @@ namespace ramses::internal TEST_F(ARendererFrameworkLogic, generatesPublishedRendererCommand) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote)); + const SceneInfo sceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::VulkanAndOpenGL, EVulkanAPIVersion::Version_1_1, ESPIRVVersion::Version_1_3 }; + fixture.handleNewSceneAvailable(sceneInfo, providerID); + EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::VulkanAndOpenGL, EVulkanAPIVersion::Version_1_1, ESPIRVVersion::Version_1_3)); visitPendingCommands(); } @@ -69,35 +70,35 @@ namespace ramses::internal fixture.handleInitializeScene(sceneInfo, providerID); InSequence seq; - EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote)); + EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::OpenGL, EVulkanAPIVersion::Invalid, ESPIRVVersion::Invalid)); EXPECT_CALL(cmdVisitor, handleSceneReceived(sceneInfo)); visitPendingCommands(); } TEST_F(ARendererFrameworkLogic, generatesUnpublishRendererCommand) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, "", EScenePublicationMode::LocalAndRemote), providerID); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, "", EScenePublicationMode::LocalAndRemote }, providerID); fixture.handleSceneBecameUnavailable(sceneId, providerID); InSequence seq; - EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote)); + EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::OpenGL, EVulkanAPIVersion::Invalid, ESPIRVVersion::Invalid)); EXPECT_CALL(cmdVisitor, handleSceneUnpublished(sceneId)); visitPendingCommands(); } TEST_F(ARendererFrameworkLogic, ignoresSecondPublishFromDifferentProvider) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), Guid(30)); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, providerID); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, Guid(30)); - EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote)); + EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::OpenGL, EVulkanAPIVersion::Invalid, ESPIRVVersion::Invalid)); visitPendingCommands(); } TEST_F(ARendererFrameworkLogic, handlesSceneUpdateWithFlush) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, "", EScenePublicationMode::LocalAndRemote), providerID); - EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote)); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, "", EScenePublicationMode::LocalAndRemote }, providerID); + EXPECT_CALL(cmdVisitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::OpenGL, EVulkanAPIVersion::Invalid, ESPIRVVersion::Invalid)); visitPendingCommands(); SceneUpdate sceneUpdate; @@ -127,8 +128,8 @@ namespace ramses::internal TEST_F(ARendererFrameworkLogic, willSendSubscribeMessageToCorrectProvider) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - fixture.handleNewSceneAvailable(SceneInfo(SceneId{123}, "foo", EScenePublicationMode::LocalAndRemote), Guid{456}); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, providerID); + fixture.handleNewSceneAvailable(SceneInfo{ SceneId{123}, "foo", EScenePublicationMode::LocalAndRemote }, Guid{ 456 }); EXPECT_CALL(sceneGraphConsumerComponent, subscribeScene(providerID, sceneId)); fixture.sendSubscribeScene(sceneId); @@ -141,8 +142,8 @@ namespace ramses::internal TEST_F(ARendererFrameworkLogic, willSendUnsubscribeMessageToCorrectProvider) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - fixture.handleNewSceneAvailable(SceneInfo(SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote), Guid{ 456 }); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, providerID); + fixture.handleNewSceneAvailable(SceneInfo{ SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote }, Guid{ 456 }); EXPECT_CALL(sceneGraphConsumerComponent, unsubscribeScene(providerID, sceneId)); fixture.sendUnsubscribeScene(sceneId); @@ -155,8 +156,8 @@ namespace ramses::internal TEST_F(ARendererFrameworkLogic, willSendCorrectSceneStateChangedMessageToCorrectProvider) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - fixture.handleNewSceneAvailable(SceneInfo(SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote), Guid{ 456 }); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, providerID); + fixture.handleNewSceneAvailable(SceneInfo{ SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote }, Guid{ 456 }); EXPECT_CALL(sceneGraphConsumerComponent, sendSceneReferenceEvent(providerID, _)).WillOnce([this](Guid const& /*unused*/, SceneReferenceEvent const& event) { @@ -175,8 +176,8 @@ namespace ramses::internal TEST_F(ARendererFrameworkLogic, willSendCorrectSceneFlushedMessageToCorrectProvider) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - fixture.handleNewSceneAvailable(SceneInfo(SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote), Guid{ 456 }); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, providerID); + fixture.handleNewSceneAvailable(SceneInfo{ SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote }, Guid{ 456 }); EXPECT_CALL(sceneGraphConsumerComponent, sendSceneReferenceEvent(providerID, _)).WillOnce([this](Guid const& /*unused*/, SceneReferenceEvent const& event) { @@ -195,8 +196,8 @@ namespace ramses::internal TEST_F(ARendererFrameworkLogic, willSendCorrectDataLinkedMessageToCorrectProvider) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - fixture.handleNewSceneAvailable(SceneInfo(SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote), Guid{ 456 }); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, providerID); + fixture.handleNewSceneAvailable(SceneInfo{ SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote }, Guid{ 456 }); EXPECT_CALL(sceneGraphConsumerComponent, sendSceneReferenceEvent(providerID, _)).WillOnce([this](Guid const& /*unused*/, SceneReferenceEvent const& event) { @@ -218,8 +219,8 @@ namespace ramses::internal TEST_F(ARendererFrameworkLogic, willSendCorrectDataUnlinkedMessageToCorrectProvider) { - fixture.handleNewSceneAvailable(SceneInfo(sceneId, sceneName, EScenePublicationMode::LocalAndRemote), providerID); - fixture.handleNewSceneAvailable(SceneInfo(SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote), Guid{ 456 }); + fixture.handleNewSceneAvailable(SceneInfo{ sceneId, sceneName, EScenePublicationMode::LocalAndRemote }, providerID); + fixture.handleNewSceneAvailable(SceneInfo{ SceneId{ 123 }, "foo", EScenePublicationMode::LocalAndRemote }, Guid{ 456 }); EXPECT_CALL(sceneGraphConsumerComponent, sendSceneReferenceEvent(providerID, _)).WillOnce([this](Guid const& /*unused*/, SceneReferenceEvent const& event) { diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/AsyncEffectUploaderTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/AsyncEffectUploaderTest.cpp index f3d8ff14d..39d1d5110 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/AsyncEffectUploaderTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/AsyncEffectUploaderTest.cpp @@ -67,7 +67,7 @@ namespace ramses::internal for(uint32_t i = 0u; i < count; ++i) { const auto randomString = std::to_string(++createdEffectCounter); - const EffectResource* effect = new EffectResource(randomString, "", "", {}, {}, {}, ""); + const EffectResource* effect = new EffectResource(randomString, "", "", {}, {}, {}, {}, "", EFeatureLevel_Latest); result.push_back(effect); createdEffects.emplace_back(effect); //keep track of created resource to avoid mem-leak diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkCachedSceneTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkCachedSceneTest.cpp index 221f405e3..e698884c6 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkCachedSceneTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkCachedSceneTest.cpp @@ -21,7 +21,7 @@ namespace ramses::internal public: ADataReferenceLinkCachedScene() : rendererScenes(rendererEventCollector) - , scene(rendererScenes.createScene(SceneInfo(SceneId(3u)))) + , scene(rendererScenes.createScene(SceneInfo{ SceneId(3u) })) , sceneAllocator(scene) { const DataLayoutHandle layout = sceneAllocator.allocateDataLayout({ DataFieldInfo(EDataType::Int32) }, ResourceContentHash::Invalid()); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkManagerTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkManagerTest.cpp index 2f8252c43..1b356296f 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkManagerTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DataReferenceLinkManagerTest.cpp @@ -26,8 +26,8 @@ namespace ramses::internal , dataReferenceLinkManager(sceneLinksManager.getDataReferenceLinkManager()) , providerSceneId(3u) , consumerSceneId(4u) - , providerScene(rendererScenes.createScene(SceneInfo(providerSceneId))) - , consumerScene(rendererScenes.createScene(SceneInfo(consumerSceneId))) + , providerScene(rendererScenes.createScene(SceneInfo{ providerSceneId })) + , consumerScene(rendererScenes.createScene(SceneInfo{ consumerSceneId })) , providerSceneAllocator(providerScene) , consumerSceneAllocator(consumerScene) , providerSlotHandle(55u) @@ -193,7 +193,7 @@ namespace ramses::internal TEST_F(ADataReferenceLinkManager, confidenceTest_canResolveLinkedWithThreeScenesAndTwoLinks) { const SceneId middleSceneId(145u); - DataReferenceLinkCachedScene& middleScene = rendererScenes.createScene(SceneInfo(middleSceneId)); + DataReferenceLinkCachedScene& middleScene = rendererScenes.createScene(SceneInfo{ middleSceneId }); SceneAllocateHelper middleSceneAllocator(middleScene); DataInstanceHandle middleProviderDataRef; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayConfigTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayConfigTest.cpp index 40fb8da85..ec31ab90e 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayConfigTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayConfigTest.cpp @@ -6,7 +6,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "gtest/gtest.h" namespace ramses::internal @@ -14,7 +14,7 @@ namespace ramses::internal class AInternalDisplayConfig : public ::testing::Test { public: - ramses::internal::DisplayConfig m_config; + ramses::internal::DisplayConfigData m_config; }; TEST_F(AInternalDisplayConfig, hasDefaultValues) @@ -125,8 +125,8 @@ namespace ramses::internal TEST_F(AInternalDisplayConfig, canBeCompared) { - ramses::internal::DisplayConfig config1; - ramses::internal::DisplayConfig config2; + ramses::internal::DisplayConfigData config1; + ramses::internal::DisplayConfigData config2; EXPECT_EQ(config1, config2); config1.setAntialiasingSampleCount(4u); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.cpp index cd1e961e8..210a8bad7 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.cpp @@ -11,13 +11,13 @@ namespace ramses::internal { - DisplayDispatcherMock::DisplayDispatcherMock(const RendererConfig& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier) - : DisplayDispatcher(std::make_unique(), config, rendererSceneSender, notifier) + DisplayDispatcherMock::DisplayDispatcherMock(const RendererConfigData& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier) + : DisplayDispatcher(std::make_unique(), config, rendererSceneSender, notifier, EFeatureLevel_Latest) { } DisplayDispatcherMock::~DisplayDispatcherMock() = default; - DisplayDispatcherFacade::DisplayDispatcherFacade(const RendererConfig& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier, bool threaded) + DisplayDispatcherFacade::DisplayDispatcherFacade(const RendererConfigData& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier, bool threaded) : DisplayDispatcherMock(config, rendererSceneSender, notifier) , m_threaded{ threaded } { @@ -100,7 +100,7 @@ namespace ramses::internal return bundle; } - DisplayDispatcher::Display DisplayDispatcherFacade::createDisplayBundle(DisplayHandle displayHandle, const DisplayConfig& dispConfig) + DisplayDispatcher::Display DisplayDispatcherFacade::createDisplayBundle(DisplayHandle displayHandle, const DisplayConfigData& dispConfig) { DisplayDispatcherMock::createDisplayBundle(displayHandle, dispConfig); return m_useNiceMock ? createDisplayBundleMocks<::testing::NiceMock>() : createDisplayBundleMocks<::testing::StrictMock>(); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.h b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.h index b9cbba765..be367e1ab 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherMock.h @@ -19,19 +19,19 @@ namespace ramses::internal class DisplayDispatcherMock : public DisplayDispatcher { public: - DisplayDispatcherMock(const RendererConfig& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier); + DisplayDispatcherMock(const RendererConfigData& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier); ~DisplayDispatcherMock() override; - MOCK_METHOD(Display, createDisplayBundle, (DisplayHandle, const DisplayConfig&), (override)); + MOCK_METHOD(Display, createDisplayBundle, (DisplayHandle, const DisplayConfigData&), (override)); }; class DisplayDispatcherFacade : public DisplayDispatcherMock { public: - DisplayDispatcherFacade(const RendererConfig& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier ,bool threaded); + DisplayDispatcherFacade(const RendererConfigData& config, IRendererSceneEventSender& rendererSceneSender, IThreadAliveNotifier& notifier ,bool threaded); ~DisplayDispatcherFacade() override; - Display createDisplayBundle(DisplayHandle displayHandle, const DisplayConfig& dispConfig) override; + Display createDisplayBundle(DisplayHandle displayHandle, const DisplayConfigData& dispConfig) override; template class MOCK_TYPE = ::testing::StrictMock> MOCK_TYPE* getDisplayBundleMock(DisplayHandle display); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherTest.cpp index bfd40b4f6..c74ac20d1 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherTest.cpp @@ -20,7 +20,7 @@ namespace ramses::internal { public: ADisplayDispatcher() - : m_displayDispatcher(RendererConfig{}, m_sceneEventSender, m_notifier, false) + : m_displayDispatcher(RendererConfigData{}, m_sceneEventSender, m_notifier, false) { m_displayDispatcher.setLoopMode(ELoopMode::UpdateOnly); m_displayDispatcher.m_expectedLoopModeForNewDisplays = ELoopMode::UpdateOnly; @@ -41,7 +41,7 @@ namespace ramses::internal void createDisplay(DisplayHandle displayHandle) { - m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ displayHandle, DisplayConfig{}, nullptr }); + m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ displayHandle, DisplayConfigData{}, nullptr }); EXPECT_CALL(m_displayDispatcher, createDisplayBundle(displayHandle, _)); update(); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherThreadedTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherThreadedTest.cpp index db7eacdf7..78fb47f54 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherThreadedTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DisplayDispatcherThreadedTest.cpp @@ -23,7 +23,7 @@ namespace ramses::internal { public: ADisplayDispatcherThreaded() - : m_displayDispatcher(RendererConfig{}, m_sceneEventSender, m_notifier, true) + : m_displayDispatcher(RendererConfigData{}, m_sceneEventSender, m_notifier, true) { m_displayDispatcher.setLoopMode(ELoopMode::UpdateOnly); m_displayDispatcher.m_expectedLoopModeForNewDisplays = ELoopMode::UpdateOnly; @@ -41,7 +41,7 @@ namespace ramses::internal void createDisplay(DisplayHandle displayHandle) { - m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ displayHandle, DisplayConfig{}, nullptr }); + m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ displayHandle, DisplayConfigData{}, nullptr }); EXPECT_CALL(m_displayDispatcher, createDisplayBundle(displayHandle, _)); update(); @@ -258,7 +258,7 @@ namespace ramses::internal DisplayHandle display{ 1u }; for (int i = 0; i < 20; ++i) { - m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ display++, DisplayConfig{}, nullptr }); + m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ display++, DisplayConfigData{}, nullptr }); m_displayDispatcher.dispatchCommands(m_commandBuffer); } @@ -290,7 +290,7 @@ namespace ramses::internal DisplayHandle display{ 1u }; for (int i = 0; i < 20; ++i) { - m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ display++, DisplayConfig{}, nullptr }); + m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ display++, DisplayConfigData{}, nullptr }); m_displayDispatcher.dispatchCommands(m_commandBuffer); } diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/DisplaySetupTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/DisplaySetupTest.cpp index f73388cb1..7d748e3da 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/DisplaySetupTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/DisplaySetupTest.cpp @@ -49,11 +49,12 @@ namespace ramses::internal TEST_F(ADisplaySetup, canRegisterFramebufferInfoWithInitialValues) { const DeviceResourceHandle bufferHandle(33u); - displaySetup.registerDisplayBuffer(bufferHandle, viewport, clearColor, false, false); + displaySetup.registerDisplayBuffer(bufferHandle, viewport, clearColor, false, 4u, false); const auto& bufferInfo = displaySetup.getDisplayBuffer(bufferHandle); EXPECT_EQ(viewport, bufferInfo.viewport); EXPECT_EQ(clearColor, bufferInfo.clearColor); + EXPECT_EQ(4u, bufferInfo.sampleCount); EXPECT_TRUE(bufferInfo.scenes.empty()); EXPECT_FALSE(bufferInfo.isInterruptible); EXPECT_TRUE(bufferInfo.needsRerender); @@ -65,11 +66,12 @@ namespace ramses::internal TEST_F(ADisplaySetup, canRegisterNonInterruptibleOBInfoWithInitialValues) { const DeviceResourceHandle bufferHandle(33u); - displaySetup.registerDisplayBuffer(bufferHandle, viewport, clearColor, true, false); + displaySetup.registerDisplayBuffer(bufferHandle, viewport, clearColor, true, 4u, false); const auto& bufferInfo = displaySetup.getDisplayBuffer(bufferHandle); EXPECT_EQ(viewport, bufferInfo.viewport); EXPECT_EQ(clearColor, bufferInfo.clearColor); + EXPECT_EQ(4u, bufferInfo.sampleCount); EXPECT_TRUE(bufferInfo.scenes.empty()); EXPECT_FALSE(bufferInfo.isInterruptible); EXPECT_TRUE(bufferInfo.needsRerender); @@ -82,11 +84,12 @@ namespace ramses::internal TEST_F(ADisplaySetup, canRegisterInterruptibleOBInfoWithInitialValues) { const DeviceResourceHandle bufferHandle(33u); - displaySetup.registerDisplayBuffer(bufferHandle, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandle, viewport, clearColor, true, 4u, true); const auto& bufferInfo = displaySetup.getDisplayBuffer(bufferHandle); EXPECT_EQ(viewport, bufferInfo.viewport); EXPECT_EQ(clearColor, bufferInfo.clearColor); + EXPECT_EQ(4u, bufferInfo.sampleCount); EXPECT_TRUE(bufferInfo.scenes.empty()); EXPECT_TRUE(bufferInfo.isInterruptible); EXPECT_TRUE(bufferInfo.needsRerender); @@ -101,9 +104,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); EXPECT_FALSE(displaySetup.getDisplayBuffer(bufferHandleFB).isOffscreenBuffer); EXPECT_TRUE(displaySetup.getDisplayBuffer(bufferHandleOB).isOffscreenBuffer); @@ -114,8 +117,8 @@ namespace ramses::internal { const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); displaySetup.unregisterDisplayBuffer(bufferHandleOB); displaySetup.unregisterDisplayBuffer(bufferHandleOBint); @@ -130,9 +133,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); EXPECT_TRUE(displaySetup.getDisplayBuffer(bufferHandleFB).needsRerender); EXPECT_TRUE(displaySetup.getDisplayBuffer(bufferHandleOB).needsRerender); @@ -147,9 +150,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); displaySetup.setDisplayBufferToBeRerendered(bufferHandleFB, false); displaySetup.setDisplayBufferToBeRerendered(bufferHandleOB, false); @@ -182,9 +185,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); displaySetup.assignSceneToDisplayBuffer(scene1, bufferHandleFB, 0); displaySetup.assignSceneToDisplayBuffer(scene2, bufferHandleOB, 0); @@ -212,7 +215,7 @@ namespace ramses::internal const SceneId scene2(13u); const SceneId scene3(14u); const DeviceResourceHandle bufferHandleOB(34u); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); displaySetup.assignSceneToDisplayBuffer(scene2, bufferHandleOB, 10); expectAssignedScenesInOrder(bufferHandleOB, { { scene2, 10, false } }); @@ -247,9 +250,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); // reset re-render state displaySetup.setDisplayBufferToBeRerendered(bufferHandleFB, false); @@ -288,7 +291,7 @@ namespace ramses::internal const SceneId scene2(13u); const SceneId scene3(14u); const DeviceResourceHandle bufferHandleOB(34u); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); displaySetup.assignSceneToDisplayBuffer(scene1, bufferHandleOB, 0); displaySetup.assignSceneToDisplayBuffer(scene2, bufferHandleOB, 10); @@ -318,9 +321,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); displaySetup.assignSceneToDisplayBuffer(scene1, bufferHandleFB, 0); displaySetup.assignSceneToDisplayBuffer(scene2, bufferHandleOB, 0); @@ -362,9 +365,9 @@ namespace ramses::internal constexpr DeviceResourceHandle bufferHandleFB{ 33u }; constexpr DeviceResourceHandle bufferHandleOB{ 34u }; constexpr DeviceResourceHandle bufferHandleOBint{ 35u }; - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); EXPECT_EQ(EClearFlag::All, displaySetup.getDisplayBuffer(bufferHandleFB).clearFlags); EXPECT_EQ(EClearFlag::All, displaySetup.getDisplayBuffer(bufferHandleOB).clearFlags); @@ -384,9 +387,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); EXPECT_EQ(clearColor, displaySetup.getDisplayBuffer(bufferHandleFB).clearColor); EXPECT_EQ(clearColor, displaySetup.getDisplayBuffer(bufferHandleOB).clearColor); @@ -409,9 +412,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); // reset re-render state displaySetup.setDisplayBufferToBeRerendered(bufferHandleFB, false); @@ -430,7 +433,7 @@ namespace ramses::internal TEST_F(ADisplaySetup, canResizeDisplayBuffer) { const DeviceResourceHandle bufferHandleFB(33u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); EXPECT_EQ(viewport.width, displaySetup.getDisplayBuffer(bufferHandleFB).viewport.width); EXPECT_EQ(viewport.height, displaySetup.getDisplayBuffer(bufferHandleFB).viewport.height); @@ -445,9 +448,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); // reset re-render state displaySetup.setDisplayBufferToBeRerendered(bufferHandleFB, false); @@ -468,9 +471,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandle1(33u); const DeviceResourceHandle bufferHandle2(34u); const DeviceResourceHandle bufferHandle3(35u); - displaySetup.registerDisplayBuffer(bufferHandle1, viewport, clearColor, true, true); - displaySetup.registerDisplayBuffer(bufferHandle2, viewport, clearColor, true, true); - displaySetup.registerDisplayBuffer(bufferHandle3, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandle1, viewport, clearColor, true, 0u, true); + displaySetup.registerDisplayBuffer(bufferHandle2, viewport, clearColor, true, 0u, true); + displaySetup.registerDisplayBuffer(bufferHandle3, viewport, clearColor, true, 0u, true); const DeviceHandleVector expectedBuffersToRerender{ bufferHandle2, bufferHandle3 }; EXPECT_EQ(expectedBuffersToRerender, displaySetup.getInterruptibleOffscreenBuffersToRender(bufferHandle2)); @@ -483,11 +486,11 @@ namespace ramses::internal const DeviceResourceHandle bufferHandle3(35u); const DeviceResourceHandle bufferHandle4(36u); const DeviceResourceHandle bufferHandle5(37u); - displaySetup.registerDisplayBuffer(bufferHandle1, viewport, clearColor, true, true); - displaySetup.registerDisplayBuffer(bufferHandle2, viewport, clearColor, true, true); - displaySetup.registerDisplayBuffer(bufferHandle3, viewport, clearColor, true, true); - displaySetup.registerDisplayBuffer(bufferHandle4, viewport, clearColor, true, true); - displaySetup.registerDisplayBuffer(bufferHandle5, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandle1, viewport, clearColor, true, 0u, true); + displaySetup.registerDisplayBuffer(bufferHandle2, viewport, clearColor, true, 0u, true); + displaySetup.registerDisplayBuffer(bufferHandle3, viewport, clearColor, true, 0u, true); + displaySetup.registerDisplayBuffer(bufferHandle4, viewport, clearColor, true, 0u, true); + displaySetup.registerDisplayBuffer(bufferHandle5, viewport, clearColor, true, 0u, true); displaySetup.setDisplayBufferToBeRerendered(bufferHandle2, false); displaySetup.setDisplayBufferToBeRerendered(bufferHandle4, false); @@ -507,9 +510,9 @@ namespace ramses::internal const DeviceResourceHandle bufferHandleFB(33u); const DeviceResourceHandle bufferHandleOB(34u); const DeviceResourceHandle bufferHandleOBint(35u); - displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, false); - displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, false); - displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, true); + displaySetup.registerDisplayBuffer(bufferHandleFB, viewport, clearColor, false, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOB, viewport, clearColor, true, 0u, false); + displaySetup.registerDisplayBuffer(bufferHandleOBint, viewport, clearColor, true, 0u, true); displaySetup.assignSceneToDisplayBuffer(scene1, bufferHandleFB, 1); displaySetup.assignSceneToDisplayBuffer(scene2, bufferHandleOB, 2); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/IntersectionUtilsTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/IntersectionUtilsTest.cpp index 704edda8b..6684bebaa 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/IntersectionUtilsTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/IntersectionUtilsTest.cpp @@ -10,7 +10,7 @@ #include "internal/RendererLib/IntersectionUtils.h" #include "internal/RendererLib/RendererEventCollector.h" #include "internal/RendererLib/RendererScenes.h" -#include "SceneAllocateHelper.h" +#include "TestSceneHelper.h" #include "internal/Core/Math3d/ProjectionParams.h" #include "internal/Core/Math3d/CameraMatrixHelper.h" #include "glm/gtx/transform.hpp" @@ -27,28 +27,12 @@ namespace ramses::internal static CameraHandle preparePickableCamera(TransformationLinkCachedScene& scene, SceneAllocateHelper& sceneAllocator, const glm::ivec2 viewportOffset, const glm::ivec2 viewportSize, const glm::vec3 translation, const glm::vec3 rotation, const glm::vec3 scale) { - NodeHandle cameraNodeHandle = sceneAllocator.allocateNode(); - const auto dataLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference} }, {}); - const auto dataInstance = sceneAllocator.allocateDataInstance(dataLayout); - const auto vpDataRefLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2I} }, {}); - const auto vpOffsetInstance = sceneAllocator.allocateDataInstance(vpDataRefLayout); - const auto vpSizeInstance = sceneAllocator.allocateDataInstance(vpDataRefLayout); - const auto frustumPlanesLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector4F} }, {}); - const auto frustumPlanes = sceneAllocator.allocateDataInstance(frustumPlanesLayout); - const auto frustumNearFarLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2F} }, {}); - const auto frustumNearFar = sceneAllocator.allocateDataInstance(frustumNearFarLayout); - scene.setDataReference(dataInstance, Camera::ViewportOffsetField, vpOffsetInstance); - scene.setDataReference(dataInstance, Camera::ViewportSizeField, vpSizeInstance); - scene.setDataReference(dataInstance, Camera::FrustumPlanesField, frustumPlanes); - scene.setDataReference(dataInstance, Camera::FrustumNearFarPlanesField, frustumNearFar); - const CameraHandle cameraHandle = sceneAllocator.allocateCamera(ECameraProjectionType::Perspective, cameraNodeHandle, dataInstance); - scene.setDataSingleVector2i(vpOffsetInstance, DataFieldHandle{ 0 }, viewportOffset); - scene.setDataSingleVector2i(vpSizeInstance, DataFieldHandle{ 0 }, viewportSize); const ProjectionParams params = ProjectionParams::Perspective(19.f, static_cast(viewportSize.x) / static_cast(viewportSize.y), 0.1f, 100.f); - scene.setDataSingleVector4f(frustumPlanes, DataFieldHandle{ 0 }, { params.leftPlane, params.rightPlane, params.bottomPlane, params.topPlane }); - scene.setDataSingleVector2f(frustumNearFar, DataFieldHandle{ 0 }, { params.nearPlane, params.farPlane }); + TestSceneHelper sceneHelper(scene, false, false); + const CameraHandle cameraHandle = sceneHelper.createCamera(params, viewportOffset, viewportSize); + const auto& camera = scene.getCamera(cameraHandle); - TransformHandle cameraTransformation = sceneAllocator.allocateTransform(cameraNodeHandle); + TransformHandle cameraTransformation = sceneAllocator.allocateTransform(camera.node); scene.setTranslation(cameraTransformation, translation); scene.setRotation(cameraTransformation, glm::vec4(rotation, 1.f), ERotationType::Euler_XYZ); scene.setScaling(cameraTransformation, scale); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/LinkManagerBaseTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/LinkManagerBaseTest.cpp index 861d9f062..d16b9a2d1 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/LinkManagerBaseTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/LinkManagerBaseTest.cpp @@ -28,8 +28,8 @@ namespace ramses::internal , linkManager(rendererScenes) , providerSceneId(3u) , consumerSceneId(4u) - , providerScene(rendererScenes.createScene(SceneInfo(providerSceneId))) - , consumerScene(rendererScenes.createScene(SceneInfo(consumerSceneId))) + , providerScene(rendererScenes.createScene(SceneInfo{ providerSceneId })) + , consumerScene(rendererScenes.createScene(SceneInfo{ consumerSceneId })) , providerSceneAllocator(providerScene) , consumerSceneAllocator(consumerScene) , providerSlotHandle(55u) diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/PendingSceneResourcesUtilsTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/PendingSceneResourcesUtilsTest.cpp index 506a2f525..10371a9a8 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/PendingSceneResourcesUtilsTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/PendingSceneResourcesUtilsTest.cpp @@ -26,7 +26,7 @@ namespace ramses::internal { APendingSceneResourcesUtils() : rendererScenes(rendererEventCollector) , sceneLinksManager(rendererScenes, rendererEventCollector) - , scene(sceneLinksManager, SceneInfo(sceneID)) + , scene(sceneLinksManager, SceneInfo{ sceneID }) , allocateHelper(scene) { allocateHelper.allocateRenderTarget(renderTargetHandle); @@ -34,6 +34,7 @@ namespace ramses::internal { allocateHelper.allocateBlitPass(RenderBufferHandle(81u), RenderBufferHandle(82u), blitPassHandle); allocateHelper.allocateDataBuffer(EDataBufferType::IndexBuffer, EDataType::UInt32, 10u, dataBufferHandle); allocateHelper.allocateTextureBuffer(EPixelStorageFormat::R8, { { 32, 32 },{ 16, 16 },{ 8, 8 } }, textureBufferHandle); + allocateHelper.allocateUniformBuffer(123u, uniformBufferHandle); } protected: @@ -43,6 +44,7 @@ namespace ramses::internal { const BlitPassHandle blitPassHandle = BlitPassHandle(8u); const DataBufferHandle dataBufferHandle = DataBufferHandle(9u); const TextureBufferHandle textureBufferHandle = TextureBufferHandle(10u); + const UniformBufferHandle uniformBufferHandle{ 11u }; const MemoryHandle dummyHandle = MemoryHandle(123u); const MemoryHandle dummyHandle2 = MemoryHandle(124u); @@ -75,6 +77,7 @@ namespace ramses::internal { static const BasicActionSet ActionSet_BlitPass{ ESceneResourceAction_CreateBlitPass, ESceneResourceAction_DestroyBlitPass }; static const BasicActionSet ActionSet_DataBuffer{ ESceneResourceAction_CreateDataBuffer, ESceneResourceAction_DestroyDataBuffer, ESceneResourceAction_UpdateDataBuffer }; static const BasicActionSet ActionSet_TextureBuffer{ ESceneResourceAction_CreateTextureBuffer, ESceneResourceAction_DestroyTextureBuffer, ESceneResourceAction_UpdateTextureBuffer }; + static const BasicActionSet ActionSet_UniformBuffer{ ESceneResourceAction_CreateUniformBuffer, ESceneResourceAction_DestroyUniformBuffer, ESceneResourceAction_UpdateUniformBuffer }; static const BasicActionSet TestSceneResourceActions[] = { @@ -82,14 +85,16 @@ namespace ramses::internal { ActionSet_RenderBuffer, ActionSet_BlitPass, ActionSet_DataBuffer, - ActionSet_TextureBuffer + ActionSet_TextureBuffer, + ActionSet_UniformBuffer }; static const BasicActionSet TestSceneResourceActions_Buffers[] = { ActionSet_DataBuffer, ActionSet_TextureBuffer, - ActionSet_RenderBuffer + ActionSet_RenderBuffer, + ActionSet_UniformBuffer }; TEST_F(APendingSceneResourcesUtils, appliesSceneResourceActions) @@ -103,6 +108,8 @@ namespace ramses::internal { actions.push_back(SceneResourceAction(dataBufferHandle.asMemoryHandle(), ESceneResourceAction_UpdateDataBuffer)); actions.push_back(SceneResourceAction(textureBufferHandle.asMemoryHandle(), ESceneResourceAction_CreateTextureBuffer)); actions.push_back(SceneResourceAction(textureBufferHandle.asMemoryHandle(), ESceneResourceAction_UpdateTextureBuffer)); + actions.push_back(SceneResourceAction(uniformBufferHandle.asMemoryHandle(), ESceneResourceAction_CreateUniformBuffer)); + actions.push_back(SceneResourceAction(uniformBufferHandle.asMemoryHandle(), ESceneResourceAction_UpdateUniformBuffer)); const std::array data{}; scene.updateTextureBuffer(textureBufferHandle, 0, 0, 0, 1, 1, data.data()); scene.updateTextureBuffer(textureBufferHandle, 1, 0, 0, 1, 1, data.data()); @@ -117,6 +124,8 @@ namespace ramses::internal { EXPECT_CALL(resourceManager, updateDataBuffer(dataBufferHandle, _, _, sceneID)); EXPECT_CALL(resourceManager, uploadTextureBuffer(textureBufferHandle, _, _, _, _, sceneID)); EXPECT_CALL(resourceManager, updateTextureBuffer(textureBufferHandle, _, _, _, _, sceneID)).Times(3u); // 3 mips + EXPECT_CALL(resourceManager, uploadUniformBuffer(uniformBufferHandle, 123u, sceneID)); + EXPECT_CALL(resourceManager, updateUniformBuffer(uniformBufferHandle, 123u, _, sceneID)); PendingSceneResourcesUtils::ApplySceneResourceActions(actions, scene, resourceManager); } @@ -128,6 +137,7 @@ namespace ramses::internal { actions.push_back(SceneResourceAction(blitPassHandle.asMemoryHandle(), ESceneResourceAction_DestroyBlitPass)); actions.push_back(SceneResourceAction(dataBufferHandle.asMemoryHandle(), ESceneResourceAction_DestroyDataBuffer)); actions.push_back(SceneResourceAction(textureBufferHandle.asMemoryHandle(), ESceneResourceAction_DestroyTextureBuffer)); + actions.push_back(SceneResourceAction(uniformBufferHandle.asMemoryHandle(), ESceneResourceAction_DestroyUniformBuffer)); InSequence seq; EXPECT_CALL(resourceManager, unloadRenderTarget(renderTargetHandle, sceneID)); @@ -135,6 +145,7 @@ namespace ramses::internal { EXPECT_CALL(resourceManager, unloadBlitPassRenderTargets(blitPassHandle, sceneID)); EXPECT_CALL(resourceManager, unloadDataBuffer(dataBufferHandle, sceneID)); EXPECT_CALL(resourceManager, unloadTextureBuffer(textureBufferHandle, sceneID)); + EXPECT_CALL(resourceManager, unloadUniformBuffer(uniformBufferHandle, sceneID)); PendingSceneResourcesUtils::ApplySceneResourceActions(actions, scene, resourceManager); } @@ -144,7 +155,7 @@ namespace ramses::internal { size_t resSize = 999u; ResourceUtils::GetAllSceneResourcesFromScene(actions, scene, resSize); EXPECT_FALSE(actions.empty()); - EXPECT_EQ(1344u, resSize); + EXPECT_EQ(1467u, resSize); static const std::array data{}; scene.updateTextureBuffer(textureBufferHandle, 0u, 0u, 0u, 32, 32, data.data()); @@ -162,6 +173,9 @@ namespace ramses::internal { EXPECT_CALL(resourceManager, updateTextureBuffer(textureBufferHandle, 0u, Quad{0u, 0u, 32, 32}, 32, _, sceneID)); EXPECT_CALL(resourceManager, updateTextureBuffer(textureBufferHandle, 1u, Quad{0u, 0u, 16, 16}, 16, _, sceneID)); EXPECT_CALL(resourceManager, updateTextureBuffer(textureBufferHandle, 2u, Quad{0u, 0u, 8, 8}, 8, _, sceneID)); + + EXPECT_CALL(resourceManager, uploadUniformBuffer(uniformBufferHandle, _, sceneID)); + EXPECT_CALL(resourceManager, updateUniformBuffer(uniformBufferHandle, _, _, sceneID)); PendingSceneResourcesUtils::ApplySceneResourceActions(actions, scene, resourceManager); } diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/PlatformTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/PlatformTest.cpp index a49bca62b..bfc1e3768 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/PlatformTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/PlatformTest.cpp @@ -7,7 +7,7 @@ // ------------------------------------------------------------------------- #include "Platform_BaseMock.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/PlatformInterface/IRenderBackend.h" #include "WindowEventHandlerMock.h" #include "RenderBackendMock.h" @@ -76,8 +76,8 @@ namespace ramses::internal VerifyAndClearExpectationsOnRenderBackendMockObjects(platform); } - RendererConfig rendererConfig; - DisplayConfig displayConfig; + RendererConfigData rendererConfig; + DisplayConfigData displayConfig; WindowEventHandlerMock windowEventHandlerMock; }; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.cpp index b7c443b5d..d85e59d08 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.cpp @@ -12,7 +12,7 @@ using namespace testing; namespace ramses::internal { - Platform_BaseMock::Platform_BaseMock(const RendererConfig& config) + Platform_BaseMock::Platform_BaseMock(const RendererConfigData& config) : Platform_Base(config) { ON_CALL(*this, createWindow(_, _)).WillByDefault(Invoke([this](auto& /*unused*/, auto& /*unused*/) { diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.h b/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.h index ada9c9ff1..3ad31f37f 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/Platform_BaseMock.h @@ -22,18 +22,18 @@ namespace ramses::internal class Platform_BaseMock : public Platform_Base { public: - explicit Platform_BaseMock(const RendererConfig& config); + explicit Platform_BaseMock(const RendererConfigData& config); ~Platform_BaseMock() override; - MOCK_METHOD(bool, createWindow, (const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler), (override)); - MOCK_METHOD(bool, createContext, (const DisplayConfig& displayConfig), (override)); + MOCK_METHOD(bool, createWindow, (const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler), (override)); + MOCK_METHOD(bool, createContext, (const DisplayConfigData& displayConfig), (override)); MOCK_METHOD(bool, createContextUploading, (), (override)); - MOCK_METHOD(bool, createDeviceExtension, (const DisplayConfig& displayConfig), (override)); + MOCK_METHOD(bool, createDeviceExtension, (const DisplayConfigData& displayConfig), (override)); MOCK_METHOD(bool, createDevice, (), (override)); MOCK_METHOD(bool, createDeviceUploading, (), (override)); - MOCK_METHOD(bool, createEmbeddedCompositor, (const DisplayConfig& displayConfig), (override)); + MOCK_METHOD(bool, createEmbeddedCompositor, (const DisplayConfigData& displayConfig), (override)); MOCK_METHOD(bool, createSystemCompositorController, (), (override)); - MOCK_METHOD(void, createTextureUploadingAdapter, (const DisplayConfig& displayConfig), (override)); + MOCK_METHOD(void, createTextureUploadingAdapter, (const DisplayConfigData& displayConfig), (override)); WindowMock* window = new ::testing::StrictMock; ContextMock* context = new ::testing::StrictMock; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorInternalStateTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorInternalStateTest.cpp index 4cb4e4369..a8ca76c61 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorInternalStateTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorInternalStateTest.cpp @@ -14,7 +14,7 @@ #include "TestEqualHelper.h" #include "ResourceDeviceHandleAccessorMock.h" #include "internal/RendererLib/RendererEventCollector.h" -#include "SceneAllocateHelper.h" +#include "TestSceneHelper.h" #include namespace ramses::internal @@ -45,7 +45,7 @@ namespace ramses::internal , m_rendererScenes(m_rendererEventCollector) , m_sceneLinksManager(m_rendererScenes.getSceneLinksManager()) , m_sceneId(666u) - , m_scene(m_rendererScenes.createScene(SceneInfo(m_sceneId))) + , m_scene(m_rendererScenes.createScene(SceneInfo{ m_sceneId })) , m_sceneAllocator(m_scene) { m_executorState.setScene(m_scene); @@ -67,31 +67,12 @@ namespace ramses::internal CameraHandle createTestCamera(const glm::vec3& translation = glm::vec3(0.0f), ECameraProjectionType camProjType = ECameraProjectionType::Perspective) { - const NodeHandle cameraNode = m_sceneAllocator.allocateNode(); - const auto dataLayout = m_sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference} }, {}); - const auto dataInstance = m_sceneAllocator.allocateDataInstance(dataLayout); - const auto vpDataRefLayout = m_sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2I} }, {}); - const auto vpOffsetInstance = m_sceneAllocator.allocateDataInstance(vpDataRefLayout); - const auto vpSizeInstance = m_sceneAllocator.allocateDataInstance(vpDataRefLayout); - const auto frustumPlanesLayout = m_sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector4F} }, {}); - const auto frustumPlanes = m_sceneAllocator.allocateDataInstance(frustumPlanesLayout); - const auto frustumNearFarLayout = m_sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2F} }, {}); - const auto frustumNearFar = m_sceneAllocator.allocateDataInstance(frustumNearFarLayout); - m_scene.setDataReference(dataInstance, Camera::ViewportOffsetField, vpOffsetInstance); - m_scene.setDataReference(dataInstance, Camera::ViewportSizeField, vpSizeInstance); - m_scene.setDataReference(dataInstance, Camera::FrustumPlanesField, frustumPlanes); - m_scene.setDataReference(dataInstance, Camera::FrustumNearFarPlanesField, frustumNearFar); - const CameraHandle camera = m_sceneAllocator.allocateCamera(camProjType, cameraNode, dataInstance); - + TestSceneHelper sceneHelper(m_scene, false, false); ProjectionParams params = ProjectionParams::Frustum(ECameraProjectionType::Orthographic, FakeLeftPlane, FakeRightPlane, FakeBottomPlane, FakeTopPlane, FakeNearPlane, FakeFarPlane); if (camProjType == ECameraProjectionType::Perspective) params = ProjectionParams::Perspective(FakeFoV, FakeAspectRatio, FakeNearPlane, FakeFarPlane); - m_scene.setDataSingleVector4f(frustumPlanes, DataFieldHandle{ 0 }, { params.leftPlane, params.rightPlane, params.bottomPlane, params.topPlane }); - m_scene.setDataSingleVector2f(frustumNearFar, DataFieldHandle{ 0 }, { params.nearPlane, params.farPlane }); - - m_scene.setDataSingleVector2i(vpOffsetInstance, DataFieldHandle{ 0 }, { 0, 0 }); - m_scene.setDataSingleVector2i(vpSizeInstance, DataFieldHandle{ 0 }, { int32_t(FakeVpWidth), int32_t(FakeVpHeight) }); - + const CameraHandle camera = sceneHelper.createCamera(params, { 0.f, 0.f }, { int32_t(FakeVpWidth), int32_t(FakeVpHeight) }); + const NodeHandle cameraNode = m_scene.getCamera(camera).node; const TransformHandle cameraTransform = m_sceneAllocator.allocateTransform(cameraNode); m_scene.setTranslation(cameraTransform, translation); @@ -119,7 +100,7 @@ namespace ramses::internal { ASSERT_EQ(&m_scene, &m_executorState.getScene()); - RendererCachedScene otherScene(m_sceneLinksManager, SceneInfo(SceneId(33u))); + RendererCachedScene otherScene(m_sceneLinksManager, SceneInfo{ SceneId(33u) }); m_executorState.setScene(otherScene); ASSERT_EQ(&otherScene, &m_executorState.getScene()); } diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorTest.cpp index 229687733..65b505b87 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RenderExecutorTest.cpp @@ -14,7 +14,7 @@ #include "internal/RendererLib/RendererScenes.h" #include "internal/SceneGraph/SceneUtils/DataLayoutCreationHelper.h" #include "internal/RendererLib/RendererEventCollector.h" -#include "SceneAllocateHelper.h" +#include "TestSceneHelper.h" #include "internal/PlatformAbstraction/PlatformMath.h" #include "internal/Components/EffectUniformTime.h" #include "MockResourceHash.h" @@ -124,14 +124,21 @@ namespace ramses::internal { dataRefFieldMatrix22f = DataFieldHandle(7); uniformInputs.push_back(EffectInputInformation("textureFieldExternal", 1, EDataType::TextureSamplerExternal, EFixedSemantics::Invalid)); textureFieldExternal = DataFieldHandle(8); - uniformInputs.push_back(EffectInputInformation("dataRefFieldBool", 1, EDataType::Bool, EFixedSemantics::Invalid)); dataRefFieldBool = DataFieldHandle(9); + uniformInputs.push_back(EffectInputInformation("uniformBuffer", 1, EDataType::UniformBuffer, EFixedSemantics::Invalid)); + uniformBufferField = DataFieldHandle{ 10 }; + uniformInputs.push_back(EffectInputInformation("modelUniformBuffer", 1, EDataType::UniformBuffer, EFixedSemantics::ModelBlock)); + modelUniformBufferField = DataFieldHandle{ 11 }; + uniformInputs.push_back(EffectInputInformation("cameraUniformBuffer", 1, EDataType::UniformBuffer, EFixedSemantics::CameraBlock)); + cameraUniformBufferField = DataFieldHandle{ 12 }; + uniformInputs.push_back(EffectInputInformation("modelCameraUniformBuffer", 1, EDataType::UniformBuffer, EFixedSemantics::ModelCameraBlock)); + modelCameraUniformBufferField = DataFieldHandle{ 13 }; if (withTimeMs) { uniformInputs.push_back(EffectInputInformation("timeMs", 1, EDataType::Int32, EFixedSemantics::TimeMs)); - dataRefTimeMs = DataFieldHandle(10); + dataRefTimeMs = DataFieldHandle(14); } attributeInputs.push_back(EffectInputInformation("vertPosField", 1, EDataType::Vector3Buffer, EFixedSemantics::Invalid)); @@ -149,6 +156,10 @@ namespace ramses::internal { DataFieldHandle dataRefField2; DataFieldHandle dataRefFieldMatrix22f; DataFieldHandle dataRefFieldBool; + DataFieldHandle uniformBufferField; + DataFieldHandle modelUniformBufferField; + DataFieldHandle cameraUniformBufferField; + DataFieldHandle modelCameraUniformBufferField; DataFieldHandle dataRefTimeMs; DataFieldHandle textureField; DataFieldHandle textureFieldMS; @@ -156,6 +167,10 @@ namespace ramses::internal { DataFieldHandle fieldModelMatrix; DataFieldHandle fieldViewMatrix; DataFieldHandle fieldProjMatrix; + + static constexpr DeviceResourceHandle modelUniformBufferDeviceHandle{ 453u }; + static constexpr DeviceResourceHandle cameraUniformBufferDeviceHandle{ 454u }; + static constexpr DeviceResourceHandle modelCameraUniformBufferDeviceHandle{ 455u }; }; @@ -166,7 +181,7 @@ namespace ramses::internal { : device(renderer.deviceMock) , renderContext{ DeviceMock::FakeFrameBufferRenderTargetDeviceHandle, fakeViewportWidth, fakeViewportHeight, {}, EClearFlag::All, glm::vec4{0.f}, false } , rendererScenes(rendererEventCollector) - , scene(rendererScenes.createScene(SceneInfo())) + , scene(rendererScenes.createScene(SceneInfo{})) , sceneAllocator(scene) , fakeEffectInputs(withTimeMs) , indicesField(0u) @@ -179,15 +194,36 @@ namespace ramses::internal { , fieldViewMatrix (fakeEffectInputs.fieldViewMatrix ) , fieldProjMatrix (fakeEffectInputs.fieldProjMatrix ) { - InputIndexVector referencedInputs; - scene.preallocateSceneSize(SceneSizeInformation(0u, 0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u)); - uniformLayout = DataLayoutCreationHelper::CreateUniformDataLayoutMatchingEffectInputs(scene, fakeEffectInputs.uniformInputs, referencedInputs, MockResourceHash::EffectHash, DataLayoutHandle(0u)); + scene.preallocateSceneSize(SceneSizeInformation(0u, 0u, 0u, 0u, 0u, 1u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u)); + std::tie(uniformLayout, std::ignore) = DataLayoutCreationHelper::CreateUniformDataLayoutMatchingEffectInputs(scene, fakeEffectInputs.uniformInputs, MockResourceHash::EffectHash, DataLayoutHandle(0u)); DataFieldInfoVector dataFields(3u); dataFields[indicesField.asMemoryHandle()] = DataFieldInfo(EDataType::Indices, 1u, EFixedSemantics::Indices); dataFields[vertPosField.asMemoryHandle()] = DataFieldInfo(EDataType::Vector3Buffer, 1u, EFixedSemantics::Invalid); dataFields[vertTexcoordField.asMemoryHandle()] = DataFieldInfo(EDataType::Vector2Buffer, 1u, EFixedSemantics::TextPositionsAttribute); geometryLayout = sceneAllocator.allocateDataLayout(dataFields, MockResourceHash::EffectHash, DataLayoutHandle(2u)); + + static constexpr size_t ExpectedModelUBOSize = 1 * 16 * 4; + static constexpr size_t ExpectedCameraUBOSize = 2 * 16 * 4 + 1 * 3 * 4; + static constexpr size_t ExpectedModelCameraUBOSize = 3 * 16 * 4; + ON_CALL(resourceManager, uploadUniformBuffer(Matcher(_), ExpectedModelUBOSize, scene.getSceneId())) + .WillByDefault([](SemanticUniformBufferHandle handle, auto /*size*/, auto /*sceneId*/) + { + EXPECT_EQ(handle.getType(), SemanticUniformBufferHandle::Type::Model); + return FakeEffectInputs::modelUniformBufferDeviceHandle; + }); + ON_CALL(resourceManager, uploadUniformBuffer(Matcher(_), ExpectedCameraUBOSize, scene.getSceneId())) + .WillByDefault([](SemanticUniformBufferHandle handle, auto /*size*/, auto /*sceneId*/) + { + EXPECT_EQ(handle.getType(), SemanticUniformBufferHandle::Type::Camera); + return FakeEffectInputs::cameraUniformBufferDeviceHandle; + }); + ON_CALL(resourceManager, uploadUniformBuffer(Matcher(_), ExpectedModelCameraUBOSize, scene.getSceneId())) + .WillByDefault([](SemanticUniformBufferHandle handle, auto /*size*/, auto /*sceneId*/) + { + EXPECT_EQ(handle.getType(), SemanticUniformBufferHandle::Type::ModelCamera); + return FakeEffectInputs::modelCameraUniformBufferDeviceHandle; + }); } protected: @@ -213,6 +249,7 @@ namespace ramses::internal { TextureSamplerHandle sampler; TextureSamplerHandle samplerMS; TextureSamplerHandle samplerExternal; + UniformBufferHandle uniformBuffer; const DataFieldHandle indicesField; const DataFieldHandle vertPosField; const DataFieldHandle vertTexcoordField; @@ -242,30 +279,13 @@ namespace ramses::internal { RenderPassHandle createRenderPassWithCamera(const ProjectionParams& params, const Viewport& viewport = { fakeViewportX, fakeViewportY, fakeViewportWidth, fakeViewportHeight }) { const RenderPassHandle pass = sceneAllocator.allocateRenderPass(); - const NodeHandle cameraNode = sceneAllocator.allocateNode(); - const auto dataLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference}, DataFieldInfo{EDataType::DataReference} }, {}); - const auto dataInstance = sceneAllocator.allocateDataInstance(dataLayout); - const auto vpDataRefLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2I} }, {}); - const auto vpOffsetInstance = sceneAllocator.allocateDataInstance(vpDataRefLayout); - const auto vpSizeInstance = sceneAllocator.allocateDataInstance(vpDataRefLayout); - const auto frustumPlanesLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector4F} }, {}); - const auto frustumPlanes = sceneAllocator.allocateDataInstance(frustumPlanesLayout); - const auto frustumNearFarLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2F} }, {}); - const auto frustumNearFar = sceneAllocator.allocateDataInstance(frustumNearFarLayout); - scene.setDataReference(dataInstance, Camera::ViewportOffsetField, vpOffsetInstance); - scene.setDataReference(dataInstance, Camera::ViewportSizeField, vpSizeInstance); - scene.setDataReference(dataInstance, Camera::FrustumPlanesField, frustumPlanes); - scene.setDataReference(dataInstance, Camera::FrustumNearFarPlanesField, frustumNearFar); - const CameraHandle camera = sceneAllocator.allocateCamera(params.getProjectionType(), cameraNode, dataInstance); - - scene.setDataSingleVector4f(frustumPlanes, DataFieldHandle{ 0 }, { params.leftPlane, params.rightPlane, params.bottomPlane, params.topPlane }); - scene.setDataSingleVector2f(frustumNearFar, DataFieldHandle{ 0 }, { params.nearPlane, params.farPlane }); - - scene.setDataSingleVector2i(vpOffsetInstance, DataFieldHandle{ 0 }, { viewport.posX, viewport.posY }); - scene.setDataSingleVector2i(vpSizeInstance, DataFieldHandle{ 0 }, { int32_t(viewport.width), int32_t(viewport.height) }); - + TestSceneHelper sceneHelper(scene, false ,false); + const CameraHandle cameraHandle = sceneHelper.createCamera(params, { viewport.posX, viewport.posY }, { int32_t(viewport.width), int32_t(viewport.height) }); + const auto& camera = scene.getCamera(cameraHandle); + const NodeHandle cameraNode = camera.node; sceneAllocator.allocateTransform(cameraNode); - scene.setRenderPassCamera(pass, camera); + scene.setRenderPassCamera(pass, cameraHandle); + return pass; } @@ -285,6 +305,8 @@ namespace ramses::internal { DataInstances createTestDataInstance(bool setTextureSampler = true, bool setIndexArray = true) { + uniformBuffer = sceneAllocator.allocateUniformBuffer(10u); + //create samplers sampler = sceneAllocator.allocateTextureSampler({ { ETextureAddressMode::Clamp, ETextureAddressMode::Repeat, ETextureAddressMode::Mirror, ETextureSamplingMethod::Nearest_MipMapNearest, ETextureSamplingMethod::Nearest, 2u }, MockResourceHash::TextureHash }); samplerMS = sceneAllocator.allocateTextureSampler({ {}, MockResourceHash::TextureHash }); @@ -311,7 +333,7 @@ namespace ramses::internal { // explicit preallocation needed because here we use DataLayoutCreationHelper which allocates inside, // we cannot use scene allocation helper MemoryHandle nextHandle = std::max(scene.getDataInstanceCount(), scene.getDataLayoutCount()); - scene.preallocateSceneSize(SceneSizeInformation(0u, 0u, 0u, 0u, 0u, nextHandle + 4u, nextHandle + 4u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u)); + scene.preallocateSceneSize(SceneSizeInformation(0u, 0u, 0u, 0u, 0u, nextHandle + 4u, nextHandle + 4u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u, 0u)); dataRef1 = DataLayoutCreationHelper::CreateAndBindDataReference( scene, dataInstances.first, fakeEffectInputs.dataRefField1, EDataType::Float, DataLayoutHandle(nextHandle), DataInstanceHandle(nextHandle)); dataRef2 = DataLayoutCreationHelper::CreateAndBindDataReference( @@ -325,6 +347,8 @@ namespace ramses::internal { scene.setDataSingleMatrix22f(dataRefMatrix22f, DataFieldHandle(0u), glm::mat2(1, 2, 3, 4)); scene.setDataSingleBoolean(dataRefBool, DataFieldHandle(0u), true); + scene.setDataUniformBuffer(dataInstances.first, fakeEffectInputs.uniformBufferField, uniformBuffer); + if (setIndexArray) { scene.setDataResource(dataInstances.second, indicesField, MockResourceHash::IndexArrayHash, DataBufferHandle::Invalid(), 2u, 0u, 0u); @@ -484,6 +508,10 @@ namespace ramses::internal { EXPECT_CALL(device, activateTextureSamplerObject(Property(&TextureSamplerStates::hash, Eq(expectedSamplerExternalStates.hash())), textureFieldExternal)).InSequence(deviceSequence); EXPECT_CALL(device, setConstant(fakeEffectInputs.dataRefFieldBool, 1, Matcher(Pointee(Eq(true))))) .InSequence(deviceSequence); + EXPECT_CALL(device, activateUniformBuffer(DeviceMock::FakeUniformBufferDeviceHandle, fakeEffectInputs.uniformBufferField)) .InSequence(deviceSequence); + EXPECT_CALL(device, activateUniformBuffer(fakeEffectInputs.modelUniformBufferDeviceHandle, fakeEffectInputs.modelUniformBufferField)) .InSequence(deviceSequence); + EXPECT_CALL(device, activateUniformBuffer(fakeEffectInputs.cameraUniformBufferDeviceHandle, fakeEffectInputs.cameraUniformBufferField)) .InSequence(deviceSequence); + EXPECT_CALL(device, activateUniformBuffer(fakeEffectInputs.modelCameraUniformBufferDeviceHandle, fakeEffectInputs.modelCameraUniformBufferField)) .InSequence(deviceSequence); if (fakeEffectInputs.dataRefTimeMs.isValid()) { @@ -540,10 +568,22 @@ namespace ramses::internal { void updateScenes(const RenderableVector& renderablesWithUpdatedVAOs) { + // simulate order of commands done by RendererSceneUpdater scene.updateRenderablesAndResourceCache(resourceManager); + for (const auto& passInfo : scene.getSortedRenderingPasses()) + { + if (passInfo.getType() == ERenderingPassType::RenderPass) + { + const auto camera = scene.getRenderPass(passInfo.getRenderPassHandle()).camera; + const auto& passRenderables = scene.getOrderedRenderablesForPass(passInfo.getRenderPassHandle()); + scene.collectDirtySemanticUniformBuffers(passRenderables, camera); + } + } scene.updateRenderableVertexArrays(resourceManager, renderablesWithUpdatedVAOs); scene.markVertexArraysClean(); scene.updateRenderableWorldMatrices(); + scene.updateSemanticUniformBuffers(); + scene.uploadSemanticUniformBuffers(resourceManager); } void expectRenderingWithProjection(RenderableHandle renderable, const glm::mat4& projMatrix, const uint32_t instanceCount = 1u) diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererCachedSceneTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererCachedSceneTest.cpp index 616e20b0e..fc02d2f7b 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererCachedSceneTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererCachedSceneTest.cpp @@ -18,7 +18,7 @@ namespace ramses::internal public: ARendererCachedScene() : rendererScenes(rendererEventCollector) - , scene(rendererScenes.createScene(SceneInfo())) + , scene(rendererScenes.createScene(SceneInfo{})) , sceneAllocator(scene) , sceneHelper(scene) { diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandBufferTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandBufferTest.cpp index 1f8411ab5..b33649cac 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandBufferTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandBufferTest.cpp @@ -27,7 +27,7 @@ namespace ramses::internal { const SceneId sceneId{ 12u }; const SceneInfo sceneInfo{ sceneId, "testScene" }; const DisplayHandle displayHandle{ 1u }; - const DisplayConfig displayConfig{}; + const DisplayConfigData displayConfig{}; const OffscreenBufferHandle obHandle{ 6u }; const SceneId providerSceneId{}; const SceneId consumerSceneId{}; @@ -70,7 +70,7 @@ namespace ramses::internal { void ARendererCommandBuffer::expectFilledBufferVisits() { InSequence seq; - EXPECT_CALL(visitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote)); + EXPECT_CALL(visitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::OpenGL, EVulkanAPIVersion::Invalid, ESPIRVVersion::Invalid)); EXPECT_CALL(visitor, handleSceneUnpublished(sceneId)); EXPECT_CALL(visitor, handleSceneReceived(sceneInfo)); EXPECT_CALL(visitor, setSceneState(sceneId, RendererSceneState::Rendered)); @@ -226,7 +226,7 @@ namespace ramses::internal { Sequence s2; Sequence s3; Sequence s4; - EXPECT_CALL(visitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote)).InSequence(s1); + EXPECT_CALL(visitor, handleScenePublished(sceneId, EScenePublicationMode::LocalAndRemote, ERenderBackendCompatibility::OpenGL, EVulkanAPIVersion::Invalid, ESPIRVVersion::Invalid)).InSequence(s1); EXPECT_CALL(visitor, handleSceneUnpublished(sceneId)).InSequence(s1); EXPECT_CALL(visitor, handleSceneReceived(sceneInfo)).InSequence(s2); EXPECT_CALL(visitor, setSceneState(sceneId, RendererSceneState::Rendered)).InSequence(s2); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandExecutorTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandExecutorTest.cpp index 2d420c36f..9ad5e78bc 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandExecutorTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererCommandExecutorTest.cpp @@ -287,7 +287,7 @@ namespace ramses::internal { TEST_F(ARendererCommandExecutor, createsAndDestroysDisplay) { const DisplayHandle displayHandle(33u); - const DisplayConfig displayConfig; + const DisplayConfigData displayConfig; m_commandBuffer.enqueueCommand(RendererCommand::CreateDisplay{ displayHandle, displayConfig, nullptr }); EXPECT_CALL(m_sceneUpdater, createDisplayContext(displayConfig, nullptr)); @@ -326,7 +326,7 @@ namespace ramses::internal { const NodeHandle node(33u); SceneUpdate actions; - SceneActionCollectionCreator creator(actions.actions); + SceneActionCollectionCreator creator(actions.actions, EFeatureLevel_Latest); creator.allocateNode(0u, node); actions.flushInfos.flushCounter = 1u; actions.flushInfos.containsValidInformation = true; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererConfigTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererConfigTest.cpp index 6f96e19a5..500556d94 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererConfigTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererConfigTest.cpp @@ -7,13 +7,13 @@ // ------------------------------------------------------------------------- #include "gtest/gtest.h" -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" namespace ramses::internal { TEST(AInternalRendererConfig, hasDefaultValues) { - ramses::internal::RendererConfig config; + ramses::internal::RendererConfigData config; EXPECT_FALSE(config.getSystemCompositorControlEnabled()); EXPECT_EQ(std::chrono::microseconds{10000u}, config.getFrameCallbackMaxPollTime()); EXPECT_EQ("", config.getWaylandDisplayForSystemCompositorController()); @@ -21,14 +21,14 @@ namespace ramses::internal TEST(AInternalRendererConfig, canEnableSystemCompositorControl) { - ramses::internal::RendererConfig config; + ramses::internal::RendererConfigData config; config.enableSystemCompositorControl(); EXPECT_TRUE(config.getSystemCompositorControlEnabled()); } TEST(AInternalRendererConfig, canSetGetMaxFramecallbackPollTime) { - ramses::internal::RendererConfig config; + ramses::internal::RendererConfigData config; config.setFrameCallbackMaxPollTime(std::chrono::microseconds{123u}); EXPECT_EQ(std::chrono::microseconds{123u}, config.getFrameCallbackMaxPollTime()); @@ -36,7 +36,7 @@ namespace ramses::internal TEST(AInternalRendererConfig, canSetGetWaylandDisplayForSystemCompositorController) { - ramses::internal::RendererConfig config; + ramses::internal::RendererConfigData config; config.setWaylandDisplayForSystemCompositorController("ramses wd"); EXPECT_EQ("ramses wd", config.getWaylandDisplayForSystemCompositorController()); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererEventCollectorTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererEventCollectorTest.cpp index d089a34f5..8ac086faa 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererEventCollectorTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererEventCollectorTest.cpp @@ -75,7 +75,7 @@ namespace ramses::internal TEST_F(ARendererEventCollector, CanAddRendererEventWithDisplayConfig) { - DisplayConfig config; + DisplayConfigData config; config.setClearColor({1, 0, 0, 1}); config.setResizable(true); config.setSwapInterval(2); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.cpp index b7fdca0b7..deff5888c 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.cpp @@ -12,7 +12,7 @@ #include "internal/RendererLib/PlatformInterface/IDisplayController.h" #include "internal/RendererLib/PlatformInterface/ISystemCompositorController.h" #include "internal/RendererLib/RendererStatistics.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" namespace ramses::internal { using namespace testing; @@ -44,7 +44,7 @@ namespace ramses::internal { RendererMockWithMockDisplay::~RendererMockWithMockDisplay() = default; template class MOCK_TYPE> - IDisplayController* RendererMockWithMockDisplay::createDisplayControllerFromConfig(const DisplayConfig& displayConfig) + IDisplayController* RendererMockWithMockDisplay::createDisplayControllerFromConfig(const DisplayConfigData& displayConfig) { assert(m_displayController == nullptr); m_displayController = new MOCK_TYPE < DisplayControllerMock >; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.h b/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.h index 1ab9687f6..bad696a8a 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererMock.h @@ -17,7 +17,7 @@ namespace ramses::internal { - class DisplayConfig; + class DisplayConfigData; class RendererScenes; class SceneExpirationMonitor; @@ -43,7 +43,7 @@ class RendererMockWithMockDisplay : public RendererMock const RendererEventCollector& eventCollector, const SceneExpirationMonitor& expirationMonitor, const RendererStatistics& statistics); ~RendererMockWithMockDisplay() override; - IDisplayController* createDisplayControllerFromConfig(const ramses::internal::DisplayConfig& displayConfig) override; + IDisplayController* createDisplayControllerFromConfig(const ramses::internal::DisplayConfigData& displayConfig) override; void markBufferWithSceneForRerender(SceneId sceneId) override; void setClearFlags(DeviceResourceHandle bufferDeviceHandle, ClearFlags clearFlags) override; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.cpp index 787275ac4..b998b593b 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.cpp @@ -53,6 +53,8 @@ namespace ramses::internal { ON_CALL(*this, getVertexArrayDeviceHandle(_, _)).WillByDefault(Return(DeviceMock::FakeVertexArrayDeviceHandle)); ON_CALL(*this, getExternalBufferDeviceHandle(Ne(ExternalBufferHandle::Invalid()))).WillByDefault(Return(DeviceMock::FakeExternalTextureDeviceHandle)); ON_CALL(*this, getEmptyExternalBufferDeviceHandle()).WillByDefault(Return(DeviceMock::FakeEmptyExternalTextureDeviceHandle)); + ON_CALL(*this, getUniformBufferDeviceHandle(Matcher(_), _)).WillByDefault(Return(DeviceMock::FakeUniformBufferDeviceHandle)); + ON_CALL(*this, getUniformBufferDeviceHandle(Matcher(_), _)).WillByDefault(Return(DeviceMock::FakeUniformBufferDeviceHandle)); ON_CALL(*this, getBlitPassRenderTargetsDeviceHandle(_, _, _, _)).WillByDefault(DoAll(SetArgReferee<2>(DeviceMock::FakeBlitPassRenderTargetDeviceHandle), SetArgReferee<3>(DeviceMock::FakeBlitPassRenderTargetDeviceHandle))); @@ -69,6 +71,8 @@ namespace ramses::internal { EXPECT_CALL(*this, getResourcesInUseByScene(_)).Times(AnyNumber()); EXPECT_CALL(*this, getExternalBufferDeviceHandle(_)).Times(AnyNumber()); EXPECT_CALL(*this, getEmptyExternalBufferDeviceHandle()).Times(AnyNumber()); + EXPECT_CALL(*this, getUniformBufferDeviceHandle(Matcher(_), _)).Times(AnyNumber()); + EXPECT_CALL(*this, getUniformBufferDeviceHandle(Matcher(_), _)).Times(AnyNumber()); } RendererResourceManagerRefCountMock::~RendererResourceManagerRefCountMock() diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.h b/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.h index ae564b805..61cec9e4d 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerMock.h @@ -34,6 +34,8 @@ namespace ramses::internal{ MOCK_METHOD(DeviceResourceHandle, getExternalBufferDeviceHandle, (ExternalBufferHandle), (const, override)); MOCK_METHOD(DeviceResourceHandle, getEmptyExternalBufferDeviceHandle, (), (const, override)); MOCK_METHOD(uint32_t, getExternalBufferGlId, (ExternalBufferHandle), (const, override)); + MOCK_METHOD(DeviceResourceHandle, getUniformBufferDeviceHandle, (UniformBufferHandle uniformBufferHandle, SceneId sceneId), (const, override)); + MOCK_METHOD(DeviceResourceHandle, getUniformBufferDeviceHandle, (SemanticUniformBufferHandle handle, SceneId sceneId), (const, override)); // IRendererResourceManager MOCK_METHOD(EResourceStatus, getResourceStatus, (const ResourceContentHash& hash), (const, override)); MOCK_METHOD(EResourceType, getResourceType, (const ResourceContentHash& hash), (const, override)); @@ -61,6 +63,13 @@ namespace ramses::internal{ MOCK_METHOD(void, unloadDataBuffer, (DataBufferHandle dataBufferHandle, SceneId sceneId), (override)); MOCK_METHOD(void, updateDataBuffer, (DataBufferHandle handle, uint32_t dataSizeInBytes, const std::byte* data, SceneId sceneId), (override)); + MOCK_METHOD(void, uploadUniformBuffer, (UniformBufferHandle uniformBufferHandle, uint32_t size, SceneId sceneId), (override)); + MOCK_METHOD(void, unloadUniformBuffer, (UniformBufferHandle uniformBufferHandle, SceneId sceneId), (override)); + MOCK_METHOD(void, updateUniformBuffer, (UniformBufferHandle uniformBufferHandle, uint32_t size, const std::byte* data, SceneId sceneId), (override)); + MOCK_METHOD(DeviceResourceHandle, uploadUniformBuffer, (SemanticUniformBufferHandle handle, uint32_t size, SceneId sceneId), (override)); + MOCK_METHOD(void, unloadUniformBuffer, (SemanticUniformBufferHandle handle, SceneId sceneId), (override)); + MOCK_METHOD(void, updateUniformBuffer, (SemanticUniformBufferHandle handle, uint32_t size, const std::byte* data, SceneId sceneId), (override)); + MOCK_METHOD(void, uploadTextureBuffer, (TextureBufferHandle textureBufferHandle, uint32_t width, uint32_t height, EPixelStorageFormat textureFormat, uint32_t mipLevelCount, SceneId sceneId), (override)); MOCK_METHOD(void, unloadTextureBuffer, (TextureBufferHandle textureBufferHandle, SceneId sceneId), (override)); MOCK_METHOD(void, updateTextureBuffer, (TextureBufferHandle textureBufferHandle, uint32_t mipLevel, const Quad& area, uint32_t stride, const std::byte* data, SceneId sceneId), (override)); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerTest.cpp index f9125111b..21b19932e 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererResourceManagerTest.cpp @@ -18,7 +18,7 @@ #include "MockResourceHash.h" #include "ResourceUploaderMock.h" #include "internal/Watchdog/ThreadAliveNotifierMock.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" namespace ramses::internal { using namespace testing; @@ -29,7 +29,7 @@ namespace ramses::internal { explicit ARendererResourceManager() : fakeSceneId(66u) , asyncEffectUploader(platform, platform.renderBackendMock, notifier, DisplayHandle{ 1 }) - , resourceManager(platform.renderBackendMock, std::unique_ptr{ resUploader }, asyncEffectUploader, embeddedCompositingManager, {}, frameTimer, stats) + , resourceManager(platform.renderBackendMock, std::unique_ptr{ resUploader }, &asyncEffectUploader, embeddedCompositingManager, {}, frameTimer, stats) { InSequence s; EXPECT_CALL(platform.renderBackendMock.contextMock, disable()).WillOnce(Return(true)); @@ -1013,7 +1013,7 @@ namespace ramses::internal { TEST_F(ARendererResourceManager, UploadAndDeleteValidShader) { - auto effectRes = std::make_unique("", "", "", std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, ""); + auto effectRes = std::make_unique("", "", "", SPIRVShaders{}, std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, "", EFeatureLevel_Latest); const ResourceContentHash resHash = effectRes->getHash(); // request some resources @@ -1029,6 +1029,66 @@ namespace ramses::internal { resourceManager.uploadAndUnloadPendingResources(); } + TEST_F(ARendererResourceManager, UploadsAndUpdatesAndUnloadsUniformBuffer) + { + constexpr UniformBufferHandle ubHandle{ 1u }; + constexpr DeviceResourceHandle deviceHandle{ 11111u }; + constexpr uint32_t uniformBufferSize{ 123u }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, allocateUniformBuffer(uniformBufferSize)).WillOnce(Return(deviceHandle)); + resourceManager.uploadUniformBuffer(ubHandle, uniformBufferSize, fakeSceneId); + + std::vector dummyData{ uniformBufferSize, std::byte{ 1 } }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, uploadUniformBufferData(deviceHandle, dummyData.data(), uniformBufferSize)); + resourceManager.updateUniformBuffer(ubHandle, uniformBufferSize, dummyData.data(), fakeSceneId); + + EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteUniformBuffer(deviceHandle)); + resourceManager.unloadUniformBuffer(ubHandle, fakeSceneId); + } + + TEST_F(ARendererResourceManager, CanGetDeviceHandleForUniformBuffer) + { + constexpr UniformBufferHandle ubHandle{ 1u }; + constexpr DeviceResourceHandle deviceHandle{ 11111u }; + constexpr uint32_t uniformBufferSize{ 123u }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, allocateUniformBuffer(uniformBufferSize)).WillOnce(Return(deviceHandle)); + resourceManager.uploadUniformBuffer(ubHandle, uniformBufferSize, fakeSceneId); + + EXPECT_EQ(deviceHandle, resourceManager.getUniformBufferDeviceHandle(ubHandle, fakeSceneId)); + + EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteUniformBuffer(deviceHandle)); + resourceManager.unloadUniformBuffer(ubHandle, fakeSceneId); + } + + TEST_F(ARendererResourceManager, UploadsAndUpdatesAndUnloadsSemanticUniformBuffer) + { + constexpr SemanticUniformBufferHandle ubHandle{ RenderableHandle{ 1u } }; + constexpr DeviceResourceHandle deviceHandle{ 11111u }; + constexpr uint32_t uniformBufferSize{ 123u }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, allocateUniformBuffer(uniformBufferSize)).WillOnce(Return(deviceHandle)); + EXPECT_EQ(deviceHandle, resourceManager.uploadUniformBuffer(ubHandle, uniformBufferSize, fakeSceneId)); + + std::vector dummyData{ uniformBufferSize, std::byte{ 1 } }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, uploadUniformBufferData(deviceHandle, dummyData.data(), uniformBufferSize)); + resourceManager.updateUniformBuffer(ubHandle, uniformBufferSize, dummyData.data(), fakeSceneId); + + EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteUniformBuffer(deviceHandle)); + resourceManager.unloadUniformBuffer(ubHandle, fakeSceneId); + } + + TEST_F(ARendererResourceManager, CanGetDeviceHandleForSemanticUniformBuffer) + { + constexpr SemanticUniformBufferHandle ubHandle{ RenderableHandle{ 1u } }; + constexpr DeviceResourceHandle deviceHandle{ 11111u }; + constexpr uint32_t uniformBufferSize{ 123u }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, allocateUniformBuffer(uniformBufferSize)).WillOnce(Return(deviceHandle)); + EXPECT_EQ(deviceHandle, resourceManager.uploadUniformBuffer(ubHandle, uniformBufferSize, fakeSceneId)); + + EXPECT_EQ(deviceHandle, resourceManager.getUniformBufferDeviceHandle(ubHandle, fakeSceneId)); + + EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteUniformBuffer(deviceHandle)); + resourceManager.unloadUniformBuffer(ubHandle, fakeSceneId); + } + TEST_F(ARendererResourceManager, DoesNotUnregisterResourceThatWasUploaded) { const ResourceContentHash resource = MockResourceHash::VertArrayHash; @@ -1050,7 +1110,7 @@ namespace ramses::internal { TEST_F(ARendererResourceManager, DoesNotUnregisterResourceThatWasScheduledForUpload) { - auto effectRes = std::make_unique("", "", "", std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, ""); + auto effectRes = std::make_unique("", "", "", SPIRVShaders{}, std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, "", EFeatureLevel_Latest); const ResourceContentHash resHash = effectRes->getHash(); // request some resources @@ -1090,7 +1150,7 @@ namespace ramses::internal { TEST_F(ARendererResourceManager, DoesNotUnloadEffectThatGetsUnreferencedAndReReferencedWhileCompiling) { - auto effectRes = std::make_unique("", "", "", std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, ""); + auto effectRes = std::make_unique("", "", "", SPIRVShaders{}, std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, "", EFeatureLevel_Latest); const ResourceContentHash resHash = effectRes->getHash(); // request some resources @@ -1148,7 +1208,7 @@ namespace ramses::internal { TEST_F(ARendererResourceManager, UploadInvalidShaderResultsInBrokenResource) { - auto effectRes = std::make_unique("", "", "", std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, ""); + auto effectRes = std::make_unique("", "", "", SPIRVShaders{}, std::optional{}, EffectInputInformationVector{}, EffectInputInformationVector{}, "", EFeatureLevel_Latest); const ResourceContentHash resHash = effectRes->getHash(); // request some resources @@ -1236,6 +1296,16 @@ namespace ramses::internal { EXPECT_CALL(platform.renderBackendMock.deviceMock, allocateVertexArray(Ref(vaInfo))); resourceManager.uploadVertexArray(renderable, vaInfo, fakeSceneId); + //upload uniform buffer + constexpr UniformBufferHandle ubHandle{ 777u }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, allocateUniformBuffer(_)); + resourceManager.uploadUniformBuffer(ubHandle, 123u, fakeSceneId); + + //upload semantic uniform buffer + constexpr SemanticUniformBufferHandle subHandle{ RenderableHandle{ 777u } }; + EXPECT_CALL(platform.renderBackendMock.deviceMock, allocateUniformBuffer(_)); + resourceManager.uploadUniformBuffer(subHandle, 123u, fakeSceneId); + // unload all scene resources EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteRenderBuffer(_)).Times(2); EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteRenderTarget(_)).Times(3); @@ -1243,6 +1313,7 @@ namespace ramses::internal { EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteVertexBuffer(_)); EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteTexture(_)); EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteVertexArray(_)); + EXPECT_CALL(platform.renderBackendMock.deviceMock, deleteUniformBuffer(_)).Times(2); resourceManager.unloadAllSceneResourcesForScene(fakeSceneId); // Make sure the resource was deleted before the resourceManager gets out of scope diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneResourceRegistryTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneResourceRegistryTest.cpp index 149e4af61..d5961201b 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneResourceRegistryTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneResourceRegistryTest.cpp @@ -6,7 +6,8 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "gtest/gtest.h" +#include +#include #include "internal/RendererLib/RendererSceneResourceRegistry.h" #include "internal/SceneGraph/SceneAPI/EDataBufferType.h" @@ -23,24 +24,13 @@ namespace ramses::internal TEST_F(ARendererSceneResourceRegistry, doesNotContainAnythingInitially) { - RenderBufferHandleVector rbs; - RenderTargetHandleVector rts; - BlitPassHandleVector bps; - DataBufferHandleVector dbs; - TextureBufferHandleVector tbs; - - registry.getAllRenderBuffers(rbs); - registry.getAllRenderTargets(rts); - registry.getAllBlitPasses(bps); - registry.getAllDataBuffers(dbs); - registry.getAllTextureBuffers(tbs); - - - EXPECT_TRUE(rbs.empty()); - EXPECT_TRUE(rts.empty()); - EXPECT_TRUE(bps.empty()); - EXPECT_TRUE(dbs.empty()); - EXPECT_TRUE(tbs.empty()); + EXPECT_TRUE(registry.getAll().empty()); + EXPECT_TRUE(registry.getAll().empty()); + EXPECT_TRUE(registry.getAll().empty()); + EXPECT_TRUE(registry.getAll().empty()); + EXPECT_TRUE(registry.getAll().empty()); + EXPECT_TRUE(registry.getAll().empty()); + EXPECT_TRUE(registry.getAll().empty()); } TEST_F(ARendererSceneResourceRegistry, canAddAndRemoveRenderBuffer) @@ -48,25 +38,24 @@ namespace ramses::internal const RenderBufferHandle rb(13u); const DeviceResourceHandle deviceHandle(123u); const RenderBuffer props{ 16u, 8u, EPixelStorageFormat::R16F, ERenderBufferAccessMode::ReadWrite, 2u }; - registry.addRenderBuffer(rb, deviceHandle, 10u, props); + registry.add(rb, deviceHandle, 10u, props); - EXPECT_EQ(deviceHandle, registry.getRenderBufferDeviceHandle(rb)); + EXPECT_EQ(deviceHandle, registry.get(rb).deviceHandle); - EXPECT_EQ(10u, registry.getRenderBufferByteSize(rb)); - EXPECT_EQ(props.width, registry.getRenderBufferProperties(rb).width); - EXPECT_EQ(props.height, registry.getRenderBufferProperties(rb).height); - EXPECT_EQ(props.format, registry.getRenderBufferProperties(rb).format); - EXPECT_EQ(props.accessMode, registry.getRenderBufferProperties(rb).accessMode); - EXPECT_EQ(props.sampleCount, registry.getRenderBufferProperties(rb).sampleCount); + EXPECT_EQ(10u, registry.get(rb).size); + EXPECT_EQ(props.width, registry.get(rb).renderBufferProperties.width); + EXPECT_EQ(props.height, registry.get(rb).renderBufferProperties.height); + EXPECT_EQ(props.format, registry.get(rb).renderBufferProperties.format); + EXPECT_EQ(props.accessMode, registry.get(rb).renderBufferProperties.accessMode); + EXPECT_EQ(props.sampleCount, registry.get(rb).renderBufferProperties.sampleCount); - RenderBufferHandleVector rbs; - registry.getAllRenderBuffers(rbs); + auto rbs = registry.getAll(); ASSERT_EQ(1u, rbs.size()); EXPECT_EQ(rb, rbs[0]); rbs.clear(); - registry.removeRenderBuffer(rb); - registry.getAllRenderBuffers(rbs); + registry.remove(rb); + rbs = registry.getAll(); EXPECT_TRUE(rbs.empty()); } @@ -74,18 +63,17 @@ namespace ramses::internal { const RenderTargetHandle rt(13u); const DeviceResourceHandle deviceHandle(123u); - registry.addRenderTarget(rt, deviceHandle); + registry.add(rt, deviceHandle); - EXPECT_EQ(deviceHandle, registry.getRenderTargetDeviceHandle(rt)); + EXPECT_EQ(deviceHandle, registry.get(rt)); - RenderTargetHandleVector rts; - registry.getAllRenderTargets(rts); + auto rts = registry.getAll(); ASSERT_EQ(1u, rts.size()); EXPECT_EQ(rt, rts[0]); rts.clear(); - registry.removeRenderTarget(rt); - registry.getAllRenderTargets(rts); + registry.remove(rt); + rts = registry.getAll(); EXPECT_TRUE(rts.empty()); } @@ -94,7 +82,7 @@ namespace ramses::internal const BlitPassHandle bp(13u); const DeviceResourceHandle deviceHandle1(123u); const DeviceResourceHandle deviceHandle2(124u); - registry.addBlitPass(bp, deviceHandle1, deviceHandle2); + registry.add(bp, deviceHandle1, deviceHandle2); DeviceResourceHandle deviceHandle1actual; DeviceResourceHandle deviceHandle2actual; @@ -102,14 +90,13 @@ namespace ramses::internal EXPECT_EQ(deviceHandle1, deviceHandle1actual); EXPECT_EQ(deviceHandle2, deviceHandle2actual); - BlitPassHandleVector bps; - registry.getAllBlitPasses(bps); + auto bps = registry.getAll(); ASSERT_EQ(1u, bps.size()); EXPECT_EQ(bp, bps[0]); bps.clear(); - registry.removeBlitPass(bp); - registry.getAllBlitPasses(bps); + registry.remove(bp); + bps = registry.getAll(); EXPECT_TRUE(bps.empty()); } @@ -118,16 +105,15 @@ namespace ramses::internal const DataBufferHandle db(13u); const DeviceResourceHandle deviceHandle(123u); const EDataBufferType dataBufferType = EDataBufferType::IndexBuffer; - registry.addDataBuffer(db, deviceHandle, dataBufferType, 0u); + registry.add(db, deviceHandle, dataBufferType, 0u); - DataBufferHandleVector dbs; - registry.getAllDataBuffers(dbs); + auto dbs = registry.getAll(); ASSERT_EQ(1u, dbs.size()); EXPECT_EQ(db, dbs[0]); dbs.clear(); - registry.removeDataBuffer(db); - registry.getAllDataBuffers(dbs); + registry.remove(db); + dbs = registry.getAll(); EXPECT_TRUE(dbs.empty()); } @@ -136,10 +122,10 @@ namespace ramses::internal const DataBufferHandle db(13u); const DeviceResourceHandle deviceHandle(123u); const EDataBufferType dataBufferType = EDataBufferType::IndexBuffer; - registry.addDataBuffer(db, deviceHandle, dataBufferType, 0u); + registry.add(db, deviceHandle, dataBufferType, 0u); - EXPECT_EQ(deviceHandle, registry.getDataBufferDeviceHandle(db)); - registry.removeDataBuffer(db); + EXPECT_EQ(deviceHandle, registry.get(db).deviceHandle); + registry.remove(db); } TEST_F(ARendererSceneResourceRegistry, canGetDataBufferType) @@ -147,26 +133,25 @@ namespace ramses::internal const DataBufferHandle db(13u); const DeviceResourceHandle deviceHandle(123u); const EDataBufferType dataBufferType = EDataBufferType::IndexBuffer; - registry.addDataBuffer(db, deviceHandle, dataBufferType, 0u); + registry.add(db, deviceHandle, dataBufferType, 0u); - EXPECT_EQ(dataBufferType, registry.getDataBufferType(db)); - registry.removeDataBuffer(db); + EXPECT_EQ(dataBufferType, registry.get(db).dataBufferType); + registry.remove(db); } TEST_F(ARendererSceneResourceRegistry, canAddAndRemoveTextureBuffers) { const TextureBufferHandle tb(13u); const DeviceResourceHandle deviceHandle(123u); - registry.addTextureBuffer(tb, deviceHandle, EPixelStorageFormat::RG8, 0u); + registry.add(tb, deviceHandle, EPixelStorageFormat::RG8, 0u); - TextureBufferHandleVector tbs; - registry.getAllTextureBuffers(tbs); + auto tbs = registry.getAll(); ASSERT_EQ(1u, tbs.size()); EXPECT_EQ(tb, tbs[0]); tbs.clear(); - registry.removeTextureBuffer(tb); - registry.getAllTextureBuffers(tbs); + registry.remove(tb); + tbs = registry.getAll(); EXPECT_TRUE(tbs.empty()); } @@ -174,10 +159,52 @@ namespace ramses::internal { const TextureBufferHandle tb(13u); const DeviceResourceHandle deviceHandle(123u); - registry.addTextureBuffer(tb, deviceHandle, EPixelStorageFormat::RG8, 0u); + registry.add(tb, deviceHandle, EPixelStorageFormat::RG8, 0u); + + EXPECT_EQ(deviceHandle, registry.get(tb).deviceHandle); + EXPECT_EQ(EPixelStorageFormat::RG8, registry.get(tb).format); + registry.remove(tb); + } - EXPECT_EQ(deviceHandle, registry.getTextureBufferDeviceHandle(tb)); - EXPECT_EQ(EPixelStorageFormat::RG8, registry.getTextureBufferFormat(tb)); - registry.removeTextureBuffer(tb); + TEST_F(ARendererSceneResourceRegistry, canAddAndRemoveUniformBuffers) + { + const UniformBufferHandle ub1{ 13u }; + const UniformBufferHandle ub2{ 14u }; + const DeviceResourceHandle deviceHandle1{ 123u }; + const DeviceResourceHandle deviceHandle2{ 124u }; + registry.add(ub1, deviceHandle1); + registry.add(ub2, deviceHandle2); + + EXPECT_THAT(registry.getAll(), ::testing::UnorderedElementsAre(ub1, ub2)); + EXPECT_EQ(deviceHandle1, registry.get(ub1)); + EXPECT_EQ(deviceHandle2, registry.get(ub2)); + + registry.remove(ub1); + EXPECT_THAT(registry.getAll(), ::testing::ElementsAre(ub2)); + EXPECT_EQ(deviceHandle2, registry.get(ub2)); + + registry.remove(ub2); + EXPECT_TRUE(registry.getAll().empty()); + } + + TEST_F(ARendererSceneResourceRegistry, canAddAndRemoveSemanticUniformBuffers) + { + const SemanticUniformBufferHandle ub1{ RenderableHandle{ 13u } }; + const SemanticUniformBufferHandle ub2{ CameraHandle{ 14u } }; + const DeviceResourceHandle deviceHandle1{ 123u }; + const DeviceResourceHandle deviceHandle2{ 124u }; + registry.add(ub1, deviceHandle1); + registry.add(ub2, deviceHandle2); + + EXPECT_THAT(registry.getAll(), ::testing::UnorderedElementsAre(ub1, ub2)); + EXPECT_EQ(deviceHandle1, registry.get(ub1)); + EXPECT_EQ(deviceHandle2, registry.get(ub2)); + + registry.remove(ub1); + EXPECT_THAT(registry.getAll(), ::testing::ElementsAre(ub2)); + EXPECT_EQ(deviceHandle2, registry.get(ub2)); + + registry.remove(ub2); + EXPECT_TRUE(registry.getAll().empty()); } } diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.cpp index b8c6219cb..1961150ec 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.cpp @@ -29,7 +29,8 @@ namespace ramses::internal const_cast(rendererEventCollector), const_cast(frameTimer), const_cast(expirationMonitor), - const_cast(notifier)) + const_cast(notifier), + EFeatureLevel_Latest) { } @@ -75,7 +76,7 @@ namespace ramses::internal std::unique_ptr RendererSceneUpdaterFacade::createResourceManager( IRenderBackend& renderBackend, IEmbeddedCompositingManager& embeddedCompositingManager, - const DisplayConfig& displayConfig, + const DisplayConfigData& displayConfig, IBinaryShaderCache* binaryShaderCache) { RendererSceneUpdaterPartialMock::createResourceManager(renderBackend, embeddedCompositingManager, displayConfig, binaryShaderCache); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.h b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.h index 4a27192f3..6f591f9f8 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterFacade.h @@ -23,7 +23,7 @@ namespace ramses::internal MOCK_METHOD(void, handleSceneUpdate, (SceneId sceneId, SceneUpdate&& update), (override)); MOCK_METHOD(void, handlePickEvent, (SceneId sceneId, glm::vec2 coords), (override)); - MOCK_METHOD(std::unique_ptr, createResourceManager, (IRenderBackend&, IEmbeddedCompositingManager&, const DisplayConfig&, IBinaryShaderCache*), (override)); + MOCK_METHOD(std::unique_ptr, createResourceManager, (IRenderBackend&, IEmbeddedCompositingManager&, const DisplayConfigData&, IBinaryShaderCache*), (override)); }; class RendererSceneUpdaterFacade : public RendererSceneUpdaterPartialMock @@ -49,7 +49,7 @@ namespace ramses::internal std::unique_ptr createResourceManager( IRenderBackend& renderBackend, IEmbeddedCompositingManager& embeddedCompositingManager, - const DisplayConfig& displayConfig, + const DisplayConfigData& displayConfig, IBinaryShaderCache* binaryShaderCache) override; }; } diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterMock.h b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterMock.h index 733d0c0d4..a76788b6b 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterMock.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterMock.h @@ -11,7 +11,7 @@ #include "gmock/gmock.h" #include "internal/RendererLib/IRendererSceneUpdater.h" #include "internal/Components/SceneUpdate.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/PlatformInterface/IBinaryShaderCache.h" namespace ramses::internal @@ -23,7 +23,7 @@ namespace ramses::internal ~RendererSceneUpdaterMock() override; MOCK_METHOD(void, handleSceneUpdate, (SceneId sceneId, SceneUpdate&& sceneUpdate), (override)); - MOCK_METHOD(void, createDisplayContext, (const DisplayConfig& displayConfig, IBinaryShaderCache*), (override)); + MOCK_METHOD(void, createDisplayContext, (const DisplayConfigData& displayConfig, IBinaryShaderCache*), (override)); MOCK_METHOD(void, destroyDisplayContext, (), (override)); MOCK_METHOD(void, handleScenePublished, (SceneId sceneId, EScenePublicationMode mode), (override)); MOCK_METHOD(void, handleSceneUnpublished, (SceneId sceneId), (override)); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.cpp index 003b9c12e..20d8cae9c 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.cpp @@ -157,7 +157,7 @@ namespace ramses::internal { EXPECT_CALL(sceneEventSender, sendSubscribeScene(getSceneId())); rendererSceneUpdater->handleSceneSubscriptionRequest(getSceneId()); - rendererSceneUpdater->handleSceneReceived(SceneInfo(getSceneId())); + rendererSceneUpdater->handleSceneReceived(SceneInfo{ getSceneId() }); // named flush ignored expectNoEvent(); @@ -282,8 +282,7 @@ namespace ramses::internal { auto& stageScene = *stagingScene[0]; const RenderPassHandle pass = stageScene.allocateRenderPass(0, {}); - const auto dataLayout = stageScene.allocateDataLayout({DataFieldInfo{EDataType::Vector2I}, DataFieldInfo{EDataType::Vector2I}}, ResourceContentHash::Invalid(), {}); - const CameraHandle camera = stageScene.allocateCamera(ECameraProjectionType::Orthographic, stageScene.allocateNode(0, {}), stageScene.allocateDataInstance(dataLayout, {}), {}); + const CameraHandle camera = createCamera(); stageScene.setRenderPassCamera(pass, camera); stageScene.setRenderPassRenderOnce(pass, true); performFlush(); @@ -877,7 +876,7 @@ namespace ramses::internal { { const auto displayWidth = WindowMock::FakeWidth; const auto displayHeight = WindowMock::FakeHeight; - DisplayConfig dispConfig; + DisplayConfigData dispConfig; dispConfig.setDesiredWindowWidth(displayWidth); dispConfig.setDesiredWindowHeight(displayHeight); createDisplayAndExpectSuccess(dispConfig); @@ -939,6 +938,31 @@ namespace ramses::internal { destroyDisplay(); } + TEST_F(ARendererSceneUpdater, createsReadPixelsFailedEventIfOffscreenBufferMultisampled) + { + createDisplayAndExpectSuccess(); + + const OffscreenBufferHandle buffer(1u); + expectOffscreenBufferUploaded(buffer); + EXPECT_TRUE(rendererSceneUpdater->handleBufferCreateRequest(buffer, 10u, 10u, 8u, false, EDepthBufferType::DepthStencil)); + expectEvent(ERendererEventType::OffscreenBufferCreated); + + const bool fullScreen = false; + const bool sendViaDLT = false; + const std::string_view filename; + readPixels(buffer, 0u, 0u, 10u, 10u, fullScreen, sendViaDLT, filename); + + EXPECT_CALL(*renderer.m_displayController, readPixels(_, _, _, _, _, _)).Times(0); + doRenderLoop(); + + expectReadPixelsEvents({ { buffer, false } }); + + rendererSceneUpdater->processScreenshotResults(); + expectNoEvent(); + + destroyDisplay(); + } + TEST_F(ARendererSceneUpdater, readPixelsFromDisplayAndSaveToFileWithoutGeneratingEvent) { createDisplayAndExpectSuccess(); @@ -966,7 +990,7 @@ namespace ramses::internal { { const auto displayWidth = WindowMock::FakeWidth; const auto displayHeight = WindowMock::FakeHeight; - DisplayConfig dispConfig; + DisplayConfigData dispConfig; dispConfig.setDesiredWindowWidth(displayWidth); dispConfig.setDesiredWindowHeight(displayHeight); createDisplayAndExpectSuccess(dispConfig); @@ -5018,7 +5042,7 @@ namespace ramses::internal { TEST_F(ARendererSceneUpdater, reportsPickedObjects) { - DisplayConfig config; + DisplayConfigData config; config.setDesiredWindowWidth(1280u); config.setDesiredWindowHeight(480u); createDisplayAndExpectSuccess(config); @@ -5242,4 +5266,228 @@ namespace ramses::internal { update(); } + TEST_F(ARendererSceneUpdater, updatesSemanticUbos_UpdatesModelUbo) + { + createDisplayAndExpectSuccess(); + createPublishAndSubscribeScene(); + mapScene(); + showScene(); + + expectResourcesReferencedAndProvided({ MockResourceHash::EffectHash, MockResourceHash::IndexArrayHash }); + expectVertexArrayUploaded(); + createRenderable(0u, false, false, EVisibilityMode::Visible, true); + setRenderableResources(); + expectSemanticCameraUniformBufferUploaded(); + expectSemanticCameraUniformBufferUpdated(); + + auto& scene = *stagingScene[0]; + const auto& renderable = scene.getRenderable(renderableHandle); + const auto transformHandle = scene.allocateTransform(renderable.node, {}); + + expectSemanticModelUniformBufferUploaded(); + expectSemanticModelUniformBufferUpdated(); + performFlush(); + update(); + + scene.setTranslation(transformHandle, { 1.f, 2.f, 3.f }); + expectSemanticModelUniformBufferUpdated(); + performFlush(); + update(); + + //update without changing transform leads to no UBO update + update(); + + hideScene(); + unmapScene(); + destroyDisplay(); + } + + TEST_F(ARendererSceneUpdater, updatesSemanticUbos_UpdatesModelUbo_TransformationLinking) + { + createDisplayAndExpectSuccess(); + + const uint32_t providerScene = createPublishAndSubscribeScene(); + const uint32_t consumerScene = createPublishAndSubscribeScene(); + mapScene(providerScene); + mapScene(consumerScene); + showScene(providerScene); + showScene(consumerScene); + + //create a renderable in each scene + expectResourcesReferencedAndProvided({ MockResourceHash::EffectHash, MockResourceHash::IndexArrayHash }, consumerScene); + expectVertexArrayUploaded(consumerScene); + createRenderable(consumerScene, false, false, EVisibilityMode::Visible, true); + setRenderableResources(consumerScene); + expectSemanticCameraUniformBufferUploaded(consumerScene); + expectSemanticCameraUniformBufferUpdated(consumerScene); + expectSemanticModelUniformBufferUploaded(consumerScene); + expectSemanticModelUniformBufferUpdated(consumerScene); + update(); + + expectResourcesReferenced({ MockResourceHash::EffectHash}, providerScene); + expectResourcesReferenced({ MockResourceHash::IndexArrayHash }, providerScene); + expectResourcesProvided(2u); + expectVertexArrayUploaded(providerScene); + createRenderable(providerScene, false, false, EVisibilityMode::Visible, true); + setRenderableResources(providerScene); + expectSemanticCameraUniformBufferUploaded(providerScene); + expectSemanticCameraUniformBufferUpdated(providerScene); + expectSemanticModelUniformBufferUploaded(providerScene); + expectSemanticModelUniformBufferUpdated(providerScene); + update(); + + //link scenes + TransformHandle providerTransform{}; + TransformHandle consumerTransform{}; + const auto providerConsumer = createTransformationSlots(&providerTransform, providerScene, consumerScene, &consumerTransform); + linkProviderToConsumer(getSceneId(providerScene), providerConsumer.first, getSceneId(consumerScene), providerConsumer.second); + + //add renderable to each scene as child to the node with the linked transform + const auto& providerRenderable = stagingScene[providerScene]->getRenderable(renderableHandle); + const auto& consumerRenderable = stagingScene[consumerScene]->getRenderable(renderableHandle); + const auto providerNode = stagingScene[providerScene]->getTransformNode(providerTransform); + const auto consumerNode = stagingScene[consumerScene]->getTransformNode(consumerTransform); + + stagingScene[providerScene]->addChildToNode(providerNode, providerRenderable.node); + stagingScene[consumerScene]->addChildToNode(consumerNode, consumerRenderable.node); + performFlush(providerScene); + performFlush(consumerScene); + // reparenting already triggers UBO updates + expectSemanticModelUniformBufferUpdated(consumerScene); + expectSemanticModelUniformBufferUpdated(providerScene); + update(); + + //update provider transform and expect both provider and consumer renderables' model UBOs get updated + stagingScene[providerScene]->setTranslation(providerTransform, { 1.f, 2.f, 3.f }); + performFlush(providerScene); + expectSemanticModelUniformBufferUpdated(consumerScene); + expectSemanticModelUniformBufferUpdated(providerScene); + update(); + + //update without changing transform leads to no UBO update + update(); + + hideScene(providerScene); + hideScene(consumerScene); + unmapScene(providerScene); + unmapScene(consumerScene); + destroyDisplay(); + } + + TEST_F(ARendererSceneUpdater, noSemanticUbosUpdateIfSceneNotRendered) + { + createDisplayAndExpectSuccess(); + createPublishAndSubscribeScene(); + mapScene(); + + expectResourcesReferencedAndProvided({ MockResourceHash::EffectHash, MockResourceHash::IndexArrayHash }); + createRenderable(0u, false, false, EVisibilityMode::Visible, true); + setRenderableResources(); + // no initial update of UBOs + + auto& scene = *stagingScene[0]; + const auto& renderable = scene.getRenderable(renderableHandle); + const auto transformHandle = scene.allocateTransform(renderable.node, {}); + + performFlush(); + update(); + + scene.setTranslation(transformHandle, { 1.f, 2.f, 3.f }); + performFlush(); + // no UBO update expected + update(); + + unmapScene(); + destroyDisplay(); + } + + TEST_F(ARendererSceneUpdater, updatesSemanticUbos_onlyOnceIfRenderableInTwoRenderPasses) + { + createDisplayAndExpectSuccess(); + createPublishAndSubscribeScene(); + mapScene(); + showScene(); + + expectResourcesReferencedAndProvided({ MockResourceHash::EffectHash, MockResourceHash::IndexArrayHash }); + expectVertexArrayUploaded(); + createRenderable(0u, false, false, EVisibilityMode::Visible, true); + setRenderableResources(); + expectSemanticCameraUniformBufferUploaded(); + expectSemanticModelUniformBufferUploaded(); + expectSemanticCameraUniformBufferUpdated(); + expectSemanticModelUniformBufferUpdated(); + + auto& scene = *stagingScene[0]; + SceneAllocateHelper sceneAllocator(scene); + const auto& renderable = scene.getRenderable(renderableHandle); + const auto transformHandle = sceneAllocator.allocateTransform(renderable.node, {}); + + //add to 2nd render pass + const auto renderPassHandle2 = sceneAllocator.allocateRenderPass(); + const auto cameraHandle2 = createCamera(0u, ECameraProjectionType::Perspective); + const auto rgHandle2 = sceneAllocator.allocateRenderGroup(); + scene.addRenderableToRenderGroup(rgHandle2, renderableHandle, 0u); + scene.addRenderGroupToRenderPass(renderPassHandle2, rgHandle2, 0u); + scene.setRenderPassCamera(renderPassHandle2, cameraHandle2); + scene.setRenderPassEnabled(renderPassHandle2, true); + expectSemanticCameraUniformBufferUploaded(); + expectSemanticModelUniformBufferUploaded(); + + performFlush(); + update(); + + scene.setTranslation(transformHandle, { 1.f, 2.f, 3.f }); + performFlush(); + // only one update + expectSemanticModelUniformBufferUpdated(); + update(); + + //update without changing transform leads to no UBO update + update(); + + hideScene(); + unmapScene(); + destroyDisplay(); + } + + TEST_F(ARendererSceneUpdater, noSemanticUbosUpdateIfRenderableNotInRenderPass) + { + createDisplayAndExpectSuccess(); + createPublishAndSubscribeScene(); + mapScene(); + showScene(); + + expectResourcesReferencedAndProvided({ MockResourceHash::EffectHash, MockResourceHash::IndexArrayHash }); + expectVertexArrayUploaded(); + createRenderable(0u, false, false, EVisibilityMode::Visible, true); + setRenderableResources(); + expectSemanticCameraUniformBufferUploaded(); + expectSemanticCameraUniformBufferUpdated(); + expectSemanticModelUniformBufferUploaded(); + expectSemanticModelUniformBufferUpdated(); + + auto& scene = *stagingScene[0]; + SceneAllocateHelper sceneAllocator(scene); + const auto& renderable = scene.getRenderable(renderableHandle); + const auto transformHandle = sceneAllocator.allocateTransform(renderable.node, {}); + + performFlush(); + update(); + + // remove renderable from group/pass + scene.removeRenderableFromRenderGroup(renderGroupHandle, renderableHandle); + performFlush(); + update(); + + // trigger change + scene.setTranslation(transformHandle, { 1.f, 2.f, 3.f }); + performFlush(); + + // no UBO update + update(); + + hideScene(); + unmapScene(); + destroyDisplay(); + } } diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.h b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.h index 6beab9810..4d115eb0b 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererSceneUpdaterTest.h @@ -25,7 +25,7 @@ #include "ResourceDeviceHandleAccessorMock.h" #include "MockResourceHash.h" #include "SceneReferenceLogicMock.h" -#include "SceneAllocateHelper.h" +#include "TestSceneHelper.h" #include "internal/PlatformAbstraction/PlatformThread.h" #include "internal/PlatformAbstraction/Collections/Pair.h" #include "RendererSceneEventSenderMock.h" @@ -54,6 +54,7 @@ namespace ramses::internal { frameTimer.startFrame(); rendererSceneUpdater->setLimitFlushesForceApply(ForceApplyFlushesLimit); rendererSceneUpdater->setLimitFlushesForceUnsubscribe(ForceUnsubscribeFlushLimit); + rendererSceneUpdater->setForceMapTimeout(std::chrono::seconds{ 20 }); // some tests fail if scene gets force mapped which can happen when running tests on overloaded system (esp. with valgrind) EXPECT_CALL(renderer, setClearColor(_, _)).Times(0); // called explicitly from tests, no sense in tracking @@ -80,7 +81,7 @@ namespace ramses::internal { { const auto sceneIndex = static_cast(stagingScene.size()); const SceneId sceneId(sceneIndex); - stagingScene.emplace_back(new ActionCollectingScene(SceneInfo(sceneId))); + stagingScene.emplace_back(new ActionCollectingScene(SceneInfo{ sceneId })); return sceneIndex; } @@ -109,7 +110,7 @@ namespace ramses::internal { void receiveScene(uint32_t sceneIndex = 0u) { const SceneId sceneId = getSceneId(sceneIndex); - rendererSceneUpdater->handleSceneReceived(SceneInfo(sceneId)); + rendererSceneUpdater->handleSceneReceived(SceneInfo{ sceneId }); EXPECT_TRUE(sceneStateExecutor.getSceneState(sceneId) == ESceneState::SubscriptionPending); EXPECT_TRUE(rendererScenes.hasScene(sceneId)); } @@ -372,7 +373,7 @@ namespace ramses::internal { SceneUpdate update; update.actions = (std::move(scene.getSceneActionCollection())); - SceneActionCollectionCreator creator(update.actions); + SceneActionCollectionCreator creator(update.actions, EFeatureLevel_Latest); ResourceContentHashVector resources; ResourceChanges resourceChanges; @@ -406,7 +407,7 @@ namespace ramses::internal { return !rendererSceneUpdater->hasPendingFlushes(stagingScene[sceneIndex]->getSceneId()); } - void createDisplayAndExpectSuccess(const DisplayConfig& displayConfig = DisplayConfig()) + void createDisplayAndExpectSuccess(const DisplayConfigData& displayConfig = DisplayConfigData()) { ASSERT_TRUE(rendererSceneUpdater->m_resourceManagerMock == nullptr); EXPECT_CALL(*rendererSceneUpdater, createResourceManager(_, _, _, _)); @@ -456,31 +457,36 @@ namespace ramses::internal { } } - void createRenderable(uint32_t sceneIndex = 0u, bool withVertexArray = false, bool withTextureSampler = false, EVisibilityMode visibility = EVisibilityMode::Visible) + void createRenderable(uint32_t sceneIndex = 0u, bool withVertexArray = false, bool withTextureSampler = false, EVisibilityMode visibility = EVisibilityMode::Visible, bool withModelUbo = false) { - createRenderableNoFlush(sceneIndex, withVertexArray, withTextureSampler, visibility); + createRenderableNoFlush(sceneIndex, withVertexArray, withTextureSampler, visibility, withModelUbo); performFlush(sceneIndex); } - void createRenderableNoFlush(uint32_t sceneIndex = 0u, bool withVertexArray = false, bool withTextureSampler = false, EVisibilityMode visibility = EVisibilityMode::Visible) + CameraHandle createCamera(uint32_t sceneIndex = 0u, ECameraProjectionType projectionType = ECameraProjectionType::Perspective) { - const NodeHandle renderableNode(1u); - const RenderPassHandle renderPassHandle(2u); - const RenderGroupHandle renderGroupHandle(3u); - const CameraHandle cameraHandle(4u); - const DataLayoutHandle uniformDataLayoutHandle(0u); - const DataLayoutHandle geometryDataLayoutHandle(1u); - const DataLayoutHandle camDataLayoutHandle(2u); - const DataInstanceHandle camDataHandle(2u); + IScene& scene = *stagingScene[sceneIndex]; + TestSceneHelper sceneHelper(scene, false, false); + const auto cameraHandle = sceneHelper.createCamera(projectionType, { 0.1f, 1.f }, { -1.f, 1.f, -1.f, 1.f }, {}, {}, {}); + + // these are overridden in tests where more concrete expectations are set + EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, uploadUniformBuffer(SemanticUniformBufferHandle{ cameraHandle }, 140u, getSceneId(sceneIndex))).Times(AtMost(1)); + EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, updateUniformBuffer(SemanticUniformBufferHandle{ cameraHandle }, 140u, _, getSceneId(sceneIndex))).Times(AnyNumber()); + return cameraHandle; + } + + void createRenderableNoFlush(uint32_t sceneIndex = 0u, bool withVertexArray = false, bool withTextureSampler = false, EVisibilityMode visibility = EVisibilityMode::Visible, bool withUbo = false) + { IScene& scene = *stagingScene[sceneIndex]; - scene.allocateRenderPass(0u, renderPassHandle); scene.allocateRenderGroup(0u, 0u, renderGroupHandle); - scene.allocateNode(0u, renderableNode); + + const RenderPassHandle renderPassHandle = scene.allocateRenderPass(0u, {}); + const NodeHandle renderableNode = scene.allocateNode(0u, {}); scene.allocateRenderable(renderableNode, renderableHandle); - scene.allocateDataLayout({ DataFieldInfo{EDataType::Vector2I}, DataFieldInfo{EDataType::Vector2I} }, MockResourceHash::EffectHash, camDataLayoutHandle); - scene.allocateCamera(ECameraProjectionType::Perspective, scene.allocateNode(0, {}), scene.allocateDataInstance(camDataLayoutHandle, camDataHandle), cameraHandle); + + const CameraHandle cameraHandle = createCamera(sceneIndex, ECameraProjectionType::Perspective); scene.addRenderableToRenderGroup(renderGroupHandle, renderableHandle, 0u); scene.addRenderGroupToRenderPass(renderPassHandle, renderGroupHandle, 0u); @@ -492,7 +498,11 @@ namespace ramses::internal { { uniformDataFields.push_back(DataFieldInfo{ EDataType::TextureSampler2D }); } - scene.allocateDataLayout(uniformDataFields, MockResourceHash::EffectHash, uniformDataLayoutHandle); + if (withUbo) + { + uniformDataFields.push_back(DataFieldInfo{ EDataType::Matrix44F, 1u, EFixedSemantics::ModelBlock }); + } + const DataLayoutHandle uniformDataLayoutHandle = scene.allocateDataLayout(uniformDataFields, MockResourceHash::EffectHash, {}); scene.allocateDataInstance(uniformDataLayoutHandle, uniformDataInstanceHandle); scene.setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Uniforms, uniformDataInstanceHandle); @@ -502,7 +512,7 @@ namespace ramses::internal { { geometryDataFields.push_back(DataFieldInfo{ EDataType::Vector3Buffer, 1u, EFixedSemantics::Invalid }); } - scene.allocateDataLayout(geometryDataFields, MockResourceHash::EffectHash, geometryDataLayoutHandle); + const DataLayoutHandle geometryDataLayoutHandle = scene.allocateDataLayout(geometryDataFields, MockResourceHash::EffectHash, {}); scene.allocateDataInstance(geometryDataLayoutHandle, geometryDataInstanceHandle); scene.setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Geometry, geometryDataInstanceHandle); scene.setRenderableVisibility(renderableHandle, visibility); @@ -510,7 +520,6 @@ namespace ramses::internal { void destroyRenderable(uint32_t sceneIndex = 0u) { - const RenderGroupHandle renderGroupHandle(3u); IScene& scene = *stagingScene[sceneIndex]; scene.removeRenderableFromRenderGroup(renderGroupHandle, renderableHandle); scene.releaseRenderable(renderableHandle); @@ -679,6 +688,35 @@ namespace ramses::internal { EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, uploadVertexArray(_, _, getSceneId(sceneIdx))); } + void expectSemanticModelUniformBufferUploaded(uint32_t sceneIdx = 0u) + { + EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, uploadUniformBuffer(Matcher(_), 64u, getSceneId(sceneIdx))) + .WillRepeatedly([](SemanticUniformBufferHandle handle, auto /*size*/, auto /*sceneId*/) + { + EXPECT_EQ(handle.getType(), SemanticUniformBufferHandle::Type::Model); + return DeviceMock::FakeUniformBufferDeviceHandle; + }); + } + void expectSemanticCameraUniformBufferUploaded(uint32_t sceneIdx = 0u) + { + EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, uploadUniformBuffer(Matcher(_), 140u, getSceneId(sceneIdx))) + .WillRepeatedly([](SemanticUniformBufferHandle handle, auto /*size*/, auto /*sceneId*/) + { + EXPECT_EQ(handle.getType(), SemanticUniformBufferHandle::Type::Camera); + return DeviceMock::FakeUniformBufferDeviceHandle; + }); + } + void expectSemanticModelUniformBufferUpdated(uint32_t sceneIdx = 0u) + { + EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, updateUniformBuffer(Matcher(_), 64u, _, getSceneId(sceneIdx))) + .WillOnce([](SemanticUniformBufferHandle handle, auto /*size*/, auto /*data*/, auto /*sceneId*/) { EXPECT_EQ(handle.getType(), SemanticUniformBufferHandle::Type::Model); }); + } + void expectSemanticCameraUniformBufferUpdated(uint32_t sceneIdx = 0u) + { + EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, updateUniformBuffer(Matcher(_), 140u, _, getSceneId(sceneIdx))) + .WillOnce([](SemanticUniformBufferHandle handle, auto /*size*/, auto /*data*/, auto /*sceneId*/) { EXPECT_EQ(handle.getType(), SemanticUniformBufferHandle::Type::Camera); }); + } + void expectVertexArrayUnloaded(uint32_t sceneIdx = 0u) { EXPECT_CALL(*rendererSceneUpdater->m_resourceManagerMock, unloadVertexArray(_, getSceneId(sceneIdx))); @@ -834,7 +872,10 @@ namespace ramses::internal { scene.setDataSlotTexture(providerDataSlot, newProvidedValue); } - std::pair createTransformationSlots(TransformHandle* providerTransformHandleOut = nullptr, uint32_t providerSceneIdx = 0u, uint32_t consumerSceneIdx = 1u) + std::pair createTransformationSlots(TransformHandle* providerTransformHandleOut = nullptr, + uint32_t providerSceneIdx = 0u, + uint32_t consumerSceneIdx = 1u, + TransformHandle* consumerTransformHandleOut = nullptr) { IScene& scene1 = *stagingScene[providerSceneIdx]; IScene& scene2 = *stagingScene[consumerSceneIdx]; @@ -843,9 +884,11 @@ namespace ramses::internal { const auto nodeHandle2 = scene2.allocateNode(0, {}); const auto providerTransformHandle = scene1.allocateTransform(nodeHandle1, {}); - scene2.allocateTransform(nodeHandle2, {}); + const auto consumerTransformHandle = scene2.allocateTransform(nodeHandle2, {}); if (nullptr != providerTransformHandleOut) *providerTransformHandleOut = providerTransformHandle; + if (nullptr != consumerTransformHandleOut) + *consumerTransformHandleOut = consumerTransformHandle; const DataSlotId providerId(getNextFreeDataSlotIdForDataLinking()); const DataSlotId consumerId(getNextFreeDataSlotIdForDataLinking()); @@ -1000,9 +1043,11 @@ namespace ramses::internal { static constexpr DisplayHandle Display{ 1u }; - const RenderableHandle renderableHandle{ 1 }; - const DataInstanceHandle uniformDataInstanceHandle{ 0 }; - const DataInstanceHandle geometryDataInstanceHandle{ 1 }; + const RenderableHandle renderableHandle{ 11 }; + const RenderGroupHandle renderGroupHandle{ 3u }; + const DataInstanceHandle uniformDataInstanceHandle{ 10 }; + const DataInstanceHandle geometryDataInstanceHandle{ 11 }; + UniformBufferHandle cameraUbo; const TextureSamplerHandle samplerHandle{ 2 }; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererScenesTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererScenesTest.cpp index 9a7eb5eb2..55e80db0d 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererScenesTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererScenesTest.cpp @@ -45,10 +45,10 @@ namespace ramses::internal { const std::string sceneName("bla"); const SceneId sceneID(12u); - SceneInfo sceneInfo(sceneID, sceneName); + SceneInfo sceneInfo{ sceneID, sceneName }; IScene& createdScene = rendererScenes.createScene(sceneInfo); - SceneSizeInformation sceneSizeInfo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18); + SceneSizeInformation sceneSizeInfo(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19); createdScene.preallocateSceneSize(sceneSizeInfo); EXPECT_EQ(1u, rendererScenes.size()); @@ -64,7 +64,7 @@ namespace ramses::internal TEST_F(ARendererScenes, destroysSceneAndStagingInfo) { const SceneId sceneID(12u); - rendererScenes.createScene(SceneInfo(sceneID)); + rendererScenes.createScene(SceneInfo{ sceneID }); rendererScenes.destroyScene(sceneID); @@ -76,13 +76,13 @@ namespace ramses::internal TEST_F(ARendererScenes, canIterateOverScenes) { const SceneId sceneID1(12u); - rendererScenes.createScene(SceneInfo(sceneID1)); + rendererScenes.createScene(SceneInfo{ sceneID1 }); const SceneId sceneID2(13u); - rendererScenes.createScene(SceneInfo(sceneID2)); + rendererScenes.createScene(SceneInfo{ sceneID2 }); const SceneId sceneID3(14u); - rendererScenes.createScene(SceneInfo(sceneID3)); + rendererScenes.createScene(SceneInfo{ sceneID3 }); EXPECT_EQ(3u, rendererScenes.size()); EXPECT_NE(rendererScenes.begin(), rendererScenes.end()); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererStatisticsTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererStatisticsTest.cpp index ab1cdbbf1..8a378f7c1 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererStatisticsTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererStatisticsTest.cpp @@ -7,6 +7,7 @@ // ------------------------------------------------------------------------- #include "internal/RendererLib/RendererStatistics.h" +#include "internal/RendererLib/FrameProfilerStatistics.h" #include "internal/Core/Utils/LogMacros.h" #include "gmock/gmock.h" @@ -33,6 +34,26 @@ namespace ramses::internal const DeviceResourceHandle ob3{ 33 }; }; + TEST_F(ARendererStatistics, VerifyStringsOfRegionNames) + { + EXPECT_EQ(RegionNames.size(), 15u); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::ExecuteRendererCommands), "RendererCommands"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateClientResources), "UpdateClientResources"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::ApplySceneActions), "ApplySceneActions"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateSceneResources), "UpdateSceneResources"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateEmbeddedCompositingResources), "UpdateEmbeddedCompositingResources"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateStreamTextures), "UpdateStreamTextures"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateScenesToBeMapped), "UpdateScenesToBeMapped"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateResourceCache), "UpdateResourceCache"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateTransformations), "UpdateTransformations"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateDataLinks), "UpdateDataLinks"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::UpdateSemanticUniformBuffers), "UpdateSemanticUniformBuffers"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::HandleDisplayEvents), "HandleDisplayEvents"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::DrawScenes), "DrawScenes"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::SwapBuffersAndNotifyClients), "SwapBuffersNotifyClients"); + EXPECT_STREQ(EnumToString(FrameProfilerStatistics::ERegion::MaxFramerateSleep), "MaxFramerateSleep"); + } + TEST_F(ARendererStatistics, tracksDrawCallsPerFrame) { stats.frameFinished(1u); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererTest.cpp index 771a38d99..cd14d13d0 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/RendererTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererTest.cpp @@ -6,7 +6,7 @@ // file, You can obtain one at https://mozilla.org/MPL/2.0/. // ------------------------------------------------------------------------- -#include "internal/RendererLib/RendererConfig.h" +#include "internal/RendererLib/RendererConfigData.h" #include "RenderBackendMock.h" #include "PlatformMock.h" #include "internal/RendererLib/RenderingContext.h" @@ -174,7 +174,7 @@ namespace ramses::internal IScene& createScene(SceneId sceneId = SceneId()) { - rendererScenes.createScene(SceneInfo(sceneId)); + rendererScenes.createScene(SceneInfo{ sceneId }); return rendererScenes.getScene(sceneId); } @@ -327,7 +327,7 @@ namespace ramses::internal const SceneId sceneId(12u); createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); EXPECT_EQ(fakeOffscreenBuffer, renderer.getBufferSceneIsAssignedTo(sceneId)); EXPECT_FALSE(renderer.isSceneAssignedToInterruptibleOffscreenBuffer(sceneId)); @@ -342,7 +342,7 @@ namespace ramses::internal const SceneId sceneId(12u); createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); EXPECT_EQ(fakeOffscreenBuffer, renderer.getBufferSceneIsAssignedTo(sceneId)); EXPECT_TRUE(renderer.isSceneAssignedToInterruptibleOffscreenBuffer(sceneId)); @@ -358,8 +358,8 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle ob(313u); const DeviceResourceHandle obInterruptible(314u); - renderer.registerOffscreenBuffer(ob, 1u, 1u, false); - renderer.registerOffscreenBuffer(obInterruptible, 1u, 1u, true); + renderer.registerOffscreenBuffer(ob, 1u, 1u, 0u, false); + renderer.registerOffscreenBuffer(obInterruptible, 1u, 1u, 0u, true); assignSceneToDisplayBuffer(sceneId, 0, obInterruptible); EXPECT_EQ(obInterruptible, renderer.getBufferSceneIsAssignedTo(sceneId)); @@ -388,7 +388,7 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); expectFrameBufferRendered(true, EClearFlag::All); // no offscreen buffer clear expectation @@ -404,7 +404,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); expectOffscreenBufferCleared(fakeOffscreenBuffer); @@ -425,7 +425,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); expectOffscreenBufferCleared(fakeOffscreenBuffer); @@ -455,7 +455,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); renderer.setClearColor(fakeOffscreenBuffer, obClearColor); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); @@ -479,7 +479,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); renderer.setClearColor(fakeOffscreenBuffer, obClearColor); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); @@ -532,8 +532,8 @@ namespace ramses::internal constexpr DeviceResourceHandle fakeOffscreenBuffer1{ 313u }; constexpr DeviceResourceHandle fakeOffscreenBuffer2{ 314u }; - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, false); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, 0u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, 0u, true); // use some non-default clear flags EXPECT_CALL(renderer, setClearFlags(fakeOffscreenBuffer1, ClearFlags(EClearFlag::Depth))); @@ -559,8 +559,8 @@ namespace ramses::internal constexpr DeviceResourceHandle fakeOffscreenBuffer1{ 313u }; constexpr DeviceResourceHandle fakeOffscreenBuffer2{ 314u }; - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, false); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, 0u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, 0u, true); // assign scene to trigger render of OB constexpr SceneId sceneId1{ 12u }; @@ -593,8 +593,8 @@ namespace ramses::internal DeviceResourceHandle fakeOffscreenBuffer1(313u); DeviceResourceHandle fakeOffscreenBuffer2(314u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, false); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, 0u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, 0u, false); const SceneId sceneId1(12u); const SceneId sceneId2(13u); @@ -626,7 +626,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); showScene(sceneId); @@ -666,8 +666,8 @@ namespace ramses::internal const DeviceResourceHandle fakeOffscreenBuffer1(313u); const DeviceResourceHandle fakeOffscreenBuffer2(314u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, false); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, 0u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, 0u, false); const SceneId sceneId1(12u); const SceneId sceneId2(13u); @@ -718,7 +718,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); EXPECT_EQ(fakeOffscreenBuffer, renderer.getBufferSceneIsAssignedTo(sceneId)); EXPECT_FALSE(renderer.isSceneAssignedToInterruptibleOffscreenBuffer(sceneId)); @@ -927,7 +927,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle obDeviceHandle{ 567u }; - renderer.registerOffscreenBuffer(obDeviceHandle, 10u, 20u, false); + renderer.registerOffscreenBuffer(obDeviceHandle, 10u, 20u, 0u, false); scheduleScreenshot(obDeviceHandle, 1u, 2u, 3u, 4u); @@ -954,7 +954,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle obDeviceHandle{ 567u }; - renderer.registerOffscreenBuffer(obDeviceHandle, 10u, 20u, true); + renderer.registerOffscreenBuffer(obDeviceHandle, 10u, 20u, 0u, true); scheduleScreenshot(obDeviceHandle, 1u, 2u, 3u, 4u); @@ -1096,7 +1096,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); showScene(sceneId); @@ -1160,7 +1160,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); showScene(sceneId); @@ -1198,7 +1198,7 @@ namespace ramses::internal createScene(sceneId); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); showScene(sceneId); @@ -1309,7 +1309,7 @@ namespace ramses::internal const glm::vec4 obClearColor1(.1f, .2f, .3f, .4f); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, false); renderer.setClearColor(fakeOffscreenBuffer, obClearColor1); assignSceneToDisplayBuffer(sceneId, 0, fakeOffscreenBuffer); showScene(sceneId); @@ -1410,7 +1410,7 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, true); const SceneId sceneId(12u); createScene(sceneId); @@ -1454,7 +1454,7 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 2u, 0u, true); const SceneId sceneId(12u); createScene(sceneId); @@ -1496,7 +1496,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneIdOB(13u); @@ -1525,7 +1525,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdOB(13u); createScene(sceneIdOB); @@ -1548,7 +1548,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdOB(13u); createScene(sceneIdOB); @@ -1595,7 +1595,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneIdOB(13u); @@ -1634,7 +1634,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneIdOB(13u); @@ -1690,7 +1690,7 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneIdOB(13u); @@ -1737,7 +1737,7 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneId1OB(13u); @@ -1806,7 +1806,7 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneId1OB(13u); @@ -1869,8 +1869,8 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer1(313u); const DeviceResourceHandle fakeOffscreenBuffer2(314u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 1u, true); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 1u, 0u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneIdOB1(13u); @@ -1943,8 +1943,8 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer1(313u); const DeviceResourceHandle fakeOffscreenBuffer2(314u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 1u, true); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 1u, 0u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneId1OB1(13u); @@ -2040,7 +2040,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneId1OB(13u); @@ -2116,8 +2116,8 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer1(313u); const DeviceResourceHandle fakeOffscreenBuffer2(314u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 1u, true); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 1u, 0u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneId1OB(13u); @@ -2197,9 +2197,9 @@ namespace ramses::internal DeviceResourceHandle disp1OB(313u); DeviceResourceHandle disp1OBint1(315u); DeviceResourceHandle disp1OBint2(316u); - renderer.registerOffscreenBuffer(disp1OB, 1u, 1u, false); - renderer.registerOffscreenBuffer(disp1OBint1, 1u, 1u, true); - renderer.registerOffscreenBuffer(disp1OBint2, 1u, 1u, true); + renderer.registerOffscreenBuffer(disp1OB, 1u, 1u, 0u, false); + renderer.registerOffscreenBuffer(disp1OBint1, 1u, 1u, 0u, true); + renderer.registerOffscreenBuffer(disp1OBint2, 1u, 1u, 0u, true); const SceneId sceneIdDisp1FB(12u); const SceneId sceneIdDisp1OBscene(14u); @@ -2283,7 +2283,7 @@ namespace ramses::internal { createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, true); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer, 1u, 1u, 0u, true); const SceneId sceneIdFB(12u); const SceneId sceneIdOB(13u); @@ -2346,8 +2346,8 @@ namespace ramses::internal DeviceResourceHandle ob(316u); DeviceResourceHandle obInt(317u); - renderer.registerOffscreenBuffer(ob, 1u, 1u, false); - renderer.registerOffscreenBuffer(obInt, 1u, 1u, true); + renderer.registerOffscreenBuffer(ob, 1u, 1u, 0u, false); + renderer.registerOffscreenBuffer(obInt, 1u, 1u, 0u, true); assignSceneToDisplayBuffer(sceneIdFB, 0); assignSceneToDisplayBuffer(sceneIdOB, 0, ob); @@ -2384,8 +2384,8 @@ namespace ramses::internal DeviceResourceHandle ob(316u); DeviceResourceHandle obInt(317u); - renderer.registerOffscreenBuffer(ob, 1u, 1u, false); - renderer.registerOffscreenBuffer(obInt, 1u, 1u, true); + renderer.registerOffscreenBuffer(ob, 1u, 1u, 0u, false); + renderer.registerOffscreenBuffer(obInt, 1u, 1u, 0u, true); assignSceneToDisplayBuffer(sceneIdFB, 0); assignSceneToDisplayBuffer(sceneIdOB, 0, ob); @@ -2427,7 +2427,7 @@ namespace ramses::internal initiateExpirationMonitoring({ sceneIdFB, sceneIdOBint }); DeviceResourceHandle obInt(317u); - renderer.registerOffscreenBuffer(obInt, 1u, 1u, true); + renderer.registerOffscreenBuffer(obInt, 1u, 1u, 0u, true); assignSceneToDisplayBuffer(sceneIdFB, 0); assignSceneToDisplayBuffer(sceneIdOBint, 0, obInt); @@ -2497,7 +2497,7 @@ namespace ramses::internal createScene(scene2); constexpr DeviceResourceHandle ob{ 317u }; - renderer.registerOffscreenBuffer(ob, 1u, 1u, false); + renderer.registerOffscreenBuffer(ob, 1u, 1u, 0u, false); assignSceneToDisplayBuffer(scene1, 0, ob); assignSceneToDisplayBuffer(scene2, 0, ob); @@ -2528,7 +2528,7 @@ namespace ramses::internal createScene(scene2); constexpr DeviceResourceHandle ob{ 317u }; - renderer.registerOffscreenBuffer(ob, 1u, 1u, true); + renderer.registerOffscreenBuffer(ob, 1u, 1u, 0u, true); assignSceneToDisplayBuffer(scene1, 0, ob); assignSceneToDisplayBuffer(scene2, 0, ob); @@ -2556,7 +2556,7 @@ namespace ramses::internal createDisplayController(); const DeviceResourceHandle fakeOffscreenBuffer1(313u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, 0u, false); const SceneId sceneId1(12u); const SceneId sceneId2(13u); @@ -2591,9 +2591,9 @@ namespace ramses::internal const DeviceResourceHandle fakeOffscreenBuffer1(313u); const DeviceResourceHandle fakeOffscreenBuffer2(314u); const DeviceResourceHandle fakeOffscreenBuffer3(315u); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, false); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, false); - renderer.registerOffscreenBuffer(fakeOffscreenBuffer3, 1u, 2u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer1, 1u, 2u, 0u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer2, 1u, 2u, 0u, false); + renderer.registerOffscreenBuffer(fakeOffscreenBuffer3, 1u, 2u, 0u, false); EXPECT_CALL(renderer, setClearFlags(fakeOffscreenBuffer1, EClearFlag::Color | EClearFlag::Stencil)); EXPECT_CALL(renderer, setClearFlags(fakeOffscreenBuffer2, EClearFlag::Color | EClearFlag::Depth)); EXPECT_CALL(renderer, setClearFlags(fakeOffscreenBuffer3, EClearFlag::Depth | EClearFlag::Stencil)); @@ -2638,7 +2638,7 @@ namespace ramses::internal createScene(sceneIdOBint); DeviceResourceHandle obInt(317u); - renderer.registerOffscreenBuffer(obInt, 1u, 1u, true); + renderer.registerOffscreenBuffer(obInt, 1u, 1u, 0u, true); assignSceneToDisplayBuffer(sceneIdFB, 0); assignSceneToDisplayBuffer(sceneIdOBint, 0, obInt); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/RendererTestingScene.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/RendererTestingScene.cpp new file mode 100644 index 000000000..d2bd81a73 --- /dev/null +++ b/tests/unittests/renderer/renderer-lib/RendererLib/RendererTestingScene.cpp @@ -0,0 +1,46 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "gtest/gtest.h" +#include "TestingScene.h" +#include "FeatureLevelTestValues.h" +#include "internal/RendererLib/RendererCachedScene.h" +#include "internal/RendererLib/RendererScenes.h" +#include "internal/RendererLib/RendererEventCollector.h" +#include "internal/RendererLib/SceneLinksManager.h" + +using namespace testing; + +namespace ramses::internal +{ + class ARendererTestingScene : public ::testing::TestWithParam + { + }; + + RAMSES_INSTANTIATE_FEATURELEVEL_TEST_SUITE(ARendererTestingScene); + + TEST_P(ARendererTestingScene, generateAndCheckContent) + { + // renderer scenes are explicitly allocated, i.e. all pool sizes have to be preallocated, + // here we get the sizes using regular scene + SceneSizeInformation sceneSizeInfo; + { + Scene sceneForSizeInfo; + TestingScene testingSceneForSizeInfo{ sceneForSizeInfo, EFeatureLevel_Latest }; + sceneSizeInfo = sceneForSizeInfo.getSceneSizeInformation(); + } + + RendererEventCollector dummyEventCollector; + RendererScenes rendererScenes{ dummyEventCollector }; + auto& scene = rendererScenes.createScene(SceneInfo{ SceneId{ 123u} }); + scene.preallocateSceneSize(sceneSizeInfo); + + TestingScene testingScene{ scene, GetParam() }; + testingScene.VerifyContent(scene); + } +} diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/ResourceCachedSceneTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/ResourceCachedSceneTest.cpp index 390dd61a2..968ed433f 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/ResourceCachedSceneTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/ResourceCachedSceneTest.cpp @@ -11,7 +11,8 @@ #include "internal/RendererLib/RendererResourceManager.h" #include "internal/RendererLib/RendererScenes.h" #include "internal/RendererLib/RendererEventCollector.h" -#include "SceneAllocateHelper.h" +#include "DeviceMock.h" +#include "MockResourceHash.h" #include namespace ramses::internal @@ -21,7 +22,7 @@ namespace ramses::internal public: explicit AResourceCachedScene(bool indexArrayAvailable = true) : rendererScenes(rendererEventCollector) - , scene(rendererScenes.createScene(SceneInfo())) + , scene(rendererScenes.createScene(SceneInfo{})) , sceneAllocator(scene) , sceneHelper(scene, indexArrayAvailable) { @@ -728,6 +729,71 @@ namespace ramses::internal EXPECT_CALL(sceneHelper.resourceManager, getStreamBufferDeviceHandle(streamBuffer)).WillOnce(Return(DeviceResourceHandle::Invalid())); updateResourcesAndExpectTexture(textureSampler, { }, DeviceMock::FakeTextureDeviceHandle); } + //uniform buffers + TEST_F(AResourceCachedScene, CanGetDeviceHandleForUniformBuffer) + { + const RenderableHandle renderable = sceneHelper.createRenderable(); + + //create data instance with one uniform buffer + const auto uniformLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::UniformBuffer} }, MockResourceHash::EffectHash); + const auto uniformDataInstance = sceneAllocator.allocateDataInstance(uniformLayout); + const auto ubHandle = sceneAllocator.allocateUniformBuffer(123u); + scene.setDataUniformBuffer(uniformDataInstance, DataFieldHandle{ 0u }, ubHandle); + scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformDataInstance); + + sceneHelper.createAndAssignVertexDataInstance(renderable); + sceneHelper.setResourcesToRenderable(renderable); + + EXPECT_CALL(sceneHelper.resourceManager, getUniformBufferDeviceHandle(ubHandle, scene.getSceneId())); + updateRenderableResourcesAndVertexArray({ renderable }); + + EXPECT_FALSE(scene.renderableResourcesDirty(renderable)); + const auto& uniformBuffersEntry = scene.getCachedHandlesForUniformInstancesBuffers()[renderable.asMemoryHandle()]; + ASSERT_EQ(1u, uniformBuffersEntry.size()); + EXPECT_EQ(DeviceMock::FakeUniformBufferDeviceHandle, uniformBuffersEntry[0]); + } + + TEST_F(AResourceCachedScene, CanGetDeviceHandleForUniformBuffer_IfDataInstanceUpdated) + { + const RenderableHandle renderable = sceneHelper.createRenderable(); + + //create data instance with one uniform buffer + const auto uniformLayout = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::UniformBuffer} }, MockResourceHash::EffectHash); + const auto uniformDataInstance = sceneAllocator.allocateDataInstance(uniformLayout); + const auto ubHandle = sceneAllocator.allocateUniformBuffer(123u); + scene.setDataUniformBuffer(uniformDataInstance, DataFieldHandle{ 0u }, ubHandle); + scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformDataInstance); + + sceneHelper.createAndAssignVertexDataInstance(renderable); + sceneHelper.setResourcesToRenderable(renderable); + + EXPECT_CALL(sceneHelper.resourceManager, getUniformBufferDeviceHandle(ubHandle, scene.getSceneId())); + updateRenderableResourcesAndVertexArray({ renderable }); + + //create a 2nd data instance with 2 uniform buffers + const auto uniformLayout2 = sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::UniformBuffer}, DataFieldInfo{EDataType::UniformBuffer} }, MockResourceHash::EffectHash); + const auto uniformDataInstance2 = sceneAllocator.allocateDataInstance(uniformLayout2); + const auto ubHandle2 = sceneAllocator.allocateUniformBuffer(123u); + const auto ubHandle3 = sceneAllocator.allocateUniformBuffer(123u); + + scene.setDataUniformBuffer(uniformDataInstance2, DataFieldHandle{ 0u }, ubHandle2); + scene.setDataUniformBuffer(uniformDataInstance2, DataFieldHandle{ 1u }, ubHandle3); + scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformDataInstance2); + scene.updateRenderablesResourcesDirtiness(); + ASSERT_TRUE(scene.renderableResourcesDirty(renderable)); + + constexpr DeviceResourceHandle ubDeviceHandle2{ 789u }; + constexpr DeviceResourceHandle ubDeviceHandle3{ 345u }; + EXPECT_CALL(sceneHelper.resourceManager, getUniformBufferDeviceHandle(ubHandle2, scene.getSceneId())).WillOnce(Return(ubDeviceHandle2)); + EXPECT_CALL(sceneHelper.resourceManager, getUniformBufferDeviceHandle(ubHandle3, scene.getSceneId())).WillOnce(Return(ubDeviceHandle3)); + updateRenderableResourcesAndVertexArray({ renderable }); + + EXPECT_FALSE(scene.renderableResourcesDirty(renderable)); + const auto& uniformBuffersEntry = scene.getCachedHandlesForUniformInstancesBuffers()[renderable.asMemoryHandle()]; + ASSERT_EQ(2u, uniformBuffersEntry.size()); + EXPECT_EQ(ubDeviceHandle2, uniformBuffersEntry[0]); + EXPECT_EQ(ubDeviceHandle3, uniformBuffersEntry[1]); + } //vertex arrays TEST_F(AResourceCachedScene, CanGetDeviceHandleForVertexArray) diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploaderTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploaderTest.cpp index c69f00e4e..8b5224179 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploaderTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploaderTest.cpp @@ -250,7 +250,7 @@ namespace ramses::internal TEST_F(AResourceUploader, canStoreBinaryShader) { - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); const SceneId sceneUsingResource(14); BinaryShaderProviderFake binaryShaderProvider; @@ -264,7 +264,7 @@ namespace ramses::internal TEST_F(AResourceUploader, doesNoStoreBinaryShaderIfFailedToGetBinaryShaderFromDevice) { - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); const SceneId sceneUsingResource(14); BinaryShaderProviderFake binaryShaderProvider; @@ -279,7 +279,7 @@ namespace ramses::internal TEST_F(AResourceUploader, ifShaderShouldNotBeCachedNoDownloadWillHappen) { - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); const SceneId sceneUsingResource(14); BinaryShaderProviderFake binaryShaderProvider; @@ -293,7 +293,7 @@ namespace ramses::internal TEST_F(AResourceUploader, doesNotTryToStoreBinaryShaderIfNoBinaryShaderCacheAvailable) { - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); const SceneId sceneUsingResource(14); EXPECT_CALL(renderer.deviceMock, getBinaryShader(_, _, _)).Times(0); @@ -302,7 +302,7 @@ namespace ramses::internal TEST_F(AResourceUploader, doesNotReturnDeviceHandleForEffectResourceWithoutBinaryShaderCache) { - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); ManagedResource managedRes{ &res, dummyManagedResourceCallback }; ResourceDescriptor resourceObject; resourceObject.resource = managedRes; @@ -314,7 +314,7 @@ namespace ramses::internal { ResourceUploader uploaderWithoutCacheOrAsyncUpload(false); - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); ManagedResource managedRes{ &res, dummyManagedResourceCallback }; ResourceDescriptor resourceObject; resourceObject.resource = managedRes; @@ -329,7 +329,7 @@ namespace ramses::internal BinaryShaderProviderFake binaryShaderProvider; ResourceUploader uploaderWithBinaryProvider(true, &binaryShaderProvider); - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); EXPECT_CALL(managedResourceDeleter, managedResourceDeleted(Ref(res))).Times(1); EXPECT_CALL(binaryShaderProvider, binaryShaderFormatsReported()); @@ -347,7 +347,7 @@ namespace ramses::internal BinaryShaderProviderFake binaryShaderProvider; ResourceUploader uploaderWithCacheButNoAsyncUpload(false, &binaryShaderProvider); - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); EXPECT_CALL(managedResourceDeleter, managedResourceDeleted(Ref(res))).Times(1); EXPECT_CALL(binaryShaderProvider, binaryShaderFormatsReported()); @@ -364,7 +364,7 @@ namespace ramses::internal TEST_F(AResourceUploader, uploadsEffectResourceFromBinaryShaderCacheWhenCacheHit) { - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); ManagedResource managedRes{ &res, dummyManagedResourceCallback }; uint8_t binaryShaderData[] = { 1u, 2u, 3u, 4u }; @@ -395,7 +395,7 @@ namespace ramses::internal TEST_F(AResourceUploader, doesNotReturnDeviceHandleForEffectResourceWithBrokenBinaryShaderCache) { - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); ManagedResource managedRes{ &res, dummyManagedResourceCallback }; SceneId sceneUsingResource(14); @@ -433,7 +433,7 @@ namespace ramses::internal BinaryShaderProviderFake binaryShaderProvider; ResourceUploader uploaderWithBinaryProvider(true, &binaryShaderProvider); - EffectResource res("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); EXPECT_CALL(managedResourceDeleter, managedResourceDeleted(Ref(res))).Times(3); EXPECT_CALL(binaryShaderProvider, binaryShaderFormatsReported()).Times(3); @@ -462,9 +462,9 @@ namespace ramses::internal ResourceUploader uploaderWithBinaryProvider2(true, &binaryShaderProvider); ResourceUploader uploaderWithBinaryProvider3(true, &binaryShaderProvider); - EffectResource res1("1", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); - EffectResource res2("2", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); - EffectResource res3("3", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + EffectResource res1("1", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); + EffectResource res2("2", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); + EffectResource res3("3", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); EXPECT_CALL(managedResourceDeleter, managedResourceDeleted(_)).Times(3); EXPECT_CALL(binaryShaderProvider, binaryShaderFormatsReported()).Times(3); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploadingManagerTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploadingManagerTest.cpp index b3bd76286..bd4421329 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploadingManagerTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/ResourceUploadingManagerTest.cpp @@ -10,7 +10,7 @@ #include "internal/RendererLib/RendererResourceRegistry.h" #include "internal/RendererLib/FrameTimer.h" #include "internal/RendererLib/RendererStatistics.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/SceneGraph/Resource/ArrayResource.h" #include "internal/SceneGraph/Resource/EffectResource.h" #include "ResourceUploaderMock.h" @@ -26,9 +26,9 @@ namespace ramses::internal namespace { - DisplayConfig makeConfig(uint64_t resourceCacheSize, SceneId preferredScene, SceneId deprivedScene) + DisplayConfigData makeConfig(uint64_t resourceCacheSize, SceneId preferredScene, SceneId deprivedScene) { - DisplayConfig cfg; + DisplayConfigData cfg; cfg.setGPUMemoryCacheSize(resourceCacheSize); if (preferredScene.isValid()) { @@ -45,14 +45,14 @@ namespace ramses::internal class AResourceUploadingManager : public ::testing::Test { public: - explicit AResourceUploadingManager(const DisplayConfig& cfg = DisplayConfig()) + explicit AResourceUploadingManager(const DisplayConfigData& cfg = DisplayConfigData()) : dummyResource(EResourceType::IndexArray, 5, EDataType::UInt16, reinterpret_cast(m_dummyData), {}) - , dummyEffectResource("", "", "", {}, EffectInputInformationVector(), EffectInputInformationVector(), "") + , dummyEffectResource("", "", "", {}, {}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest) , dummyManagedResourceCallback(managedResourceDeleter) , sceneId(66u) , uploader(new StrictMock) , asyncEffectUploader(platformMock, platformMock.renderBackendMock, notifier, DisplayHandle{ 1 }) - , rendererResourceUploader(resourceRegistry, std::unique_ptr{ uploader }, platformMock.renderBackendMock, asyncEffectUploader, cfg, frameTimer, stats) + , rendererResourceUploader(resourceRegistry, std::unique_ptr{ uploader }, platformMock.renderBackendMock, &asyncEffectUploader, cfg, frameTimer, stats) { InSequence s; EXPECT_CALL(platformMock.renderBackendMock.contextMock, disable()).WillOnce(Return(true)); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.cpp index 1e6b751b0..0322b3984 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.cpp @@ -83,6 +83,10 @@ namespace ramses::internal { return sizeInfo.dataBufferCount; } + template <> uint32_t& getObjectCount(SceneSizeInformation& sizeInfo) + { + return sizeInfo.uniformBufferCount; + } template <> uint32_t& getObjectCount(SceneSizeInformation& sizeInfo) { return sizeInfo.textureBufferCount; @@ -192,6 +196,11 @@ namespace ramses::internal return m_scene.allocateDataBuffer(dataBufferType, dataType, maximumSizeInBytes, preallocateHandle(handle)); } + UniformBufferHandle SceneAllocateHelper::allocateUniformBuffer(uint32_t size, UniformBufferHandle handle) + { + return m_scene.allocateUniformBuffer(size, preallocateHandle(handle)); + } + TextureBufferHandle SceneAllocateHelper::allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle /*= TextureBufferHandle::Invalid()*/) { return m_scene.allocateTextureBuffer(textureFormat, mipMapDimensions, preallocateHandle(handle)); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.h b/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.h index 5739a8e28..9a6d4031d 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/SceneAllocateHelper.h @@ -44,6 +44,7 @@ namespace ramses::internal RenderBufferHandle allocateRenderBuffer(const RenderBuffer& renderBuffer, RenderBufferHandle handle = RenderBufferHandle::Invalid()); DataSlotHandle allocateDataSlot(const DataSlot& dataSlot, DataSlotHandle handle = DataSlotHandle::Invalid()); DataBufferHandle allocateDataBuffer(EDataBufferType dataBufferType, EDataType dataType, uint32_t maximumSizeInBytes, DataBufferHandle handle = DataBufferHandle::Invalid()); + UniformBufferHandle allocateUniformBuffer(uint32_t size, UniformBufferHandle handle = {}); TextureBufferHandle allocateTextureBuffer(EPixelStorageFormat textureFormat, const MipMapDimensions& mipMapDimensions, TextureBufferHandle handle = TextureBufferHandle::Invalid()); PickableObjectHandle allocatePickableObject(DataBufferHandle geometryHandle, NodeHandle nodeHandle, PickableObjectId id, PickableObjectHandle pickableHandle = PickableObjectHandle::Invalid()); SceneReferenceHandle allocateSceneReference(SceneId sceneId, SceneReferenceHandle handle = {}); diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/SceneLinksManagerTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/SceneLinksManagerTest.cpp index 47ee1af08..28912b90f 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/SceneLinksManagerTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/SceneLinksManagerTest.cpp @@ -26,8 +26,8 @@ namespace ramses::internal , concreteLinkManager(GetConcreteLinkManager(sceneLinksManager)) , providerSceneId(3u) , consumerSceneId(4u) - , providerScene(rendererScenes.createScene(SceneInfo(providerSceneId))) - , consumerScene(rendererScenes.createScene(SceneInfo(consumerSceneId))) + , providerScene(rendererScenes.createScene(SceneInfo{ providerSceneId })) + , consumerScene(rendererScenes.createScene(SceneInfo{ consumerSceneId })) , providerSceneAllocator(providerScene) , consumerSceneAllocator(consumerScene) , providerId(33u) diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/SceneReferenceLogicWithSceneUpdaterTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/SceneReferenceLogicWithSceneUpdaterTest.cpp index 8fd79a5bf..d3f53eb13 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/SceneReferenceLogicWithSceneUpdaterTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/SceneReferenceLogicWithSceneUpdaterTest.cpp @@ -41,7 +41,7 @@ namespace ramses::internal , m_expirationMonitor(m_scenes, m_eventCollector, m_rendererStatistics) , m_renderer(DisplayId, m_scenes, m_eventCollector, m_expirationMonitor, m_rendererStatistics) , m_sceneStateExecutor(m_renderer, m_sceneEventSenderFromSceneUpdater, m_eventCollector) - , m_sceneUpdater(DisplayId, m_platform, m_renderer, m_scenes, m_sceneStateExecutor, m_eventCollector, m_frameTimer, m_expirationMonitor, m_notifier) + , m_sceneUpdater(DisplayId, m_platform, m_renderer, m_scenes, m_sceneStateExecutor, m_eventCollector, m_frameTimer, m_expirationMonitor, m_notifier, EFeatureLevel_Latest) , m_sceneLogic(m_sceneUpdater) , m_sceneRefLogic(m_scenes, m_sceneLogic, m_sceneUpdater, m_sceneEventSenderFromSceneRefLogic, m_sceneRefOwnership) { @@ -78,7 +78,7 @@ namespace ramses::internal void flushScene(SceneId sceneId) { SceneUpdate sceneUpdate; - SceneActionCollectionCreator creator(sceneUpdate.actions); + SceneActionCollectionCreator creator(sceneUpdate.actions, EFeatureLevel_Latest); sceneUpdate.flushInfos.flushCounter = 1u; sceneUpdate.flushInfos.containsValidInformation = true; m_sceneUpdater.handleSceneUpdate(sceneId, std::move(sceneUpdate)); @@ -87,7 +87,7 @@ namespace ramses::internal void flushSceneWithRefSceneStateRequest(SceneId sceneId, SceneReferenceHandle refSceneHandle, RendererSceneState refSceneState) { SceneUpdate sceneUpdate; - SceneActionCollectionCreator creator(sceneUpdate.actions); + SceneActionCollectionCreator creator(sceneUpdate.actions, EFeatureLevel_Latest); creator.requestSceneReferenceState(refSceneHandle, refSceneState); sceneUpdate.flushInfos.flushCounter = 1u; sceneUpdate.flushInfos.containsValidInformation = true; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/SceneResourceUploaderTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/SceneResourceUploaderTest.cpp index c60f0745a..78a26d196 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/SceneResourceUploaderTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/SceneResourceUploaderTest.cpp @@ -20,7 +20,7 @@ namespace ramses::internal { { public: ASceneResourceUploader() - : scene(SceneInfo(sceneID)) + : scene(SceneInfo{ sceneID }) , allocateHelper(scene) { } diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/SemanticUniformBufferHandleTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/SemanticUniformBufferHandleTest.cpp new file mode 100644 index 000000000..62dca6131 --- /dev/null +++ b/tests/unittests/renderer/renderer-lib/RendererLib/SemanticUniformBufferHandleTest.cpp @@ -0,0 +1,77 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "internal/RendererLib/SemanticUniformBufferHandle.h" +#include +#include +#include + +namespace ramses::internal +{ + using namespace testing; + + class ASemanticUniformBufferHandle : public ::testing::Test + { + }; + + TEST_F(ASemanticUniformBufferHandle, canConstructHandleForModelUBO) + { + constexpr RenderableHandle renderable{ 1u }; + constexpr SemanticUniformBufferHandle uboHandle{ renderable }; + EXPECT_EQ(SemanticUniformBufferHandle::Type::Model, uboHandle.getType()); + EXPECT_EQ(renderable, uboHandle.getRenderable()); + EXPECT_EQ("model(1)", fmt::to_string(uboHandle)); + } + + TEST_F(ASemanticUniformBufferHandle, canConstructHandleForCameraUBO) + { + constexpr CameraHandle camera{ 1u }; + constexpr SemanticUniformBufferHandle uboHandle{ camera }; + EXPECT_EQ(SemanticUniformBufferHandle::Type::Camera, uboHandle.getType()); + EXPECT_EQ(camera, uboHandle.getCamera()); + EXPECT_EQ("camera(1)", fmt::to_string(uboHandle)); + } + + TEST_F(ASemanticUniformBufferHandle, canConstructHandleForModelCameraUBO) + { + constexpr RenderableHandle renderable{ 1u }; + constexpr CameraHandle camera{ 2u }; + + constexpr SemanticUniformBufferHandle uboHandle{ renderable, camera }; + EXPECT_EQ(SemanticUniformBufferHandle::Type::ModelCamera, uboHandle.getType()); + EXPECT_EQ(renderable, uboHandle.getRenderable()); + EXPECT_EQ(camera, uboHandle.getCamera()); + EXPECT_EQ("modelCamera(1:2)", fmt::to_string(uboHandle)); + } + + TEST_F(ASemanticUniformBufferHandle, UBOHandlesConstructedFromDifferentTypesButSameHandleValuesAreNotEqual) + { + for (uint32_t val : { 0u, 1u, InvalidMemoryHandle - 3 }) // test with few corner cases + { + const RenderableHandle renderable{ val }; + const CameraHandle camera{ val }; + + const SemanticUniformBufferHandle uboHandleModel{ renderable }; + const SemanticUniformBufferHandle uboHandleCamera{ camera }; + const SemanticUniformBufferHandle uboHandleModelCamera{ renderable, camera }; + + EXPECT_NE(uboHandleModel, uboHandleCamera); + EXPECT_NE(uboHandleModel, uboHandleModelCamera); + EXPECT_NE(uboHandleModelCamera, uboHandleCamera); + + // all considered unique + std::vector vec{ uboHandleModel, uboHandleCamera, uboHandleModelCamera }; + std::sort(vec.begin(), vec.end()); + EXPECT_EQ(vec.end(), std::unique(vec.begin(), vec.end())); + + // all having unique hash + std::unordered_set set{ uboHandleModel, uboHandleCamera, uboHandleModelCamera }; + EXPECT_EQ(3u, set.size()); + } + } +} diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/SemanticUniformBuffersTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/SemanticUniformBuffersTest.cpp new file mode 100644 index 000000000..0688eea9d --- /dev/null +++ b/tests/unittests/renderer/renderer-lib/RendererLib/SemanticUniformBuffersTest.cpp @@ -0,0 +1,1033 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "internal/RendererLib/SemanticUniformBuffers.h" +#include "internal/RendererLib/RendererCachedScene.h" +#include "internal/RendererLib/RendererScenes.h" +#include "internal/RendererLib/RendererEventCollector.h" +#include "TestSceneHelper.h" +#include "RendererResourceManagerMock.h" +#include +#include + +namespace ramses::internal +{ + using namespace testing; + + class ASemanticUniformBuffers : public ::testing::Test + { + public: + ASemanticUniformBuffers() + : m_rendererScenes{ m_rendererEventCollector } + , m_scene{ m_rendererScenes.createScene(SceneInfo{}) } + , m_sceneHelper{ m_scene, false, false } + { + // add some transformation to camera + addTransformation(m_camera); + } + + protected: + void addTransformation(CameraHandle camera) + { + const auto cameraTransform = m_sceneHelper.m_sceneAllocator.allocateTransform(m_scene.getCamera(camera).node); + m_scene.setRotation(cameraTransform, { 1, 2, 3, 4 }, ERotationType::Quaternion); + } + + RenderableHandle createRenderable(RenderGroupHandle renderGroup, const std::unordered_set& semantics = {}, RenderableHandle handle = {}) + { + const auto renderable = m_sceneHelper.createRenderable(renderGroup, {}, semantics, handle); + + // add some transformation + const auto renderableTransform = m_sceneHelper.m_sceneAllocator.allocateTransform(m_scene.getRenderable(renderable).node); + m_scene.setTranslation(renderableTransform, { 1, 2, 3 }); + + return renderable; + } + + void makeTransformChange(RenderableHandle renderable) + { + const auto node = m_scene.getRenderable(renderable).node; + for (const auto& transform : m_scene.getTransforms()) + { + if (transform.second->node == node) + m_scene.setTranslation(transform.first, m_scene.getTranslation(transform.first) + glm::vec3{ 1.f }); + } + } + + void makeTransformChange(CameraHandle camera) + { + const auto node = m_scene.getCamera(camera).node; + for (const auto& transform : m_scene.getTransforms()) + { + if (transform.second->node == node) + m_scene.setTranslation(transform.first, m_scene.getTranslation(transform.first) + glm::vec3{ 1.f }); + } + } + + void makeProjectionChange(CameraHandle camera) + { + const auto& cam = m_scene.getCamera(camera); + const auto& ref = m_scene.getDataReference(cam.dataInstance, Camera::FrustumNearFarPlanesField); + m_scene.setDataSingleVector2f(ref, DataFieldHandle{ 0 }, m_scene.getDataSingleVector2f(ref, DataFieldHandle{ 0 }) + glm::vec2{ 0.01f }); + } + + void sceneUpdaterUpdate() + { + // simulate order of commands done by RendererSceneUpdater + m_scene.updateRenderablesAndResourceCache(m_resourceManagerMock); + for (const auto& passInfo : m_scene.getSortedRenderingPasses()) + { + const auto camera = m_scene.getRenderPass(passInfo.getRenderPassHandle()).camera; + const auto& passRenderables = m_scene.getOrderedRenderablesForPass(passInfo.getRenderPassHandle()); + m_scene.collectDirtySemanticUniformBuffers(passRenderables, camera); + } + m_scene.updateRenderableWorldMatrices(); + m_scene.updateSemanticUniformBuffers(); + m_scene.uploadSemanticUniformBuffers(m_resourceManagerMock); + Mock::VerifyAndClearExpectations(&m_resourceManagerMock); + } + + DeviceResourceHandle expectUBOUpload(SemanticUniformBufferHandle uboHandle) + { + static DeviceResourceHandle deviceHandle{ 0u }; + uint32_t expectedUBOSize = 0u; + switch (uboHandle.getType()) + { + case SemanticUniformBufferHandle::Type::Model: + expectedUBOSize = ExpectedModelUBOSize; + break; + case SemanticUniformBufferHandle::Type::Camera: + expectedUBOSize = ExpectedCameraUBOSize; + break; + case SemanticUniformBufferHandle::Type::ModelCamera: + expectedUBOSize = ExpectedModelCameraUBOSize; + break; + default: + assert(false); + break; + } + EXPECT_CALL(m_resourceManagerMock, uploadUniformBuffer(uboHandle, expectedUBOSize, m_scene.getSceneId())) + .WillOnce(Return(++deviceHandle)); + + return deviceHandle; + } + + void expectUBOUnload(SemanticUniformBufferHandle uboHandle) + { + EXPECT_CALL(m_resourceManagerMock, unloadUniformBuffer(uboHandle, m_scene.getSceneId())); + } + + void expectUBOUpdate(RenderableHandle renderable, std::optional expectModelMat = {}) + { + EXPECT_CALL(m_resourceManagerMock, updateUniformBuffer(SemanticUniformBufferHandle{ renderable }, ExpectedModelUBOSize, _, m_scene.getSceneId())) + .WillOnce([=](auto /*handle*/, auto /*size*/, const std::byte* data, auto /*sceneId*/) + { + if (expectModelMat) + { + const auto* floatData = reinterpret_cast(data); + const auto mMat = glm::make_mat4(floatData); + for (size_t i = 0; i < 16; ++i) + EXPECT_FLOAT_EQ(glm::value_ptr(*expectModelMat)[i], glm::value_ptr(mMat)[i]) << i; + } + }); + } + + void expectUBOUpdate(CameraHandle camera, + std::optional expectPMat = {}, + std::optional expectVMat = {}, + std::optional expectPos = {}) + { + EXPECT_CALL(m_resourceManagerMock, updateUniformBuffer(SemanticUniformBufferHandle{ camera }, ExpectedCameraUBOSize, _, m_scene.getSceneId())) + .WillOnce([=](auto /*handle*/, auto /*size*/, const std::byte* data, auto /*sceneId*/) + { + const auto* floatData = reinterpret_cast(data); + const auto pMat = glm::make_mat4(floatData); + const auto vMat = glm::make_mat4(floatData + 16); + const auto pos = glm::make_vec3(floatData + 32); + + if (expectPMat) + { + for (size_t i = 0; i < 16; ++i) + EXPECT_FLOAT_EQ(glm::value_ptr(*expectPMat)[i], glm::value_ptr(pMat)[i]) << i; + } + + if (expectVMat) + { + for (size_t i = 0; i < 16; ++i) + EXPECT_FLOAT_EQ(glm::value_ptr(*expectVMat)[i], glm::value_ptr(vMat)[i]) << i; + } + + if (expectPos) + { + for (size_t i = 0; i < 3; ++i) + EXPECT_FLOAT_EQ(glm::value_ptr(*expectPos)[i], glm::value_ptr(pos)[i]) << i; + } + }); + } + + void expectUBOUpdate(RenderableHandle renderable, CameraHandle camera, + std::optional expectMVPMat = {}, + std::optional expectMVMat = {}, + std::optional expectNormalMat = {}) + { + EXPECT_CALL(m_resourceManagerMock, updateUniformBuffer(SemanticUniformBufferHandle{ renderable, camera }, ExpectedModelCameraUBOSize, _, m_scene.getSceneId())) + .WillOnce([=](auto /*handle*/, auto /*size*/, const std::byte* data, auto /*sceneId*/) + { + const auto* floatData = reinterpret_cast(data); + const auto mvpMat = glm::make_mat4(floatData); + const auto mvMat = glm::make_mat4(floatData + 16); + const auto normalMat = glm::make_mat4(floatData + 32); + + if (expectMVPMat) + { + for (size_t i = 0; i < 16; ++i) + EXPECT_FLOAT_EQ(glm::value_ptr(*expectMVPMat)[i], glm::value_ptr(mvpMat)[i]) << i; + } + + if (expectMVMat) + { + for (size_t i = 0; i < 16; ++i) + EXPECT_FLOAT_EQ(glm::value_ptr(*expectMVMat)[i], glm::value_ptr(mvMat)[i]) << i; + } + + if (expectNormalMat) + { + for (size_t i = 0; i < 16; ++i) + EXPECT_FLOAT_EQ(glm::value_ptr(*expectNormalMat)[i], glm::value_ptr(normalMat)[i]) << i; + } + }); + } + + RendererEventCollector m_rendererEventCollector; + RendererScenes m_rendererScenes; + RendererCachedScene& m_scene; + TestSceneHelper m_sceneHelper; + StrictMock m_resourceManagerMock; + + static constexpr size_t ExpectedModelUBOSize = 1 * 16 * 4; + static constexpr size_t ExpectedCameraUBOSize = 2 * 16 * 4 + 1 * 3 * 4; + static constexpr size_t ExpectedModelCameraUBOSize = 3 * 16 * 4; + + // These match default transformations in this test. + // Intentionally hardcoded so there is no dependency on internal code to calculate them + const glm::mat4 ExpectedMMat{ + 1.f, 0.f, 0.f, 0.f, + 0.f, 1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 1.f, 2.f, 3.f, 1.f }; + const glm::mat4 ExpectedPMat{ + 0.1f, 0.f, 0.f, 0.f, + 0.f, 0.1f, 0.f, 0.f, + 0.f, 0.f, -1.222222f, -1.f, + 0.f, 0.f, -0.2222222f, 0.f }; + const glm::mat4 ExpectedVMat{ + -25.f, -20.f, 22.f, 0.f, + 28.f, -19.f, 4.f, 0.f, + -10.f, 20.f, -9.f, 0.f, + 0.f, 0.f, 0.f, 1.f }; + const glm::vec3 ExpectedPos{ 0.f, 0.f, 0.f }; + const glm::mat4 ExpectedMVPMat{ + -2.5f, -2.f, -26.888891f, -22.f, + 2.8f, -1.9f, -4.888889f, -4.f, + -1.f, 2.f, 11.000001f, 9.f, + 0.1f, 0.2f, -3.8888893f, -3.f }; + const glm::mat4 ExpectedMVMat{ + -25.f, -20.f, 22.f, 0.f, + 28.f, -19.f, 4.f, 0.f, + -10.f, 20.f, -9.f, 0.f, + 1.f, 2.f, 3.f, 1.f }; + const glm::mat4 ExpectedNormalMat{ + 0.056f, 0.13046152889728546f, 0.22769230604171753f, -1.f, + 0.16f, 0.27384614944458008f, 0.43076923489570618f, -2.f, + 0.208f, 0.44061538577079773f, 0.63692307472229004f, -3.f, + 0.f, 0.f, 0.f, 1.f }; + + const RenderPassHandle m_rp = m_sceneHelper.createRenderPassWithCamera(); + const CameraHandle m_camera = m_scene.getRenderPass(m_rp).camera; + const RenderGroupHandle m_rg = m_sceneHelper.createRenderGroup(m_rp); + }; + + TEST_F(ASemanticUniformBuffers, noUBOUploadIfNoRenderables) + { + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, uploadsAndUpdatesUBOWhenAddedRenderable_model) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock }); + + const auto deviceHandleC = expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + const auto deviceHandleMC = expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(renderable, ExpectedMMat); + sceneUpdaterUpdate(); + EXPECT_EQ(deviceHandleC, m_scene.getDeviceHandle(m_camera)); + EXPECT_EQ(deviceHandleMC, m_scene.getDeviceHandle(renderable)); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, uploadsAndUpdatesUBOWhenAddedRenderable_modelCamera) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelCameraBlock }); + + const auto deviceHandleC = expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + const auto deviceHandleMC = expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + EXPECT_EQ(deviceHandleC, m_scene.getDeviceHandle(m_camera)); + EXPECT_EQ(deviceHandleMC, m_scene.getDeviceHandle(renderable, m_camera)); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, uploadsAndUpdatesUBOWhenAddedRenderable_modelAndModelCamera) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + + const auto deviceHandleC = expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + const auto deviceHandle1 = expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + const auto deviceHandle2 = expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + EXPECT_EQ(deviceHandleC, m_scene.getDeviceHandle(m_camera)); + EXPECT_EQ(deviceHandle1, m_scene.getDeviceHandle(renderable)); + EXPECT_EQ(deviceHandle2, m_scene.getDeviceHandle(renderable, m_camera)); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, doesNotUploadUBOWhenAddedRenderablesWithoutSemantic) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelCameraBlock }); + + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // renderable with no semantic + createRenderable(m_rg, {}); + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, uploadsAndUpdatesUBOsForAllCameraRenderables) + { + sceneUpdaterUpdate(); + + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto renderable2 = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + + const auto deviceHandleC = expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + const auto deviceHandleM1 = expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + const auto deviceHandleM2 = expectUBOUpload(SemanticUniformBufferHandle{ renderable2 }); + const auto deviceHandleMC1 = expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + const auto deviceHandleMC2 = expectUBOUpload(SemanticUniformBufferHandle{ renderable2, m_camera }); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable2, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable2, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + + EXPECT_EQ(deviceHandleC, m_scene.getDeviceHandle(m_camera)); + EXPECT_EQ(deviceHandleM1, m_scene.getDeviceHandle(renderable)); + EXPECT_EQ(deviceHandleM2, m_scene.getDeviceHandle(renderable2)); + EXPECT_EQ(deviceHandleMC1, m_scene.getDeviceHandle(renderable, m_camera)); + EXPECT_EQ(deviceHandleMC2, m_scene.getDeviceHandle(renderable2, m_camera)); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, uploadsAndUpdatesUBOsForAllCamerasRenderable) + { + // create another render pass with camera + const auto rp2 = m_sceneHelper.createRenderPassWithCamera(); + const auto camera2 = m_scene.getRenderPass(rp2).camera; + addTransformation(camera2); + const auto rg2 = m_sceneHelper.createRenderGroup(rp2); + sceneUpdaterUpdate(); + + // renderable in RP1 + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + // renderable in RP2 + m_scene.addRenderableToRenderGroup(rg2, renderable, 0); + + const auto deviceHandleC1 = expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + const auto deviceHandleC2 = expectUBOUpload(SemanticUniformBufferHandle{ camera2 }); + const auto deviceHandleM1 = expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + const auto deviceHandleMC1 = expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + const auto deviceHandleMC2 = expectUBOUpload(SemanticUniformBufferHandle{ renderable, camera2 }); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(camera2, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable, camera2, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + + EXPECT_EQ(deviceHandleC1, m_scene.getDeviceHandle(m_camera)); + EXPECT_EQ(deviceHandleC2, m_scene.getDeviceHandle(camera2)); + EXPECT_EQ(deviceHandleM1, m_scene.getDeviceHandle(renderable)); + EXPECT_EQ(deviceHandleMC1, m_scene.getDeviceHandle(renderable, m_camera)); + EXPECT_EQ(deviceHandleMC2, m_scene.getDeviceHandle(renderable, camera2)); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, doesNotUpdateAgainUBOsForAdditionalCamerasRenderablWhichAlreadyExists) + { + // renderable in RP1 + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + + // create another render pass with the SAME camera and the SAME renderable + const auto rp2 = m_sceneHelper.m_sceneAllocator.allocateRenderPass(); + m_scene.setRenderPassCamera(rp2, m_camera); + const auto rg2 = m_sceneHelper.createRenderGroup(rp2); + m_scene.addRenderableToRenderGroup(rg2, renderable, 0); + + // UBOs for renderable and renderable/camera pair already exist and are up-to-date -> expect nothing + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, uploadsAndUpdatesUBOForNewCameraRenderablePairButBothCameraAndRenderableNotDirty) + { + // camera1 + renderable1 in RP1 + const auto renderable1 = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + // camera2 + renderable2 in RP2 + const auto rp2 = m_sceneHelper.createRenderPassWithCamera(); + const auto camera2 = m_scene.getRenderPass(rp2).camera; + addTransformation(camera2); + const auto rg2 = m_sceneHelper.createRenderGroup(rp2); + const auto renderable2 = createRenderable(rg2, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + + // upload all, all objects not dirty afterwards + { + expectUBOUpload(SemanticUniformBufferHandle{ camera2 }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable1 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable1, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2, camera2 }); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(camera2, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(renderable1, ExpectedMMat); + expectUBOUpdate(renderable2, ExpectedMMat); + expectUBOUpdate(renderable1, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable2, camera2, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + } + + // create third render pass with camera1 + renderable2 + const auto rp3 = m_sceneHelper.m_sceneAllocator.allocateRenderPass(); + m_scene.setRenderPassCamera(rp3, m_camera); + const auto rg3 = m_sceneHelper.createRenderGroup(rp3); + m_scene.addRenderableToRenderGroup(rg3, renderable2, 0); + + // a new UBO for camera1 + renderable2, both NOT dirty + { + expectUBOUpload(SemanticUniformBufferHandle{ renderable2, m_camera }); + expectUBOUpdate(renderable2, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + } + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, updatesOnlyRelevantUBOOnChangeOfEitherCameraOrRenderable) + { + // setup 2 RPs, each with camera and renderable + const auto rp2 = m_sceneHelper.createRenderPassWithCamera(); + const auto camera2 = m_scene.getRenderPass(rp2).camera; + addTransformation(camera2); + const auto rg2 = m_sceneHelper.createRenderGroup(rp2); + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto renderable2 = createRenderable(rg2, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + + // third RP uses existing camera and renderable2 + const auto rp3 = m_sceneHelper.m_sceneAllocator.allocateRenderPass(); + m_scene.setRenderPassCamera(rp3, m_camera); + const auto rg3 = m_sceneHelper.createRenderGroup(rp3); + m_scene.addRenderableToRenderGroup(rg3, renderable2, 0); + + // and another renderable with no MVP + const auto renderable3 = createRenderable(m_rg, {}); + + const auto deviceHandleC1 = expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + const auto deviceHandleC2 = expectUBOUpload(SemanticUniformBufferHandle{ camera2 }); + const auto deviceHandleM1 = expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + const auto deviceHandleM2 = expectUBOUpload(SemanticUniformBufferHandle{ renderable2 }); + const auto deviceHandleMC1 = expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + const auto deviceHandleMC2 = expectUBOUpload(SemanticUniformBufferHandle{ renderable2, camera2 }); + const auto deviceHandleMC3 = expectUBOUpload(SemanticUniformBufferHandle{ renderable2, m_camera }); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(camera2, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable2, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable2, camera2, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable2, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + // always updating twice, making sure additional update with no other change is noop + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + // modify renderable + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + makeTransformChange(renderable); + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + // modify renderable2 + expectUBOUpdate(renderable2); + expectUBOUpdate(renderable2, camera2); + expectUBOUpdate(renderable2, m_camera); + makeTransformChange(renderable2); + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + // modify renderable3 (no MVP) + makeTransformChange(renderable3); + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + // modify camera transformation + expectUBOUpdate(m_camera); + expectUBOUpdate(renderable, m_camera); + expectUBOUpdate(renderable2, m_camera); + makeTransformChange(m_camera); + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + // modify camera2 transformation + expectUBOUpdate(camera2); + expectUBOUpdate(renderable2, camera2); + makeTransformChange(camera2); + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + // modify camera projection + expectUBOUpdate(m_camera); + expectUBOUpdate(renderable, m_camera); + expectUBOUpdate(renderable2, m_camera); + makeProjectionChange(m_camera); + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + // modify camera2 projection + expectUBOUpdate(camera2); + expectUBOUpdate(renderable2, camera2); + makeProjectionChange(camera2); + sceneUpdaterUpdate(); + sceneUpdaterUpdate(); + + EXPECT_EQ(deviceHandleC1, m_scene.getDeviceHandle(m_camera)); + EXPECT_EQ(deviceHandleC2, m_scene.getDeviceHandle(camera2)); + EXPECT_EQ(deviceHandleM1, m_scene.getDeviceHandle(renderable)); + EXPECT_EQ(deviceHandleM2, m_scene.getDeviceHandle(renderable2)); + EXPECT_EQ(deviceHandleMC1, m_scene.getDeviceHandle(renderable, m_camera)); + EXPECT_EQ(deviceHandleMC2, m_scene.getDeviceHandle(renderable2, camera2)); + EXPECT_EQ(deviceHandleMC3, m_scene.getDeviceHandle(renderable2, m_camera)); + } + + TEST_F(ASemanticUniformBuffers, updatesOnlyRelevantUBOOnChangeDependingOnWhichRenderableSemanticIsUsed) + { + // prepare data instances with various usages of renderable ubo semantics + ResourceContentHash dummy; + const auto dataLayoutWithModelSemantics = m_sceneHelper.m_sceneAllocator.allocateDataLayout({ + DataFieldInfo{ EDataType::Matrix44F, 1u, EFixedSemantics::ModelBlock }}, dummy, {}); + const auto dataLayoutWithModelAndModelCameraSemantics = m_sceneHelper.m_sceneAllocator.allocateDataLayout({ + DataFieldInfo{ EDataType::Matrix44F, 1u, EFixedSemantics::ModelBlock }, + DataFieldInfo{ EDataType::Matrix44F, 1u, EFixedSemantics::ModelCameraBlock } }, dummy, {}); + const auto uniformsWithModelSemantics = m_sceneHelper.m_sceneAllocator.allocateDataInstance(dataLayoutWithModelSemantics); + const auto uniformsWithModelAndModelCameraSemantics = m_sceneHelper.m_sceneAllocator.allocateDataInstance(dataLayoutWithModelAndModelCameraSemantics); + const auto uniformsWithNoSemantics = DataInstanceHandle::Invalid(); + + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + + // note that camera ubo is currently always processed regardless of uniform semantics + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + + // no semantics no ubo + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformsWithNoSemantics); + sceneUpdaterUpdate(); + + // model semantics + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformsWithModelSemantics); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpdate(renderable, ExpectedMMat); + sceneUpdaterUpdate(); + + // model and model/camera semantics + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformsWithModelAndModelCameraSemantics); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + + // modify renderable -> both ubos updated + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + + // change to model only and modify -> only model ubo updated + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformsWithModelSemantics); + makeTransformChange(renderable); + expectUBOUpdate(renderable); + sceneUpdaterUpdate(); + + // change to no semantics and modify -> no ubo updated + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformsWithNoSemantics); + makeTransformChange(renderable); + sceneUpdaterUpdate(); + + // change back to both semantics -> both ubos updated + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformsWithModelAndModelCameraSemantics); + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, unloadsUBOOnlyWhenNotUsedLongEnough_byReleasingIt) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto renderableUnused = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableUnused }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableUnused, m_camera }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderableUnused, ExpectedMMat); + expectUBOUpdate(renderableUnused, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // make renderable unused by removing it + m_scene.removeRenderableFromRenderGroup(m_rg, renderableUnused); + m_scene.releaseRenderable(renderableUnused); + + // no unload, decays not even processed if no update + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate; ++decay) + sceneUpdaterUpdate(); + + // decays/unloads are processed only if there is a change (dirty caused by modification or new MVP) + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate - 1; ++decay) + { + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + } + + // decay of unused renderable reached threshold to release its UBOs + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + expectUBOUnload(SemanticUniformBufferHandle{ renderableUnused }); + expectUBOUnload(SemanticUniformBufferHandle{ renderableUnused, m_camera }); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, unloadsUBOOnlyWhenNotUsedLongEnough_byRemovingItsSemanticUsage) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto renderableUnused = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableUnused }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableUnused, m_camera }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderableUnused, ExpectedMMat); + expectUBOUpdate(renderableUnused, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // make renderable unused by removing its semantic usage + m_scene.setRenderableDataInstance(renderableUnused, ERenderableDataSlotType::ERenderableDataSlotType_Uniforms, DataInstanceHandle::Invalid()); + + // no unload, decays not even processed if no update + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate; ++decay) + sceneUpdaterUpdate(); + + // decays/unloads are processed only if there is a change (dirty caused by modification or new MVP) + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate - 1; ++decay) + { + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + } + + // decay of unused renderable reached threshold to release its UBOs + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + expectUBOUnload(SemanticUniformBufferHandle{ renderableUnused }); + expectUBOUnload(SemanticUniformBufferHandle{ renderableUnused, m_camera }); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, reallocatingRenderableTriggersNewUploadAndUpdate) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // remove renderable + m_scene.removeRenderableFromRenderGroup(m_rg, renderable); + m_scene.releaseRenderable(renderable); + sceneUpdaterUpdate(); + + // recreate and expect new upload and update + const auto renderableRenewed = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + EXPECT_NE(renderable, renderableRenewed); + expectUBOUpload(SemanticUniformBufferHandle{ renderableRenewed }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableRenewed, m_camera }); + expectUBOUpdate(renderableRenewed, ExpectedMMat); + expectUBOUpdate(renderableRenewed, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, reallocatingRenderableTriggersNewUpdateNotUpload_reusingSameHandle) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // remove renderable + m_scene.removeRenderableFromRenderGroup(m_rg, renderable); + m_scene.releaseRenderable(renderable); + sceneUpdaterUpdate(); + + // recreate and expect update (UBOs kept uploaded) + const auto renderableRenewed = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }, renderable); + EXPECT_EQ(renderable, renderableRenewed); + expectUBOUpdate(renderableRenewed, ExpectedMMat); + expectUBOUpdate(renderableRenewed, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, reallocatingRenderableTriggersNewUploadAndUpdate_withDecay) + { + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto renderableToReallocate = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableToReallocate }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableToReallocate, m_camera }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderableToReallocate, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderableToReallocate, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // remove renderable + m_scene.removeRenderableFromRenderGroup(m_rg, renderableToReallocate); + m_scene.releaseRenderable(renderableToReallocate); + sceneUpdaterUpdate(); + + // decay and let MVP unload + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate - 1; ++decay) + { + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + } + makeTransformChange(renderable); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + expectUBOUnload(SemanticUniformBufferHandle{ renderableToReallocate }); + expectUBOUnload(SemanticUniformBufferHandle{ renderableToReallocate, m_camera }); + sceneUpdaterUpdate(); + + // recreate and expect new upload and update + const auto renderableRenewed = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }, renderableToReallocate); + EXPECT_EQ(renderableToReallocate, renderableRenewed); + expectUBOUpload(SemanticUniformBufferHandle{ renderableRenewed }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableRenewed, m_camera }); + expectUBOUpdate(renderableRenewed, ExpectedMMat); + expectUBOUpdate(renderableRenewed, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, decaysAndRefreshesUBOsOfDisabledAndReenabledRenderPass) + { + // setup 2 RPs, each with camera and renderable + const auto rp2 = m_sceneHelper.createRenderPassWithCamera(); + const auto camera2 = m_scene.getRenderPass(rp2).camera; + addTransformation(camera2); + const auto rg2 = m_sceneHelper.createRenderGroup(rp2); + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto renderable2 = createRenderable(rg2, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ camera2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2, camera2 }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable2, ExpectedMMat); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable2, camera2, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(camera2, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // disable RP1 + m_scene.setRenderPassEnabled(m_rp, false); + sceneUpdaterUpdate(); + + // let its UBOs decay + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate - 1; ++decay) + { + // updating both renderable and camera so their decays are tracked (decay only tracked when something changed) + makeTransformChange(renderable2); + makeTransformChange(camera2); + expectUBOUpdate(renderable2); + expectUBOUpdate(renderable2, camera2); + expectUBOUpdate(camera2); + sceneUpdaterUpdate(); + } + makeTransformChange(renderable2); + makeTransformChange(camera2); + expectUBOUpdate(renderable2); + expectUBOUpdate(renderable2, camera2); + expectUBOUpdate(camera2); + expectUBOUnload(SemanticUniformBufferHandle{ renderable }); + expectUBOUnload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUnload(SemanticUniformBufferHandle{ m_camera }); + sceneUpdaterUpdate(); + + // reenable RP1 and expect reupload+update + m_scene.setRenderPassEnabled(m_rp, true); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(m_camera); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + + // disable RP2 + m_scene.setRenderPassEnabled(rp2, false); + sceneUpdaterUpdate(); + + // let RP2 UBOs decay + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate - 1; ++decay) + { + makeTransformChange(renderable); + makeTransformChange(m_camera); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + expectUBOUpdate(m_camera); + sceneUpdaterUpdate(); + } + makeTransformChange(renderable); + makeTransformChange(m_camera); + expectUBOUpdate(renderable); + expectUBOUpdate(renderable, m_camera); + expectUBOUpdate(m_camera); + expectUBOUnload(SemanticUniformBufferHandle{ renderable2 }); + expectUBOUnload(SemanticUniformBufferHandle{ renderable2, camera2 }); + expectUBOUnload(SemanticUniformBufferHandle{ camera2 }); + sceneUpdaterUpdate(); + + // reenable RP2 and expect reupload+update + m_scene.setRenderPassEnabled(rp2, true); + expectUBOUpload(SemanticUniformBufferHandle{ camera2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2, camera2 }); + expectUBOUpdate(renderable2); + expectUBOUpdate(renderable2, camera2); + expectUBOUpdate(camera2); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, decaysAllUBOsOfDisabledRenderPass) + { + // setup 2 RPs, first with 2 renderables + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto renderable2 = createRenderable(m_rg, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + const auto rp2 = m_sceneHelper.createRenderPassWithCamera(); + const auto camera2 = m_scene.getRenderPass(rp2).camera; + addTransformation(camera2); + const auto rg2 = m_sceneHelper.createRenderGroup(rp2); + const auto renderableDummy = createRenderable(rg2, { EFixedSemantics::ModelBlock, EFixedSemantics::ModelCameraBlock }); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ camera2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableDummy }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable2, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderableDummy, camera2 }); + expectUBOUpdate(renderable, ExpectedMMat); + expectUBOUpdate(renderable2, ExpectedMMat); + expectUBOUpdate(renderableDummy); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable2, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderableDummy, camera2); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(camera2, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // disable RP1 + m_scene.setRenderPassEnabled(m_rp, false); + sceneUpdaterUpdate(); + + // let its UBOs decay + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate - 1; ++decay) + { + makeTransformChange(renderableDummy); + makeTransformChange(camera2); + expectUBOUpdate(renderableDummy); + expectUBOUpdate(renderableDummy, camera2); + expectUBOUpdate(camera2); + sceneUpdaterUpdate(); + } + + // expect all RP1 UBOs unloaded + makeTransformChange(renderableDummy); + makeTransformChange(camera2); + expectUBOUpdate(renderableDummy); + expectUBOUpdate(renderableDummy, camera2); + expectUBOUpdate(camera2); + expectUBOUnload(SemanticUniformBufferHandle{ renderable }); + expectUBOUnload(SemanticUniformBufferHandle{ renderable2 }); + expectUBOUnload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUnload(SemanticUniformBufferHandle{ renderable2, m_camera }); + expectUBOUnload(SemanticUniformBufferHandle{ m_camera }); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, decaysOnlyUnusedMVPOfTwoMVPsUsingSameRenderable) + { + // setup 2 RPs, each with its camera but using same renderable + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelCameraBlock }); + const auto rp2 = m_sceneHelper.createRenderPassWithCamera(); + const auto camera2 = m_scene.getRenderPass(rp2).camera; + const auto rg2 = m_sceneHelper.createRenderGroup(rp2); + m_scene.addRenderableToRenderGroup(rg2, renderable, 0); + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ camera2 }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, camera2 }); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(renderable, camera2); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + expectUBOUpdate(camera2); + sceneUpdaterUpdate(); + + // disable RP2 + m_scene.setRenderPassEnabled(rp2, false); + sceneUpdaterUpdate(); + + // let its MVPs decay + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate - 1; ++decay) + { + makeTransformChange(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + } + + // expect only the MVP from disabled RP2 unloaded + makeTransformChange(renderable); + expectUBOUpdate(renderable, m_camera); + expectUBOUnload(SemanticUniformBufferHandle{ renderable, camera2 }); + sceneUpdaterUpdate(); + + // another update with no change + sceneUpdaterUpdate(); + } + + TEST_F(ASemanticUniformBuffers, decaysNoMVPIfCameraRenderablePairUsedInTwoRPsAndOneDisabled) + { + // setup 2 RPs, using same camera and same renderable + const auto renderable = createRenderable(m_rg, { EFixedSemantics::ModelCameraBlock }); + const auto rp2 = m_sceneHelper.m_sceneAllocator.allocateRenderPass(); + m_scene.setRenderPassCamera(rp2, m_camera); + m_scene.addRenderGroupToRenderPass(rp2, m_rg, 0); + + expectUBOUpload(SemanticUniformBufferHandle{ m_camera }); + expectUBOUpload(SemanticUniformBufferHandle{ renderable, m_camera }); + expectUBOUpdate(renderable, m_camera, ExpectedMVPMat, ExpectedMVMat, ExpectedNormalMat); + expectUBOUpdate(m_camera, ExpectedPMat, ExpectedVMat, ExpectedPos); + sceneUpdaterUpdate(); + + // disable RP2 + m_scene.setRenderPassEnabled(rp2, false); + sceneUpdaterUpdate(); + + // expect no unload because the MVP from disabled RP2 is also used actively in RP1 + for (uint32_t decay = 0u; decay < SemanticUniformBuffers_ModelCamera::DecayCountToDeallocate + 10; ++decay) + { + makeTransformChange(renderable); + expectUBOUpdate(renderable, m_camera); + sceneUpdaterUpdate(); + } + } +} diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/TestSceneHelper.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/TestSceneHelper.cpp new file mode 100644 index 000000000..99ae8d3b7 --- /dev/null +++ b/tests/unittests/renderer/renderer-lib/RendererLib/TestSceneHelper.cpp @@ -0,0 +1,220 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2024 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "TestSceneHelper.h" + +#include "internal/SceneGraph/SceneAPI/TextureSampler.h" +#include "internal/SceneGraph/SceneAPI/Camera.h" +#include "DeviceMock.h" +#include "MockResourceHash.h" + +namespace ramses::internal +{ + TestSceneHelper::TestSceneHelper(IScene& scene, bool indexArrayAvailable, bool createDefaultLayouts) + : m_scene(scene) + , m_sceneAllocator(m_scene) + , m_sceneID(scene.getSceneId()) + , m_indexArrayAvailable(indexArrayAvailable) + { + if (m_indexArrayAvailable) + { + ON_CALL(resourceManager, getResourceDeviceHandle(MockResourceHash::IndexArrayHash)).WillByDefault(Return(DeviceMock::FakeIndexBufferDeviceHandle)); + } + else + { + ON_CALL(resourceManager, getResourceDeviceHandle(MockResourceHash::IndexArrayHash)).WillByDefault(Return(DeviceResourceHandle::Invalid())); + } + + if (createDefaultLayouts) + { + DataFieldInfoVector geometryDataFields(2u); + geometryDataFields[indicesField.asMemoryHandle()] = DataFieldInfo(EDataType::Indices, 1u, EFixedSemantics::Indices); + geometryDataFields[vertAttribField.asMemoryHandle()] = DataFieldInfo(EDataType::Vector3Buffer, 1u, EFixedSemantics::Invalid); + m_sceneAllocator.allocateDataLayout(geometryDataFields, MockResourceHash::EffectHash, testGeometryLayout); + + DataFieldInfoVector uniformDataFields(2u); + uniformDataFields[dataField.asMemoryHandle()] = DataFieldInfo(EDataType::Float); + uniformDataFields[samplerField.asMemoryHandle()] = DataFieldInfo(EDataType::TextureSampler2D); + m_sceneAllocator.allocateDataLayout(uniformDataFields, MockResourceHash::EffectHash, testUniformLayout); + } + } + + RenderGroupHandle TestSceneHelper::createRenderGroup(RenderPassHandle pass1, RenderPassHandle pass2) + { + const RenderGroupHandle renderGroupHandle = m_sceneAllocator.allocateRenderGroup(); + if (pass1.isValid()) + { + m_scene.addRenderGroupToRenderPass(pass1, renderGroupHandle, 0); + } + if (pass2.isValid()) + { + m_scene.addRenderGroupToRenderPass(pass2, renderGroupHandle, 0); + } + + return renderGroupHandle; + } + + RenderableHandle TestSceneHelper::createRenderable(RenderGroupHandle group1, RenderGroupHandle group2, const std::unordered_set& semantics, RenderableHandle handle) + { + const NodeHandle nodeHandle = m_sceneAllocator.allocateNode(); + const RenderableHandle renderableHandle = m_sceneAllocator.allocateRenderable(nodeHandle, handle); + + if (group1.isValid()) + { + m_scene.addRenderableToRenderGroup(group1, renderableHandle, 0); + } + if (group2.isValid()) + { + m_scene.addRenderableToRenderGroup(group2, renderableHandle, 0); + } + + if (!semantics.empty()) + { + DataFieldInfoVector uniformDataFields; + for (const auto s : semantics) + uniformDataFields.push_back(DataFieldInfo{ EDataType::Matrix44F, 1u, s }); + const auto uniformDataLayoutHandle = m_sceneAllocator.allocateDataLayout(uniformDataFields, MockResourceHash::EffectHash, {}); + const auto uniformDataInstanceHandle = m_sceneAllocator.allocateDataInstance(uniformDataLayoutHandle); + m_scene.setRenderableDataInstance(renderableHandle, ERenderableDataSlotType_Uniforms, uniformDataInstanceHandle); + } + + return renderableHandle; + } + + void TestSceneHelper::removeRenderable(RenderableHandle renderable, RenderGroupHandle group1, RenderGroupHandle group2) + { + m_scene.releaseRenderable(renderable); + if (group1.isValid()) + { + m_scene.removeRenderableFromRenderGroup(group1, renderable); + } + if (group2.isValid()) + { + m_scene.removeRenderableFromRenderGroup(group2, renderable); + } + } + + CameraHandle TestSceneHelper::createCamera(ECameraProjectionType projectionType, vec2f frustumNearFar, vec4f frustumPlanes, vec2f viewportOffset, vec2f viewportSize, CameraHandle handle) + { + const DataFieldInfoVector dataRefFiels(4u, DataFieldInfo{ EDataType::DataReference }); + const auto dataLayout = m_sceneAllocator.allocateDataLayout(dataRefFiels, {}, {}); + const auto dataInstance = m_sceneAllocator.allocateDataInstance(dataLayout, {}); + const auto viewportDataReferenceLayout = m_sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2I} }, {}, {}); + const auto viewportOffsetDataReference = m_sceneAllocator.allocateDataInstance(viewportDataReferenceLayout, {}); + const auto viewportSizeDataReference = m_sceneAllocator.allocateDataInstance(viewportDataReferenceLayout, {}); + const auto frustumPlanesDataReferenceLayout = m_sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector4F} }, {}, {}); + const auto frustumPlanesDataReference = m_sceneAllocator.allocateDataInstance(frustumPlanesDataReferenceLayout, {}); + const auto frustumNearFarDataReferenceLayout = m_sceneAllocator.allocateDataLayout({ DataFieldInfo{EDataType::Vector2F} }, {}, {}); + const auto frustumNearFarDataReference = m_sceneAllocator.allocateDataInstance(frustumNearFarDataReferenceLayout, {}); + + m_scene.setDataReference(dataInstance, Camera::ViewportOffsetField, viewportOffsetDataReference); + m_scene.setDataReference(dataInstance, Camera::ViewportSizeField, viewportSizeDataReference); + m_scene.setDataReference(dataInstance, Camera::FrustumPlanesField, frustumPlanesDataReference); + m_scene.setDataReference(dataInstance, Camera::FrustumNearFarPlanesField, frustumNearFarDataReference); + + m_scene.setDataSingleVector2f(frustumNearFarDataReference, DataFieldHandle{ 0 }, frustumNearFar); + m_scene.setDataSingleVector4f(frustumPlanesDataReference, DataFieldHandle{ 0 }, frustumPlanes); + m_scene.setDataSingleVector2i(viewportOffsetDataReference, DataFieldHandle{ 0 }, viewportOffset); + m_scene.setDataSingleVector2i(viewportSizeDataReference, DataFieldHandle{ 0 }, viewportSize); + + const auto nodeHandle = m_sceneAllocator.allocateNode(0u, {}); + + return m_sceneAllocator.allocateCamera(projectionType, nodeHandle, dataInstance, handle); + } + + CameraHandle TestSceneHelper::createCamera(const ProjectionParams& params, vec2f viewportOffset, vec2f viewportSize, CameraHandle handle) + { + return createCamera(params.getProjectionType(), + { params.nearPlane, params.farPlane }, + { params.leftPlane, params.rightPlane, params.bottomPlane, params.topPlane }, + viewportOffset, + viewportSize, handle); + } + + RenderPassHandle TestSceneHelper::createRenderPassWithCamera() + { + const RenderPassHandle pass = m_sceneAllocator.allocateRenderPass(); + const CameraHandle camera = createCamera(); + m_scene.setRenderPassCamera(pass, camera); + return pass; + } + + BlitPassHandle TestSceneHelper::createBlitPassWithDummyRenderBuffers() + { + const RenderBufferHandle sourceRenderBuffer = m_sceneAllocator.allocateRenderBuffer({ 16u, 12u, EPixelStorageFormat::R8, ERenderBufferAccessMode::ReadWrite, 0u }); + const RenderBufferHandle destinationRenderBuffer = m_sceneAllocator.allocateRenderBuffer({ 16u, 12u, EPixelStorageFormat::R8, ERenderBufferAccessMode::ReadWrite, 0u }); + const BlitPassHandle pass = m_sceneAllocator.allocateBlitPass(sourceRenderBuffer, destinationRenderBuffer); + + return pass; + } + + void TestSceneHelper::createRenderTarget() + { + m_sceneAllocator.allocateRenderTarget(renderTarget); + m_sceneAllocator.allocateRenderBuffer({ 16u, 12u, EPixelStorageFormat::R8, ERenderBufferAccessMode::ReadWrite, 0u }, renderTargetColorBuffer); + m_scene.addRenderTargetRenderBuffer(renderTarget, renderTargetColorBuffer); + } + + template + TextureSamplerHandle TestSceneHelper::createTextureSampler(TextureContentHandle handleOrHash) + { + return m_sceneAllocator.allocateTextureSampler({ {}, handleOrHash }); + } + template TextureSamplerHandle TestSceneHelper::createTextureSampler(TextureBufferHandle handleOrHash); + template TextureSamplerHandle TestSceneHelper::createTextureSampler(RenderBufferHandle handleOrHash); + template TextureSamplerHandle TestSceneHelper::createTextureSampler(ResourceContentHash handleOrHash); + + TextureSamplerHandle TestSceneHelper::createTextureSamplerWithFakeTexture() + { + return createTextureSampler(MockResourceHash::TextureHash); + } + + DataInstanceHandle TestSceneHelper::createAndAssignUniformDataInstance(RenderableHandle renderable, TextureSamplerHandle sampler) + { + const DataInstanceHandle uniformData = m_sceneAllocator.allocateDataInstance(testUniformLayout); + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformData); + m_scene.setDataTextureSamplerHandle(uniformData, samplerField, sampler); + + return uniformData; + } + + DataInstanceHandle TestSceneHelper::createAndAssignVertexDataInstance(RenderableHandle renderable) + { + const DataInstanceHandle geometryData = m_sceneAllocator.allocateDataInstance(testGeometryLayout); + m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Geometry, geometryData); + + return geometryData; + } + + void TestSceneHelper::setResourcesToRenderable( + RenderableHandle renderable, + bool setVertices, + bool setIndices) + { + auto vertexData = m_scene.getRenderable(renderable).dataInstances[ERenderableDataSlotType_Geometry]; + if (setVertices) + m_scene.setDataResource(vertexData, vertAttribField, MockResourceHash::VertArrayHash, DataBufferHandle::Invalid(), 0u, 0u, 0u); + if (setIndices) + m_scene.setDataResource(vertexData, indicesField, MockResourceHash::IndexArrayHash, DataBufferHandle::Invalid(), 0u, 0u, 0u); + } + + template + void TestSceneHelper::recreateSamplerWithDifferentContent(TextureSamplerHandle handle, TextureContentHandle contentHandleOrHash) + { + const auto& samplerStates = m_scene.getTextureSampler(handle).states; + m_scene.releaseTextureSampler(handle); + m_scene.allocateTextureSampler({ samplerStates, contentHandleOrHash }, handle); + [[maybe_unused]] bool hasDataSlot = false; + for (DataSlotHandle d(0u); d < m_scene.getDataSlotCount(); ++d) + hasDataSlot |= (m_scene.isDataSlotAllocated(d) && m_scene.getDataSlot(d).attachedTextureSampler == handle); + assert(!hasDataSlot && "Recreating sampler that had data slot assigned, data slot must be recreated as well"); + } + + template void TestSceneHelper::recreateSamplerWithDifferentContent(TextureSamplerHandle handle, RenderBufferHandle contentHandleOrHash); + template void TestSceneHelper::recreateSamplerWithDifferentContent(TextureSamplerHandle handle, ResourceContentHash contentHandleOrHash); +} diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/TestSceneHelper.h b/tests/unittests/renderer/renderer-lib/RendererLib/TestSceneHelper.h index 0ea8aacc4..297851e99 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/TestSceneHelper.h +++ b/tests/unittests/renderer/renderer-lib/RendererLib/TestSceneHelper.h @@ -9,169 +9,45 @@ #pragma once #include "internal/SceneGraph/SceneAPI/IScene.h" -#include "internal/SceneGraph/SceneAPI/Renderable.h" -#include "internal/SceneGraph/SceneAPI/SceneTypes.h" -#include "internal/SceneGraph/SceneAPI/TextureSampler.h" -#include "internal/RendererLib/RendererResourceManager.h" +#include "internal/Core/Math3d/ProjectionParams.h" +#include "SceneAllocateHelper.h" #include "RendererResourceManagerMock.h" #include "EmbeddedCompositingManagerMock.h" -#include "DeviceMock.h" -#include "SceneAllocateHelper.h" -#include "internal/SceneGraph/Scene/DataLayout.h" -#include "MockResourceHash.h" +#include namespace ramses::internal { class TestSceneHelper { public: - explicit TestSceneHelper(IScene& scene, bool indexArrayAvailable = true) - : m_scene(scene) - , m_sceneAllocator(m_scene) - , m_sceneID(scene.getSceneId()) - , m_indexArrayAvailable(indexArrayAvailable) - { - if (m_indexArrayAvailable) - { - ON_CALL(resourceManager, getResourceDeviceHandle(MockResourceHash::IndexArrayHash)).WillByDefault(Return(DeviceMock::FakeIndexBufferDeviceHandle)); - } - else - { - ON_CALL(resourceManager, getResourceDeviceHandle(MockResourceHash::IndexArrayHash)).WillByDefault(Return(DeviceResourceHandle::Invalid())); - } - - DataFieldInfoVector geometryDataFields(2u); - geometryDataFields[indicesField.asMemoryHandle()] = DataFieldInfo(EDataType::Indices, 1u, EFixedSemantics::Indices); - geometryDataFields[vertAttribField.asMemoryHandle()] = DataFieldInfo(EDataType::Vector3Buffer, 1u, EFixedSemantics::Invalid); - m_sceneAllocator.allocateDataLayout(geometryDataFields, MockResourceHash::EffectHash, testGeometryLayout); - - DataFieldInfoVector uniformDataFields(2u); - uniformDataFields[dataField.asMemoryHandle()] = DataFieldInfo(EDataType::Float); - uniformDataFields[samplerField.asMemoryHandle()] = DataFieldInfo(EDataType::TextureSampler2D); - m_sceneAllocator.allocateDataLayout(uniformDataFields, MockResourceHash::EffectHash, testUniformLayout); - } - - RenderGroupHandle createRenderGroup(RenderPassHandle pass1 = RenderPassHandle::Invalid(), RenderPassHandle pass2 = RenderPassHandle::Invalid()) - { - const RenderGroupHandle renderGroupHandle = m_sceneAllocator.allocateRenderGroup(); - if (pass1.isValid()) - { - m_scene.addRenderGroupToRenderPass(pass1, renderGroupHandle, 0); - } - if (pass2.isValid()) - { - m_scene.addRenderGroupToRenderPass(pass2, renderGroupHandle, 0); - } - - return renderGroupHandle; - } - - RenderableHandle createRenderable(RenderGroupHandle group1 = RenderGroupHandle::Invalid(), RenderGroupHandle group2 = RenderGroupHandle::Invalid()) - { - const NodeHandle nodeHandle = m_sceneAllocator.allocateNode(); - const RenderableHandle renderableHandle = m_sceneAllocator.allocateRenderable(nodeHandle); - - if (group1.isValid()) - { - m_scene.addRenderableToRenderGroup(group1, renderableHandle, 0); - } - if (group2.isValid()) - { - m_scene.addRenderableToRenderGroup(group2, renderableHandle, 0); - } - - return renderableHandle; - } - - void removeRenderable(RenderableHandle renderable, RenderGroupHandle group1 = RenderGroupHandle::Invalid(), RenderGroupHandle group2 = RenderGroupHandle::Invalid()) - { - m_scene.releaseRenderable(renderable); - if (group1.isValid()) - { - m_scene.removeRenderableFromRenderGroup(group1, renderable); - } - if (group2.isValid()) - { - m_scene.removeRenderableFromRenderGroup(group2, renderable); - } - } - - RenderPassHandle createRenderPassWithCamera() - { - const RenderPassHandle pass = m_sceneAllocator.allocateRenderPass(); - const auto dataLayout = m_sceneAllocator.allocateDataLayout({DataFieldInfo{EDataType::Vector2I}, DataFieldInfo{EDataType::Vector2I}}, ResourceContentHash::Invalid()); - const CameraHandle camera = m_sceneAllocator.allocateCamera(ECameraProjectionType::Perspective, m_sceneAllocator.allocateNode(), m_sceneAllocator.allocateDataInstance(dataLayout)); - m_scene.setRenderPassCamera(pass, camera); - return pass; - } - - BlitPassHandle createBlitPassWithDummyRenderBuffers() - { - const RenderBufferHandle sourceRenderBuffer = m_sceneAllocator.allocateRenderBuffer({ 16u, 12u, EPixelStorageFormat::R8, ERenderBufferAccessMode::ReadWrite, 0u }); - const RenderBufferHandle destinationRenderBuffer = m_sceneAllocator.allocateRenderBuffer({ 16u, 12u, EPixelStorageFormat::R8, ERenderBufferAccessMode::ReadWrite, 0u }); - const BlitPassHandle pass = m_sceneAllocator.allocateBlitPass(sourceRenderBuffer, destinationRenderBuffer); - - return pass; - } - - void createRenderTarget() - { - m_sceneAllocator.allocateRenderTarget(renderTarget); - m_sceneAllocator.allocateRenderBuffer({ 16u, 12u, EPixelStorageFormat::R8, ERenderBufferAccessMode::ReadWrite, 0u }, renderTargetColorBuffer); - m_scene.addRenderTargetRenderBuffer(renderTarget, renderTargetColorBuffer); - } + explicit TestSceneHelper(IScene& scene, bool indexArrayAvailable = true, bool createDefaultLayouts = true); + + RenderGroupHandle createRenderGroup(RenderPassHandle pass1 = RenderPassHandle::Invalid(), RenderPassHandle pass2 = RenderPassHandle::Invalid()); + RenderableHandle createRenderable(RenderGroupHandle group1 = RenderGroupHandle::Invalid(), RenderGroupHandle group2 = RenderGroupHandle::Invalid(), + const std::unordered_set& semantics = {}, RenderableHandle handle = {}); + void removeRenderable(RenderableHandle renderable, RenderGroupHandle group1 = RenderGroupHandle::Invalid(), RenderGroupHandle group2 = RenderGroupHandle::Invalid()); + CameraHandle createCamera(ECameraProjectionType projectionType = ECameraProjectionType::Perspective, + vec2f frustumNearFar = { 0.1f, 1.f }, + vec4f frustumPlanes = { -1.f, 1.f, -1.f, 1.f }, + vec2f viewportOffset = {}, + vec2f viewportSize = {}, + CameraHandle handle = {}); + CameraHandle createCamera(const ProjectionParams& params, vec2f viewportOffset = {}, vec2f viewportSize = {}, CameraHandle handle = {}); + RenderPassHandle createRenderPassWithCamera(); + BlitPassHandle createBlitPassWithDummyRenderBuffers(); + void createRenderTarget(); template - TextureSamplerHandle createTextureSampler(TextureContentHandle handleOrHash) - { - return m_sceneAllocator.allocateTextureSampler({ {}, handleOrHash }); - } - - TextureSamplerHandle createTextureSamplerWithFakeTexture() - { - return createTextureSampler(MockResourceHash::TextureHash); - } - - DataInstanceHandle createAndAssignUniformDataInstance(RenderableHandle renderable, TextureSamplerHandle sampler) - { - const DataInstanceHandle uniformData = m_sceneAllocator.allocateDataInstance(testUniformLayout); - m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Uniforms, uniformData); - m_scene.setDataTextureSamplerHandle(uniformData, samplerField, sampler); - - return uniformData; - } - - DataInstanceHandle createAndAssignVertexDataInstance(RenderableHandle renderable) - { - const DataInstanceHandle geometryData = m_sceneAllocator.allocateDataInstance(testGeometryLayout); - m_scene.setRenderableDataInstance(renderable, ERenderableDataSlotType_Geometry, geometryData); + TextureSamplerHandle createTextureSampler(TextureContentHandle handleOrHash); - return geometryData; - } + TextureSamplerHandle createTextureSamplerWithFakeTexture(); + DataInstanceHandle createAndAssignUniformDataInstance(RenderableHandle renderable, TextureSamplerHandle sampler); + DataInstanceHandle createAndAssignVertexDataInstance(RenderableHandle renderable); - void setResourcesToRenderable( - RenderableHandle renderable, - bool setVertices = true, - bool setIndices = true) - { - auto vertexData = m_scene.getRenderable(renderable).dataInstances[ERenderableDataSlotType_Geometry]; - if (setVertices) - m_scene.setDataResource(vertexData, vertAttribField, MockResourceHash::VertArrayHash, DataBufferHandle::Invalid(), 0u, 0u, 0u); - if (setIndices) - m_scene.setDataResource(vertexData, indicesField, MockResourceHash::IndexArrayHash, DataBufferHandle::Invalid(), 0u, 0u, 0u); - } + void setResourcesToRenderable(RenderableHandle renderable, bool setVertices = true, bool setIndices = true); template - void recreateSamplerWithDifferentContent(TextureSamplerHandle handle, TextureContentHandle contentHandleOrHash) - { - const auto& samplerStates = m_scene.getTextureSampler(handle).states; - m_scene.releaseTextureSampler(handle); - m_scene.allocateTextureSampler({ samplerStates, contentHandleOrHash }, handle); - [[maybe_unused]] bool hasDataSlot = false; - for (DataSlotHandle d(0u); d < m_scene.getDataSlotCount(); ++d) - hasDataSlot |= (m_scene.isDataSlotAllocated(d) && m_scene.getDataSlot(d).attachedTextureSampler == handle); - assert(!hasDataSlot && "Recreating sampler that had data slot assigned, data slot must be recreated as well"); - } + void recreateSamplerWithDifferentContent(TextureSamplerHandle handle, TextureContentHandle contentHandleOrHash); public: IScene& m_scene; diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/TextureLinkManagerTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/TextureLinkManagerTest.cpp index c445d4def..05fa759c2 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/TextureLinkManagerTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/TextureLinkManagerTest.cpp @@ -13,8 +13,8 @@ #include "internal/RendererLib/ResourceCachedScene.h" #include "internal/RendererLib/RendererEventCollector.h" #include "TestSceneHelper.h" -#include "SceneAllocateHelper.h" #include "MockResourceHash.h" +#include "DeviceMock.h" namespace ramses::internal { using namespace testing; @@ -28,8 +28,8 @@ namespace ramses::internal { : rendererScenes(rendererEventCollector) , sceneLinksManager(rendererScenes.getSceneLinksManager()) , textureLinkManager(sceneLinksManager.getTextureLinkManager()) - , providerScene(rendererScenes.createScene(SceneInfo(providerSceneId))) - , consumerScene(rendererScenes.createScene(SceneInfo(consumerSceneId))) + , providerScene(rendererScenes.createScene(SceneInfo{ providerSceneId })) + , consumerScene(rendererScenes.createScene(SceneInfo{ consumerSceneId })) , providerSceneAllocator(providerScene) , consumerSceneAllocator(consumerScene) , sceneHelper(consumerScene) diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkCachedSceneTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkCachedSceneTest.cpp index e00aaa663..4eb8c3bc3 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkCachedSceneTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkCachedSceneTest.cpp @@ -25,11 +25,11 @@ namespace ramses::internal ATransformationLinkCachedScene() : rendererScenes(rendererEventCollector) , sceneLinksManager(rendererScenes.getSceneLinksManager()) - , providerScene(rendererScenes.createScene(SceneInfo(SceneId(0u)))) - , consumer1Scene(rendererScenes.createScene(SceneInfo(SceneId(1u)))) - , consumer2Scene(rendererScenes.createScene(SceneInfo(SceneId(2u)))) - , consumer2ndLevelScene(rendererScenes.createScene(SceneInfo(SceneId(3u)))) - , consumerWithoutTransformsScene(rendererScenes.createScene(SceneInfo(SceneId(4u)))) + , providerScene(rendererScenes.createScene(SceneInfo{ SceneId(0u) })) + , consumer1Scene(rendererScenes.createScene(SceneInfo{ SceneId(1u) })) + , consumer2Scene(rendererScenes.createScene(SceneInfo{ SceneId(2u) })) + , consumer2ndLevelScene(rendererScenes.createScene(SceneInfo{ SceneId(3u) })) + , consumerWithoutTransformsScene(rendererScenes.createScene(SceneInfo{ SceneId(4u) })) , providerSceneAllocator(providerScene) , consumer1SceneAllocator(consumer1Scene) , consumer2SceneAllocator(consumer2Scene) diff --git a/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkManagerTest.cpp b/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkManagerTest.cpp index 2c240864e..4c02d2b8b 100644 --- a/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkManagerTest.cpp +++ b/tests/unittests/renderer/renderer-lib/RendererLib/TransformationLinkManagerTest.cpp @@ -28,8 +28,8 @@ namespace ramses::internal , transformationLinkManager(const_cast(sceneLinksManager.getTransformationLinkManager())) , providerSceneId(3u) , consumerSceneId(4u) - , providerScene(rendererScenes.createScene(SceneInfo(providerSceneId))) - , consumerScene(rendererScenes.createScene(SceneInfo(consumerSceneId))) + , providerScene(rendererScenes.createScene(SceneInfo{ providerSceneId })) + , consumerScene(rendererScenes.createScene(SceneInfo{ consumerSceneId })) , providerSceneAllocator(providerScene) , consumerSceneAllocator(consumerScene) , providerNode(8u) diff --git a/tests/unittests/renderer/renderer-test-common/ContextMock.h b/tests/unittests/renderer/renderer-test-common/ContextMock.h index dbeace7a4..7215979da 100644 --- a/tests/unittests/renderer/renderer-test-common/ContextMock.h +++ b/tests/unittests/renderer/renderer-test-common/ContextMock.h @@ -27,6 +27,6 @@ namespace ramses::internal MOCK_METHOD(bool, disable, (), (override)); MOCK_METHOD(DeviceResourceMapper&, getResources, (), (override)); - MOCK_METHOD(void*, getProcAddress, (const char*), (const, override)); + MOCK_METHOD(GlProcLoadFunc, getGlProcLoadFunc, (), (const, override)); }; } diff --git a/tests/unittests/renderer/renderer-test-common/DeviceMock.cpp b/tests/unittests/renderer/renderer-test-common/DeviceMock.cpp index 178aafa57..6af5725a8 100644 --- a/tests/unittests/renderer/renderer-test-common/DeviceMock.cpp +++ b/tests/unittests/renderer/renderer-test-common/DeviceMock.cpp @@ -25,6 +25,7 @@ namespace ramses::internal const DeviceResourceHandle DeviceMock::FakeDmaRenderBufferDeviceHandle(7778u); const DeviceResourceHandle DeviceMock::FakeTextureSamplerDeviceHandle(8888u); const DeviceResourceHandle DeviceMock::FakeBlitPassRenderTargetDeviceHandle(9999u); + const DeviceResourceHandle DeviceMock::FakeUniformBufferDeviceHandle(9998u); DeviceMock::DeviceMock() { @@ -55,6 +56,7 @@ namespace ramses::internal ON_CALL(*this, uploadRenderBuffer(_, _, _, _, _)).WillByDefault(Return(FakeRenderBufferDeviceHandle)); ON_CALL(*this, uploadDmaRenderBuffer(_, _, _, _, _)).WillByDefault(Return(FakeDmaRenderBufferDeviceHandle)); ON_CALL(*this, uploadRenderTarget(_)).WillByDefault(Return(FakeRenderTargetDeviceHandle)); + ON_CALL(*this, allocateUniformBuffer(_)).WillByDefault(Return(FakeUniformBufferDeviceHandle)); ON_CALL(*this, getFramebufferRenderTarget()).WillByDefault(Return(FakeFrameBufferRenderTargetDeviceHandle)); EXPECT_CALL(*this, getSupportedBinaryProgramFormats(_)).Times(AnyNumber()); diff --git a/tests/unittests/renderer/renderer-test-common/DeviceMock.h b/tests/unittests/renderer/renderer-test-common/DeviceMock.h index f6048203b..af773c25b 100644 --- a/tests/unittests/renderer/renderer-test-common/DeviceMock.h +++ b/tests/unittests/renderer/renderer-test-common/DeviceMock.h @@ -57,6 +57,10 @@ namespace ramses::internal MOCK_METHOD(void, drawMode, (EDrawMode), (override)); MOCK_METHOD(void, setViewport, (int32_t, int32_t, uint32_t, uint32_t), (override)); + MOCK_METHOD(DeviceResourceHandle, allocateUniformBuffer, (uint32_t), (override)); + MOCK_METHOD(void, uploadUniformBufferData, (DeviceResourceHandle, const std::byte*, uint32_t), (override)); + MOCK_METHOD(void, activateUniformBuffer, (DeviceResourceHandle, DataFieldHandle), (override)); + MOCK_METHOD(void, deleteUniformBuffer, (DeviceResourceHandle), (override)); MOCK_METHOD(DeviceResourceHandle, allocateVertexBuffer, (uint32_t), (override)); MOCK_METHOD(void, uploadVertexBufferData, (DeviceResourceHandle, const std::byte*, uint32_t), (override)); MOCK_METHOD(void, deleteVertexBuffer, (DeviceResourceHandle), (override)); @@ -131,6 +135,7 @@ namespace ramses::internal static const DeviceResourceHandle FakeDmaRenderBufferDeviceHandle ; static const DeviceResourceHandle FakeTextureSamplerDeviceHandle ; static const DeviceResourceHandle FakeBlitPassRenderTargetDeviceHandle ; + static const DeviceResourceHandle FakeUniformBufferDeviceHandle ; static constexpr BinaryShaderFormatID FakeSupportedBinaryShaderFormat{ 63666u }; static constexpr uint32_t FakeExternalTextureGlId{ 162023u }; diff --git a/tests/unittests/renderer/renderer-test-common/MockResourceHash.h b/tests/unittests/renderer/renderer-test-common/MockResourceHash.h index 32dd71860..d646d6ce9 100644 --- a/tests/unittests/renderer/renderer-test-common/MockResourceHash.h +++ b/tests/unittests/renderer/renderer-test-common/MockResourceHash.h @@ -32,7 +32,7 @@ namespace ramses::internal std::unique_ptr res; if (hash == EffectHash) { - res = std::make_unique("", "", "", std::optional{}, EffectInputInformationVector(), EffectInputInformationVector(), ""); + res = std::make_unique("", "", "", SPIRVShaders{}, std::optional{}, EffectInputInformationVector(), EffectInputInformationVector(), "", EFeatureLevel_Latest); } else if (hash == VertArrayHash || hash == VertArrayHash2) { diff --git a/tests/unittests/renderer/renderer-test-common/PlatformFactoryMock.h b/tests/unittests/renderer/renderer-test-common/PlatformFactoryMock.h index 56b09d3f3..9c7651a7c 100644 --- a/tests/unittests/renderer/renderer-test-common/PlatformFactoryMock.h +++ b/tests/unittests/renderer/renderer-test-common/PlatformFactoryMock.h @@ -25,7 +25,7 @@ namespace ramses::internal return std::make_unique>();}); } - MOCK_METHOD(std::unique_ptr, createPlatform, (const RendererConfig& rendererConfig, const DisplayConfig& dispConfig), (override)); + MOCK_METHOD(std::unique_ptr, createPlatform, (const RendererConfigData& rendererConfig, const DisplayConfigData& dispConfig), (override)); }; using PlatformFactoryNiceMock = PlatformFactoryMock< ::testing::NiceMock>; diff --git a/tests/unittests/renderer/renderer-test-common/PlatformMock.h b/tests/unittests/renderer/renderer-test-common/PlatformMock.h index d11aa9318..55814124c 100644 --- a/tests/unittests/renderer/renderer-test-common/PlatformMock.h +++ b/tests/unittests/renderer/renderer-test-common/PlatformMock.h @@ -15,7 +15,7 @@ namespace ramses::internal { - class RendererConfig; + class RendererConfigData; template class MOCK_TYPE> class PlatformMock : public IPlatform @@ -24,7 +24,7 @@ namespace ramses::internal explicit PlatformMock(); ~PlatformMock() override; - MOCK_METHOD(IRenderBackend*, createRenderBackend, (const DisplayConfig& displayConfig, IWindowEventHandler& windowEventHandler), (override)); + MOCK_METHOD(IRenderBackend*, createRenderBackend, (const DisplayConfigData& displayConfig, IWindowEventHandler& windowEventHandler), (override)); MOCK_METHOD(void, destroyRenderBackend, (), (override)); MOCK_METHOD(IResourceUploadRenderBackend*, createResourceUploadRenderBackend, (), (override)); MOCK_METHOD(void, destroyResourceUploadRenderBackend, (), (override)); diff --git a/tests/unittests/renderer/renderer-test-common/RendererCommandVisitorMock.h b/tests/unittests/renderer/renderer-test-common/RendererCommandVisitorMock.h index 777f4a214..bb71a5c87 100644 --- a/tests/unittests/renderer/renderer-test-common/RendererCommandVisitorMock.h +++ b/tests/unittests/renderer/renderer-test-common/RendererCommandVisitorMock.h @@ -9,9 +9,10 @@ #pragma once #include "internal/RendererLib/RendererCommands.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/SceneGraph/SceneAPI/SceneId.h" #include "internal/RendererLib/Types.h" +#include "TestEqualHelper.h" #include "gmock/gmock.h" namespace ramses::internal @@ -29,7 +30,7 @@ namespace ramses::internal void operator()(const RendererCommand::ScenePublished& cmd) { - handleScenePublished(cmd.scene, cmd.publicationMode); + handleScenePublished(cmd.scene, cmd.publicationMode, cmd.renderBackendCompatibility, cmd.vulkanAPIVersion, cmd.spirvVersion); } void operator()(const RendererCommand::SceneUnpublished& cmd) @@ -228,14 +229,14 @@ namespace ramses::internal assert(!"unhandled command"); } - MOCK_METHOD(void, handleScenePublished, (SceneId, EScenePublicationMode)); + MOCK_METHOD(void, handleScenePublished, (SceneId, EScenePublicationMode, ERenderBackendCompatibility, EVulkanAPIVersion, ESPIRVVersion)); MOCK_METHOD(void, handleSceneUnpublished, (SceneId)); MOCK_METHOD(void, handleSceneReceived, (const SceneInfo&)); MOCK_METHOD(void, handleSceneUpdate, (SceneId, const SceneUpdate&)); MOCK_METHOD(void, setSceneState, (SceneId, RendererSceneState)); MOCK_METHOD(void, setSceneMapping, (SceneId, DisplayHandle)); MOCK_METHOD(void, setSceneDisplayBufferAssignment, (SceneId, OffscreenBufferHandle, int32_t)); - MOCK_METHOD(void, createDisplayContext, (const DisplayConfig&, DisplayHandle, IBinaryShaderCache*)); + MOCK_METHOD(void, createDisplayContext, (const DisplayConfigData&, DisplayHandle, IBinaryShaderCache*)); MOCK_METHOD(void, destroyDisplayContext, (DisplayHandle)); MOCK_METHOD(void, handleSceneDataLinkRequest, (SceneId, DataSlotId, SceneId, DataSlotId)); MOCK_METHOD(void, handleDataUnlinkRequest, (SceneId, DataSlotId)); diff --git a/tests/unittests/renderer/renderer-test-common/ResourceDeviceHandleAccessorMock.h b/tests/unittests/renderer/renderer-test-common/ResourceDeviceHandleAccessorMock.h index f2055e138..ca8ef435c 100644 --- a/tests/unittests/renderer/renderer-test-common/ResourceDeviceHandleAccessorMock.h +++ b/tests/unittests/renderer/renderer-test-common/ResourceDeviceHandleAccessorMock.h @@ -32,6 +32,8 @@ namespace ramses::internal MOCK_METHOD(DeviceResourceHandle, getExternalBufferDeviceHandle, (ExternalBufferHandle), (const, override)); MOCK_METHOD(DeviceResourceHandle, getEmptyExternalBufferDeviceHandle, (), (const, override)); MOCK_METHOD(uint32_t, getExternalBufferGlId, (ExternalBufferHandle), (const, override)); + MOCK_METHOD(DeviceResourceHandle, getUniformBufferDeviceHandle, (UniformBufferHandle uniformBufferHandle, SceneId sceneId), (const, override)); + MOCK_METHOD(DeviceResourceHandle, getUniformBufferDeviceHandle, (SemanticUniformBufferHandle handle, SceneId sceneId), (const, override)); }; } diff --git a/tests/unittests/renderer/window-wayland-common/AWindowWayland.h b/tests/unittests/renderer/window-wayland-common/AWindowWayland.h index 8aa6335a8..a9999f4e0 100644 --- a/tests/unittests/renderer/window-wayland-common/AWindowWayland.h +++ b/tests/unittests/renderer/window-wayland-common/AWindowWayland.h @@ -10,7 +10,7 @@ #include "WindowEventHandlerMock.h" #include "TestWithWaylandEnvironment.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/Platform/Wayland/UnixDomainSocket.h" #include @@ -45,7 +45,7 @@ namespace ramses::internal } ::testing::StrictMock m_eventHandlerMock; - ramses::internal::DisplayConfig m_config; + ramses::internal::DisplayConfigData m_config; WINDOWTYPE* m_window = nullptr; }; } diff --git a/tests/unittests/renderer/window-windows/Window_Window_Test.cpp b/tests/unittests/renderer/window-windows/Window_Window_Test.cpp index f7893fe25..cc5be1d8d 100644 --- a/tests/unittests/renderer/window-windows/Window_Window_Test.cpp +++ b/tests/unittests/renderer/window-windows/Window_Window_Test.cpp @@ -9,7 +9,7 @@ #include "gmock/gmock.h" #include "internal/Platform/Windows/Window_Windows.h" #include "WindowEventHandlerMock.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/Enums/EKeyModifier.h" using namespace testing; @@ -63,7 +63,7 @@ namespace ramses::internal processAllEvents(); } - DisplayConfig config; + DisplayConfigData config; NiceMock eventHandlerMock; Window_Windows window; }; @@ -79,7 +79,7 @@ namespace ramses::internal TEST(Window_Windows, propagatesResizeEvents) { - DisplayConfig config; + DisplayConfigData config; config.setResizable(true); NiceMock eventHandlerMock; Window_Windows window(config, eventHandlerMock, 0); @@ -99,7 +99,7 @@ namespace ramses::internal TEST(Window_Windows, propagatesWindowMoveEvents) { - DisplayConfig config; + DisplayConfigData config; config.setResizable(true); NiceMock eventHandlerMock; Window_Windows window(config, eventHandlerMock, 0); @@ -249,7 +249,7 @@ namespace ramses::internal TEST_F(AWindowWindows, canSetExternallyOwnedWindowSize) { - DisplayConfig otherConfig; + DisplayConfigData otherConfig; otherConfig.setWindowsWindowHandle(WindowsWindowHandle{window.getNativeWindowHandle()}); Window_Windows externallyOwnedWindow(otherConfig, eventHandlerMock, 123u); ASSERT_TRUE(externallyOwnedWindow.init()); diff --git a/tests/unittests/renderer/window-x11/Window_X11_Test.cpp b/tests/unittests/renderer/window-x11/Window_X11_Test.cpp index 15f884557..158e7343a 100644 --- a/tests/unittests/renderer/window-x11/Window_X11_Test.cpp +++ b/tests/unittests/renderer/window-x11/Window_X11_Test.cpp @@ -9,7 +9,7 @@ #include "gmock/gmock.h" #include "internal/Platform/X11/Window_X11.h" #include "WindowEventHandlerMock.h" -#include "internal/RendererLib/DisplayConfig.h" +#include "internal/RendererLib/DisplayConfigData.h" #include "internal/RendererLib/Enums/EKeyModifier.h" using namespace testing; @@ -155,7 +155,7 @@ namespace ramses::internal proceseAllEvents(); } - DisplayConfig config; + DisplayConfigData config; NiceMock eventHandlerMock; Window_X11 window; }; @@ -273,7 +273,7 @@ namespace ramses::internal TEST_F(WindowX11, canCreateDisplayWithExternallyOwnedWindow) { - DisplayConfig otherConfig; + DisplayConfigData otherConfig; otherConfig.setX11WindowHandle(X11WindowHandle{window.getNativeWindowHandle()}); Window_X11 externallyOwnedWindow(otherConfig, eventHandlerMock, 123u); ASSERT_TRUE(externallyOwnedWindow.init()); @@ -281,7 +281,7 @@ namespace ramses::internal TEST_F(WindowX11, canReCreateDisplayWithSameExternallyOwnedWindowSeveralTimes) { - DisplayConfig otherConfig; + DisplayConfigData otherConfig; otherConfig.setX11WindowHandle(X11WindowHandle{window.getNativeWindowHandle()}); { @@ -302,7 +302,7 @@ namespace ramses::internal TEST_F(WindowX11, canSetExternallyOwnedWindowSize) { - DisplayConfig otherConfig; + DisplayConfigData otherConfig; otherConfig.setX11WindowHandle(X11WindowHandle{window.getNativeWindowHandle()}); Window_X11 externallyOwnedWindow(otherConfig, eventHandlerMock, 123u); ASSERT_TRUE(externallyOwnedWindow.init()); diff --git a/tests/unittests/tools/CMakeLists.txt b/tests/unittests/tools/CMakeLists.txt index 7ec1dae0d..20982403a 100644 --- a/tests/unittests/tools/CMakeLists.txt +++ b/tests/unittests/tools/CMakeLists.txt @@ -6,6 +6,4 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. # ------------------------------------------------------------------------- -if(ramses-sdk_ENABLE_LOGIC) - add_subdirectory(ramses-viewer) -endif() +add_subdirectory(ramses-viewer) diff --git a/tests/unittests/tools/ramses-viewer/CMakeLists.txt b/tests/unittests/tools/ramses-viewer/CMakeLists.txt index 88a70afdc..2d5d1f7b2 100644 --- a/tests/unittests/tools/ramses-viewer/CMakeLists.txt +++ b/tests/unittests/tools/ramses-viewer/CMakeLists.txt @@ -11,7 +11,7 @@ createModule( TYPE BINARY ENABLE_INSTALL ON INCLUDE_PATHS ${PROJECT_SOURCE_DIR}/tools/ramses-viewer - ${PROJECT_SOURCE_DIR}/tests/unittests/client/logic/shared + ${PROJECT_SOURCE_DIR}/tests/unittests/client/utils SRC_FILES LogicViewerTestBase.h LogicViewerTestBase.cpp LogicViewerTest.cpp @@ -22,6 +22,7 @@ createModule( ramses-client ramses-gmock ramses-gmock-main + glslang-init-gtest-env ) MakeTestFromTarget( diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index ac31731cb..f8e8eafe0 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -8,10 +8,8 @@ add_subdirectory(ramses-daemon) -if(ramses-sdk_ENABLE_LOGIC) - add_subdirectory(test-asset-producer) - add_subdirectory(ramses-viewer) -endif() +add_subdirectory(test-asset-producer) +add_subdirectory(ramses-viewer) if(TARGET ramses-renderer) add_subdirectory(ramses-renderer-standalone) diff --git a/tools/ramses-imgui/include/ImguiClientHelper.h b/tools/ramses-imgui/include/ImguiClientHelper.h index f4a43956a..b3efd77da 100644 --- a/tools/ramses-imgui/include/ImguiClientHelper.h +++ b/tools/ramses-imgui/include/ImguiClientHelper.h @@ -22,19 +22,13 @@ #include "ramses/client/ramses-client.h" #include "ramses/client/ramses-utils.h" -#include "ramses/renderer/RamsesRenderer.h" -#include "ramses/renderer/RendererSceneControl.h" #include "ramses/renderer/IRendererEventHandler.h" -#include "ramses/renderer/IRendererSceneControlEventHandler.h" -#include -#include #include -#include namespace ramses::internal { - class ImguiClientHelper : public ramses::RendererEventHandlerEmpty, public ramses::RendererSceneControlEventHandlerEmpty + class ImguiClientHelper : public ramses::RendererEventHandlerEmpty { public: ImguiClientHelper(ramses::RamsesClient& client, uint32_t width, uint32_t height, ramses::sceneId_t sceneid); @@ -48,85 +42,35 @@ namespace ramses::internal */ void setDisplayId(ramses::displayId_t displayId); - void setRenderer(ramses::RamsesRenderer* renderer); - - void dispatchEvents(); - - void dispatchClickEvent(std::pair& clickEventOut); - void draw(); - [[nodiscard]] bool isRunning() const; ramses::Scene* getScene(); - [[nodiscard]] uint32_t getViewportWidth() const; - [[nodiscard]] uint32_t getViewportHeight() const; - - bool saveScreenshot(const std::string& filename); - bool saveScreenshot(const std::string& filename, ramses::displayBufferId_t screenshotBuf, uint32_t x, uint32_t y, uint32_t width, uint32_t height); - - bool waitForDisplay(ramses::displayId_t displayId); - bool waitForSceneState(ramses::Scene& scene, ramses::RendererSceneState state); - bool waitForSceneVersion(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t version); - bool waitForOffscreenBufferCreated(const ramses::displayBufferId_t offscreenBufferId); - bool waitForOffscreenBufferLinked(const ramses::sceneId_t sceneId); - bool waitForScreenshot(); - - // SceneControlEvents - void sceneStateChanged(ramses::sceneId_t sceneId, ramses::RendererSceneState state) override; - void sceneFlushed(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t sceneVersion) override; - void offscreenBufferCreated(ramses::displayId_t displayId_t, ramses::displayBufferId_t offscreenBufferId, ramses::ERendererEventResult result) override; - void offscreenBufferLinked(ramses::displayBufferId_t offscreenBufferId, ramses::sceneId_t consumerScene, ramses::dataConsumerId_t consumerId, bool success) override; // Renderer events - void displayCreated(ramses::displayId_t displayId, ramses::ERendererEventResult result) override; - void displayDestroyed(ramses::displayId_t displayId, ramses::ERendererEventResult result) override; void mouseEvent(ramses::displayId_t displayId, ramses::EMouseEvent eventType, int32_t mousePosX, int32_t mousePosY) override; void keyEvent(ramses::displayId_t displayId, ramses::EKeyEvent eventType, ramses::KeyModifiers keyModifiers, ramses::EKeyCode keyCode) override; void windowResized(ramses::displayId_t displayId, uint32_t width, uint32_t height) override; - void windowClosed(ramses::displayId_t displayId) override; - void framebufferPixelsRead(const uint8_t* pixelData, - const uint32_t pixelDataSize, - ramses::displayId_t displayId, - ramses::displayBufferId_t displayBuffer, - ramses::ERendererEventResult result) override; + + std::pair createTextureConsumer(); + + ramses::RenderGroup* getBackgroundGroup(); private: - bool waitUntil(const std::function& conditionFunction, ramses::Scene* scene = nullptr); - - struct SceneInfo - { - ramses::RendererSceneState state = ramses::RendererSceneState::Unavailable; - ramses::sceneVersionTag_t version = ramses::InvalidSceneVersionTag; - }; - - using SceneSet = std::unordered_map; - using OffscreenBufferSet = std::unordered_set; - using DisplaySet = std::unordered_set; - - SceneSet m_scenes; - SceneSet m_scenesAssignedToOffscreenBuffer; - SceneSet m_scenesConsumingOffscreenBuffer; - DisplaySet m_displays; - OffscreenBufferSet m_offscreenBuffers; - ramses::RamsesRenderer* m_renderer = nullptr; ramses::displayId_t m_displayId; ramses::Scene* m_imguiscene = nullptr; ramses::OrthographicCamera* imguicamera = nullptr; ramses::TextureSampler* sampler = nullptr; ramses::Effect* effect = nullptr; ramses::RenderGroup* renderGroup = nullptr; + ramses::RenderGroup* m_backgroundGroup = nullptr; + ramses::Texture2D* m_placeholderTexture = nullptr; + uint32_t m_nextTextureConsumerId = 700; std::optional textureInput{std::nullopt}; std::optional inputPosition{std::nullopt}; std::optional inputUV{std::nullopt}; std::optional inputColor{std::nullopt}; std::vector todeleteMeshes; std::vector todeleteRes; - std::pair m_clickEvent; - std::string m_screenshot; - uint32_t m_screenshotWidth = 0U; - uint32_t m_screenshotHeight = 0U; - bool m_screenshotSaved = false; - bool m_isRunning = true; ImGuiContext* m_context = nullptr; }; @@ -135,23 +79,13 @@ namespace ramses::internal return m_imguiscene; } - inline bool ImguiClientHelper::isRunning() const - { - return m_isRunning; - } - - inline void ImguiClientHelper::setRenderer(ramses::RamsesRenderer* renderer) - { - m_renderer = renderer; - } - - inline uint32_t ImguiClientHelper::getViewportWidth() const + inline void ImguiClientHelper::setDisplayId(ramses::displayId_t displayId) { - return imguicamera->getViewportWidth(); + m_displayId = displayId; } - inline uint32_t ImguiClientHelper::getViewportHeight() const + inline ramses::RenderGroup* ImguiClientHelper::getBackgroundGroup() { - return imguicamera->getViewportHeight(); + return m_backgroundGroup; } } diff --git a/tools/ramses-imgui/include/ImguiWidgets.h b/tools/ramses-imgui/include/ImguiWidgets.h index 8a263c6b4..891514bad 100644 --- a/tools/ramses-imgui/include/ImguiWidgets.h +++ b/tools/ramses-imgui/include/ImguiWidgets.h @@ -18,12 +18,15 @@ WARNING_DISABLE_LINUX(-Wold-style-cast) WARNINGS_POP -#include "absl/types/span.h" #include "internal/SceneGraph/SceneAPI/TextureEnums.h" #include "internal/SceneGraph/Resource/TextureMetaInfo.h" -#include #include "internal/SceneGraph/SceneAPI/Handles.h" +#include "absl/types/span.h" +#include "fmt/format.h" + +#include + namespace ramses { @@ -69,6 +72,21 @@ namespace ramses::internal const TextureSwizzleArray& swizzle = DefaultTextureSwizzleArray); std::string SaveTextureToPng(const TextureResource* resource, const std::string& filename); + + template + void HelpMarker(const char* desc, Args&& ... args) + { + // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) 3rd party interface + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered()) + { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(fmt::format(desc, args...).c_str()); + ImGui::PopTextWrapPos(); + ImGui::EndTooltip(); + } + } } } diff --git a/tools/ramses-imgui/src/ImguiClientHelper.cpp b/tools/ramses-imgui/src/ImguiClientHelper.cpp index f26df70ec..3fad15f2b 100644 --- a/tools/ramses-imgui/src/ImguiClientHelper.cpp +++ b/tools/ramses-imgui/src/ImguiClientHelper.cpp @@ -121,8 +121,10 @@ namespace ramses::internal ramses::RenderPass* renderPass = m_imguiscene->createRenderPass("imgui render pass"); renderPass->setClearFlags(ramses::EClearFlag::None); renderPass->setCamera(*imguicamera); + m_backgroundGroup = m_imguiscene->createRenderGroup("backgroundGroup"); + renderPass->addRenderGroup(*m_backgroundGroup); renderGroup = m_imguiscene->createRenderGroup(); - renderPass->addRenderGroup(*renderGroup); + renderPass->addRenderGroup(*renderGroup, 1); ramses::EffectDescription effectDescImgui; effectDescImgui.setFragmentShader(ImguiFragShader); effectDescImgui.setVertexShader(ImguiVertShader); @@ -135,6 +137,9 @@ namespace ramses::internal inputUV = effect->findAttributeInput("a_texcoord"); inputColor = effect->findAttributeInput("Color"); + static const std::vector placeholderPixels(4, std::byte{ 255 }); + m_placeholderTexture = m_imguiscene->createTexture2D(ramses::ETextureFormat::RGBA8, 1, 1, {placeholderPixels}); + if (!ImGui::GetCurrentContext()) { m_context = ImGui::CreateContext(); @@ -199,9 +204,14 @@ namespace ramses::internal ImGui::DestroyContext(m_context); } - void ImguiClientHelper::setDisplayId(ramses::displayId_t displayId) + std::pair ImguiClientHelper::createTextureConsumer() { - m_displayId = displayId; + auto* textureSampler = m_imguiscene->createTextureSampler( + ramses::ETextureAddressMode::Clamp, ramses::ETextureAddressMode::Clamp, + ramses::ETextureSamplingMethod::Linear, ramses::ETextureSamplingMethod::Linear, *m_placeholderTexture); + auto id = ramses::dataConsumerId_t{m_nextTextureConsumerId++}; + m_imguiscene->createTextureConsumer(*textureSampler, id); + return std::make_pair(id, textureSampler); } void ImguiClientHelper::draw() @@ -300,56 +310,6 @@ namespace ramses::internal m_imguiscene->flush(); } - void ImguiClientHelper::sceneStateChanged(ramses::sceneId_t sceneId, ramses::RendererSceneState state) - { - m_scenes[sceneId].state = state; - } - - void ImguiClientHelper::sceneFlushed(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t sceneVersion) - { - m_scenes[sceneId].version = sceneVersion; - } - - void ImguiClientHelper::offscreenBufferCreated(ramses::displayId_t /*displayId_t*/, ramses::displayBufferId_t offscreenBufferId, ramses::ERendererEventResult result) - { - if (ramses::ERendererEventResult::Failed != result) - { - m_offscreenBuffers.insert(offscreenBufferId); - } - } - - void ImguiClientHelper::offscreenBufferLinked(ramses::displayBufferId_t /*offscreenBufferId*/, ramses::sceneId_t consumerScene, ramses::dataConsumerId_t /*consumerId*/, bool success) - { - if (success) - { - m_scenesConsumingOffscreenBuffer[consumerScene].state = ramses::RendererSceneState::Unavailable; - } - } - - void ImguiClientHelper::displayCreated(ramses::displayId_t displayId, ramses::ERendererEventResult result) - { - if (ramses::ERendererEventResult::Failed != result) - { - m_displays.insert(displayId); - } - else - { - m_isRunning = false; - } - } - - void ImguiClientHelper::displayDestroyed(ramses::displayId_t displayId, ramses::ERendererEventResult result) - { - if (ramses::ERendererEventResult::Failed != result) - { - m_displays.erase(displayId); - } - else - { - m_isRunning = false; - } - } - void ImguiClientHelper::mouseEvent(ramses::displayId_t displayId, ramses::EMouseEvent eventType, int32_t mousePosX, int32_t mousePosY) { if (!m_displayId.isValid() || displayId == m_displayId) @@ -360,7 +320,6 @@ namespace ramses::internal { case ramses::EMouseEvent::LeftButtonUp: io.MouseDown[0] = false; - m_clickEvent = {mousePosX, mousePosY}; break; case ramses::EMouseEvent::LeftButtonDown: io.MouseDown[0] = true; @@ -434,112 +393,5 @@ namespace ramses::internal io.DisplaySize.y = static_cast(height); } } - - void ImguiClientHelper::windowClosed(ramses::displayId_t /*displayId*/) - { - m_isRunning = false; - } - - void ImguiClientHelper::framebufferPixelsRead(const uint8_t* pixelData, - const uint32_t pixelDataSize, - ramses::displayId_t displayId, - ramses::displayBufferId_t displayBuffer, - ramses::ERendererEventResult result) - { - static_cast(displayId); - static_cast(displayBuffer); - if (!m_screenshot.empty()) - { - m_screenshotSaved = false; - if (result == ramses::ERendererEventResult::Ok) - { - std::vector buffer; - // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) - buffer.insert(buffer.end(), &pixelData[0], &pixelData[pixelDataSize]); - m_screenshotSaved = ramses::RamsesUtils::SaveImageBufferToPng(m_screenshot, buffer, m_screenshotWidth, m_screenshotHeight, true); - } - m_screenshot.clear(); - } - } - - void ImguiClientHelper::dispatchClickEvent(std::pair& clickEventOut) - { - clickEventOut = m_clickEvent; - m_clickEvent = {std::numeric_limits::max(), std::numeric_limits::max()}; - } - - void ImguiClientHelper::dispatchEvents() - { - m_renderer->dispatchEvents(*this); - m_renderer->getSceneControlAPI()->dispatchEvents(*this); - } - - bool ImguiClientHelper::saveScreenshot(const std::string& filename) - { - return saveScreenshot(filename, ramses::displayBufferId_t(), 0, 0, imguicamera->getViewportWidth(), imguicamera->getViewportHeight()); - } - - bool ImguiClientHelper::saveScreenshot(const std::string& filename, ramses::displayBufferId_t screenshotBuf, uint32_t x, uint32_t y, uint32_t width, uint32_t height) - { - if (m_renderer && m_screenshot.empty() && !filename.empty()) - { - m_screenshotSaved = false; - m_screenshot = filename; - m_screenshotWidth = width - x; - m_screenshotHeight = height - x; - m_renderer->readPixels(m_displayId, screenshotBuf, x, y, width, height); - m_renderer->flush(); - return true; - } - return false; - } - - bool ImguiClientHelper::waitForDisplay(ramses::displayId_t displayId) - { - return waitUntil([&] { return m_displays.find(displayId) != m_displays.end(); }); - } - - bool ImguiClientHelper:: waitForSceneState(ramses::Scene& scene, ramses::RendererSceneState state) - { - return waitUntil([&] { return m_scenes[scene.getSceneId()].state == state; }, &scene); - } - - bool ImguiClientHelper::waitForSceneVersion(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t version) - { - return waitUntil([&] { return m_scenes[sceneId].version == version; }); - } - - bool ImguiClientHelper::waitForOffscreenBufferCreated(const ramses::displayBufferId_t offscreenBufferId) - { - return waitUntil([&] { return m_offscreenBuffers.find(offscreenBufferId) != m_offscreenBuffers.end(); }); - } - - bool ImguiClientHelper::waitForOffscreenBufferLinked(const ramses::sceneId_t sceneId) - { - return waitUntil([&] { return m_scenesConsumingOffscreenBuffer.count(sceneId) > 0; }); - } - - bool ImguiClientHelper::waitForScreenshot() - { - waitUntil([&] { return m_screenshot.empty(); }); - return m_screenshotSaved; - } - - bool ImguiClientHelper::waitUntil(const std::function& conditionFunction, ramses::Scene* scene) - { - const std::chrono::steady_clock::time_point timeoutTS = std::chrono::steady_clock::now() + std::chrono::seconds{5}; - while (m_isRunning && !conditionFunction() && std::chrono::steady_clock::now() < timeoutTS) - { - if (scene) - scene->flush(); // make sure scene gets flushed if subscribing - std::this_thread::sleep_for(std::chrono::milliseconds{5}); // will give the renderer time to process changes - m_renderer->dispatchEvents(*this); - auto* sceneControl = m_renderer->getSceneControlAPI(); - sceneControl->dispatchEvents(*this); - } - - return conditionFunction(); - } - } diff --git a/tools/ramses-viewer/CMakeLists.txt b/tools/ramses-viewer/CMakeLists.txt index 618903763..165bfc062 100644 --- a/tools/ramses-viewer/CMakeLists.txt +++ b/tools/ramses-viewer/CMakeLists.txt @@ -44,8 +44,14 @@ target_sources(ramses-viewer-gui-lib INTERFACE LogicEngineGui.cpp LogicViewerGui.h LogicViewerGui.cpp + RemoteScenesGui.h + RemoteScenesGui.cpp + RendererControl.h + RendererControl.cpp SceneViewerGui.h SceneViewerGui.cpp + StreamViewer.h + StreamViewer.cpp ViewerGui.h ViewerGui.cpp ViewerGuiApp.h diff --git a/tools/ramses-viewer/LogicEngineGui.cpp b/tools/ramses-viewer/LogicEngineGui.cpp index e4ad10d71..61d6c44e3 100644 --- a/tools/ramses-viewer/LogicEngineGui.cpp +++ b/tools/ramses-viewer/LogicEngineGui.cpp @@ -12,7 +12,6 @@ #include "ViewerSettings.h" #include "ramses/client/Scene.h" #include "ramses/client/logic/LogicEngine.h" -#include "internal/logic/StdFilesystemWrapper.h" #include "internal/PlatformAbstraction/FmtBase.h" #include "glm/gtc/type_ptr.hpp" diff --git a/tools/ramses-viewer/LogicViewerGui.cpp b/tools/ramses-viewer/LogicViewerGui.cpp index c3b88400d..b151ce11e 100644 --- a/tools/ramses-viewer/LogicViewerGui.cpp +++ b/tools/ramses-viewer/LogicViewerGui.cpp @@ -29,7 +29,6 @@ #include "ramses/client/logic/AnchorPoint.h" #include "ramses/client/logic/SkinBinding.h" #include "ramses/client/logic/RenderBufferBinding.h" -#include "internal/logic/StdFilesystemWrapper.h" #include "internal/PlatformAbstraction/FmtBase.h" #include "glm/gtc/type_ptr.hpp" @@ -42,6 +41,10 @@ #pragma GCC diagnostic pop #endif +#include + +namespace fs = std::filesystem; + template <> struct fmt::formatter { template constexpr auto parse(ParseContext& ctx) @@ -126,21 +129,6 @@ namespace ramses::internal } return name; } - - template - void HelpMarker(const char* desc, Args&& ... args) - { - // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) 3rd party interface - ImGui::TextDisabled("(?)"); - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); - ImGui::TextUnformatted(fmt::format(desc, args...).c_str()); - ImGui::PopTextWrapPos(); - ImGui::EndTooltip(); - } - } } LogicViewerGui::LogicViewerGui(ViewerGuiApp& app, std::string& errorMessage) @@ -306,7 +294,7 @@ namespace ramses::internal { ImGui::TextUnformatted(fmt::format("Average Update Time: {} ms", m_viewer.getUpdateReport(engine).getTotalTime().average).c_str()); ImGui::SameLine(); - HelpMarker("Time it took to update the whole logic nodes network (LogicEngine::update())."); + imgui::HelpMarker("Time it took to update the whole logic nodes network (LogicEngine::update())."); ImGui::SameLine(); std::string detailsText = "Show Details"; if (m_viewer.getLogicEngines().size() > 1) @@ -334,24 +322,24 @@ namespace ramses::internal ImGui::Separator(); ImGui::TextUnformatted("Summary:"); ImGui::SameLine(); - HelpMarker("Timing data is collected and summarized for {} frames.\n'min', 'max', 'avg' show the minimum, maximum, and average value for the measured interval.", + imgui::HelpMarker("Timing data is collected and summarized for {} frames.\n'min', 'max', 'avg' show the minimum, maximum, and average value for the measured interval.", m_settings.updateReportInterval); ImGui::Indent(); const auto& updateTime = report.getTotalTime(); ImGui::TextUnformatted(fmt::format("Total Update Time (ms): max:{} min:{} avg:{}", updateTime.maxValue, updateTime.minValue, updateTime.average).c_str()); ImGui::SameLine(); - HelpMarker("Time it took to update the whole logic nodes network (LogicEngine::update())."); + imgui::HelpMarker("Time it took to update the whole logic nodes network (LogicEngine::update())."); const auto& sortTime = report.getSortTime(); ImGui::TextUnformatted(fmt::format("Topology Sort Time (ms): max:{} min:{} avg:{}", sortTime.maxValue, sortTime.minValue, sortTime.average).c_str()); ImGui::SameLine(); - HelpMarker("Time it took to sort logic nodes by their topology during update (see ramses::LogicEngineReport::getTopologySortExecutionTime()"); + imgui::HelpMarker("Time it took to sort logic nodes by their topology during update (see ramses::LogicEngineReport::getTopologySortExecutionTime()"); const auto& links = report.getLinkActivations(); ImGui::TextUnformatted(fmt::format("Activated Links: max:{} min:{} avg:{}", links.maxValue, links.minValue, links.average).c_str()); ImGui::SameLine(); - HelpMarker("Number of input properties that had been updated by an output property (see ramses::LogicEngineReport::getTotalLinkActivations())."); + imgui::HelpMarker("Number of input properties that had been updated by an output property (see ramses::LogicEngineReport::getTotalLinkActivations())."); ImGui::Unindent(); ImGui::TextUnformatted(fmt::format("Details for the longest update ({} ms):", longest).c_str()); diff --git a/tools/ramses-viewer/RemoteScenesGui.cpp b/tools/ramses-viewer/RemoteScenesGui.cpp new file mode 100644 index 000000000..630b76590 --- /dev/null +++ b/tools/ramses-viewer/RemoteScenesGui.cpp @@ -0,0 +1,80 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2023 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "RemoteScenesGui.h" +#include "ImguiWrapper.h" +#include "ViewerGuiApp.h" + +namespace ramses::internal +{ + RemoteScenesGui::RemoteScenesGui(ViewerGuiApp& app) + : m_rendererControl(app.getRendererControl()) + , m_imguiScene(app.getImguiClientHelper()->getScene()->getSceneId()) + { + if (app.getScene()) + m_loadedScene = app.getScene()->getSceneId(); + } + + void RemoteScenesGui::drawContents(bool open) + { + const auto& sceneSet = m_rendererControl->getRendererScenes(); + if (m_loadedScene.isValid() && sceneSet.size() == 2) + return; // no remote scenes - simplify ui + + if (ImGui::CollapsingHeader("Remote Scenes", open ? ImGuiTreeNodeFlags_DefaultOpen : 0)) + { + int availableScenes = 0; + for (auto& it : sceneSet) + { + if (it.first == m_imguiScene) + continue; + if (it.second.state == RendererSceneState::Unavailable) + continue; + ++availableScenes; + ImGui::PushID(&it.second); + if (it.first == m_loadedScene) + { + ImGui::TextUnformatted(fmt::format("Scene:{} (local scene)", it.first, it.second.buffer.getValue()).c_str()); + } + else + { + ImGui::TextUnformatted(fmt::format("Scene:{}", it.first).c_str()); + } + auto newState = it.second.state; + int renderOrder = it.second.renderOrder; + + bool renderOrderChanged = false; + if (!it.second.buffer.isValid()) + { + renderOrderChanged = ImGui::DragInt("Render order", &renderOrder, 1.f, 0, 255); + ImGui::SameLine(); + imgui::HelpMarker("Changing the render order may not have a visual effect, if the remote scenes use depth testing."); + } + else + { + ImGui::TextUnformatted(fmt::format("Offscreen buffer: {}", it.second.buffer.getValue()).c_str()); + ImGui::SameLine(); + imgui::HelpMarker("The offscreen buffer is part of the gui scene, i.e. it will cover the other scenes (even if the scene is in Ready or Available state)."); + } + + if (ImGui::RadioButton("Available", it.second.state == RendererSceneState::Available)) + newState = RendererSceneState::Available; + if (ImGui::RadioButton("Ready", it.second.state == RendererSceneState::Ready)) + newState = RendererSceneState::Ready; + if (ImGui::RadioButton("Rendered", it.second.state == RendererSceneState::Rendered)) + newState = RendererSceneState::Rendered; + + if (renderOrderChanged || newState != it.second.state) + m_rendererControl->setupSceneState(it.first, newState, renderOrder); + ImGui::PopID(); + } + if (availableScenes == 0) + ImGui::TextWrapped("No remote scenes available."); + } + } +} diff --git a/tools/ramses-viewer/RemoteScenesGui.h b/tools/ramses-viewer/RemoteScenesGui.h new file mode 100644 index 000000000..1914edbb9 --- /dev/null +++ b/tools/ramses-viewer/RemoteScenesGui.h @@ -0,0 +1,31 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2023 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "ramses/framework/RamsesFrameworkTypes.h" + + +namespace ramses::internal +{ + class ViewerGuiApp; + class RendererControl; + + class RemoteScenesGui + { + public: + explicit RemoteScenesGui(ViewerGuiApp& app); + void drawContents(bool open); + + private: + RendererControl* m_rendererControl; + sceneId_t m_imguiScene; + sceneId_t m_loadedScene; + }; +} + diff --git a/tools/ramses-viewer/RendererControl.cpp b/tools/ramses-viewer/RendererControl.cpp new file mode 100644 index 000000000..6fac0c841 --- /dev/null +++ b/tools/ramses-viewer/RendererControl.cpp @@ -0,0 +1,229 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2023 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "RendererControl.h" +#include +#include "impl/RendererEventChainer.h" +#include "ramses/client/ramses-utils.h" +#include "ramses/client/Scene.h" + +namespace ramses::internal +{ + RendererControl::RendererControl(RamsesRenderer* renderer, displayId_t display, uint32_t displayWidth, uint32_t displayHeight, + IRendererEventHandler* rendererEventHandler, IRendererSceneControlEventHandler* sceneControlEventHandler) + : m_renderer(renderer) + , m_rendererEventHandler(rendererEventHandler) + , m_sceneControlEventHandler(sceneControlEventHandler) + , m_displayId(display) + , m_displayWidth(displayWidth) + , m_displayHeight(displayHeight) + { + } + + void RendererControl::setupSceneState(sceneId_t sceneId, RendererSceneState state, displayBufferId_t buffer, int32_t renderOrder) + { + m_scenes[sceneId].configuredManually = true; + m_scenes[sceneId].buffer = buffer; + m_scenes[sceneId].renderOrder = renderOrder; + auto* sceneControl = m_renderer->getSceneControlAPI(); + if (m_scenes[sceneId].state <= RendererSceneState::Available) + sceneControl->setSceneMapping(sceneId, m_displayId); + sceneControl->setSceneDisplayBufferAssignment(sceneId, buffer, renderOrder); + sceneControl->setSceneState(sceneId, state); + sceneControl->flush(); + } + + void RendererControl::setupSceneState(sceneId_t sceneId, RendererSceneState state, int32_t renderOrder) + { + setupSceneState(sceneId, state, m_scenes[sceneId].buffer, renderOrder); + } + + void RendererControl::dispatchEvents() + { + if (m_rendererEventHandler) + { + RendererEventChainer chainer2{ *this, *m_rendererEventHandler }; + m_renderer->dispatchEvents(chainer2); + } + else + { + m_renderer->dispatchEvents(*this); + } + if (m_sceneControlEventHandler) + { + RendererSceneControlEventChainer chainer{ *this, *m_sceneControlEventHandler }; + m_renderer->getSceneControlAPI()->dispatchEvents(chainer); + } + else + { + m_renderer->getSceneControlAPI()->dispatchEvents(*this); + } + m_renderer->flush(); + m_renderer->getSceneControlAPI()->flush(); + } + + void RendererControl::sceneStateChanged(ramses::sceneId_t sceneId, ramses::RendererSceneState state) + { + const bool scenePublished = m_scenes[sceneId].state == RendererSceneState::Unavailable; + m_scenes[sceneId].state = state; + + if (m_autoShow && scenePublished && state == RendererSceneState::Available && !m_scenes[sceneId].configuredManually) + { + auto* sceneControl = m_renderer->getSceneControlAPI(); + sceneControl->setSceneMapping(sceneId, m_displayId); + sceneControl->setSceneState(sceneId, RendererSceneState::Rendered); + } + } + + void RendererControl::sceneFlushed(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t sceneVersion) + { + m_scenes[sceneId].version = sceneVersion; + } + + void RendererControl::offscreenBufferCreated(ramses::displayId_t /*displayId_t*/, ramses::displayBufferId_t offscreenBufferId, ramses::ERendererEventResult result) + { + if (ramses::ERendererEventResult::Failed != result) + { + m_offscreenBuffers.insert(offscreenBufferId); + } + } + + void RendererControl::offscreenBufferLinked(ramses::displayBufferId_t /*offscreenBufferId*/, ramses::sceneId_t consumerScene, ramses::dataConsumerId_t /*consumerId*/, bool success) + { + if (success) + { + m_scenesConsumingOffscreenBuffer[consumerScene].state = ramses::RendererSceneState::Unavailable; + } + } + + void RendererControl::displayCreated(ramses::displayId_t displayId, ramses::ERendererEventResult result) + { + if (ramses::ERendererEventResult::Failed != result) + { + m_displays.insert(displayId); + } + else + { + m_isRunning = false; + } + } + + void RendererControl::displayDestroyed(ramses::displayId_t displayId, ramses::ERendererEventResult result) + { + if (ramses::ERendererEventResult::Failed != result) + { + m_displays.erase(displayId); + } + else + { + m_isRunning = false; + } + } + + void RendererControl::windowResized(ramses::displayId_t displayId, uint32_t width, uint32_t height) + { + if (m_displayId == displayId) + { + m_displayWidth = width; + m_displayHeight = height; + } + } + + void RendererControl::windowClosed(ramses::displayId_t /*displayId*/) + { + m_isRunning = false; + } + + void RendererControl::framebufferPixelsRead(const uint8_t* pixelData, + const uint32_t pixelDataSize, + ramses::displayId_t displayId, + ramses::displayBufferId_t displayBuffer, + ramses::ERendererEventResult result) + { + static_cast(displayId); + static_cast(displayBuffer); + if (!m_screenshot.empty()) + { + m_screenshotSaved = false; + if (result == ramses::ERendererEventResult::Ok) + { + std::vector buffer; + // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) + buffer.insert(buffer.end(), &pixelData[0], &pixelData[pixelDataSize]); + m_screenshotSaved = ramses::RamsesUtils::SaveImageBufferToPng(m_screenshot, buffer, m_screenshotWidth, m_screenshotHeight, true); + } + m_screenshot.clear(); + } + } + + bool RendererControl::waitForDisplay(ramses::displayId_t displayId) + { + return waitUntil([&] { return m_displays.find(displayId) != m_displays.end(); }); + } + + bool RendererControl:: waitForSceneState(ramses::Scene& scene, ramses::RendererSceneState state) + { + return waitUntil([&] { return m_scenes[scene.getSceneId()].state == state; }, [&]() { scene.flush(); }); + } + + bool RendererControl::waitForSceneVersion(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t version) + { + return waitUntil([&] { return m_scenes[sceneId].version == version; }); + } + + bool RendererControl::waitForOffscreenBufferCreated(const ramses::displayBufferId_t offscreenBufferId) + { + return waitUntil([&] { return m_offscreenBuffers.find(offscreenBufferId) != m_offscreenBuffers.end(); }); + } + + bool RendererControl::waitForOffscreenBufferLinked(const ramses::sceneId_t sceneId) + { + return waitUntil([&] { return m_scenesConsumingOffscreenBuffer.count(sceneId) > 0; }); + } + + bool RendererControl::waitForScreenshot() + { + waitUntil([&] { return m_screenshot.empty(); }); + return m_screenshotSaved; + } + + bool RendererControl::waitUntil(const std::function& conditionFunction, const std::function& dispatch) + { + const std::chrono::steady_clock::time_point timeoutTS = std::chrono::steady_clock::now() + std::chrono::seconds{5}; + while (m_isRunning && !conditionFunction() && std::chrono::steady_clock::now() < timeoutTS) + { + if (dispatch) + dispatch(); + std::this_thread::sleep_for(std::chrono::milliseconds{5}); // will give the renderer time to process changes + dispatchEvents(); + } + + return conditionFunction(); + } + + bool RendererControl::saveScreenshot(const std::string& filename) + { + return saveScreenshot(filename, ramses::displayBufferId_t(), 0, 0, m_displayWidth, m_displayHeight); + } + + bool RendererControl::saveScreenshot(const std::string& filename, ramses::displayBufferId_t screenshotBuf, uint32_t x, uint32_t y, uint32_t width, uint32_t height) + { + if (m_renderer && m_screenshot.empty() && !filename.empty()) + { + m_screenshotSaved = false; + m_screenshot = filename; + m_screenshotWidth = width - x; + m_screenshotHeight = height - x; + m_renderer->readPixels(m_displayId, screenshotBuf, x, y, width, height); + m_renderer->flush(); + return true; + } + return false; + } + +} diff --git a/tools/ramses-viewer/RendererControl.h b/tools/ramses-viewer/RendererControl.h new file mode 100644 index 000000000..c9743a4ea --- /dev/null +++ b/tools/ramses-viewer/RendererControl.h @@ -0,0 +1,138 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2023 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "ramses/renderer/RamsesRenderer.h" +#include "ramses/renderer/RendererSceneControl.h" +#include "ramses/renderer/IRendererEventHandler.h" +#include "ramses/renderer/IRendererSceneControlEventHandler.h" + +#include + +namespace ramses +{ + class Scene; +} + +namespace ramses::internal +{ + class RendererControl : public RendererEventHandlerEmpty, public RendererSceneControlEventHandlerEmpty + { + public: + RendererControl(RamsesRenderer* renderer, displayId_t display, uint32_t displayWidth, uint32_t displayHeight, + IRendererEventHandler* rendererEventHandler = nullptr, + IRendererSceneControlEventHandler* sceneControlEventHandler = nullptr); + + void setupSceneState(sceneId_t sceneId, RendererSceneState state, displayBufferId_t buffer, int32_t renderOrder); + + void setupSceneState(sceneId_t sceneId, RendererSceneState state, int32_t renderOrder); + + void setAutoShow(bool autoShow) + { + m_autoShow = autoShow; + } + + void dispatchEvents(); + + struct SceneInfo + { + ramses::RendererSceneState state = ramses::RendererSceneState::Unavailable; + ramses::sceneVersionTag_t version = ramses::InvalidSceneVersionTag; + ramses::displayBufferId_t buffer = {}; + int32_t renderOrder = 0; + bool configuredManually = false; // won't be auto-shown if true + }; + + using SceneSet = std::unordered_map; + + const SceneSet& getRendererScenes() const + { + return m_scenes; + } + + RamsesRenderer* getRenderer() + { + return m_renderer; + } + + displayId_t getDisplayId() const + { + return m_displayId; + } + + uint32_t getDisplayWidth() const + { + return m_displayWidth; + } + + uint32_t getDisplayHeight() const + { + return m_displayHeight; + } + + [[nodiscard]] bool isRunning() const + { + return m_isRunning; + } + + bool saveScreenshot(const std::string& filename); + bool saveScreenshot(const std::string& filename, ramses::displayBufferId_t screenshotBuf, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + + bool waitForDisplay(ramses::displayId_t displayId); + bool waitForSceneState(ramses::Scene& scene, ramses::RendererSceneState state); + bool waitForSceneVersion(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t version); + bool waitForOffscreenBufferCreated(const ramses::displayBufferId_t offscreenBufferId); + bool waitForOffscreenBufferLinked(const ramses::sceneId_t sceneId); + bool waitForScreenshot(); + + // SceneControlEvents + void sceneStateChanged(ramses::sceneId_t sceneId, ramses::RendererSceneState state) override; + void sceneFlushed(ramses::sceneId_t sceneId, ramses::sceneVersionTag_t sceneVersion) override; + void offscreenBufferCreated(ramses::displayId_t displayId_t, ramses::displayBufferId_t offscreenBufferId, ramses::ERendererEventResult result) override; + void offscreenBufferLinked(ramses::displayBufferId_t offscreenBufferId, ramses::sceneId_t consumerScene, ramses::dataConsumerId_t consumerId, bool success) override; + + // Renderer events + void displayCreated(ramses::displayId_t displayId, ramses::ERendererEventResult result) override; + void displayDestroyed(ramses::displayId_t displayId, ramses::ERendererEventResult result) override; + void windowResized(ramses::displayId_t displayId, uint32_t width, uint32_t height) override; + void windowClosed(ramses::displayId_t displayId) override; + void framebufferPixelsRead(const uint8_t* pixelData, + const uint32_t pixelDataSize, + ramses::displayId_t displayId, + ramses::displayBufferId_t displayBuffer, + ramses::ERendererEventResult result) override; + + private: + bool waitUntil(const std::function& conditionFunction, const std::function& dispatch = {}); + + using OffscreenBufferSet = std::unordered_set; + using DisplaySet = std::unordered_set; + + SceneSet m_scenes; + SceneSet m_scenesAssignedToOffscreenBuffer; + SceneSet m_scenesConsumingOffscreenBuffer; + DisplaySet m_displays; + OffscreenBufferSet m_offscreenBuffers; + ramses::RamsesRenderer* m_renderer; + IRendererEventHandler* m_rendererEventHandler; + IRendererSceneControlEventHandler* m_sceneControlEventHandler; + ramses::displayId_t m_displayId; + + uint32_t m_displayWidth; + uint32_t m_displayHeight; + + std::string m_screenshot; + uint32_t m_screenshotWidth = 0U; + uint32_t m_screenshotHeight = 0U; + bool m_screenshotSaved = false; + bool m_isRunning = true; + bool m_autoShow = true; + }; +} + diff --git a/tools/ramses-viewer/SceneSetup.h b/tools/ramses-viewer/SceneSetup.h index dc2499154..5fd2b4e4c 100644 --- a/tools/ramses-viewer/SceneSetup.h +++ b/tools/ramses-viewer/SceneSetup.h @@ -8,7 +8,7 @@ #pragma once -#include "ImguiClientHelper.h" +#include "RendererControl.h" #include "ramses/client/ramses-client.h" @@ -37,53 +37,44 @@ class ISceneSetup class OffscreenSetup : public ISceneSetup { public: - OffscreenSetup(ramses::internal::ImguiClientHelper& imguiHelper, ramses::RamsesRenderer* renderer, ramses::Scene* scene, ramses::displayId_t display, uint32_t width, uint32_t height) - : m_imguiHelper(imguiHelper) - , m_sceneControl(renderer->getSceneControlAPI()) + OffscreenSetup(ramses::internal::RendererControl& rendererControl, ramses::Scene* imguiScene, ramses::Scene* scene) + : m_rendererControl(rendererControl) + , m_sceneControl(rendererControl.getRenderer()->getSceneControlAPI()) + , m_imguiScene(imguiScene) , m_scene(scene) - , m_width(width) - , m_height(height) + , m_width(rendererControl.getDisplayWidth()) + , m_height(rendererControl.getDisplayHeight()) { - m_ob = renderer->createOffscreenBuffer(display, width, height); - renderer->flush(); + m_ob = rendererControl.getRenderer()->createOffscreenBuffer(rendererControl.getDisplayId(), m_width, m_height); + rendererControl.getRenderer()->flush(); static const std::vector imgbuf(4, std::byte{ 255 }); const std::vector mipLevelData = { imgbuf }; - auto* texture = imguiHelper.getScene()->createTexture2D(ramses::ETextureFormat::RGBA8, 1, 1, mipLevelData); - m_sampler = imguiHelper.getScene()->createTextureSampler( + auto* texture = imguiScene->createTexture2D(ramses::ETextureFormat::RGBA8, 1, 1, mipLevelData); + m_sampler = imguiScene->createTextureSampler( ramses::ETextureAddressMode::Clamp, ramses::ETextureAddressMode::Clamp, ramses::ETextureSamplingMethod::Linear, ramses::ETextureSamplingMethod::Linear, *texture); + imguiScene->createTextureConsumer(*m_sampler, consumerId); - const auto guiSceneId = imguiHelper.getScene()->getSceneId(); - m_sceneControl->setSceneMapping(scene->getSceneId(), display); - m_sceneControl->setSceneMapping(guiSceneId, display); - m_sceneControl->setSceneState(scene->getSceneId(), ramses::RendererSceneState::Ready); - m_sceneControl->setSceneState(guiSceneId, ramses::RendererSceneState::Ready); - m_sceneControl->flush(); + rendererControl.setupSceneState(scene->getSceneId(), ramses::RendererSceneState::Ready, m_ob, 0); + rendererControl.setupSceneState(imguiScene->getSceneId(), ramses::RendererSceneState::Ready, {}, 256); } void apply() override { - const auto guiSceneId = m_imguiHelper.getScene()->getSceneId(); - const ramses::dataConsumerId_t consumerId(519); - - m_imguiHelper.waitForSceneState(*m_imguiHelper.getScene(), ramses::RendererSceneState::Ready); - m_imguiHelper.waitForSceneState(*m_scene, ramses::RendererSceneState::Ready); - - m_imguiHelper.getScene()->createTextureConsumer(*m_sampler, consumerId); - m_imguiHelper.getScene()->flush(42); - m_imguiHelper.waitForSceneVersion(guiSceneId, 42); - m_imguiHelper.waitForOffscreenBufferCreated(m_ob); + m_rendererControl.waitForSceneState(*m_imguiScene, ramses::RendererSceneState::Ready); + m_rendererControl.waitForSceneState(*m_scene, ramses::RendererSceneState::Ready); + m_rendererControl.waitForOffscreenBufferCreated(m_ob); - m_sceneControl->setSceneDisplayBufferAssignment(m_scene->getSceneId(), m_ob); + const auto guiSceneId = m_imguiScene->getSceneId(); m_sceneControl->linkOffscreenBuffer(m_ob, guiSceneId, consumerId); m_sceneControl->flush(); - m_imguiHelper.waitForOffscreenBufferLinked(guiSceneId); + m_rendererControl.waitForOffscreenBufferLinked(guiSceneId); m_sceneControl->setSceneState(guiSceneId, ramses::RendererSceneState::Rendered); m_sceneControl->setSceneState(m_scene->getSceneId(), ramses::RendererSceneState::Rendered); m_sceneControl->flush(); - m_imguiHelper.waitForSceneState(*m_scene, ramses::RendererSceneState::Rendered); - m_imguiHelper.waitForSceneState(*m_imguiHelper.getScene(), ramses::RendererSceneState::Rendered); + m_rendererControl.waitForSceneState(*m_scene, ramses::RendererSceneState::Rendered); + m_rendererControl.waitForSceneState(*m_imguiScene, ramses::RendererSceneState::Rendered); } [[nodiscard]] uint32_t getWidth() const override @@ -107,8 +98,10 @@ class OffscreenSetup : public ISceneSetup } private: - ramses::internal::ImguiClientHelper& m_imguiHelper; + const ramses::dataConsumerId_t consumerId{519}; + ramses::internal::RendererControl& m_rendererControl; ramses::RendererSceneControl* m_sceneControl; + ramses::Scene* m_imguiScene; ramses::Scene* m_scene; uint32_t m_width; uint32_t m_height; @@ -119,45 +112,35 @@ class OffscreenSetup : public ISceneSetup class FramebufferSetup : public ISceneSetup { public: - FramebufferSetup(ramses::internal::ImguiClientHelper& imguiHelper, ramses::RamsesRenderer* renderer, ramses::Scene* scene, ramses::displayId_t display) - : m_imguiHelper(imguiHelper) - , m_sceneControl(renderer->getSceneControlAPI()) + FramebufferSetup(ramses::internal::RendererControl& rendererControl, ramses::Scene* imguiScene, ramses::Scene* scene) + : m_rendererControl(rendererControl) + , m_imguiScene(imguiScene) , m_scene(scene) { - const auto guiSceneId = imguiHelper.getScene()->getSceneId(); - if (scene) - { - m_sceneControl->setSceneMapping(scene->getSceneId(), display); - } - m_sceneControl->setSceneMapping(guiSceneId, display); - // inspection gui must be drawn on top - m_sceneControl->setSceneDisplayBufferAssignment(guiSceneId, ramses::displayBufferId_t(), 255); if (scene) { - m_sceneControl->setSceneState(scene->getSceneId(), ramses::RendererSceneState::Rendered); + rendererControl.setupSceneState(scene->getSceneId(), ramses::RendererSceneState::Rendered, 0); } - m_sceneControl->flush(); + rendererControl.setupSceneState(imguiScene->getSceneId(), ramses::RendererSceneState::Rendered, 256); } void apply() override { + m_rendererControl.waitForSceneState(*m_imguiScene, ramses::RendererSceneState::Rendered); if (m_scene) { - m_imguiHelper.waitForSceneState(*m_scene, ramses::RendererSceneState::Rendered); + m_rendererControl.waitForSceneState(*m_scene, ramses::RendererSceneState::Rendered); } - const auto guiSceneId = m_imguiHelper.getScene()->getSceneId(); - m_sceneControl->setSceneState(guiSceneId, ramses::RendererSceneState::Rendered); - m_sceneControl->flush(); } [[nodiscard]] uint32_t getWidth() const override { - return m_imguiHelper.getViewportWidth(); + return m_rendererControl.getDisplayWidth(); } [[nodiscard]] uint32_t getHeight() const override { - return m_imguiHelper.getViewportHeight(); + return m_rendererControl.getDisplayHeight(); } [[nodiscard]] ramses::displayBufferId_t getOffscreenBuffer() const override @@ -171,8 +154,8 @@ class FramebufferSetup : public ISceneSetup } private: - ramses::internal::ImguiClientHelper& m_imguiHelper; - ramses::RendererSceneControl* m_sceneControl; + ramses::internal::RendererControl& m_rendererControl; + ramses::Scene* m_imguiScene; ramses::Scene* m_scene; }; diff --git a/tools/ramses-viewer/SceneViewerGui.cpp b/tools/ramses-viewer/SceneViewerGui.cpp index 7115073e5..9d8e7c73e 100644 --- a/tools/ramses-viewer/SceneViewerGui.cpp +++ b/tools/ramses-viewer/SceneViewerGui.cpp @@ -161,6 +161,8 @@ namespace ramses::internal return "TextureSamplerCube"; case ramses::EDataType::TextureSamplerExternal: return "TextureSamplerExternal"; + case ramses::EDataType::UniformBuffer: + return "UniformBuffer"; } return nullptr; } @@ -1460,6 +1462,7 @@ namespace ramses::internal case ramses::EDataType::Matrix33F: case ramses::EDataType::Matrix44F: case ramses::EDataType::ByteBlob: + case ramses::EDataType::UniformBuffer: ImGui::Text("tbd. %s", EnumToString(uniform.impl().getInternalDataType())); break; } diff --git a/tools/ramses-viewer/StreamViewer.cpp b/tools/ramses-viewer/StreamViewer.cpp new file mode 100644 index 000000000..eb15b3fe9 --- /dev/null +++ b/tools/ramses-viewer/StreamViewer.cpp @@ -0,0 +1,204 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2023 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#include "StreamViewer.h" +#include "ImguiWrapper.h" +#include "fmt/format.h" + +constexpr const char* const vertexShader = R"##( +#version 300 es + +in vec2 a_position; +void main() +{ + gl_Position = vec4(a_position, 0.0, 1.0); +} +)##"; + +constexpr const char* const fragmentShader = R"##( +#version 300 es + +uniform sampler2D textureSampler; +out highp vec4 fragColor; +void main(void) +{ + highp vec2 ts = vec2(textureSize(textureSampler, 0)); + if(gl_FragCoord.x < ts.x && gl_FragCoord.y < ts.y) + { + fragColor = texelFetch(textureSampler, +#ifdef FLIP_Y + ivec2(gl_FragCoord.xy), +#else + ivec2(gl_FragCoord.x, ts.y-gl_FragCoord.y), +#endif + 0); + } + else + { + fragColor = vec4(0.2); + } +} +)##"; + + +namespace ramses::internal { + + StreamViewer::StreamViewer(ImguiClientHelper& imguiHelper, RamsesRenderer& renderer, displayId_t displayId) + : m_imguiHelper(imguiHelper) + , m_renderer(renderer) + , m_displayId(displayId) + { + auto* scene = imguiHelper.getScene(); + // prepare triangle geometry: vertex position array and index array + const std::array vertexPositionsArray{ ramses::vec2f{-1.0f, -1.0f}, ramses::vec2f{1.0f, -1.0f}, ramses::vec2f{-1.0f, 1.0f}, ramses::vec2f{1.0f, 1.0f} }; + auto* vertexPositions = scene->createArrayResource(4u, vertexPositionsArray.data()); + + std::array indicesArray = {0, 1, 2, 2, 1, 3}; + auto* indices = scene->createArrayResource(6u, indicesArray.data()); + + EffectDescription effectDesc; + effectDesc.setVertexShader(vertexShader); + effectDesc.setFragmentShader(fragmentShader); + m_effect = scene->createEffect(effectDesc, "streambuf shader"); + + m_appearance = scene->createAppearance(*m_effect); + auto* geometry = scene->createGeometry(*m_effect); + geometry->setInputBuffer(*m_effect->findAttributeInput("a_position"), *vertexPositions); + geometry->setIndices(*indices); + m_meshNode = scene->createMeshNode(); + m_meshNode->setAppearance(*m_appearance); + m_meshNode->setGeometry(*geometry); + m_meshNode->setVisibility(EVisibilityMode::Invisible); + + m_imguiHelper.getBackgroundGroup()->addMeshNode(*m_meshNode); + scene->flush(); + } + + void StreamViewer::draw(bool defaultOpen) + { + if( m_streamEntries.empty()) + return; + if (ImGui::CollapsingHeader("Stream Surfaces", defaultOpen ? ImGuiTreeNodeFlags_DefaultOpen : 0)) + { + for (auto& it : m_streamEntries) + { + if (it.second.streamBuffer.isValid()) + { + bool isActive = m_activeStream == it.second.sampler; + bool update = ImGui::Checkbox(fmt::format("Ivi Surface: {}", it.first.getValue()).c_str(), &isActive); + ImVec2 textureSize(128, 128); // TODO: there seems to be no API to get the size + if (ImGui::ImageButton(it.second.sampler, textureSize, ImVec2(0, 0), ImVec2(1, 1))) + { + isActive = !isActive; + update = true; + } + if (update) + setActiveSurface(isActive ? it.first : waylandIviSurfaceId_t()); + } + } + } + } + + void StreamViewer::streamAvailabilityChanged(waylandIviSurfaceId_t streamId, bool available) + { + if (available) + { + auto& entry = findOrCreateStreamEntry(streamId); + if (m_dataConsumers.find(entry.consumerId) != m_dataConsumers.end()) + { + createAndLinkStreamBuffer(streamId, entry); + } + } + else + { + auto it = m_streamEntries.find(streamId); + if (it != m_streamEntries.end()) + { + unlinkAndDestroyStreamBuffer(it->second); + } + } + } + + void StreamViewer::dataConsumerCreated(sceneId_t sceneId, dataConsumerId_t dataConsumerId) + { + if (sceneId != m_imguiHelper.getScene()->getSceneId()) + return; + auto it = std::find_if(m_streamEntries.begin(), m_streamEntries.end(), [&dataConsumerId](const auto& entry){ return entry.second.consumerId == dataConsumerId;}); + if (it == m_streamEntries.end()) + return; // unrelated data consumer + + m_dataConsumers.insert(dataConsumerId); + assert(it->second.streamBuffer == streamBufferId_t()); + createAndLinkStreamBuffer(it->first, it->second); + } + + void StreamViewer::dataConsumerDestroyed(sceneId_t sceneId, dataConsumerId_t dataConsumerId) + { + if (sceneId != m_imguiHelper.getScene()->getSceneId()) + return; + m_dataConsumers.erase(dataConsumerId); + } + + StreamViewer::StreamEntry& StreamViewer::findOrCreateStreamEntry(waylandIviSurfaceId_t surfaceId) + { + auto& entry = m_streamEntries[surfaceId]; + if (!entry.sampler) + { + auto consumer = m_imguiHelper.createTextureConsumer(); + entry.consumerId = consumer.first; + entry.sampler = consumer.second; + } + return entry; + } + + void StreamViewer::setActiveSurface(waylandIviSurfaceId_t surfaceId) + { + if (surfaceId.isValid()) + { + m_activeStream = m_streamEntries[surfaceId].sampler; + m_appearance->setInputTexture(*m_effect->findUniformInput("textureSampler"), *m_activeStream); + m_meshNode->setVisibility(EVisibilityMode::Visible); + } + else + { + m_activeStream = nullptr; + m_meshNode->setVisibility(EVisibilityMode::Invisible); + } + } + + void StreamViewer::createAndLinkStreamBuffer(waylandIviSurfaceId_t surfaceId, StreamEntry& entry) + { + if (m_autoShow) + setActiveSurface(surfaceId); + entry.streamBuffer = m_renderer.createStreamBuffer(m_displayId, surfaceId); + m_renderer.getSceneControlAPI()->linkStreamBuffer(entry.streamBuffer, m_imguiHelper.getScene()->getSceneId(), entry.consumerId); + m_renderer.flush(); + m_renderer.getSceneControlAPI()->flush(); + } + + void StreamViewer::unlinkAndDestroyStreamBuffer(StreamEntry &entry) + { + m_renderer.getSceneControlAPI()->unlinkData(m_imguiHelper.getScene()->getSceneId(), entry.consumerId); + m_renderer.getSceneControlAPI()->flush(); + m_renderer.destroyStreamBuffer(m_displayId, entry.streamBuffer); + entry.streamBuffer = streamBufferId_t(); + if (m_activeStream == entry.sampler) + { + auto it = std::find_if(m_streamEntries.begin(), m_streamEntries.end(), [](const auto& e){ return e.second.streamBuffer.isValid();}); + if (it != m_streamEntries.end()) + { + setActiveSurface(it->first); + } + else + { + setActiveSurface({}); + } + } + m_renderer.flush(); + } +} diff --git a/tools/ramses-viewer/StreamViewer.h b/tools/ramses-viewer/StreamViewer.h new file mode 100644 index 000000000..4ed1d4dbb --- /dev/null +++ b/tools/ramses-viewer/StreamViewer.h @@ -0,0 +1,68 @@ +// ------------------------------------------------------------------------- +// Copyright (C) 2023 BMW AG +// ------------------------------------------------------------------------- +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at https://mozilla.org/MPL/2.0/. +// ------------------------------------------------------------------------- + +#pragma once + +#include "ramses/framework/RamsesFrameworkTypes.h" +#include "ramses/renderer/IRendererSceneControlEventHandler.h" +#include "RendererControl.h" +#include "ImguiClientHelper.h" + +#include +#include + +namespace ramses::internal +{ + class StreamViewer : public RendererSceneControlEventHandlerEmpty + { + public: + explicit StreamViewer(ImguiClientHelper& imguiHelper, RamsesRenderer& renderer, displayId_t displayId); + + void draw(bool defaultOpen); + + void setAutoShow(bool autoShow) + { + m_autoShow = autoShow; + } + + void streamAvailabilityChanged(waylandIviSurfaceId_t streamId, bool available) override; + + void dataConsumerCreated(sceneId_t sceneId, dataConsumerId_t dataConsumerId) override; + + void dataConsumerDestroyed(sceneId_t sceneId, dataConsumerId_t dataConsumerId) override; + + private: + struct StreamEntry + { + TextureSampler* sampler = nullptr; + dataConsumerId_t consumerId; + streamBufferId_t streamBuffer; + }; + using StreamEntries = std::unordered_map; + + StreamEntry& findOrCreateStreamEntry(waylandIviSurfaceId_t surfaceId); + + void setActiveSurface(waylandIviSurfaceId_t surfaceId); + + void createAndLinkStreamBuffer(waylandIviSurfaceId_t surfaceId, StreamEntry& entry); + void unlinkAndDestroyStreamBuffer(StreamEntry& entry); + + ImguiClientHelper& m_imguiHelper; + RamsesRenderer& m_renderer; + displayId_t m_displayId; + StreamEntries m_streamEntries; + std::unordered_set m_dataConsumers; + + Effect* m_effect = nullptr; + Appearance* m_appearance = nullptr; + MeshNode* m_meshNode = nullptr; + TextureSampler* m_activeStream = nullptr; + + bool m_autoShow = true; + }; +} diff --git a/tools/ramses-viewer/ViewerApp.cpp b/tools/ramses-viewer/ViewerApp.cpp index cd9ee5584..5d9a7882d 100644 --- a/tools/ramses-viewer/ViewerApp.cpp +++ b/tools/ramses-viewer/ViewerApp.cpp @@ -15,14 +15,17 @@ #include "impl/ValidationReportImpl.h" -#include "internal/logic/StdFilesystemWrapper.h" #include "internal/Core/Utils/File.h" #include "internal/Core/Utils/LogMacros.h" #include "ramses-sdk-build-config.h" #include "ImguiWrapper.h" +#include "ramses/framework/EFeatureLevel.h" +#include #include +#include +namespace fs = std::filesystem; namespace ramses::internal { @@ -48,10 +51,10 @@ Loads and shows a ramses scene from the . is auto-resolved if matching file with *.lua extension is found in the same path as . (Explicit argument overrides autodetection.) )"); cli.set_version_flag("--version", ramses_sdk::RAMSES_SDK_RAMSES_VERSION); - cli.add_option("-s,--scene,scene", m_sceneFile, "Scene file to load")->check(CLI::ExistingFile)->required(); - cli.add_option("luafile,--lua", m_luaFile, "Lua configuration file")->check(CLI::ExistingFile); + auto* cliScene = cli.add_option("-s,--scene,scene", m_sceneFiles, "Scene files to load and merge")->check(CLI::ExistingFile); + cli.add_option("--lua", m_luaFile, "Lua configuration file")->check(CLI::ExistingFile)->needs(cliScene); auto exec = cli.add_option("--exec", m_luaFunction, "Calls the given lua function and exits."); - cli.add_option("--exec-lua", m_luaExec, "Calls the given lua code and exits.")->excludes(exec); + cli.add_option("--exec-lua", m_luaExec, "Calls the given lua code and exits.")->excludes(exec)->needs(cliScene); auto setWriteConfig = [&](const std::string& filename) { m_luaFile = filename; m_writeConfig = true; @@ -59,7 +62,8 @@ Loads and shows a ramses scene from the . cli.add_option_function("--write-config", setWriteConfig, "Writes the default lua configuration file and exits") ->expected(0, 1) ->type_name("[FILE]") - ->excludes(exec); + ->excludes(exec) + ->needs(cliScene); auto nv = cli.add_flag("--no-validation", m_noValidation, "Disable scene validation (faster startup for complex scenes)"); m_report = cli.add_option("--report", m_validationReportFile, "Prints the validation report to the given file (or stdout if no filename is given)")->expected(0, 1)->excludes(nv); @@ -68,11 +72,31 @@ Loads and shows a ramses scene from the . ViewerApp::ExitCode ViewerApp::loadScene() { - ramses::EFeatureLevel featureLevel = ramses::EFeatureLevel_01; - if (!ramses::RamsesClient::GetFeatureLevelFromFile(m_sceneFile, featureLevel)) - return ExitCode::ErrorUsage; + std::optional featureLevel; + if (!m_sceneFiles.empty()) + { + for (const auto& sceneFile: m_sceneFiles) + { + if (sceneFile.empty()) + { + return ExitCode::ErrorUsage; + } + ramses::EFeatureLevel fileFeatureLevel = ramses::EFeatureLevel_Latest; + if (!ramses::RamsesClient::GetFeatureLevelFromFile(sceneFile, fileFeatureLevel)) + { + LOG_ERROR(CONTEXT_CLIENT, "File does not exist: {}", sceneFile); + return ExitCode::ErrorUsage; + } + if (featureLevel.has_value() && featureLevel.value() != fileFeatureLevel) + { + LOG_ERROR(CONTEXT_CLIENT, "Feature Level of files to merge have to match. {} != {}", featureLevel.value(), fileFeatureLevel); + return ExitCode::ErrorUsage; + } + featureLevel = fileFeatureLevel; + } + } - m_frameworkConfig.setFeatureLevel(featureLevel); + m_frameworkConfig.setFeatureLevel(featureLevel.value_or(EFeatureLevel::EFeatureLevel_Latest)); m_framework = std::make_unique(m_frameworkConfig); m_client = m_framework->createClient("ramses-viewer"); @@ -82,23 +106,40 @@ Loads and shows a ramses scene from the . return ExitCode::ErrorClient; } - // scene viewer relies on resources being kept in memory (e.g. to query size), - // load scene as 'remote' which uses a shadowcopy scene and guarantees to keep resources in memory - m_scene = m_client->loadSceneFromFile(m_sceneFile, SceneConfig({}, EScenePublicationMode::LocalAndRemote)); - if (!m_scene) + if (!m_sceneFiles.empty()) { - LOG_ERROR(CONTEXT_CLIENT, "Loading scene failed! ({})", m_sceneFile); - return ExitCode::ErrorScene; - } - m_scene->publish(); - m_scene->flush(); + auto sceneIt = m_sceneFiles.begin(); + auto const & sceneFile = *sceneIt; - if (!m_noValidation) - { - m_scene->validate(m_validationReport); - if (m_report->count() > 0) + // scene viewer relies on resources being kept in memory (e.g. to query size), + // load scene as 'remote' which uses a shadowcopy scene and guarantees to keep resources in memory + m_scene = m_client->loadSceneFromFile(sceneFile, SceneConfig({}, EScenePublicationMode::LocalAndRemote)); + if (!m_scene) + { + LOG_ERROR(CONTEXT_CLIENT, "Loading scene failed! ({})", sceneFile); + return ExitCode::ErrorScene; + } + + while ((++sceneIt) != m_sceneFiles.end()) + { + auto const & sceneFileMerge = *sceneIt; + if (!m_client->mergeSceneFromFile(*m_scene, sceneFileMerge)) + { + LOG_ERROR(CONTEXT_CLIENT, "Merging scene failed! ({})", sceneFileMerge); + return ExitCode::ErrorScene; + } + } + + m_scene->publish(); + m_scene->flush(); + + if (!m_noValidation) { - printValidationReport(); + m_scene->validate(m_validationReport); + if (m_report->count() > 0) + { + printValidationReport(); + } } } @@ -123,7 +164,7 @@ Loads and shows a ramses scene from the . assert(!m_logicViewer->getLogicEngines().empty()); if (m_luaFile.empty()) { - m_luaFile = fs::path(m_sceneFile).replace_extension("lua").string(); + m_luaFile = fs::path(getSceneFile()).replace_extension("lua").string(); } if (m_writeConfig) diff --git a/tools/ramses-viewer/ViewerApp.h b/tools/ramses-viewer/ViewerApp.h index 6fdba0ae9..10381d5b0 100644 --- a/tools/ramses-viewer/ViewerApp.h +++ b/tools/ramses-viewer/ViewerApp.h @@ -62,7 +62,8 @@ namespace ramses::internal [[nodiscard]] const ramses::ValidationReport& getValidationReport() const; - [[nodiscard]] const std::string& getSceneFile() const; + [[nodiscard]] const std::string& getSceneFile(std::size_t i = 0) const; + [[nodiscard]] const std::vector& getSceneFiles() const; [[nodiscard]] const std::string& getLuaFile() const; @@ -88,7 +89,7 @@ namespace ramses::internal void printValidationReport() const; void printValidationReport(std::ostream& os) const; - std::string m_sceneFile; + std::vector m_sceneFiles; std::string m_validationReportFile; std::string m_luaFile; std::string m_luaFunction; @@ -140,9 +141,15 @@ namespace ramses::internal return m_validationReport; } - inline const std::string& ViewerApp::getSceneFile() const + inline const std::string& ViewerApp::getSceneFile(std::size_t i) const { - return m_sceneFile; + assert(i < m_sceneFiles.size()); + return m_sceneFiles[i]; + } + + inline const std::vector& ViewerApp::getSceneFiles() const + { + return m_sceneFiles; } inline const std::string& ViewerApp::getLuaFile() const diff --git a/tools/ramses-viewer/ViewerGui.cpp b/tools/ramses-viewer/ViewerGui.cpp index 65149618b..52efa9008 100644 --- a/tools/ramses-viewer/ViewerGui.cpp +++ b/tools/ramses-viewer/ViewerGui.cpp @@ -20,7 +20,10 @@ namespace ramses::internal { auto* scene = app.getScene(); if (scene) + { m_sceneGui = std::make_unique(app, *app.getScene(), m_lastErrorMessage, m_progress); + } + m_remoteScenesGui = std::make_unique(app); if (app.getLogicViewer()) m_logicGui = std::make_unique(app, m_lastErrorMessage); @@ -85,11 +88,18 @@ namespace ramses::internal void ViewerGui::drawWindow() { - const auto featureLevel = m_app.getScene()->getRamsesClient().getRamsesFramework().getFeatureLevel(); - const std::string windowTitle = - m_app.getScene()->getName().empty() - ? fmt::format("Scene[{}] (FeatureLevel 0{})", m_app.getScene()->getSceneId().getValue(), featureLevel) - : fmt::format("Scene[{}]: {} (FeatureLevel 0{})", m_app.getScene()->getSceneId().getValue(), m_app.getScene()->getName(), featureLevel); + std::string windowTitle; + if (m_app.getScene()) + { + const auto featureLevel = m_app.getScene()->getRamsesClient().getRamsesFramework().getFeatureLevel(); + windowTitle = m_app.getScene()->getName().empty() + ? fmt::format("Scene[{}] (FeatureLevel 0{})", m_app.getScene()->getSceneId().getValue(), featureLevel) + : fmt::format("Scene[{}]: {} (FeatureLevel 0{})", m_app.getScene()->getSceneId().getValue(), m_app.getScene()->getName(), featureLevel); + } + else + { + windowTitle = "Ramses Viewer"; + } if (!ImGui::Begin(windowTitle.c_str(), &m_settings.showWindow, ImGuiWindowFlags_MenuBar)) { @@ -109,6 +119,10 @@ namespace ramses::internal if (m_sceneGui) m_sceneGui->drawContents(); + + if (m_remoteScenesGui) + m_remoteScenesGui->drawContents(m_sceneGui == nullptr); + m_app.getStreamViewer()->draw(m_sceneGui == nullptr); ImGui::End(); } @@ -123,17 +137,20 @@ namespace ramses::internal { if (ImGui::BeginMenuBar()) { - if (ImGui::BeginMenu("File")) + if (m_sceneGui || m_logicGui) { - if (m_sceneGui) - m_sceneGui->drawFileMenuItems(); - if (m_logicGui) + if (ImGui::BeginMenu("File")) { - ImGui::Separator(); - m_logicGui->drawMenuItemReload(); - m_logicGui->drawMenuItemSaveDefaultLua(); + if (m_sceneGui) + m_sceneGui->drawFileMenuItems(); + if (m_logicGui) + { + ImGui::Separator(); + m_logicGui->drawMenuItemReload(); + m_logicGui->drawMenuItemSaveDefaultLua(); + } + ImGui::EndMenu(); } - ImGui::EndMenu(); } if (ImGui::BeginMenu("Settings")) { diff --git a/tools/ramses-viewer/ViewerGui.h b/tools/ramses-viewer/ViewerGui.h index 736b3cd08..a4588d866 100644 --- a/tools/ramses-viewer/ViewerGui.h +++ b/tools/ramses-viewer/ViewerGui.h @@ -10,6 +10,7 @@ #include "SceneViewerGui.h" #include "LogicViewerGui.h" +#include "RemoteScenesGui.h" #include namespace ramses @@ -58,6 +59,7 @@ namespace ramses::internal std::unique_ptr m_sceneGui; std::unique_ptr m_logicGui; + std::unique_ptr m_remoteScenesGui; ramses::TextureSampler* m_sceneTexture = nullptr; ImVec2 m_sceneTextureSize; diff --git a/tools/ramses-viewer/ViewerGuiApp.cpp b/tools/ramses-viewer/ViewerGuiApp.cpp index d8be7c542..8502964c5 100644 --- a/tools/ramses-viewer/ViewerGuiApp.cpp +++ b/tools/ramses-viewer/ViewerGuiApp.cpp @@ -7,6 +7,7 @@ // ------------------------------------------------------------------------- #include "ViewerGuiApp.h" +#include "fmt/format.h" #include "ramses-cli.h" #include "ramses/client/ramses-client.h" #include "ramses/client/ramses-utils.h" @@ -22,9 +23,11 @@ namespace ramses::internal { namespace { - void SetPreferredSize(ramses::DisplayConfig& cfg, const ramses::Scene& scene) + void SetPreferredSize(ramses::DisplayConfig& cfg, const ramses::Scene* scene) { - ramses::SceneObjectIterator it(scene, ramses::ERamsesObjectType::RenderPass); + if (!scene) + return; + ramses::SceneObjectIterator it(*scene, ramses::ERamsesObjectType::RenderPass); ramses::RamsesObject* obj = nullptr; while (nullptr != (obj = it.getNext())) { @@ -46,6 +49,7 @@ namespace ramses::internal ViewerGuiApp::ViewerGuiApp() { m_displayConfig.setResizable(true); + m_displayConfig.setWindowTitle("RAMSES Viewer"); auto* fontAtlas = ImGui::GetIO().Fonts; fontAtlas->AddFontDefault(); @@ -86,10 +90,20 @@ namespace ramses::internal if (exitCode != ExitCode::Ok) return exitCode; + if (!getSceneFiles().empty()) + { + const auto& sceneFile = getSceneFile(); + if (!sceneFile.empty()) + { + + m_displayConfig.setWindowTitle(fmt::format("{} - RAMSES Viewer", fmt::join(getSceneFiles(), " + "))); + } + } + const bool customWidth = m_width ? (m_width->count() > 0) : false; const bool customHeight = m_height ? (m_height->count() > 0) : false; if (!customHeight && !customWidth) - SetPreferredSize(m_displayConfig, *getScene()); + SetPreferredSize(m_displayConfig, getScene()); int32_t winX = 0; int32_t winY = 0; uint32_t winWidth = 0u; @@ -97,7 +111,7 @@ namespace ramses::internal m_displayConfig.getWindowRectangle(winX, winY, winWidth, winHeight); // avoid sceneId collision - const auto imguiSceneId = ramses::sceneId_t(getScene()->getSceneId().getValue() + 1); + const auto imguiSceneId = getScene() ? ramses::sceneId_t(getScene()->getSceneId().getValue() + 1) : ramses::sceneId_t(std::numeric_limits::max() - 1); m_imguiHelper = std::make_unique(*getClient(), winWidth, winHeight, imguiSceneId); if (m_headless) @@ -117,51 +131,57 @@ namespace ramses::internal const ramses::displayId_t displayId = renderer->createDisplay(m_displayConfig); renderer->flush(); + m_streamViewer = std::make_unique(*m_imguiHelper, *renderer, displayId); + m_streamViewer->setAutoShow(getScene() == nullptr); + m_rendererControl = std::make_unique(renderer, displayId, winWidth, winHeight, m_imguiHelper.get(), m_streamViewer.get()); + m_rendererControl->setAutoShow(getScene() == nullptr); m_imguiHelper->setDisplayId(displayId); - m_imguiHelper->setRenderer(renderer); - if (!m_imguiHelper->waitForDisplay(displayId)) - { - return ExitCode::ErrorDisplay; - } - - switch (m_guiMode) + switch (getScene() ? m_guiMode : GuiMode::Only) { case GuiMode::On: - m_sceneSetup = std::make_unique(*m_imguiHelper, renderer, getScene(), displayId, winWidth, winHeight); + m_sceneSetup = std::make_unique(*m_rendererControl, m_imguiHelper->getScene(), getScene()); break; case GuiMode::Only: - m_sceneSetup = std::make_unique(*m_imguiHelper, renderer, nullptr, displayId); + m_sceneSetup = std::make_unique(*m_rendererControl, m_imguiHelper->getScene(), nullptr); break; case GuiMode::Overlay: case GuiMode::Off: - m_sceneSetup = std::make_unique(*m_imguiHelper, renderer, getScene(), displayId); + m_sceneSetup = std::make_unique(*m_rendererControl, m_imguiHelper->getScene(), getScene()); break; } - getScene()->flush(); + + if (!m_rendererControl->waitForDisplay(displayId)) + { + return ExitCode::ErrorDisplay; + } + getSettings()->clearColor = m_displayConfig.impl().getInternalDisplayConfig().getClearColor(); renderer->setDisplayBufferClearColor(displayId, m_sceneSetup->getOffscreenBuffer(), getSettings()->clearColor); m_sceneSetup->apply(); - auto takeScreenshot = [&](const std::string& filename) { - static ramses::sceneVersionTag_t ver = 42; - ++ver; - getScene()->flush(ver); - if (m_imguiHelper->waitForSceneVersion(getScene()->getSceneId(), ver)) - { - if (m_imguiHelper->saveScreenshot(filename, m_sceneSetup->getOffscreenBuffer(), 0, 0, m_sceneSetup->getWidth(), m_sceneSetup->getHeight())) + if (getScene()) + { + auto takeScreenshot = [&](const std::string& filename) { + static ramses::sceneVersionTag_t ver = 42; + ++ver; + getScene()->flush(ver); + if (m_rendererControl->waitForSceneVersion(getScene()->getSceneId(), ver)) { - if (m_imguiHelper->waitForScreenshot()) + if (m_rendererControl->saveScreenshot(filename, m_sceneSetup->getOffscreenBuffer(), 0, 0, m_sceneSetup->getWidth(), m_sceneSetup->getHeight())) { - return true; + if (m_rendererControl->waitForScreenshot()) + { + return true; + } } } - } - return false; - }; - exitCode = createLogicViewer(takeScreenshot); - if (exitCode != ExitCode::Ok) - return exitCode; + return false; + }; + exitCode = createLogicViewer(takeScreenshot); + if (exitCode != ExitCode::Ok) + return exitCode; + } m_gui = std::make_unique(*this); m_gui->setSceneTexture(m_sceneSetup->getTextureSampler(), winWidth, winHeight); @@ -169,12 +189,12 @@ namespace ramses::internal if (!m_screenshotFile.empty()) { - if (!m_imguiHelper->saveScreenshot(m_screenshotFile, m_sceneSetup->getOffscreenBuffer(), 0, 0, winWidth, winHeight)) + if (!m_rendererControl->saveScreenshot(m_screenshotFile, m_sceneSetup->getOffscreenBuffer(), 0, 0, winWidth, winHeight)) { LOG_ERROR(CONTEXT_CLIENT, "Failure when saving screenshot"); return ExitCode::ErrorScreenshot; } - if (!m_imguiHelper->waitForScreenshot()) + if (!m_rendererControl->waitForScreenshot()) { LOG_ERROR(CONTEXT_CLIENT, "Screenshot not saved"); return ExitCode::ErrorScreenshot; @@ -200,15 +220,16 @@ namespace ramses::internal bool ViewerGuiApp::doOneLoop() { - const bool isRunning = isInteractive() && m_imguiHelper->isRunning(); + const bool isRunning = isInteractive() && m_rendererControl->isRunning(); if (!isRunning) return false; Result updateStatus; if (getLogicViewer()) updateStatus = getLogicViewer()->update(); - getScene()->flush(); - m_imguiHelper->dispatchEvents(); + if (getScene()) + getScene()->flush(); + m_rendererControl->dispatchEvents(); if (m_guiMode != GuiMode::Off) { ImGui::NewFrame(); diff --git a/tools/ramses-viewer/ViewerGuiApp.h b/tools/ramses-viewer/ViewerGuiApp.h index 2b6d5488b..415a7cfd3 100644 --- a/tools/ramses-viewer/ViewerGuiApp.h +++ b/tools/ramses-viewer/ViewerGuiApp.h @@ -16,6 +16,8 @@ #include "ViewerGui.h" #include "SceneViewerGui.h" #include "LogicViewerGui.h" +#include "RendererControl.h" +#include "StreamViewer.h" namespace ramses::internal { @@ -30,6 +32,8 @@ namespace ramses::internal // for integration tests [[nodiscard]] ImguiClientHelper* getImguiClientHelper(); + [[nodiscard]] RendererControl* getRendererControl(); + [[nodiscard]] StreamViewer* getStreamViewer(); [[nodiscard]] ExitCode setup(); [[nodiscard]] bool doOneLoop(); @@ -57,6 +61,8 @@ namespace ramses::internal bool m_headless = false; std::unique_ptr m_imguiHelper; + std::unique_ptr m_rendererControl; + std::unique_ptr m_streamViewer; std::unique_ptr m_sceneSetup; std::unique_ptr m_gui; }; @@ -66,6 +72,16 @@ namespace ramses::internal return m_imguiHelper.get(); } + inline RendererControl* ViewerGuiApp::getRendererControl() + { + return m_rendererControl.get(); + } + + inline StreamViewer* ViewerGuiApp::getStreamViewer() + { + return m_streamViewer.get(); + } + inline ViewerGuiApp::GuiMode ViewerGuiApp::getGuiMode() const { return m_guiMode; diff --git a/tools/ramses-viewer/ViewerHeadlessApp.cpp b/tools/ramses-viewer/ViewerHeadlessApp.cpp index 5162d80dd..4f549323d 100644 --- a/tools/ramses-viewer/ViewerHeadlessApp.cpp +++ b/tools/ramses-viewer/ViewerHeadlessApp.cpp @@ -7,6 +7,7 @@ // ------------------------------------------------------------------------- #include "ViewerHeadlessApp.h" #include "ImguiWrapper.h" +#include "CLI/CLI.hpp" namespace ramses::internal { @@ -25,6 +26,7 @@ namespace ramses::internal void ViewerHeadlessApp::registerOptions(CLI::App& cli) { ViewerApp::registerOptions(cli); + cli.get_option("scene")->required(); } ViewerHeadlessApp::ExitCode ViewerHeadlessApp::run() diff --git a/tools/test-asset-producer/CMakeLists.txt b/tools/test-asset-producer/CMakeLists.txt index a3f4501b6..743999bd8 100644 --- a/tools/test-asset-producer/CMakeLists.txt +++ b/tools/test-asset-producer/CMakeLists.txt @@ -15,5 +15,7 @@ createModule( ) add_custom_target(RL_REGEN_TEST_ASSETS - COMMAND test-asset-producer ${PROJECT_SOURCE_DIR}/tests/unittests/client/res) + COMMAND test-asset-producer ${PROJECT_SOURCE_DIR}/tests/unittests/client/res # FL02 + COMMAND test-asset-producer ${PROJECT_SOURCE_DIR}/tests/unittests/client/res "testScene_01.ramses" 1 # FL01 + ) set_property(TARGET RL_REGEN_TEST_ASSETS PROPERTY FOLDER "CMakePredefinedTargets") diff --git a/tools/test-asset-producer/main.cpp b/tools/test-asset-producer/main.cpp index ed010e5c2..0971da077 100644 --- a/tools/test-asset-producer/main.cpp +++ b/tools/test-asset-producer/main.cpp @@ -57,31 +57,87 @@ ramses::Appearance* createTestAppearance(ramses::Scene& scene) return scene.createAppearance(*scene.createEffect(effectDesc), "test appearance"); } -void createTriangle(ramses::Scene& scene) +void createTriangle(ramses::Scene& scene, ramses::EFeatureLevel featureLevel) { - const std::string_view vertShader = R"( - #version 100 + const std::string_view vertShader_FL01 = R"( + #version 310 es + precision highp float; uniform highp mat4 mvpMatrix; - attribute vec3 a_position; + in vec3 a_position; void main() { gl_Position = mvpMatrix * vec4(a_position, 1.0); })"; - const std::string_view fragShader = R"( - #version 100 + const std::string_view vertShader_FL02 = R"( + #version 310 es + precision highp float; + + layout(std140,binding=0) uniform modelCameraBlock_t + { + mat4 mvpMat; + mat4 mvMat; + mat4 normalMat; + } modelCameraBlock; + + in vec3 a_position; + + void main() + { + gl_Position = modelCameraBlock.mvpMat * vec4(a_position, 1.0); + })"; + + const std::string_view fragShader_FL01 = R"( + #version 310 es + precision highp float; + + struct ColorPair{ float c1; float c2; }; + struct colorBlock_t + { + ColorPair color[2]; + }; + uniform colorBlock_t colorBlock; + + out vec4 fragColor; void main(void) { - gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); + fragColor = vec4(colorBlock.color[0].c1, colorBlock.color[0].c2, colorBlock.color[1].c1, colorBlock.color[1].c2); + })"; + + const std::string_view fragShader_FL02 = R"( + #version 310 es + precision highp float; + + struct ColorPair{ float c1; float c2; }; + layout(std140,binding=1) uniform colorBlock_t + { + ColorPair color[2]; + } colorBlock; + + out vec4 fragColor; + + void main(void) + { + fragColor = vec4(colorBlock.color[0].c1, colorBlock.color[0].c2, colorBlock.color[1].c1, colorBlock.color[1].c2); })"; ramses::EffectDescription effectDesc; - effectDesc.setUniformSemantic("mvpMatrix", ramses::EEffectUniformSemantic::ModelViewProjectionMatrix); - effectDesc.setVertexShader(vertShader.data()); - effectDesc.setFragmentShader(fragShader.data()); + switch (featureLevel) + { + case ramses::EFeatureLevel_01: + effectDesc.setUniformSemantic("mvpMatrix", ramses::EEffectUniformSemantic::ModelViewProjectionMatrix); + effectDesc.setVertexShader(vertShader_FL01.data()); + effectDesc.setFragmentShader(fragShader_FL01.data()); + break; + case ramses::EFeatureLevel_02: + effectDesc.setUniformSemantic("modelCameraBlock", ramses::EEffectUniformSemantic::ModelCameraBlock); + effectDesc.setVertexShader(vertShader_FL02.data()); + effectDesc.setFragmentShader(fragShader_FL02.data()); + break; + } auto effect = scene.createEffect(effectDesc); auto appearance = scene.createAppearance(*effect, "triangle appearance"); @@ -145,6 +201,14 @@ void createTriangleLogic(ramses::LogicEngine& logic, ramses::Scene& scene) intf->getInputs()->getChild("CraneGimbal")->getChild("Pitch")->set(0.f); intf->getInputs()->getChild("Viewport")->getChild("Width")->set(1280); intf->getInputs()->getChild("Viewport")->getChild("Height")->set(480); + + // no links, only set UBO values via binding + auto appearance = scene.findObject("triangle appearance"); + auto appearanceBinding = logic.createAppearanceBinding(*appearance, "triangle appearance binding"); + appearanceBinding->getInputs()->getChild("colorBlock.color[0].c1")->set(1.f); + appearanceBinding->getInputs()->getChild("colorBlock.color[0].c2")->set(0.1f); + appearanceBinding->getInputs()->getChild("colorBlock.color[1].c1")->set(0.2f); + appearanceBinding->getInputs()->getChild("colorBlock.color[1].c2")->set(1.f); } int main(int argc, char* argv[]) @@ -152,29 +216,43 @@ int main(int argc, char* argv[]) // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) bounds are checked const std::vector args(argv, argv + argc); - constexpr ramses::EFeatureLevel featureLevel = ramses::EFeatureLevel_Latest; + ramses::EFeatureLevel featureLevel = ramses::EFeatureLevel_Latest; std::string basePath {"."}; std::string ramsesFilename = std::string("testScene_0") + std::to_string(featureLevel) + ".ramses"; - if (args.size() == 2u) - { - basePath = args[1]; - } - else if (args.size() == 3u) - { + if (args.size() >= 2u) basePath = args[1]; + + if (args.size() >= 3u) ramsesFilename = args[2]; + + if (args.size() == 4u) + { + auto featureLevelAsInt = std::stoi(args[3]); + switch (featureLevelAsInt) + { + case 1: + featureLevel = ramses::EFeatureLevel_01; + break; + case 2: + featureLevel = ramses::EFeatureLevel_02; + break; + default: + std::cerr << "Invalid feature level.\n\n"; + return 1; + } } - if (args.size() > 3u) + if (args.size() > 4u) { std::cerr << "Generator of ramses and ramses logic test content.\n\n" << "Synopsis:\n" << " test-asset-producer\n" << " test-asset-producer \n" - << " test-asset-producer \n\n"; + << " test-asset-producer \n\n" + << " test-asset-producer \n\n"; return 1; } @@ -296,7 +374,7 @@ int main(int argc, char* argv[]) auto renderBuffer = scene->createRenderBuffer(16u, 16u, ramses::ERenderBufferFormat::RGBA8, ramses::ERenderBufferAccessMode::ReadWrite, 0u, "renderBuffer"); // create triangle that can actually be visible when rendered - createTriangle(*scene); + createTriangle(*scene, featureLevel); createTriangleLogic(logicEngine, *scene); ramses::NodeBinding* nodeBinding = logicEngine.createNodeBinding(*node, ramses::ERotationType::Euler_XYZ, "nodebinding"); @@ -346,13 +424,15 @@ int main(int argc, char* argv[]) if (report.hasIssue()) { for (const auto& issue : report.getIssues()) - std::cout << (issue.type == ramses::EIssueType::Error ? "ERROR: " : "Warn: ") << issue.message << std::endl; + std::cout << (issue.type == ramses::EIssueType::Error ? "ERROR: " : "Warn: ") << (issue.object ? issue.object->getName() : "") << ": " << issue.message << std::endl; } ramses::SaveFileConfig saveConfig; saveConfig.setMetadataString("test-asset-producer"); const auto filePath = basePath + "/" + ramsesFilename; + std::cout << "==============================================" << std::endl; std::cout << "Saving to " << filePath << std::endl; + std::cout << "==============================================" << std::endl; if (!scene->saveToFile(filePath, saveConfig)) return EXIT_FAILURE;