From f27e8868eb730b021c675294ec3ea20619d5f7ce Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Mar 2018 12:25:12 +1300 Subject: [PATCH 01/15] Add HMD JSDoc --- .../src/scripting/HMDScriptingInterface.h | 257 +++++++++++++++++- .../AbstractHMDScriptingInterface.h | 21 ++ tools/jsdoc/plugins/hifi.js | 5 +- 3 files changed, 278 insertions(+), 5 deletions(-) diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index ef8ea95704..1acafab361 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -24,6 +24,36 @@ class QScriptEngine; #include +/**jsdoc + * The HMD API provides access to the HMD used in VR display mode. + * + * @namespace HMD + * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise + * {@link Vec3(0)|Vec3.ZERO}. Read-only. + * @property {Quat} orientation - The orientation of the HMD if currently in VR display mode, otherwise + * {@link Quat(0)|Quat.IDENTITY}.Read-only. + * @property {boolean} active - true if the display mode is HMD, otherwise false. Read-only. + * @property {boolean} mounted - true if currently in VR display mode and the HMD is being worn, otherwise + * false. Read-only. + * + * @property {number} playerHeight - The real-world height of the user. Read-only. Currently always returns a + * value of 1.755. + * @property {number} eyeHeight - The real-world height of the user's eyes. Read-only. Currently always returns a + * value of 1.655. + * @property {number} ipd - The inter-pupillary distance (distance between eyes) of the user, used for rendering. Defaults to + * the human average of 0.064 unless set by the HMD. Read-only. + * @property {number} ipdScale=1.0 - A scale factor applied to the ipd property value. + * + * @property {boolean} showTablet - true if the tablet is being displayed, false otherwise. + * Read-only. + * @property {boolean} tabletContextualMode - true if the tablet has been opened in contextual mode, otherwise + * false. In contextual mode, the tablet has been opened at a specific world position and orientation rather + * than at a position and orientation relative to the user. Read-only. + * @property {Uuid} tabletID - The UUID of the tablet body model overlay. + * @property {Uuid} tabletScreenID - The UUID of the tablet's screen overlay. + * @property {Uuid} homeButtonID - The UUID of the tablet's "home" button overlay. + * @property {Uuid} homeButtonHighlightID - The UUID of the tablet's "home" button highlight overlay. + */ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency { Q_OBJECT Q_PROPERTY(glm::vec3 position READ getPosition) @@ -37,26 +67,200 @@ class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Depen Q_PROPERTY(QUuid tabletScreenID READ getCurrentTabletScreenID WRITE setCurrentTabletScreenID) public: + + /**jsdoc + * Calculate the intersection of a ray with the HUD overlay. + * @function HMD.calculateRayUICollisionPoint + * @param {Vec3} position - The origin of the ray. + * @param {Vec3} direction - The direction of the ray. + * @returns {Vec3} The point of intersection with the HUD overlay if it intersects, otherwise {@link Vec3(0)|Vec3.ZERO}. + */ Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const; + + /**jsdoc + * Get the 2D HUD overlay coordinates of a 3D point on the HUD overlay. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * @function HMD.overlayFromWorldPoint + * @param {Vec3} position - The point on the HUD overlay in world coordinates. + * @returns {Vec2} The point on the HUD overlay in HUD coordinates. + * @example Draw a square on the HUD overlay in the direction you're looking. + * var hudIntersection = HMD.calculateRayUICollisionPoint(MyAvatar.getHeadPosition(), + * Quat.getForward(MyAvatar.headOrientation)); + * var hudPoint = HMD.overlayFromWorldPoint(hudIntersection); + * + * var DIMENSIONS = { x: 50, y: 50 }; + * var square = Overlays.addOverlay("rectangle", { + * x: hudPoint.x - DIMENSIONS.x / 2, + * y: hudPoint.y - DIMENSIONS.y / 2, + * width: DIMENSIONS.x, + * height: DIMENSIONS.y, + * color: { red: 255, green: 0, blue: 0 } + * }); + * + * Script.scriptEnding.connect(function () { + * Overlays.deleteOverlay(square); + * }); + */ Q_INVOKABLE glm::vec2 overlayFromWorldPoint(const glm::vec3& position) const; + + /**jsdoc + * Get the 3D world coordinates of a 2D point on the HUD overlay. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * @function HMD.worldPointFromOverlay + * @param {Vec2} coordinates - The point on the HUD overlay in HUD coordinates. + * @returns {Vec3} The point on the HUD overlay in world coordinates. + */ Q_INVOKABLE glm::vec3 worldPointFromOverlay(const glm::vec2& overlay) const; + + /**jsdoc + * Get the 2D point on the HUD overlay represented by given spherical coordinates. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * Spherical coordinates are polar coordinates in radians with { x: 0, y: 0 } being the center of the HUD + * overlay. + * @function HMD.sphericalToOverlay + * @param {Vec2} sphericalPos - The point on the HUD overlay in spherical coordinates. + * @returns {Vec2} The point on the HUD overlay in HUD coordinates. + */ Q_INVOKABLE glm::vec2 sphericalToOverlay(const glm::vec2 & sphericalPos) const; + + /**jsdoc + * Get the spherical coordinates of a 2D point on the HUD overlay. + * 2D HUD overlay coordinates are pixels with the origin at the top left of the overlay. + * Spherical coordinates are polar coordinates in radians with { x: 0, y: 0 } being the center of the HUD + * overlay. + * @function HMD.overlayToSpherical + * @param {Vec2} overlayPos - The point on the HUD overlay in HUD coordinates. + * @returns {Vec2} The point on the HUD overlay in spherical coordinates. + */ Q_INVOKABLE glm::vec2 overlayToSpherical(const glm::vec2 & overlayPos) const; + + /**jsdoc + * Recenter the HMD HUD to the current HMD position and orientation. + * @function HMD.centerUI + */ + Q_INVOKABLE void centerUI(); + + + /**jsdoc + * Get the name of the HMD audio input device. + * @function HMD.preferredAudioInput + * @returns {string} The name of the HMD audio input device if in HMD mode, otherwise an empty string. + */ Q_INVOKABLE QString preferredAudioInput() const; + + /**jsdoc + * Get the name of the HMD audio output device. + * @function HMD.preferredAudioOutput + * @returns {string} The name of the HMD audio output device if in HMD mode, otherwise an empty string. + */ Q_INVOKABLE QString preferredAudioOutput() const; + + /**jsdoc + * Check whether there is an HMD available. + * @function HMD.isHMDAvailable + * @param {string} [name=""] - The name of the HMD to check for, e.g., "Oculus Rift". The name is the same as + * may be displayed in Interface's "Display" menu. If no name is specified then any HMD matches. + * @returns {boolean} true if an HMD of the specified name is available, otherwise + * false. + * @example Report on HMD availability. + * print("Is any HMD available: " + HMD.isHMDAvailable()); + * print("Is an Oculus Rift HMD available: " + HMD.isHMDAvailable("Oculus Rift")); + * print("Is a Vive HMD available: " + HMD.isHMDAvailable("OpenVR (Vive)")); + */ Q_INVOKABLE bool isHMDAvailable(const QString& name = ""); + + /**jsdoc + * Check whether there is an HMD head controller available. + * @function HMD.isHeadControllerAvailable + * @param {string} [name=""] - The name of the HMD head controller to check for, e.g., "Oculus". If no name is + * specified then any HMD head controller matches. + * @returns {boolean} true if an HMD head controller of the specified name is available, + * otherwise false. + * @example Report HMD head controller availability. + * print("Is any HMD head controller available: " + HMD.isHeadControllerAvailable()); + * print("Is an Oculus head controller available: " + HMD.isHeadControllerAvailable("Oculus")); + * print("Is a Vive head controller available: " + HMD.isHeadControllerAvailable("OpenVR")); + */ Q_INVOKABLE bool isHeadControllerAvailable(const QString& name = ""); + + /**jsdoc + * Check whether there are HMD hand controllers available. + * @function HMD.isHandControllerAvailable + * @param {string} [name=""] - The name of the HMD hand controller to check for, e.g., "Oculus". If no name is + * specified then any HMD hand controller matches. + * @returns {boolean} true if an HMD hand controller of the specified name is available, + * otherwise false. + * @example Report HMD hand controller availability. + * print("Are any HMD hand controllers available: " + HMD.isHandControllerAvailable()); + * print("Are Oculus hand controllers available: " + HMD.isHandControllerAvailable("Oculus")); + * print("Are Vive hand controllers available: " + HMD.isHandControllerAvailable("OpenVR")); + */ Q_INVOKABLE bool isHandControllerAvailable(const QString& name = ""); + + /**jsdoc + * Check whether there are specific HMD controllers available. + * @function HMD.isSubdeviceContainingNameAvailable + * @param {string} - The name of the HMD controller to check for, e.g., "OculusTouch". + * @returns {boolean} true if an HMD controller with a name containing the specified name is + * available, otherwise false. + * @example Report if particular Oculus controllers are available. + * print("Is an Oculus Touch controller available: " + HMD.isSubdeviceContainingNameAvailable("Touch")); + * print("Is an Oculus Remote controller available: " + HMD.isSubdeviceContainingNameAvailable("Remote")); + */ Q_INVOKABLE bool isSubdeviceContainingNameAvailable(const QString& name); + /**jsdoc + * Signal that models of the HMD hand controllers being used should be displayed. The models are displayed at their actual, + * real-world locations. + * @function HMD.requestShowHandControllers + * @example Show your hand controllers for 10 seconds. + * HMD.requestShowHandControllers(); + * Script.setTimeout(function () { + * HMD.requestHideHandControllers(); + * }, 10000); + */ Q_INVOKABLE void requestShowHandControllers(); + + /**jsdoc + * Signal that it is no longer necessary to display models of the HMD hand controllers being used. If no other scripts + * want the models displayed then they are no longer displayed. + * @function HMD.requestHideHandControllers + */ Q_INVOKABLE void requestHideHandControllers(); + + /**jsdoc + * Check whether any script wants models of the HMD hand controllers displayed. Requests are made and canceled using + * {@link HMD.requestShowHandControllers|requestShowHandControllers} and + * {@link HMD.requestHideHandControllers|requestHideHandControllers}. + * @function HMD.shouldShowHandControllers + * @returns {boolean} true if any script is requesting that HMD hand controller models be displayed. + */ Q_INVOKABLE bool shouldShowHandControllers() const; + + /**jsdoc + * Causes the borders and decorations in HUD windows to be enlarged when the laser intersects them in HMD mode. By default, + * borders and decorations are not enlarged. + * @function HMD.activateHMDHandMouse + */ Q_INVOKABLE void activateHMDHandMouse(); + + /**jsdoc + * Causes the border and decorations in HUD windows to no longer be enlarged when the laser intersects them in HMD mode. By + * default, borders and decorations are not enlarged. + * @function HMD.deactivateHMDHandMouse + */ Q_INVOKABLE void deactivateHMDHandMouse(); + + /**jsdoc + * Suppress the activation of the HMD-provided keyboard, if any. Successful calls should be balanced with a call to + * {@link HMD.unspressKeyboard|unspressKeyboard} within a reasonable amount of time. + * @function HMD.suppressKeyboard + * @returns {boolean} true if the current HMD provides a keyboard and it was successfully suppressed (e.g., it + * isn't being displayed), otherwise false. + */ /// Suppress the activation of any on-screen keyboard so that a script operation will /// not be interrupted by a keyboard popup /// Returns false if there is already an active keyboard displayed. @@ -65,21 +269,68 @@ public: /// call to unsuppressKeyboard() within a reasonable amount of time Q_INVOKABLE bool suppressKeyboard(); + /**jsdoc + * Unsuppress the activation of the HMD-provided keyboard, if any. + * @function HMD.unsuppressKeyboard + */ /// Enable the keyboard following a suppressKeyboard call Q_INVOKABLE void unsuppressKeyboard(); + /**jsdoc + * Check whether the HMD-provided keyboard, if any, is visible. + * @function HMD.isKeyboardVisible + * @returns {boolean} true if the current HMD provides a keyboard and it is visible, otherwise + * false. + */ /// Query the display plugin to determine the current VR keyboard visibility Q_INVOKABLE bool isKeyboardVisible(); - // rotate the overlay UI sphere so that it is centered about the the current HMD position and orientation - Q_INVOKABLE void centerUI(); - + /**jsdoc + * Closes the tablet if it is open. + * @function HMD.closeTablet + */ Q_INVOKABLE void closeTablet(); + /**jsdoc + * Opens the tablet if the tablet is used in the current display mode and it isn't already showing, and sets the tablet to + * contextual mode if requested. In contextual mode, the page displayed on the tablet is wholly controlled by script (i.e., + * the user cannot navigate to another). + * @function HMD.openTablet + * @param {boolean} [contextualMode=false] - If true then the tablet is opened at a specific position and + * orientation already set by the script, otherwise it opens at a position and orientation relative to the user. For + * contextual mode, set the world or local position and orientation of the HMD.tabletID overlay. + */ Q_INVOKABLE void openTablet(bool contextualMode = false); signals: + /**jsdoc + * Triggered when a request to show or hide models of the HMD hand controllers is made using + * {@link HMD.requestShowHandControllers|requestShowHandControllers} or + * {@link HMD.requestHideHandControllers|requestHideHandControllers}. + * @function HMD.shouldShowHandControllersChanged + * @returns {Signal} + * @example Report when showing of hand controllers changes. + * function onShouldShowHandControllersChanged() { + * print("Should show hand controllers: " + HMD.shouldShowHandControllers()); + * } + * HMD.shouldShowHandControllersChanged.connect(onShouldShowHandControllersChanged); + * + * HMD.requestShowHandControllers(); + * Script.setTimeout(function () { + * HMD.requestHideHandControllers(); + * }, 10000); + */ bool shouldShowHandControllersChanged(); + + /**jsdoc + * Triggered when the HMD.mounted property value changes. + * @function HMD.mountedChanged + * @returns {Signal} + * @example Report when there's a change in the HMD being worn. + * HMD.mountedChanged.connect(function () { + * print("Mounted changed. HMD is mounted: " + HMD.mounted); + * }); + */ void mountedChanged(); public: diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h index f260fa959f..36e1952d3c 100644 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h +++ b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h @@ -12,6 +12,7 @@ #include +// These properties have JSDoc documentation in HMDScriptingInterface.h. class AbstractHMDScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(bool active READ isHMDMode) @@ -30,7 +31,27 @@ public: bool isHMDMode() const; signals: + /**jsdoc + * Triggered when the HMD.ipdScale property value changes. + * @function HMD.IPDScaleChanged + * @returns {Signal} + */ void IPDScaleChanged(); + + /**jsdoc + * Triggered when Interface's display mode changes and when the user puts on or takes off their HMD. + * @function HMD.displayModeChanged + * @param {boolean} isHMDMode - true if the display mode is HMD, otherwise false. This is the + * same value as provided by HMD.active. + * @returns {Signal} + * @example Report when the display mode changes. + * HMD.displayModeChanged.connect(function (isHMDMode) { + * print("Display mode changed"); + * print("isHMD = " + isHMD); + * print("HMD.active = " + HMD.active); + * print("HMD.mounted = " + HMD.mounted); + * }); + */ void displayModeChanged(bool isHMDMode); private: diff --git a/tools/jsdoc/plugins/hifi.js b/tools/jsdoc/plugins/hifi.js index 1f73f14b2b..e4da94ccd5 100644 --- a/tools/jsdoc/plugins/hifi.js +++ b/tools/jsdoc/plugins/hifi.js @@ -24,11 +24,12 @@ exports.handlers = { '../../libraries/animation/src', '../../libraries/avatars/src', '../../libraries/controllers/src/controllers/', - '../../libraries/graphics-scripting/src/graphics-scripting/', + '../../libraries/display-plugins/src/display-plugins/', '../../libraries/entities/src', + '../../libraries/graphics-scripting/src/graphics-scripting/', '../../libraries/model-networking/src/model-networking/', - '../../libraries/octree/src', '../../libraries/networking/src', + '../../libraries/octree/src', '../../libraries/physics/src', '../../libraries/pointers/src', '../../libraries/script-engine/src', From b35ee5ce8aece5472e7b8a650192ff6b6ffa667a Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Mar 2018 12:25:49 +1300 Subject: [PATCH 02/15] Fix JSDoc links to Vec3 constants --- libraries/entities/src/EntityItemProperties.cpp | 16 ++++++++-------- .../entities/src/EntityScriptingInterface.h | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f9a96d2293..90d6d942fd 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -481,13 +481,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Vec3} position=0,0,0 - The position of the entity. * @property {Quat} rotation=0,0,0,1 - The orientation of the entity with respect to world coordinates. * @property {Vec3} registrationPoint=0.5,0.5,0.5 - The point in the entity that is set to the entity's position and is rotated - * about, {@link Vec3|Vec3.ZERO} – {@link Vec3|Vec3.ONE}. A value of {@link Vec3|Vec3.ZERO} is the entity's - * minimum x, y, z corner; a value of {@link Vec3|Vec3.ONE} is the entity's maximum x, y, z corner. + * about, {@link Vec3(0)|Vec3.ZERO} – {@link Vec3(0)|Vec3.ONE}. A value of {@link Vec3(0)|Vec3.ZERO} is the entity's + * minimum x, y, z corner; a value of {@link Vec3(0)|Vec3.ONE} is the entity's maximum x, y, z corner. * * @property {Vec3} naturalPosition=0,0,0 - The center of the entity's unscaled mesh model if it has one, otherwise - * {@link Vec3|Vec3.ZERO}. Read-only. + * {@link Vec3(0)|Vec3.ZERO}. Read-only. * @property {Vec3} naturalDimensions - The dimensions of the entity's unscaled mesh model if it has one, otherwise - * {@link Vec3|Vec3.ONE}. Read-only. + * {@link Vec3(0)|Vec3.ONE}. Read-only. * * @property {Vec3} velocity=0,0,0 - The linear velocity of the entity in m/s with respect to world coordinates. * @property {number} damping=0.39347 - How much to slow down the linear velocity of an entity over time, 0.0 @@ -504,13 +504,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {Vec3} gravity=0,0,0 - The acceleration due to gravity in m/s2 that the entity should move with, in * world coordinates. Set to { x: 0, y: -9.8, z: 0 } to simulate Earth's gravity. Gravity is applied to an * entity's motion only if its dynamic property is true. If changing an entity's - * gravity from {@link Vec3|Vec3.ZERO}, you need to give it a small velocity in order to kick off - * physics simulation. + * gravity from {@link Vec3(0)|Vec3.ZERO}, you need to give it a small velocity in order to kick + * off physics simulation. * The gravity value is applied in addition to the acceleration value. * @property {Vec3} acceleration=0,0,0 - A general acceleration in m/s2 that the entity should move with, in world * coordinates. The acceleration is applied to an entity's motion only if its dynamic property is - * true. If changing an entity's acceleration from {@link Vec3|Vec3.ZERO}, you need to give it a - * small velocity in order to kick off physics simulation. + * true. If changing an entity's acceleration from {@link Vec3(0)|Vec3.ZERO}, you need to give it + * a small velocity in order to kick off physics simulation. * The acceleration value is applied in addition to the gravity value. * @property {number} restitution=0.5 - The "bounciness" of an entity when it collides, 0.0 – * 0.99. The higher the value, the more bouncy. diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 9613a7a310..633f427342 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -699,7 +699,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} voxelCoords - The voxel coordinates. May be fractional and outside the entity's bounding box. * @returns {Vec3} The world coordinates of the voxelCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. * @example Create a PolyVox cube with the 0,0,0 voxel replaced by a sphere. * // Cube PolyVox with 0,0,0 voxel missing. * var polyVox = Entities.addEntity({ @@ -734,7 +734,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} worldCoords - The world coordinates. May be outside the entity's bounding box. * @returns {Vec3} The voxel coordinates of the worldCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. The value may be fractional. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be fractional. */ // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 worldCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 worldCoords); @@ -746,7 +746,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} voxelCoords - The voxel coordinates. May be fractional and outside the entity's bounding box. * @returns {Vec3} The local coordinates of the voxelCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. * @example Get the world dimensions of a voxel in a PolyVox entity. * var polyVox = Entities.addEntity({ * type: "PolyVox", @@ -768,7 +768,7 @@ public slots: * @param {Uuid} entityID - The ID of the {@link Entities.EntityType|PolyVox} entity. * @param {Vec3} localCoords - The local coordinates. May be outside the entity's bounding box. * @returns {Vec3} The voxel coordinates of the worldCoords if the entityID is a - * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3|Vec3.ZERO}. The value may be fractional. + * {@link Entities.EntityType|PolyVox} entity, otherwise {@link Vec3(0)|Vec3.ZERO}. The value may be fractional. */ // FIXME move to a renderable entity interface Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords); From 1bcb9738f0a5ee4e7ed50c6bb5581c2cde50f414 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Wed, 28 Mar 2018 12:26:08 +1300 Subject: [PATCH 03/15] Miscellaneous fixes noticed in passing --- interface/resources/qml/windows/Decoration.qml | 2 +- libraries/entities/src/EntityItemProperties.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/windows/Decoration.qml b/interface/resources/qml/windows/Decoration.qml index 843ae25596..f8fd9f4e6c 100644 --- a/interface/resources/qml/windows/Decoration.qml +++ b/interface/resources/qml/windows/Decoration.qml @@ -1,5 +1,5 @@ // -// DefaultFrame.qml +// Decoration.qml // // Created by Bradley Austin Davis on 12 Jan 2016 // Copyright 2016 High Fidelity, Inc. diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 90d6d942fd..8602f60e3d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -476,7 +476,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {boolean} visible=true - Whether or not the entity is rendered. If true then the entity is rendered. * @property {boolean} canCastShadows=true - Whether or not the entity casts shadows. Currently applicable only to * {@link Entities.EntityType|Model} and {@link Entities.EntityType|Shape} entities. Shadows are cast if inside a - * {@link Entities.EntityType|Zone} entity with castShadows enabled in its {@link Entities.EntityProperties-Zone|keyLight} property. + * {@link Entities.EntityType|Zone} entity with castShadows enabled in its + * {@link Entities.EntityProperties-Zone|keyLight} property. * * @property {Vec3} position=0,0,0 - The position of the entity. * @property {Quat} rotation=0,0,0,1 - The orientation of the entity with respect to world coordinates. From 9b6306601af9b9b93e73c9ec705767b48a1f288b Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 9 Apr 2018 13:21:03 -0700 Subject: [PATCH 04/15] Merge Clement's PR12700 diffs for early trace start --- interface/src/main.cpp | 13 ++++++++++++- libraries/gpu/src/gpu/Context.cpp | 1 + libraries/gpu/src/gpu/Shader.cpp | 1 + libraries/qml/src/qml/OffscreenSurface.cpp | 10 +++++++++- libraries/qml/src/qml/impl/SharedObject.cpp | 6 +++++- libraries/render-utils/src/BloomEffect.cpp | 1 + libraries/render-utils/src/HighlightEffect.cpp | 1 + libraries/render-utils/src/RenderDeferredTask.cpp | 1 + libraries/render-utils/src/RenderForwardTask.cpp | 1 + libraries/render-utils/src/RenderShadowTask.cpp | 1 + libraries/render-utils/src/RenderViewTask.cpp | 1 + libraries/render-utils/src/UpdateSceneTask.cpp | 1 + libraries/render-utils/src/ZoneRenderer.cpp | 1 + .../render/src/render/RenderFetchCullSortTask.cpp | 1 + libraries/render/src/render/ShapePipeline.cpp | 9 ++++++--- libraries/shared/src/Profile.cpp | 1 + libraries/shared/src/Profile.h | 1 + libraries/ui/src/ui/OffscreenQmlSurface.cpp | 9 +++++++++ libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp | 2 ++ 19 files changed, 56 insertions(+), 6 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 51ec4b1327..8d98766bfc 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -31,6 +31,8 @@ #include "UserActivityLogger.h" #include "MainWindow.h" +#include "Profile.h" + #ifdef Q_OS_WIN extern "C" { typedef int(__stdcall * CHECKMINSPECPROC) (); @@ -39,7 +41,10 @@ extern "C" { int main(int argc, const char* argv[]) { setupHifiApplication(BuildInfo::INTERFACE_NAME); - + auto tracer = DependencyManager::set(); + tracer->startTracing(); + PROFILE_SYNC_BEGIN(startup, "main startup", ""); + #ifdef Q_OS_LINUX QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); #endif @@ -235,7 +240,10 @@ int main(int argc, const char* argv[]) { argvExtended.push_back("--ignore-gpu-blacklist"); int argcExtended = (int)argvExtended.size(); + PROFILE_SYNC_END(startup, "main startup", ""); + PROFILE_SYNC_BEGIN(startup, "app full ctor", ""); Application app(argcExtended, const_cast(argvExtended.data()), startupTime, runningMarkerExisted); + PROFILE_SYNC_END(startup, "app full ctor", ""); #if 0 // If we failed the OpenGLVersion check, log it. @@ -273,6 +281,9 @@ int main(int argc, const char* argv[]) { qCDebug(interfaceapp, "Created QT Application."); exitCode = app.exec(); server.close(); + + tracer->stopTracing(); + tracer->serialize(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/Traces/trace-startup.json.gz"); } Application::shutdownPlugins(); diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index e1b68c88ca..dc2273ecb6 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -129,6 +129,7 @@ void Context::executeFrame(const FramePointer& frame) const { } bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler) { + PROFILE_RANGE(app, "makeProgram"); // If we're running in another DLL context, we need to fetch the program callback out of the application // FIXME find a way to do this without reliance on Qt app properties if (!_makeProgramCallback) { diff --git a/libraries/gpu/src/gpu/Shader.cpp b/libraries/gpu/src/gpu/Shader.cpp index aa7898569b..b539a84925 100755 --- a/libraries/gpu/src/gpu/Shader.cpp +++ b/libraries/gpu/src/gpu/Shader.cpp @@ -75,6 +75,7 @@ Shader::Pointer Shader::createGeometry(const Source& source) { } ShaderPointer Shader::createOrReuseProgramShader(Type type, const Pointer& vertexShader, const Pointer& geometryShader, const Pointer& pixelShader) { + PROFILE_RANGE(app, "createOrReuseProgramShader"); ProgramMapKey key(0); if (vertexShader && vertexShader->getType() == VERTEX) { diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 9c1bb79355..2f1b3910c6 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -27,6 +27,8 @@ #include "impl/SharedObject.h" #include "impl/TextureCache.h" +#include "Profile.h" + using namespace hifi::qml; using namespace hifi::qml::impl; @@ -284,6 +286,7 @@ void OffscreenSurface::loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& callback) { + PROFILE_RANGE(app, "loadInternal"); if (QThread::currentThread() != thread()) { qFatal("Called load on a non-surface thread"); } @@ -304,7 +307,11 @@ void OffscreenSurface::loadInternal(const QUrl& qmlSource, } auto targetContext = contextForUrl(finalQmlSource, parent, createNewContext); - auto qmlComponent = new QQmlComponent(getSurfaceContext()->engine(), finalQmlSource, QQmlComponent::PreferSynchronous); + QQmlComponent* qmlComponent; + { + PROFILE_RANGE(app, "new QQmlComponent"); + qmlComponent = new QQmlComponent(getSurfaceContext()->engine(), finalQmlSource, QQmlComponent::PreferSynchronous); + } if (qmlComponent->isLoading()) { connect(qmlComponent, &QQmlComponent::statusChanged, this, [=](QQmlComponent::Status) { finishQmlLoad(qmlComponent, targetContext, parent, callback); }); @@ -318,6 +325,7 @@ void OffscreenSurface::finishQmlLoad(QQmlComponent* qmlComponent, QQmlContext* qmlContext, QQuickItem* parent, const QmlContextObjectCallback& callback) { + PROFILE_RANGE(app, "finishQmlLoad"); disconnect(qmlComponent, &QQmlComponent::statusChanged, this, 0); if (qmlComponent->isError()) { for (const auto& error : qmlComponent->errors()) { diff --git a/libraries/qml/src/qml/impl/SharedObject.cpp b/libraries/qml/src/qml/impl/SharedObject.cpp index d593169d94..b2057117f6 100644 --- a/libraries/qml/src/qml/impl/SharedObject.cpp +++ b/libraries/qml/src/qml/impl/SharedObject.cpp @@ -105,7 +105,10 @@ void SharedObject::create(OffscreenSurface* surface) { // Create a QML engine. auto qmlEngine = acquireEngine(surface); - _qmlContext = new QQmlContext(qmlEngine->rootContext(), qmlEngine); + { + PROFILE_RANGE(startup, "new QQmlContext"); + _qmlContext = new QQmlContext(qmlEngine->rootContext(), qmlEngine); + } surface->onRootContextCreated(_qmlContext); emit surface->rootContextCreated(_qmlContext); @@ -175,6 +178,7 @@ static size_t globalEngineRefCount{ 0 }; #endif QQmlEngine* SharedObject::acquireEngine(OffscreenSurface* surface) { + PROFILE_RANGE(startup, "acquireEngine"); Q_ASSERT(QThread::currentThread() == qApp->thread()); QQmlEngine* result = nullptr; diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index ddd63f012f..75ddb5f8e9 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -326,6 +326,7 @@ Bloom::Bloom() { } void Bloom::configure(const Config& config) { + PROFILE_RANGE(startup, "Bloom::build"); std::string blurName{ "BloomBlurN" }; for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { diff --git a/libraries/render-utils/src/HighlightEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp index d151da766b..5876b40d2b 100644 --- a/libraries/render-utils/src/HighlightEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -476,6 +476,7 @@ void DrawHighlightTask::configure(const Config& config) { } void DrawHighlightTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { + PROFILE_RANGE(startup, "Bloom::build"); const auto items = inputs.getN(0).get(); const auto sceneFrameBuffer = inputs.getN(1); const auto primaryFramebuffer = inputs.getN(2); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 2377f5131f..6d44e7f182 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -76,6 +76,7 @@ const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, cons } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { + PROFILE_RANGE(startup, "RenderDeferredTask::build"); const auto& items = input.get(); auto fadeEffect = DependencyManager::get(); diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index 63370109e0..e7603d73d9 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -40,6 +40,7 @@ extern void initForwardPipelines(ShapePlumber& plumber, extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false); void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { + PROFILE_RANGE(startup, "RenderForwardTask::build"); auto items = input.get(); auto fadeEffect = DependencyManager::get(); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 69c5b3c689..84fd46f429 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -215,6 +215,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cameraCullFunctor, uint8_t tagBits, uint8_t tagMask) { ::CullFunctor shadowCullFunctor = [this](const RenderArgs* args, const AABox& bounds) { + PROFILE_RANGE(startup, "RenderShadowTask::build"); return _cullFunctor(args, bounds); }; diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index 122fc16e61..aed2972243 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -17,6 +17,7 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits, uint8_t tagMask) { // auto items = input.get(); + PROFILE_RANGE(startup, "RenderViewTask::build"); // Warning : the cull functor passed to the shadow pass should only be testing for LOD culling. If frustum culling // is performed, then casters not in the view frustum will be removed, which is not what we wish. task.addJob("RenderShadowTask", cullFunctor, tagBits, tagMask); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index e05f28ef0d..2b4e626fed 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -19,6 +19,7 @@ #include "DeferredLightingEffect.h" void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { + PROFILE_RANGE(startup, "UpdateSceneTask::build"); task.addJob("LightStageSetup"); task.addJob("BackgroundStageSetup"); task.addJob("HazeStageSetup"); diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 51939efd4f..bd03668b11 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -42,6 +42,7 @@ protected: const Selection::Name ZoneRendererTask::ZONES_SELECTION { "RankedZones" }; void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& ouput) { + PROFILE_RANGE(startup, "ZoneRendererTask::build"); // Filter out the sorted list of zones const auto zoneItems = task.addJob("FilterZones", input, ZONES_SELECTION.c_str()); diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 7b9765dca1..629bcf81bf 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -20,6 +20,7 @@ using namespace render; void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; + PROFILE_RANGE(startup, "RenderFetchCullSortTask::build"); // CPU jobs: // Fetch and cull the items from the scene const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered().withTagBits(tagBits, tagMask); diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index 92e22d86f6..35cc66315b 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -134,9 +134,12 @@ void ShapePlumber::addPipeline(const Filter& filter, const gpu::ShaderPointer& p locations->lightClusterFrustumBufferUnit = -1; } - auto gpuPipeline = gpu::Pipeline::create(program, state); - auto shapePipeline = std::make_shared(gpuPipeline, locations, batchSetter, itemSetter); - addPipelineHelper(filter, key, 0, shapePipeline); + { + PROFILE_RANGE(app, "Pipeline::create"); + auto gpuPipeline = gpu::Pipeline::create(program, state); + auto shapePipeline = std::make_shared(gpuPipeline, locations, batchSetter, itemSetter); + addPipelineHelper(filter, key, 0, shapePipeline); + } } const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Key& key) const { diff --git a/libraries/shared/src/Profile.cpp b/libraries/shared/src/Profile.cpp index 97def2015a..f3cbbf9262 100644 --- a/libraries/shared/src/Profile.cpp +++ b/libraries/shared/src/Profile.cpp @@ -27,6 +27,7 @@ Q_LOGGING_CATEGORY(trace_simulation_animation, "trace.simulation.animation") Q_LOGGING_CATEGORY(trace_simulation_animation_detail, "trace.simulation.animation.detail") Q_LOGGING_CATEGORY(trace_simulation_physics, "trace.simulation.physics") Q_LOGGING_CATEGORY(trace_simulation_physics_detail, "trace.simulation.physics.detail") +Q_LOGGING_CATEGORY(trace_startup, "trace.startup") Q_LOGGING_CATEGORY(trace_workload, "trace.workload") #if defined(NSIGHT_FOUND) diff --git a/libraries/shared/src/Profile.h b/libraries/shared/src/Profile.h index f2a747afa3..e78ce210c9 100644 --- a/libraries/shared/src/Profile.h +++ b/libraries/shared/src/Profile.h @@ -32,6 +32,7 @@ Q_DECLARE_LOGGING_CATEGORY(trace_simulation_animation) Q_DECLARE_LOGGING_CATEGORY(trace_simulation_animation_detail) Q_DECLARE_LOGGING_CATEGORY(trace_simulation_physics) Q_DECLARE_LOGGING_CATEGORY(trace_simulation_physics_detail) +Q_DECLARE_LOGGING_CATEGORY(trace_startup) Q_DECLARE_LOGGING_CATEGORY(trace_workload) class Duration { diff --git a/libraries/ui/src/ui/OffscreenQmlSurface.cpp b/libraries/ui/src/ui/OffscreenQmlSurface.cpp index 12e9b8b87c..cfff0405c0 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurface.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurface.cpp @@ -256,6 +256,15 @@ void OffscreenQmlSurface::initializeEngine(QQmlEngine* engine) { #if !defined(Q_OS_ANDROID) rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext)); rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext)); + { + PROFILE_RANGE(startup, "FileTypeProfile"); + rootContext->setContextProperty("FileTypeProfile", new FileTypeProfile(rootContext)); + } + { + PROFILE_RANGE(startup, "HFWebEngineProfile"); + rootContext->setContextProperty("HFWebEngineProfile", new HFWebEngineProfile(rootContext)); + + } #endif rootContext->setContextProperty("Paths", DependencyManager::get().data()); rootContext->setContextProperty("Tablet", DependencyManager::get().data()); diff --git a/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp b/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp index 7efa36624b..51fe11fdc7 100644 --- a/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp +++ b/libraries/ui/src/ui/OffscreenQmlSurfaceCache.cpp @@ -12,6 +12,7 @@ #include #include "OffscreenQmlSurface.h" +#include "Profile.h" OffscreenQmlSurfaceCache::OffscreenQmlSurfaceCache() { } @@ -38,6 +39,7 @@ void OffscreenQmlSurfaceCache::reserve(const QString& rootSource, int count) { } void OffscreenQmlSurfaceCache::release(const QString& rootSource, const QSharedPointer& surface) { + PROFILE_RANGE(app, "buildSurface"); surface->pause(); _cache[rootSource].push_back(surface); } From 513a4875f0081fc7b4eafa8e82428fe3513ae851 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Mon, 9 Apr 2018 15:45:58 -0700 Subject: [PATCH 05/15] Move --traceFile option to start of main() --- interface/src/Application.cpp | 2 ++ interface/src/main.cpp | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 343074f61c..7d5a608a68 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -959,6 +959,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); +#if 0 { const QString TEST_SCRIPT = "--testScript"; const QString TRACE_FILE = "--traceFile"; @@ -976,6 +977,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo } } } +#endif // make sure the debug draw singleton is initialized on the main thread. DebugDraw::getInstance().removeMarker(""); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 8d98766bfc..677edb0bf3 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -42,9 +42,18 @@ extern "C" { int main(int argc, const char* argv[]) { setupHifiApplication(BuildInfo::INTERFACE_NAME); auto tracer = DependencyManager::set(); - tracer->startTracing(); + const char * traceFile = ""; + { + for (int a = 1; a < argc; ++a) { + if (strcmp(argv[a], "--traceFile") == 0 && argc > a + 1) { + traceFile = argv[a + 1]; + tracer->startTracing(); + break; + } + } + } PROFILE_SYNC_BEGIN(startup, "main startup", ""); - + #ifdef Q_OS_LINUX QApplication::setAttribute(Qt::AA_DontUseNativeMenuBar); #endif @@ -283,7 +292,7 @@ int main(int argc, const char* argv[]) { server.close(); tracer->stopTracing(); - tracer->serialize(QStandardPaths::writableLocation(QStandardPaths::DesktopLocation) + "/Traces/trace-startup.json.gz"); + tracer->serialize(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/" + traceFile); } Application::shutdownPlugins(); From cf3648409d5c419b20384e3dc297ab7322e23fde Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 10 Apr 2018 12:19:42 -0700 Subject: [PATCH 06/15] Allow duration for tracing, other fixes --- interface/src/Application.cpp | 7 ------- interface/src/main.cpp | 36 ++++++++++++++++++++++++++--------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 7d5a608a68..a0fe9ef13a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -959,10 +959,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); -#if 0 { const QString TEST_SCRIPT = "--testScript"; - const QString TRACE_FILE = "--traceFile"; const QStringList args = arguments(); for (int i = 0; i < args.size() - 1; ++i) { if (args.at(i) == TEST_SCRIPT) { @@ -970,14 +968,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); } - } else if (args.at(i) == TRACE_FILE) { - QString traceFilePath = args.at(i + 1); - setProperty(hifi::properties::TRACING, traceFilePath); - DependencyManager::get()->startTracing(); } } } -#endif // make sure the debug draw singleton is initialized on the main thread. DebugDraw::getInstance().removeMarker(""); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 677edb0bf3..5f2afa9155 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -41,17 +41,25 @@ extern "C" { int main(int argc, const char* argv[]) { setupHifiApplication(BuildInfo::INTERFACE_NAME); + + // Early check for --traceFile argument auto tracer = DependencyManager::set(); - const char * traceFile = ""; - { - for (int a = 1; a < argc; ++a) { - if (strcmp(argv[a], "--traceFile") == 0 && argc > a + 1) { - traceFile = argv[a + 1]; - tracer->startTracing(); - break; + const char * traceFile = nullptr; + const QString traceFileFlag("--traceFile"); + float traceDuration = 0.0f; + for (int a = 1; a < argc; ++a) { + if (traceFileFlag == argv[a] && argc > a + 1) { + traceFile = argv[a + 1]; + if (argc > a + 2) { + traceDuration = atof(argv[a + 2]); } + break; } } + if (traceFile != nullptr) { + tracer->startTracing(); + } + PROFILE_SYNC_BEGIN(startup, "main startup", ""); #ifdef Q_OS_LINUX @@ -253,6 +261,14 @@ int main(int argc, const char* argv[]) { PROFILE_SYNC_BEGIN(startup, "app full ctor", ""); Application app(argcExtended, const_cast(argvExtended.data()), startupTime, runningMarkerExisted); PROFILE_SYNC_END(startup, "app full ctor", ""); + + + QTimer exitTimer; + if (traceDuration > 0.0) { + exitTimer.setSingleShot(true); + QObject::connect(&exitTimer, &QTimer::timeout, &app, &Application::quit); + exitTimer.start(int(1000 * traceDuration)); + } #if 0 // If we failed the OpenGLVersion check, log it. @@ -291,8 +307,10 @@ int main(int argc, const char* argv[]) { exitCode = app.exec(); server.close(); - tracer->stopTracing(); - tracer->serialize(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/" + traceFile); + if (traceFile != nullptr) { + tracer->stopTracing(); + tracer->serialize(QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation) + "/" + traceFile); + } } Application::shutdownPlugins(); From ca5720c0158a8a3b261b32b53f7ccff9af908263 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Tue, 10 Apr 2018 13:52:46 -0700 Subject: [PATCH 07/15] Take out superfluous DependencyManager::set() --- interface/src/Application.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a0fe9ef13a..11427fb1e6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -773,7 +773,6 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { steamClient->init(); } - DependencyManager::set(); PROFILE_SET_THREAD_NAME("Main Thread"); #if defined(Q_OS_WIN) From 0c069574c59042d59f6b46b881e211f66bb13d33 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Fri, 30 Mar 2018 16:35:51 -0700 Subject: [PATCH 08/15] forward pipelines for primitives --- .../src/RenderableShapeEntityItem.cpp | 27 +++++- .../procedural/src/procedural/Procedural.cpp | 63 ++++++++------ .../procedural/src/procedural/Procedural.h | 15 ++-- .../src/procedural/ProceduralSkybox.cpp | 6 +- .../render-utils/src/DefaultMaterials.slh | 23 +++++ .../render-utils/src/DeferredBufferWrite.slh | 9 +- libraries/render-utils/src/GeometryCache.cpp | 75 ++++++++++++---- libraries/render-utils/src/GeometryCache.h | 5 +- libraries/render-utils/src/LightAmbient.slh | 8 +- libraries/render-utils/src/LightingModel.slh | 20 +++-- libraries/render-utils/src/Shadows_shared.slh | 2 - libraries/render-utils/src/forward_simple.slf | 85 ++++++++++++++++++ .../src/forward_simple_textured.slf | 51 +++++++++++ .../forward_simple_textured_transparent.slf | 52 +++++++++++ .../src/forward_simple_textured_unlit.slf | 35 ++++++++ .../src/forward_simple_transparent.slf | 87 +++++++++++++++++++ libraries/render-utils/src/simple.slf | 57 ++++-------- libraries/render-utils/src/simple.slv | 3 +- libraries/render-utils/src/simple_fade.slv | 3 +- .../render-utils/src/simple_textured.slf | 35 ++------ .../render-utils/src/simple_transparent.slf | 65 ++++++++++++++ .../src/simple_transparent_textured.slf | 41 ++------- 22 files changed, 587 insertions(+), 180 deletions(-) create mode 100644 libraries/render-utils/src/DefaultMaterials.slh create mode 100644 libraries/render-utils/src/forward_simple.slf create mode 100644 libraries/render-utils/src/forward_simple_textured.slf create mode 100644 libraries/render-utils/src/forward_simple_textured_transparent.slf create mode 100644 libraries/render-utils/src/forward_simple_textured_unlit.slf create mode 100644 libraries/render-utils/src/forward_simple_transparent.slf create mode 100644 libraries/render-utils/src/simple_transparent.slf diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index b05854da4e..62b2794c94 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -18,6 +18,18 @@ #include "render-utils/simple_vert.h" #include "render-utils/simple_frag.h" +#include "render-utils/simple_transparent_frag.h" +#include "render-utils/forward_simple_frag.h" +#include "render-utils/forward_simple_transparent_frag.h" + +#include + +#if defined(USE_GLES) +static bool DISABLE_DEFERRED = true; +#else +static const QString RENDER_FORWARD{ "HIFI_RENDER_FORWARD" }; +static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD); +#endif #include "RenderPipelines.h" @@ -35,13 +47,20 @@ static const float SPHERE_ENTITY_SCALE = 0.5f; ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { _procedural._vertexSource = simple_vert::getSource(); - _procedural._fragmentSource = simple_frag::getSource(); + _procedural._opaquefragmentSource = DISABLE_DEFERRED ? forward_simple_frag::getSource() : simple_frag::getSource(); + _procedural._transparentfragmentSource = DISABLE_DEFERRED ? forward_simple_transparent_frag::getSource() : simple_transparent_frag::getSource(); _procedural._opaqueState->setCullMode(gpu::State::CULL_NONE); _procedural._opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL); PrepareStencil::testMaskDrawShape(*_procedural._opaqueState); _procedural._opaqueState->setBlendFunction(false, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + _procedural._transparentState->setCullMode(gpu::State::CULL_BACK); + _procedural._transparentState->setDepthTest(true, true, gpu::LESS_EQUAL); + PrepareStencil::testMask(*_procedural._transparentState); + _procedural._transparentState->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); } bool ShapeEntityRenderer::needsRenderUpdate() const { @@ -216,9 +235,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { if (mat) { outColor = glm::vec4(mat->getAlbedo(), mat->getOpacity()); if (_procedural.isReady()) { - _procedural.prepare(batch, _position, _dimensions, _orientation); outColor = _procedural.getColor(outColor); outColor.a *= _procedural.isFading() ? Interpolate::calculateFadeRatio(_procedural.getFadeStartTime()) : 1.0f; + _procedural.prepare(batch, _position, _dimensions, _orientation, outColor); proceduralRender = true; } } @@ -230,9 +249,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { if (proceduralRender) { if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { - geometryCache->renderWireShape(batch, geometryShape, outColor); + geometryCache->renderWireShapeColor(batch, geometryShape, outColor); } else { - geometryCache->renderShape(batch, geometryShape, outColor); + geometryCache->renderShapeColor(batch, geometryShape, outColor); } } else if (!useMaterialPipeline()) { // FIXME, support instanced multi-shape rendering using multidraw indirect diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index d8b72c8838..0488bb2eb7 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -219,7 +219,29 @@ bool Procedural::isReady() const { return true; } -void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation) { +std::string Procedural::replaceProceduralBlock(const std::string& fragmentSource) { + std::string fragmentShaderSource = fragmentSource; + size_t replaceIndex = fragmentShaderSource.find(PROCEDURAL_COMMON_BLOCK); + if (replaceIndex != std::string::npos) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), ProceduralCommon_frag::getSource()); + } + + replaceIndex = fragmentShaderSource.find(PROCEDURAL_VERSION); + if (replaceIndex != std::string::npos) { + if (_data.version == 1) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V1 1"); + } else if (_data.version == 2) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V2 1"); + } + } + replaceIndex = fragmentShaderSource.find(PROCEDURAL_BLOCK); + if (replaceIndex != std::string::npos) { + fragmentShaderSource.replace(replaceIndex, PROCEDURAL_BLOCK.size(), _shaderSource.toLocal8Bit().data()); + } + return fragmentShaderSource; +} + +void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec4& color) { _entityDimensions = size; _entityPosition = position; _entityOrientation = glm::mat3_cast(orientation); @@ -242,49 +264,36 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm } // Build the fragment shader - std::string fragmentShaderSource = _fragmentSource; - size_t replaceIndex = fragmentShaderSource.find(PROCEDURAL_COMMON_BLOCK); - if (replaceIndex != std::string::npos) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_COMMON_BLOCK.size(), ProceduralCommon_frag::getSource()); - } - - replaceIndex = fragmentShaderSource.find(PROCEDURAL_VERSION); - if (replaceIndex != std::string::npos) { - if (_data.version == 1) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V1 1"); - } else if (_data.version == 2) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_VERSION.size(), "#define PROCEDURAL_V2 1"); - } - } - replaceIndex = fragmentShaderSource.find(PROCEDURAL_BLOCK); - if (replaceIndex != std::string::npos) { - fragmentShaderSource.replace(replaceIndex, PROCEDURAL_BLOCK.size(), _shaderSource.toLocal8Bit().data()); - } + std::string opaqueShaderSource = replaceProceduralBlock(_opaquefragmentSource); + std::string transparentShaderSource = replaceProceduralBlock(_transparentfragmentSource); // Leave this here for debugging // qCDebug(procedural) << "FragmentShader:\n" << fragmentShaderSource.c_str(); - _fragmentShader = gpu::Shader::createPixel(fragmentShaderSource); - _shader = gpu::Shader::createProgram(_vertexShader, _fragmentShader); + _opaqueFragmentShader = gpu::Shader::createPixel(opaqueShaderSource); + _opaqueShader = gpu::Shader::createProgram(_vertexShader, _opaqueFragmentShader); + _transparentFragmentShader = gpu::Shader::createPixel(transparentShaderSource); + _transparentShader = gpu::Shader::createProgram(_vertexShader, _transparentFragmentShader); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("iChannel0"), 0)); slotBindings.insert(gpu::Shader::Binding(std::string("iChannel1"), 1)); slotBindings.insert(gpu::Shader::Binding(std::string("iChannel2"), 2)); slotBindings.insert(gpu::Shader::Binding(std::string("iChannel3"), 3)); - gpu::Shader::makeProgram(*_shader, slotBindings); + gpu::Shader::makeProgram(*_opaqueShader, slotBindings); + gpu::Shader::makeProgram(*_transparentShader, slotBindings); - _opaquePipeline = gpu::Pipeline::create(_shader, _opaqueState); - _transparentPipeline = gpu::Pipeline::create(_shader, _transparentState); + _opaquePipeline = gpu::Pipeline::create(_opaqueShader, _opaqueState); + _transparentPipeline = gpu::Pipeline::create(_transparentShader, _transparentState); for (size_t i = 0; i < NUM_STANDARD_UNIFORMS; ++i) { const std::string& name = STANDARD_UNIFORM_NAMES[i]; - _standardUniformSlots[i] = _shader->getUniforms().findLocation(name); + _standardUniformSlots[i] = _opaqueShader->getUniforms().findLocation(name); } _start = usecTimestampNow(); _frameCount = 0; } - batch.setPipeline(isFading() ? _transparentPipeline : _opaquePipeline); + batch.setPipeline(color.a < 1.0f ? _transparentPipeline : _opaquePipeline); if (_shaderDirty || _uniformsDirty) { setupUniforms(); @@ -324,7 +333,7 @@ void Procedural::setupUniforms() { // Set any userdata specified uniforms foreach(QString key, _data.uniforms.keys()) { std::string uniformName = key.toLocal8Bit().data(); - int32_t slot = _shader->getUniforms().findLocation(uniformName); + int32_t slot = _opaqueShader->getUniforms().findLocation(uniformName); if (gpu::Shader::INVALID_LOCATION == slot) { continue; } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 9c29a681f0..4e30a003d6 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -55,8 +55,8 @@ public: bool isReady() const; bool isEnabled() const { return _enabled; } - void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation); - const gpu::ShaderPointer& getShader() const { return _shader; } + void prepare(gpu::Batch& batch, const glm::vec3& position, const glm::vec3& size, const glm::quat& orientation, const glm::vec4& color = glm::vec4(1)); + const gpu::ShaderPointer& getOpaqueShader() const { return _opaqueShader; } glm::vec4 getColor(const glm::vec4& entityColor); quint64 getFadeStartTime() const { return _fadeStartTime; } @@ -65,7 +65,8 @@ public: void setDoesFade(bool doesFade) { _doesFade = doesFade; } std::string _vertexSource; - std::string _fragmentSource; + std::string _opaquefragmentSource; + std::string _transparentfragmentSource; gpu::StatePointer _opaqueState { std::make_shared() }; gpu::StatePointer _transparentState { std::make_shared() }; @@ -106,8 +107,10 @@ protected: gpu::PipelinePointer _opaquePipeline; gpu::PipelinePointer _transparentPipeline; gpu::ShaderPointer _vertexShader; - gpu::ShaderPointer _fragmentShader; - gpu::ShaderPointer _shader; + gpu::ShaderPointer _opaqueFragmentShader; + gpu::ShaderPointer _transparentFragmentShader; + gpu::ShaderPointer _opaqueShader; + gpu::ShaderPointer _transparentShader; // Entity metadata glm::vec3 _entityDimensions; @@ -119,6 +122,8 @@ private: void setupUniforms(); void setupChannels(bool shouldCreate); + std::string replaceProceduralBlock(const std::string& fragmentSource); + mutable quint64 _fadeStartTime { 0 }; mutable bool _hasStartedFade { false }; mutable bool _isFading { false }; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 43633e47ad..0c6501928b 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -20,7 +20,7 @@ ProceduralSkybox::ProceduralSkybox() : graphics::Skybox() { _procedural._vertexSource = skybox_vert::getSource(); - _procedural._fragmentSource = skybox_frag::getSource(); + _procedural._opaquefragmentSource = skybox_frag::getSource(); // Adjust the pipeline state for background using the stencil test _procedural.setDoesFade(false); // Must match PrepareStencil::STENCIL_BACKGROUND @@ -61,8 +61,8 @@ void ProceduralSkybox::render(gpu::Batch& batch, const ViewFrustum& viewFrustum, auto& procedural = skybox._procedural; procedural.prepare(batch, glm::vec3(0), glm::vec3(1), glm::quat()); - auto textureSlot = procedural.getShader()->getTextures().findLocation("cubeMap"); - auto bufferSlot = procedural.getShader()->getUniformBuffers().findLocation("skyboxBuffer"); + auto textureSlot = procedural.getOpaqueShader()->getTextures().findLocation("cubeMap"); + auto bufferSlot = procedural.getOpaqueShader()->getUniformBuffers().findLocation("skyboxBuffer"); skybox.prepare(batch, textureSlot, bufferSlot); batch.draw(gpu::TRIANGLE_STRIP, 4); } diff --git a/libraries/render-utils/src/DefaultMaterials.slh b/libraries/render-utils/src/DefaultMaterials.slh new file mode 100644 index 0000000000..afb3dc2b28 --- /dev/null +++ b/libraries/render-utils/src/DefaultMaterials.slh @@ -0,0 +1,23 @@ + +<@if not DEFAULT_MATERIAL_SLH@> +<@def DEFAULT_MATERIAL_SLH@> + +const float DEFAULT_ROUGHNESS = 0.9; +const float DEFAULT_SHININESS = 10.0; +const float DEFAULT_METALLIC = 0.0; +const vec3 DEFAULT_SPECULAR = vec3(0.1); +const vec3 DEFAULT_EMISSIVE = vec3(0.0); +const float DEFAULT_OCCLUSION = 1.0; +const float DEFAULT_SCATTERING = 0.0; +const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE; + +<@endif@> diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 2f6bfaeb61..49db49af2a 100644 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -26,14 +26,7 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { return mix(alpha, 1.0 - alpha, step(mapAlpha, alphaThreshold)); } -const float DEFAULT_ROUGHNESS = 0.9; -const float DEFAULT_SHININESS = 10.0; -const float DEFAULT_METALLIC = 0.0; -const vec3 DEFAULT_SPECULAR = vec3(0.1); -const vec3 DEFAULT_EMISSIVE = vec3(0.0); -const float DEFAULT_OCCLUSION = 1.0; -const float DEFAULT_SCATTERING = 0.0; -const vec3 DEFAULT_FRESNEL = DEFAULT_EMISSIVE; +<@include DefaultMaterials.slh@> void packDeferredFragment(vec3 normal, float alpha, vec3 albedo, float roughness, float metallic, vec3 emissive, float occlusion, float scattering) { if (alpha != 1.0) { diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 3fd18a0eaf..52dc1d6cac 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -40,6 +40,7 @@ #include "simple_vert.h" #include "simple_textured_frag.h" +#include "simple_transparent_textured_frag.h" #include "simple_textured_unlit_frag.h" #include "simple_fade_vert.h" #include "simple_textured_fade_frag.h" @@ -49,6 +50,19 @@ #include "glowLine_vert.h" #include "glowLine_frag.h" +#include "forward_simple_textured_frag.h" +#include "forward_simple_textured_transparent_frag.h" +#include "forward_simple_textured_unlit_frag.h" + +#include "DeferredLightingEffect.h" + +#if defined(USE_GLES) +static bool DISABLE_DEFERRED = true; +#else +static const QString RENDER_FORWARD{ "HIFI_RENDER_FORWARD" }; +static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD); +#endif + #include "grid_frag.h" //#define WANT_DEBUG @@ -679,6 +693,7 @@ gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { QHash GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader; +gpu::ShaderPointer GeometryCache::_transparentShader; gpu::ShaderPointer GeometryCache::_unlitShader; gpu::ShaderPointer GeometryCache::_simpleFadeShader; gpu::ShaderPointer GeometryCache::_unlitFadeShader; @@ -774,8 +789,12 @@ render::ShapePipelinePointer GeometryCache::getShapePipeline(bool textured, bool bool unlit, bool depthBias) { return std::make_shared(getSimplePipeline(textured, transparent, culled, unlit, depthBias, false, true), nullptr, - [](const render::ShapePipeline& , gpu::Batch& batch, render::Args*) { + [](const render::ShapePipeline& pipeline, gpu::Batch& batch, render::Args* args) { batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); + DependencyManager::get()->setupKeyLightBatch(args, batch, + pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("keyLightBuffer"), + pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("lightAmbientBuffer"), + pipeline.pipeline->getProgram()->getUniformBuffers().findLocation("skyboxMap")); } ); } @@ -798,7 +817,7 @@ render::ShapePipelinePointer GeometryCache::getOpaqueShapePipeline(bool isFading return isFading ? _simpleOpaqueFadePipeline : _simpleOpaquePipeline; } -render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { +render::ShapePipelinePointer GeometryCache::getTransparentShapePipeline(bool isFading) { return isFading ? _simpleTransparentFadePipeline : _simpleTransparentPipeline; } @@ -826,6 +845,20 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::v _shapes[shape].drawWire(batch); } +void GeometryCache::renderShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color) { + batch.setInputFormat(getInstancedSolidStreamFormat()); + // Color must be set after input format + batch._glColor4f(color.r, color.g, color.b, color.a); + _shapes[shape].draw(batch); +} + +void GeometryCache::renderWireShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color) { + batch.setInputFormat(getInstancedSolidStreamFormat()); + // Color must be set after input format + batch._glColor4f(color.r, color.g, color.b, color.a); + _shapes[shape].drawWire(batch); +} + void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); @@ -843,7 +876,7 @@ void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, siz _shapes[shape].drawWireInstances(batch, count); } -void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, +void setupBatchFadeInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer, gpu::BufferPointer fadeBuffer1, gpu::BufferPointer fadeBuffer2, gpu::BufferPointer fadeBuffer3) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); gpu::BufferView texCoord2View(fadeBuffer1, TEXCOORD4_ELEMENT); @@ -2003,7 +2036,7 @@ void GeometryCache::renderGlowLine(gpu::Batch& batch, const glm::vec3& p1, const auto program = gpu::Shader::createProgram(VS, PS); state->setCullMode(gpu::State::CULL_NONE); state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, + state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); @@ -2231,29 +2264,40 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp static std::once_flag once; std::call_once(once, [&]() { auto VS = simple_vert::getShader(); - auto PS = simple_textured_frag::getShader(); - auto PSUnlit = simple_textured_unlit_frag::getShader(); + auto PS = DISABLE_DEFERRED ? forward_simple_textured_frag::getShader() : simple_textured_frag::getShader(); + auto PSTransparent = DISABLE_DEFERRED ? forward_simple_textured_transparent_frag::getShader() : simple_transparent_textured_frag::getShader(); + auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit_frag::getShader() : simple_textured_unlit_frag::getShader(); _simpleShader = gpu::Shader::createProgram(VS, PS); + _transparentShader = gpu::Shader::createProgram(VS, PSTransparent); _unlitShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), render::ShapePipeline::Slot::LIGHTING_MODEL)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), render::ShapePipeline::Slot::KEY_LIGHT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), render::ShapePipeline::Slot::MAP::LIGHT_AMBIENT)); gpu::Shader::makeProgram(*_simpleShader, slotBindings); + gpu::Shader::makeProgram(*_transparentShader, slotBindings); gpu::Shader::makeProgram(*_unlitShader, slotBindings); }); } else { static std::once_flag once; std::call_once(once, [&]() { auto VS = simple_fade_vert::getShader(); - auto PS = simple_textured_fade_frag::getShader(); - auto PSUnlit = simple_textured_unlit_fade_frag::getShader(); + auto PS = DISABLE_DEFERRED ? forward_simple_textured_frag::getShader() : simple_textured_fade_frag::getShader(); + auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit_frag::getShader() : simple_textured_unlit_fade_frag::getShader(); _simpleFadeShader = gpu::Shader::createProgram(VS, PS); _unlitFadeShader = gpu::Shader::createProgram(VS, PSUnlit); gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("originalTexture"), render::ShapePipeline::Slot::MAP::ALBEDO)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightingModelBuffer"), render::ShapePipeline::Slot::LIGHTING_MODEL)); + slotBindings.insert(gpu::Shader::Binding(std::string("keyLightBuffer"), render::ShapePipeline::Slot::KEY_LIGHT)); + slotBindings.insert(gpu::Shader::Binding(std::string("lightAmbientBuffer"), render::ShapePipeline::Slot::LIGHT_AMBIENT_BUFFER)); + slotBindings.insert(gpu::Shader::Binding(std::string("skyboxMap"), render::ShapePipeline::Slot::MAP::LIGHT_AMBIENT)); slotBindings.insert(gpu::Shader::Binding(std::string("fadeMaskMap"), render::ShapePipeline::Slot::MAP::FADE_MASK)); gpu::Shader::makeProgram(*_simpleFadeShader, slotBindings); gpu::Shader::makeProgram(*_unlitFadeShader, slotBindings); @@ -2282,7 +2326,8 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp PrepareStencil::testMaskDrawShapeNoAA(*state); } - gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : (config.isFading() ? _simpleFadeShader : _simpleShader); + gpu::ShaderPointer program = (config.isUnlit()) ? (config.isFading() ? _unlitFadeShader : _unlitShader) : + (config.isFading() ? _simpleFadeShader : (config.isTransparent() ? _transparentShader : _simpleShader)); gpu::PipelinePointer pipeline = gpu::Pipeline::create(program, state); _simplePrograms.insert(config, pipeline); return pipeline; @@ -2363,11 +2408,11 @@ void renderFadeInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& c pipeline->prepare(batch, args); if (isWire) { - DependencyManager::get()->renderWireFadeShapeInstances(batch, shape, data.count(), + DependencyManager::get()->renderWireFadeShapeInstances(batch, shape, data.count(), buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); } else { - DependencyManager::get()->renderFadeShapeInstances(batch, shape, data.count(), + DependencyManager::get()->renderFadeShapeInstances(batch, shape, data.count(), buffers[INSTANCE_COLOR_BUFFER], buffers[INSTANCE_FADE_BUFFER1], buffers[INSTANCE_FADE_BUFFER2], buffers[INSTANCE_FADE_BUFFER3]); } }); @@ -2383,15 +2428,15 @@ void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, renderInstances(args, batch, color, true, pipeline, shape); } -void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, - int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, +void GeometryCache::renderSolidFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, + int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, false, pipeline, shape); } -void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, - int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, +void GeometryCache::renderWireFadeShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, + int fadeCategory, float fadeThreshold, const glm::vec3& fadeNoiseOffset, const glm::vec3& fadeBaseOffset, const glm::vec3& fadeBaseInvSize, const render::ShapePipelinePointer& pipeline) { assert(pipeline != nullptr); renderFadeInstances(args, batch, color, fadeCategory, fadeThreshold, fadeNoiseOffset, fadeBaseOffset, fadeBaseInvSize, true, pipeline, shape); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index e0ba99b09e..bec166aded 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -253,6 +253,8 @@ public: void renderWireShape(gpu::Batch& batch, Shape shape); void renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); void renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); + void renderShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color); + void renderWireShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color); size_t getShapeTriangleCount(Shape shape); void renderCube(gpu::Batch& batch); @@ -471,6 +473,7 @@ private: QHash _registeredGridBuffers; static gpu::ShaderPointer _simpleShader; + static gpu::ShaderPointer _transparentShader; static gpu::ShaderPointer _unlitShader; static gpu::ShaderPointer _simpleFadeShader; static gpu::ShaderPointer _unlitFadeShader; @@ -478,8 +481,6 @@ private: static render::ShapePipelinePointer _simpleTransparentPipeline; static render::ShapePipelinePointer _simpleOpaqueFadePipeline; static render::ShapePipelinePointer _simpleTransparentFadePipeline; - static render::ShapePipelinePointer _simpleOpaqueOverlayPipeline; - static render::ShapePipelinePointer _simpleTransparentOverlayPipeline; static render::ShapePipelinePointer _simpleWirePipeline; gpu::PipelinePointer _glowLinePipeline; diff --git a/libraries/render-utils/src/LightAmbient.slh b/libraries/render-utils/src/LightAmbient.slh index 008f29da01..b2377d1904 100644 --- a/libraries/render-utils/src/LightAmbient.slh +++ b/libraries/render-utils/src/LightAmbient.slh @@ -111,15 +111,11 @@ void evalLightingAmbient(out vec3 diffuse, out vec3 specular, LightAmbient ambie } <@endif@> - if (!(isObscuranceEnabled() > 0.0)) { - obscurance = 1.0; - } + obscurance = mix(1.0, obscurance, isObscuranceEnabled()); float lightEnergy = obscurance * getLightAmbientIntensity(ambient); - if (isAlbedoEnabled() > 0.0) { - diffuse *= albedo; - } + diffuse *= mix(vec3(1), albedo, isAlbedoEnabled()); lightEnergy *= isAmbientEnabled(); diffuse *= lightEnergy * isDiffuseEnabled(); diff --git a/libraries/render-utils/src/LightingModel.slh b/libraries/render-utils/src/LightingModel.slh index 2280d12465..3f615f11db 100644 --- a/libraries/render-utils/src/LightingModel.slh +++ b/libraries/render-utils/src/LightingModel.slh @@ -13,11 +13,19 @@ <@func declareLightingModel()@> +#ifndef PRECISIONQ +#ifdef GL_ES +#define PRECISIONQ highp +#else +#define PRECISIONQ +#endif +#endif + struct LightingModel { - vec4 _UnlitEmissiveLightmapBackground; - vec4 _ScatteringDiffuseSpecularAlbedo; - vec4 _AmbientDirectionalPointSpot; - vec4 _ShowContourObscuranceWireframe; + PRECISIONQ vec4 _UnlitEmissiveLightmapBackground; + PRECISIONQ vec4 _ScatteringDiffuseSpecularAlbedo; + PRECISIONQ vec4 _AmbientDirectionalPointSpot; + PRECISIONQ vec4 _ShowContourObscuranceWireframe; }; uniform lightingModelBuffer{ @@ -256,9 +264,7 @@ void evalFragShading(out vec3 diffuse, out vec3 specular, float metallic, vec3 fresnel, SurfaceData surface, vec3 albedo) { vec4 shading = evalPBRShading(metallic, fresnel, surface); diffuse = vec3(shading.w); - if (isAlbedoEnabled() > 0.0) { - diffuse *= albedo; - } + diffuse *= mix(vec3(1.0), albedo, isAlbedoEnabled()); specular = shading.xyz; } diff --git a/libraries/render-utils/src/Shadows_shared.slh b/libraries/render-utils/src/Shadows_shared.slh index 0d49fc037e..bc8063e018 100644 --- a/libraries/render-utils/src/Shadows_shared.slh +++ b/libraries/render-utils/src/Shadows_shared.slh @@ -1,10 +1,8 @@ // glsl / C++ compatible source as interface for Shadows #ifdef __cplusplus # define MAT4 glm::mat4 -# define VEC3 glm::vec3 #else # define MAT4 mat4 -# define VEC3 vec3 #endif #define SHADOW_CASCADE_MAX_COUNT 4 diff --git a/libraries/render-utils/src/forward_simple.slf b/libraries/render-utils/src/forward_simple.slf new file mode 100644 index 0000000000..497afe93a3 --- /dev/null +++ b/libraries/render-utils/src/forward_simple.slf @@ -0,0 +1,85 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +<@include DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalSkyboxGlobalColor()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +// the interpolated normal +in vec3 _normal; +in vec3 _modelNormal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +//PROCEDURAL_COMMON_BLOCK + +#line 1001 +//PROCEDURAL_BLOCK + +#line 2030 +void main(void) { + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; + vec3 specular = DEFAULT_SPECULAR; + float shininess = DEFAULT_SHININESS; + float emissiveAmount = 0.0; + +#ifdef PROCEDURAL + +#ifdef PROCEDURAL_V1 + specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + //specular = pow(specular, vec3(2.2)); + emissiveAmount = 1.0; +#else + emissiveAmount = getProceduralColors(diffuse, specular, shininess); +#endif + +#endif + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + if (emissiveAmount > 0.0) { + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + diffuse, + specular, + DEFAULT_METALLIC, + max(0.0, 1.0 - shininess / 128.0)), + 1.0); + } else { + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + diffuse, + DEFAULT_FRESNEL, + length(specular), + max(0.0, 1.0 - shininess / 128.0)), + 1.0); + } +} diff --git a/libraries/render-utils/src/forward_simple_textured.slf b/libraries/render-utils/src/forward_simple_textured.slf new file mode 100644 index 0000000000..c88482c208 --- /dev/null +++ b/libraries/render-utils/src/forward_simple_textured.slf @@ -0,0 +1,51 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple_textured.slf +// fragment shader +// +// Created by Clément Brisset on 5/29/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +<@include DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalSkyboxGlobalColor()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a * texel.a; + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + _fragColor0 = vec4(evalSkyboxGlobalColor( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normal), + _color.rgb * texel.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_ROUGHNESS), + 1.0); +} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_transparent.slf b/libraries/render-utils/src/forward_simple_textured_transparent.slf new file mode 100644 index 0000000000..a8f23907d3 --- /dev/null +++ b/libraries/render-utils/src/forward_simple_textured_transparent.slf @@ -0,0 +1,52 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple_textured_transparent.slf +// fragment shader +// +// Created by Clément Brisset on 5/29/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +<@include DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +// the albedo texture +uniform sampler2D originalTexture; + +// the interpolated normal +in vec3 _normal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a * texel.a; + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normalize(_normal), + _color.rgb * texel.rgb, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, colorAlpha), + colorAlpha); +} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_textured_unlit.slf b/libraries/render-utils/src/forward_simple_textured_unlit.slf new file mode 100644 index 0000000000..b65de16c61 --- /dev/null +++ b/libraries/render-utils/src/forward_simple_textured_unlit.slf @@ -0,0 +1,35 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_textured_unlit.frag +// fragment shader +// +// Created by Clément Brisset on 5/29/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include LightingModel.slh@> +<@include gpu/Color.slh@> + +layout(location = 0) out vec4 _fragColor0; + +// the albedo texture +uniform sampler2D originalTexture; + +in vec4 _color; +in vec2 _texCoord0; + +void main(void) { + vec4 texel = texture(originalTexture, _texCoord0.st); + float colorAlpha = _color.a; + if (_color.a <= 0.0) { + texel = color_sRGBAToLinear(texel); + colorAlpha = -_color.a; + } + + _fragColor0 = vec4(_color.rgb * texel.rgb * isUnlitEnabled(), colorAlpha * texel.a); +} \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_transparent.slf b/libraries/render-utils/src/forward_simple_transparent.slf new file mode 100644 index 0000000000..4c7a2df6a6 --- /dev/null +++ b/libraries/render-utils/src/forward_simple_transparent.slf @@ -0,0 +1,87 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// forward_simple_transparent.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +<@include DefaultMaterials.slh@> + +<@include ForwardGlobalLight.slh@> +<$declareEvalGlobalLightingAlphaBlended()$> + +<@include gpu/Transform.slh@> +<$declareStandardCameraTransform()$> + +// the interpolated normal +in vec3 _normal; +in vec3 _modelNormal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _eyePosition; + +layout(location = 0) out vec4 _fragColor0; + +//PROCEDURAL_COMMON_BLOCK + +#line 1001 +//PROCEDURAL_BLOCK + +#line 2030 +void main(void) { + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; + vec3 specular = DEFAULT_SPECULAR; + float shininess = DEFAULT_SHININESS; + float emissiveAmount = 0.0; + +#ifdef PROCEDURAL + +#ifdef PROCEDURAL_V1 + specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + //specular = pow(specular, vec3(2.2)); + emissiveAmount = 1.0; +#else + emissiveAmount = getProceduralColors(diffuse, specular, shininess); +#endif + +#endif + + TransformCamera cam = getTransformCamera(); + vec3 fragPosition = _eyePosition.xyz; + + if (emissiveAmount > 0.0) { + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + specular, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, _color.a), + _color.a); + } else { + _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( + cam._viewInverse, + 1.0, + DEFAULT_OCCLUSION, + fragPosition, + normal, + diffuse, + DEFAULT_FRESNEL, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_ROUGHNESS, _color.a), + _color.a); + } +} diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 7b32541c63..8e7df452cc 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -13,7 +13,6 @@ // <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> // the interpolated normal in vec3 _normal; @@ -29,7 +28,6 @@ in vec4 _position; #line 2030 void main(void) { - Material material = getMaterial(); vec3 normal = normalize(_normal.xyz); vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; @@ -49,43 +47,24 @@ void main(void) { #endif - const float ALPHA_THRESHOLD = 0.999; - if (_color.a < ALPHA_THRESHOLD) { - if (emissiveAmount > 0.0) { - packDeferredFragmentTranslucent( - normal, - _color.a, - specular, - DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragmentTranslucent( - normal, - _color.a, - diffuse, - DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); - } + if (emissiveAmount > 0.0) { + packDeferredFragmentLightmap( + normal, + 1.0, + diffuse, + max(0.0, 1.0 - shininess / 128.0), + DEFAULT_METALLIC, + specular, + vec3(clamp(emissiveAmount, 0.0, 1.0))); } else { - if (emissiveAmount > 0.0) { - packDeferredFragmentLightmap( - normal, - 1.0, - diffuse, - max(0.0, 1.0 - shininess / 128.0), - DEFAULT_METALLIC, - specular, - vec3(clamp(emissiveAmount, 0.0, 1.0))); - } else { - packDeferredFragment( - normal, - 1.0, - diffuse, - max(0.0, 1.0 - shininess / 128.0), - length(specular), - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); - } + packDeferredFragment( + normal, + 1.0, + diffuse, + max(0.0, 1.0 - shininess / 128.0), + length(specular), + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); } } diff --git a/libraries/render-utils/src/simple.slv b/libraries/render-utils/src/simple.slv index 0ce6505a65..f63ccb61a6 100644 --- a/libraries/render-utils/src/simple.slv +++ b/libraries/render-utils/src/simple.slv @@ -23,6 +23,7 @@ out vec3 _modelNormal; out vec4 _color; out vec2 _texCoord0; out vec4 _position; +out vec4 _eyePosition; void main(void) { _color = color_sRGBAToLinear(inColor); @@ -33,6 +34,6 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _eyePosition, gl_Position)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_fade.slv b/libraries/render-utils/src/simple_fade.slv index 85946045ac..6dbe40485a 100644 --- a/libraries/render-utils/src/simple_fade.slv +++ b/libraries/render-utils/src/simple_fade.slv @@ -26,6 +26,7 @@ out vec3 _modelNormal; out vec4 _color; out vec2 _texCoord0; out vec4 _position; +out vec4 _eyePosition; out vec4 _worldPosition; void main(void) { @@ -37,7 +38,7 @@ void main(void) { // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); - <$transformModelToClipPos(cam, obj, inPosition, gl_Position)$> + <$transformModelToEyeAndClipPos(cam, obj, inPosition, _eyePosition, gl_Position)$> <$transformModelToWorldPos(obj, inPosition, _worldPosition)$> <$transformModelToWorldDir(cam, obj, inNormal.xyz, _normal)$> <$passThroughFadeObjectParams()$> diff --git a/libraries/render-utils/src/simple_textured.slf b/libraries/render-utils/src/simple_textured.slf index 4fd734aad5..bb50c9d158 100644 --- a/libraries/render-utils/src/simple_textured.slf +++ b/libraries/render-utils/src/simple_textured.slf @@ -12,9 +12,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> // the albedo texture uniform sampler2D originalTexture; @@ -26,29 +24,14 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } - const float ALPHA_THRESHOLD = 0.999; - if (colorAlpha * texel.a < ALPHA_THRESHOLD) { - packDeferredFragmentTranslucent( - normalize(_normal), - colorAlpha * texel.a, - _color.rgb * texel.rgb, - DEFAULT_FRESNEL, - DEFAULT_ROUGHNESS); - } else { - packDeferredFragment( - normalize(_normal), - 1.0, - _color.rgb * texel.rgb, - DEFAULT_ROUGHNESS, - DEFAULT_METALLIC, - DEFAULT_EMISSIVE, - DEFAULT_OCCLUSION, - DEFAULT_SCATTERING); - } + packDeferredFragment( + normalize(_normal), + 1.0, + _color.rgb * texel.rgb, + DEFAULT_ROUGHNESS, + DEFAULT_METALLIC, + DEFAULT_EMISSIVE, + DEFAULT_OCCLUSION, + DEFAULT_SCATTERING); } \ No newline at end of file diff --git a/libraries/render-utils/src/simple_transparent.slf b/libraries/render-utils/src/simple_transparent.slf new file mode 100644 index 0000000000..fe544d1283 --- /dev/null +++ b/libraries/render-utils/src/simple_transparent.slf @@ -0,0 +1,65 @@ +<@include gpu/Config.slh@> +<$VERSION_HEADER$> +// Generated on <$_SCRIBE_DATE$> +// +// simple_transparent.frag +// fragment shader +// +// Created by Andrzej Kapolka on 9/15/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +<@include DeferredBufferWrite.slh@> + +// the interpolated normal +in vec3 _normal; +in vec3 _modelNormal; +in vec4 _color; +in vec2 _texCoord0; +in vec4 _position; + +//PROCEDURAL_COMMON_BLOCK + +#line 1001 +//PROCEDURAL_BLOCK + +#line 2030 +void main(void) { + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; + vec3 specular = DEFAULT_SPECULAR; + float shininess = DEFAULT_SHININESS; + float emissiveAmount = 0.0; + +#ifdef PROCEDURAL + +#ifdef PROCEDURAL_V1 + specular = getProceduralColor().rgb; + // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline + //specular = pow(specular, vec3(2.2)); + emissiveAmount = 1.0; +#else + emissiveAmount = getProceduralColors(diffuse, specular, shininess); +#endif + +#endif + + if (emissiveAmount > 0.0) { + packDeferredFragmentTranslucent( + normal, + _color.a, + specular, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } else { + packDeferredFragmentTranslucent( + normal, + _color.a, + diffuse, + DEFAULT_FRESNEL, + DEFAULT_ROUGHNESS); + } +} diff --git a/libraries/render-utils/src/simple_transparent_textured.slf b/libraries/render-utils/src/simple_transparent_textured.slf index c6b0d83914..7c7168ec0f 100644 --- a/libraries/render-utils/src/simple_transparent_textured.slf +++ b/libraries/render-utils/src/simple_transparent_textured.slf @@ -12,51 +12,24 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -<@include gpu/Color.slh@> - <@include DeferredBufferWrite.slh@> -<@include DeferredGlobalLight.slh@> -<$declareEvalGlobalLightingAlphaBlendedWithHaze()$> - -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> // the albedo texture uniform sampler2D originalTexture; // the interpolated normal -in vec4 _position; in vec3 _normal; in vec4 _color; in vec2 _texCoord0; void main(void) { - vec4 texel = texture(originalTexture, _texCoord0.st); - float opacity = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - opacity = -_color.a; - } - opacity *= texel.a; - vec3 albedo = _color.rgb * texel.rgb; + vec4 texel = texture(originalTexture, _texCoord0); + float colorAlpha = _color.a * texel.a; - vec3 fragPosition = _position.xyz; - vec3 fragNormal = normalize(_normal); - - TransformCamera cam = getTransformCamera(); - - _fragColor0 = vec4(evalGlobalLightingAlphaBlendedWithHaze( - cam._viewInverse, - 1.0, - 1.0, - fragPosition, - fragNormal, - albedo, + packDeferredFragmentTranslucent( + normalize(_normal), + colorAlpha, + _color.rgb * texel.rgb, DEFAULT_FRESNEL, - 0.0, - vec3(0.0f), - DEFAULT_ROUGHNESS, - opacity), - opacity); - + DEFAULT_ROUGHNESS); } \ No newline at end of file From e0b2c076ef33424c7ff296648d57b645fe71054b Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 10 Apr 2018 17:10:29 -0700 Subject: [PATCH 09/15] cleanup and fix forward procedural rendering --- .../src/RenderableShapeEntityItem.cpp | 20 +++---- .../procedural/src/procedural/Procedural.cpp | 52 +++++++++++-------- .../procedural/src/procedural/Procedural.h | 8 +-- libraries/render-utils/src/GeometryCache.cpp | 17 +----- libraries/render-utils/src/GeometryCache.h | 2 - libraries/render-utils/src/forward_simple.slf | 12 ++--- .../src/forward_simple_textured_unlit.slf | 8 +-- .../src/forward_simple_transparent.slf | 11 ++-- libraries/render-utils/src/simple.slf | 6 +-- libraries/render-utils/src/simple_fade.slf | 2 - .../render-utils/src/simple_textured_fade.slf | 1 - .../render-utils/src/simple_transparent.slf | 6 +-- 12 files changed, 60 insertions(+), 85 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 2743c8b29d..1d34837a58 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -22,15 +22,6 @@ #include "render-utils/forward_simple_frag.h" #include "render-utils/forward_simple_transparent_frag.h" -#include - -#if defined(USE_GLES) -static bool DISABLE_DEFERRED = true; -#else -static const QString RENDER_FORWARD{ "HIFI_RENDER_FORWARD" }; -static bool DISABLE_DEFERRED = QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD); -#endif - #include "RenderPipelines.h" //#define SHAPE_ENTITY_USE_FADE_EFFECT @@ -47,8 +38,11 @@ static const float SPHERE_ENTITY_SCALE = 0.5f; ShapeEntityRenderer::ShapeEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { _procedural._vertexSource = simple_vert::getSource(); - _procedural._opaquefragmentSource = DISABLE_DEFERRED ? forward_simple_frag::getSource() : simple_frag::getSource(); - _procedural._transparentfragmentSource = DISABLE_DEFERRED ? forward_simple_transparent_frag::getSource() : simple_transparent_frag::getSource(); + // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering + _procedural._opaquefragmentSource = simple_frag::getSource(); + // FIXME: Transparent procedural entities only seem to work if they use the opaque pipelines + //_procedural._transparentfragmentSource = simple_transparent_frag::getSource(); + _procedural._transparentfragmentSource = simple_frag::getSource(); _procedural._opaqueState->setCullMode(gpu::State::CULL_NONE); _procedural._opaqueState->setDepthTest(true, true, gpu::LESS_EQUAL); PrepareStencil::testMaskDrawShape(*_procedural._opaqueState); @@ -251,9 +245,9 @@ void ShapeEntityRenderer::doRender(RenderArgs* args) { if (proceduralRender) { if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { - geometryCache->renderWireShapeColor(batch, geometryShape, outColor); + geometryCache->renderWireShape(batch, geometryShape, outColor); } else { - geometryCache->renderShapeColor(batch, geometryShape, outColor); + geometryCache->renderShape(batch, geometryShape, outColor); } } else if (!useMaterialPipeline()) { // FIXME, support instanced multi-shape rendering using multidraw indirect diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 0488bb2eb7..c155d5bd7f 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -287,22 +287,25 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm _transparentPipeline = gpu::Pipeline::create(_transparentShader, _transparentState); for (size_t i = 0; i < NUM_STANDARD_UNIFORMS; ++i) { const std::string& name = STANDARD_UNIFORM_NAMES[i]; - _standardUniformSlots[i] = _opaqueShader->getUniforms().findLocation(name); + _standardOpaqueUniformSlots[i] = _opaqueShader->getUniforms().findLocation(name); + _standardTransparentUniformSlots[i] = _transparentShader->getUniforms().findLocation(name); } _start = usecTimestampNow(); _frameCount = 0; } - batch.setPipeline(color.a < 1.0f ? _transparentPipeline : _opaquePipeline); + bool transparent = color.a < 1.0f; + batch.setPipeline(transparent ? _transparentPipeline : _opaquePipeline); - if (_shaderDirty || _uniformsDirty) { - setupUniforms(); + if (_shaderDirty || _uniformsDirty || _prevTransparent != transparent) { + setupUniforms(transparent); } - if (_shaderDirty || _uniformsDirty || _channelsDirty) { - setupChannels(_shaderDirty || _uniformsDirty); + if (_shaderDirty || _uniformsDirty || _channelsDirty || _prevTransparent != transparent) { + setupChannels(_shaderDirty || _uniformsDirty, transparent); } + _prevTransparent = transparent; _shaderDirty = _uniformsDirty = _channelsDirty = false; for (auto lambda : _uniforms) { @@ -328,12 +331,12 @@ void Procedural::prepare(gpu::Batch& batch, const glm::vec3& position, const glm } } -void Procedural::setupUniforms() { +void Procedural::setupUniforms(bool transparent) { _uniforms.clear(); // Set any userdata specified uniforms foreach(QString key, _data.uniforms.keys()) { std::string uniformName = key.toLocal8Bit().data(); - int32_t slot = _opaqueShader->getUniforms().findLocation(uniformName); + int32_t slot = (transparent ? _transparentShader : _opaqueShader)->getUniforms().findLocation(uniformName); if (gpu::Shader::INVALID_LOCATION == slot) { continue; } @@ -394,15 +397,17 @@ void Procedural::setupUniforms() { } } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[TIME]) { + auto uniformSlots = transparent ? _standardTransparentUniformSlots : _standardOpaqueUniformSlots; + + if (gpu::Shader::INVALID_LOCATION != uniformSlots[TIME]) { _uniforms.push_back([=](gpu::Batch& batch) { // Minimize floating point error by doing an integer division to milliseconds, before the floating point division to seconds float time = (float)((usecTimestampNow() - _start) / USECS_PER_MSEC) / MSECS_PER_SECOND; - batch._glUniform(_standardUniformSlots[TIME], time); + batch._glUniform(uniformSlots[TIME], time); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[DATE]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[DATE]) { _uniforms.push_back([=](gpu::Batch& batch) { QDateTime now = QDateTime::currentDateTimeUtc(); QDate date = now.date(); @@ -415,40 +420,41 @@ void Procedural::setupUniforms() { v.z = date.day(); float fractSeconds = (time.msec() / 1000.0f); v.w = (time.hour() * 3600) + (time.minute() * 60) + time.second() + fractSeconds; - batch._glUniform(_standardUniformSlots[DATE], v); + batch._glUniform(uniformSlots[DATE], v); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[FRAME_COUNT]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[FRAME_COUNT]) { _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[FRAME_COUNT], ++_frameCount); + batch._glUniform(uniformSlots[FRAME_COUNT], ++_frameCount); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[SCALE]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[SCALE]) { // FIXME move into the 'set once' section, since this doesn't change over time _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[SCALE], _entityDimensions); + batch._glUniform(uniformSlots[SCALE], _entityDimensions); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[ORIENTATION]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[ORIENTATION]) { // FIXME move into the 'set once' section, since this doesn't change over time _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[ORIENTATION], _entityOrientation); + batch._glUniform(uniformSlots[ORIENTATION], _entityOrientation); }); } - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[POSITION]) { + if (gpu::Shader::INVALID_LOCATION != uniformSlots[POSITION]) { // FIXME move into the 'set once' section, since this doesn't change over time _uniforms.push_back([=](gpu::Batch& batch) { - batch._glUniform(_standardUniformSlots[POSITION], _entityPosition); + batch._glUniform(uniformSlots[POSITION], _entityPosition); }); } } -void Procedural::setupChannels(bool shouldCreate) { - if (gpu::Shader::INVALID_LOCATION != _standardUniformSlots[CHANNEL_RESOLUTION]) { +void Procedural::setupChannels(bool shouldCreate, bool transparent) { + auto uniformSlots = transparent ? _standardTransparentUniformSlots : _standardOpaqueUniformSlots; + if (gpu::Shader::INVALID_LOCATION != uniformSlots[CHANNEL_RESOLUTION]) { if (!shouldCreate) { // Instead of modifying the last element, just remove and recreate it. _uniforms.pop_back(); @@ -460,7 +466,7 @@ void Procedural::setupChannels(bool shouldCreate) { channelSizes[i] = vec3(_channels[i]->getWidth(), _channels[i]->getHeight(), 1.0); } } - batch._glUniform3fv(_standardUniformSlots[CHANNEL_RESOLUTION], MAX_PROCEDURAL_TEXTURE_CHANNELS, &channelSizes[0].x); + batch._glUniform3fv(uniformSlots[CHANNEL_RESOLUTION], MAX_PROCEDURAL_TEXTURE_CHANNELS, &channelSizes[0].x); }); } } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 4e30a003d6..1d3b0b3b5a 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -102,7 +102,8 @@ protected: // Rendering objects UniformLambdas _uniforms; - int32_t _standardUniformSlots[NUM_STANDARD_UNIFORMS]; + int32_t _standardOpaqueUniformSlots[NUM_STANDARD_UNIFORMS]; + int32_t _standardTransparentUniformSlots[NUM_STANDARD_UNIFORMS]; NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS]; gpu::PipelinePointer _opaquePipeline; gpu::PipelinePointer _transparentPipeline; @@ -119,8 +120,8 @@ protected: private: // This should only be called from the render thread, as it shares data with Procedural::prepare - void setupUniforms(); - void setupChannels(bool shouldCreate); + void setupUniforms(bool transparent); + void setupChannels(bool shouldCreate, bool transparent); std::string replaceProceduralBlock(const std::string& fragmentSource); @@ -128,6 +129,7 @@ private: mutable bool _hasStartedFade { false }; mutable bool _isFading { false }; bool _doesFade { true }; + bool _prevTransparent { false }; }; #endif diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 52dc1d6cac..ecfa9881a3 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -845,20 +845,6 @@ void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::v _shapes[shape].drawWire(batch); } -void GeometryCache::renderShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color) { - batch.setInputFormat(getInstancedSolidStreamFormat()); - // Color must be set after input format - batch._glColor4f(color.r, color.g, color.b, color.a); - _shapes[shape].draw(batch); -} - -void GeometryCache::renderWireShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color) { - batch.setInputFormat(getInstancedSolidStreamFormat()); - // Color must be set after input format - batch._glColor4f(color.r, color.g, color.b, color.a); - _shapes[shape].drawWire(batch); -} - void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer colorBuffer) { gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT); batch.setInputBuffer(gpu::Stream::COLOR, colorView); @@ -2265,7 +2251,8 @@ gpu::PipelinePointer GeometryCache::getSimplePipeline(bool textured, bool transp std::call_once(once, [&]() { auto VS = simple_vert::getShader(); auto PS = DISABLE_DEFERRED ? forward_simple_textured_frag::getShader() : simple_textured_frag::getShader(); - auto PSTransparent = DISABLE_DEFERRED ? forward_simple_textured_transparent_frag::getShader() : simple_transparent_textured_frag::getShader(); + // Use the forward pipeline for both here, otherwise transparents will be unlit + auto PSTransparent = DISABLE_DEFERRED ? forward_simple_textured_transparent_frag::getShader() : forward_simple_textured_transparent_frag::getShader(); auto PSUnlit = DISABLE_DEFERRED ? forward_simple_textured_unlit_frag::getShader() : simple_textured_unlit_frag::getShader(); _simpleShader = gpu::Shader::createProgram(VS, PS); diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index bec166aded..fcbf5ee128 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -253,8 +253,6 @@ public: void renderWireShape(gpu::Batch& batch, Shape shape); void renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); void renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color); - void renderShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color); - void renderWireShapeColor(gpu::Batch& batch, Shape shape, const glm::vec4& color); size_t getShapeTriangleCount(Shape shape); void renderCube(gpu::Batch& batch); diff --git a/libraries/render-utils/src/forward_simple.slf b/libraries/render-utils/src/forward_simple.slf index 497afe93a3..ac2aa63697 100644 --- a/libraries/render-utils/src/forward_simple.slf +++ b/libraries/render-utils/src/forward_simple.slf @@ -16,14 +16,12 @@ <@include ForwardGlobalLight.slh@> <$declareEvalSkyboxGlobalColor()$> -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - // the interpolated normal in vec3 _normal; in vec3 _modelNormal; in vec4 _color; in vec2 _texCoord0; +in vec4 _position; in vec4 _eyePosition; layout(location = 0) out vec4 _fragColor0; @@ -35,12 +33,12 @@ layout(location = 0) out vec4 _fragColor0; #line 2030 void main(void) { - vec3 normal = normalize(_normal.xyz); - vec3 diffuse = _color.rgb; + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; float shininess = DEFAULT_SHININESS; float emissiveAmount = 0.0; - + #ifdef PROCEDURAL #ifdef PROCEDURAL_V1 @@ -48,7 +46,7 @@ void main(void) { // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline //specular = pow(specular, vec3(2.2)); emissiveAmount = 1.0; -#else +#else emissiveAmount = getProceduralColors(diffuse, specular, shininess); #endif diff --git a/libraries/render-utils/src/forward_simple_textured_unlit.slf b/libraries/render-utils/src/forward_simple_textured_unlit.slf index b65de16c61..0cc241b75e 100644 --- a/libraries/render-utils/src/forward_simple_textured_unlit.slf +++ b/libraries/render-utils/src/forward_simple_textured_unlit.slf @@ -25,11 +25,7 @@ in vec2 _texCoord0; void main(void) { vec4 texel = texture(originalTexture, _texCoord0.st); - float colorAlpha = _color.a; - if (_color.a <= 0.0) { - texel = color_sRGBAToLinear(texel); - colorAlpha = -_color.a; - } + float colorAlpha = _color.a * texel.a; - _fragColor0 = vec4(_color.rgb * texel.rgb * isUnlitEnabled(), colorAlpha * texel.a); + _fragColor0 = vec4(_color.rgb * texel.rgb * isUnlitEnabled(), colorAlpha); } \ No newline at end of file diff --git a/libraries/render-utils/src/forward_simple_transparent.slf b/libraries/render-utils/src/forward_simple_transparent.slf index 4c7a2df6a6..551e10282a 100644 --- a/libraries/render-utils/src/forward_simple_transparent.slf +++ b/libraries/render-utils/src/forward_simple_transparent.slf @@ -16,9 +16,6 @@ <@include ForwardGlobalLight.slh@> <$declareEvalGlobalLightingAlphaBlended()$> -<@include gpu/Transform.slh@> -<$declareStandardCameraTransform()$> - // the interpolated normal in vec3 _normal; in vec3 _modelNormal; @@ -35,12 +32,12 @@ layout(location = 0) out vec4 _fragColor0; #line 2030 void main(void) { - vec3 normal = normalize(_normal.xyz); - vec3 diffuse = _color.rgb; + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; float shininess = DEFAULT_SHININESS; float emissiveAmount = 0.0; - + #ifdef PROCEDURAL #ifdef PROCEDURAL_V1 @@ -48,7 +45,7 @@ void main(void) { // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline //specular = pow(specular, vec3(2.2)); emissiveAmount = 1.0; -#else +#else emissiveAmount = getProceduralColors(diffuse, specular, shininess); #endif diff --git a/libraries/render-utils/src/simple.slf b/libraries/render-utils/src/simple.slf index 8e7df452cc..1c2ad9a413 100644 --- a/libraries/render-utils/src/simple.slf +++ b/libraries/render-utils/src/simple.slf @@ -28,8 +28,8 @@ in vec4 _position; #line 2030 void main(void) { - vec3 normal = normalize(_normal.xyz); - vec3 diffuse = _color.rgb; + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; float shininess = DEFAULT_SHININESS; float emissiveAmount = 0.0; @@ -41,7 +41,7 @@ void main(void) { // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline //specular = pow(specular, vec3(2.2)); emissiveAmount = 1.0; -#else +#else emissiveAmount = getProceduralColors(diffuse, specular, shininess); #endif diff --git a/libraries/render-utils/src/simple_fade.slf b/libraries/render-utils/src/simple_fade.slf index ce9251b9a5..1c74612ff0 100644 --- a/libraries/render-utils/src/simple_fade.slf +++ b/libraries/render-utils/src/simple_fade.slf @@ -13,7 +13,6 @@ // <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> <@include Fade.slh@> <$declareFadeFragmentInstanced()$> @@ -39,7 +38,6 @@ void main(void) { <$fetchFadeObjectParamsInstanced(fadeParams)$> applyFade(fadeParams, _worldPosition.xyz, fadeEmissive); - Material material = getMaterial(); vec3 normal = normalize(_normal.xyz); vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; diff --git a/libraries/render-utils/src/simple_textured_fade.slf b/libraries/render-utils/src/simple_textured_fade.slf index d378e7a5c1..e5ecd94852 100644 --- a/libraries/render-utils/src/simple_textured_fade.slf +++ b/libraries/render-utils/src/simple_textured_fade.slf @@ -14,7 +14,6 @@ <@include gpu/Color.slh@> <@include DeferredBufferWrite.slh@> -<@include graphics/Material.slh@> <@include Fade.slh@> diff --git a/libraries/render-utils/src/simple_transparent.slf b/libraries/render-utils/src/simple_transparent.slf index fe544d1283..65ffe0504a 100644 --- a/libraries/render-utils/src/simple_transparent.slf +++ b/libraries/render-utils/src/simple_transparent.slf @@ -28,8 +28,8 @@ in vec4 _position; #line 2030 void main(void) { - vec3 normal = normalize(_normal.xyz); - vec3 diffuse = _color.rgb; + vec3 normal = normalize(_normal.xyz); + vec3 diffuse = _color.rgb; vec3 specular = DEFAULT_SPECULAR; float shininess = DEFAULT_SHININESS; float emissiveAmount = 0.0; @@ -41,7 +41,7 @@ void main(void) { // Procedural Shaders are expected to be Gamma corrected so let's bring back the RGB in linear space for the rest of the pipeline //specular = pow(specular, vec3(2.2)); emissiveAmount = 1.0; -#else +#else emissiveAmount = getProceduralColors(diffuse, specular, shininess); #endif From c2f0f7ef5f87dd918cde14954eae4e1466ec0432 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Thu, 12 Apr 2018 10:54:35 +1200 Subject: [PATCH 10/15] Doc review --- .../src/scripting/HMDScriptingInterface.h | 29 +++++++++++++++---- .../AbstractHMDScriptingInterface.h | 2 +- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 1acafab361..9b2482e73a 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -31,7 +31,7 @@ class QScriptEngine; * @property {Vec3} position - The position of the HMD if currently in VR display mode, otherwise * {@link Vec3(0)|Vec3.ZERO}. Read-only. * @property {Quat} orientation - The orientation of the HMD if currently in VR display mode, otherwise - * {@link Quat(0)|Quat.IDENTITY}.Read-only. + * {@link Quat(0)|Quat.IDENTITY}. Read-only. * @property {boolean} active - true if the display mode is HMD, otherwise false. Read-only. * @property {boolean} mounted - true if currently in VR display mode and the HMD is being worn, otherwise * false. Read-only. @@ -74,6 +74,23 @@ public: * @param {Vec3} position - The origin of the ray. * @param {Vec3} direction - The direction of the ray. * @returns {Vec3} The point of intersection with the HUD overlay if it intersects, otherwise {@link Vec3(0)|Vec3.ZERO}. + * @example Draw a square on the HUD overlay in the direction you're looking. + * var hudIntersection = HMD.calculateRayUICollisionPoint(MyAvatar.getHeadPosition(), + * Quat.getForward(MyAvatar.headOrientation)); + * var hudPoint = HMD.overlayFromWorldPoint(hudIntersection); + * + * var DIMENSIONS = { x: 50, y: 50 }; + * var square = Overlays.addOverlay("rectangle", { + * x: hudPoint.x - DIMENSIONS.x / 2, + * y: hudPoint.y - DIMENSIONS.y / 2, + * width: DIMENSIONS.x, + * height: DIMENSIONS.y, + * color: { red: 255, green: 0, blue: 0 } + * }); + * + * Script.scriptEnding.connect(function () { + * Overlays.deleteOverlay(square); + * }); */ Q_INVOKABLE glm::vec3 calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction) const; @@ -201,7 +218,7 @@ public: /**jsdoc * Check whether there are specific HMD controllers available. * @function HMD.isSubdeviceContainingNameAvailable - * @param {string} - The name of the HMD controller to check for, e.g., "OculusTouch". + * @param {string} name - The name of the HMD controller to check for, e.g., "OculusTouch". * @returns {boolean} true if an HMD controller with a name containing the specified name is * available, otherwise false. * @example Report if particular Oculus controllers are available. @@ -240,15 +257,15 @@ public: /**jsdoc - * Causes the borders and decorations in HUD windows to be enlarged when the laser intersects them in HMD mode. By default, - * borders and decorations are not enlarged. + * Causes the borders in HUD windows to be enlarged when the laser intersects them in HMD mode. By default, borders are not + * enlarged. * @function HMD.activateHMDHandMouse */ Q_INVOKABLE void activateHMDHandMouse(); /**jsdoc - * Causes the border and decorations in HUD windows to no longer be enlarged when the laser intersects them in HMD mode. By - * default, borders and decorations are not enlarged. + * Causes the border in HUD windows to no longer be enlarged when the laser intersects them in HMD mode. By default, + * borders are not enlarged. * @function HMD.deactivateHMDHandMouse */ Q_INVOKABLE void deactivateHMDHandMouse(); diff --git a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h index 36e1952d3c..392fa7e2a2 100644 --- a/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h +++ b/libraries/display-plugins/src/display-plugins/AbstractHMDScriptingInterface.h @@ -47,7 +47,7 @@ signals: * @example Report when the display mode changes. * HMD.displayModeChanged.connect(function (isHMDMode) { * print("Display mode changed"); - * print("isHMD = " + isHMD); + * print("isHMD = " + isHMDMode); * print("HMD.active = " + HMD.active); * print("HMD.mounted = " + HMD.mounted); * }); From adcf99112596f0f802ddf8b79448f091be982251 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 11 Apr 2018 17:36:32 -0700 Subject: [PATCH 11/15] Improvements to profiling data capture Use code-provided task names for profile blocks; record QML URLs for loadInternal. --- libraries/gpu/src/gpu/Context.cpp | 2 +- libraries/qml/src/qml/OffscreenSurface.cpp | 2 +- libraries/render-utils/src/BloomEffect.cpp | 1 - .../render-utils/src/HighlightEffect.cpp | 1 - .../render-utils/src/RenderDeferredTask.cpp | 1 - .../render-utils/src/RenderForwardTask.cpp | 1 - .../render-utils/src/RenderShadowTask.cpp | 1 - libraries/render-utils/src/RenderViewTask.cpp | 1 - .../render-utils/src/UpdateSceneTask.cpp | 1 - libraries/render-utils/src/ZoneRenderer.cpp | 1 - libraries/render/src/render/Engine.cpp | 2 +- .../src/render/RenderFetchCullSortTask.cpp | 1 - libraries/task/src/task/Task.h | 55 ++++++++++--------- 13 files changed, 33 insertions(+), 37 deletions(-) diff --git a/libraries/gpu/src/gpu/Context.cpp b/libraries/gpu/src/gpu/Context.cpp index dc2273ecb6..7dc6965076 100644 --- a/libraries/gpu/src/gpu/Context.cpp +++ b/libraries/gpu/src/gpu/Context.cpp @@ -129,7 +129,7 @@ void Context::executeFrame(const FramePointer& frame) const { } bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings, const Shader::CompilationHandler& handler) { - PROFILE_RANGE(app, "makeProgram"); + PROFILE_RANGE_EX(app, "makeProgram", 0xff4040c0, shader.getID()); // If we're running in another DLL context, we need to fetch the program callback out of the application // FIXME find a way to do this without reliance on Qt app properties if (!_makeProgramCallback) { diff --git a/libraries/qml/src/qml/OffscreenSurface.cpp b/libraries/qml/src/qml/OffscreenSurface.cpp index 2f1b3910c6..2da1c41340 100644 --- a/libraries/qml/src/qml/OffscreenSurface.cpp +++ b/libraries/qml/src/qml/OffscreenSurface.cpp @@ -286,7 +286,7 @@ void OffscreenSurface::loadInternal(const QUrl& qmlSource, bool createNewContext, QQuickItem* parent, const QmlContextObjectCallback& callback) { - PROFILE_RANGE(app, "loadInternal"); + PROFILE_RANGE_EX(app, "OffscreenSurface::loadInternal", 0xffff00ff, 0, { std::make_pair("url", qmlSource.toDisplayString()) }); if (QThread::currentThread() != thread()) { qFatal("Called load on a non-surface thread"); } diff --git a/libraries/render-utils/src/BloomEffect.cpp b/libraries/render-utils/src/BloomEffect.cpp index 75ddb5f8e9..ddd63f012f 100644 --- a/libraries/render-utils/src/BloomEffect.cpp +++ b/libraries/render-utils/src/BloomEffect.cpp @@ -326,7 +326,6 @@ Bloom::Bloom() { } void Bloom::configure(const Config& config) { - PROFILE_RANGE(startup, "Bloom::build"); std::string blurName{ "BloomBlurN" }; for (auto i = 0; i < BLOOM_BLUR_LEVEL_COUNT; i++) { diff --git a/libraries/render-utils/src/HighlightEffect.cpp b/libraries/render-utils/src/HighlightEffect.cpp index 5876b40d2b..d151da766b 100644 --- a/libraries/render-utils/src/HighlightEffect.cpp +++ b/libraries/render-utils/src/HighlightEffect.cpp @@ -476,7 +476,6 @@ void DrawHighlightTask::configure(const Config& config) { } void DrawHighlightTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs) { - PROFILE_RANGE(startup, "Bloom::build"); const auto items = inputs.getN(0).get(); const auto sceneFrameBuffer = inputs.getN(1); const auto primaryFramebuffer = inputs.getN(2); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 6d44e7f182..2377f5131f 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -76,7 +76,6 @@ const render::Varying RenderDeferredTask::addSelectItemJobs(JobModel& task, cons } void RenderDeferredTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { - PROFILE_RANGE(startup, "RenderDeferredTask::build"); const auto& items = input.get(); auto fadeEffect = DependencyManager::get(); diff --git a/libraries/render-utils/src/RenderForwardTask.cpp b/libraries/render-utils/src/RenderForwardTask.cpp index e7603d73d9..63370109e0 100755 --- a/libraries/render-utils/src/RenderForwardTask.cpp +++ b/libraries/render-utils/src/RenderForwardTask.cpp @@ -40,7 +40,6 @@ extern void initForwardPipelines(ShapePlumber& plumber, extern void initOverlay3DPipelines(render::ShapePlumber& plumber, bool depthTest = false); void RenderForwardTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { - PROFILE_RANGE(startup, "RenderForwardTask::build"); auto items = input.get(); auto fadeEffect = DependencyManager::get(); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 84fd46f429..69c5b3c689 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -215,7 +215,6 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, con void RenderShadowTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cameraCullFunctor, uint8_t tagBits, uint8_t tagMask) { ::CullFunctor shadowCullFunctor = [this](const RenderArgs* args, const AABox& bounds) { - PROFILE_RANGE(startup, "RenderShadowTask::build"); return _cullFunctor(args, bounds); }; diff --git a/libraries/render-utils/src/RenderViewTask.cpp b/libraries/render-utils/src/RenderViewTask.cpp index aed2972243..122fc16e61 100644 --- a/libraries/render-utils/src/RenderViewTask.cpp +++ b/libraries/render-utils/src/RenderViewTask.cpp @@ -17,7 +17,6 @@ void RenderViewTask::build(JobModel& task, const render::Varying& input, render::Varying& output, render::CullFunctor cullFunctor, bool isDeferred, uint8_t tagBits, uint8_t tagMask) { // auto items = input.get(); - PROFILE_RANGE(startup, "RenderViewTask::build"); // Warning : the cull functor passed to the shadow pass should only be testing for LOD culling. If frustum culling // is performed, then casters not in the view frustum will be removed, which is not what we wish. task.addJob("RenderShadowTask", cullFunctor, tagBits, tagMask); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index 2b4e626fed..e05f28ef0d 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -19,7 +19,6 @@ #include "DeferredLightingEffect.h" void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { - PROFILE_RANGE(startup, "UpdateSceneTask::build"); task.addJob("LightStageSetup"); task.addJob("BackgroundStageSetup"); task.addJob("HazeStageSetup"); diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index bd03668b11..51939efd4f 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -42,7 +42,6 @@ protected: const Selection::Name ZoneRendererTask::ZONES_SELECTION { "RankedZones" }; void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& ouput) { - PROFILE_RANGE(startup, "ZoneRendererTask::build"); // Filter out the sorted list of zones const auto zoneItems = task.addJob("FilterZones", input, ZONES_SELECTION.c_str()); diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index 463b45451b..b0842d63cd 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -36,7 +36,7 @@ public: } }; -Engine::Engine() : Task("Engine", EngineTask::JobModel::create()), +Engine::Engine() : Task(EngineTask::JobModel::create("Engine")), _renderContext(std::make_shared()) { } diff --git a/libraries/render/src/render/RenderFetchCullSortTask.cpp b/libraries/render/src/render/RenderFetchCullSortTask.cpp index 629bcf81bf..7b9765dca1 100644 --- a/libraries/render/src/render/RenderFetchCullSortTask.cpp +++ b/libraries/render/src/render/RenderFetchCullSortTask.cpp @@ -20,7 +20,6 @@ using namespace render; void RenderFetchCullSortTask::build(JobModel& task, const Varying& input, Varying& output, CullFunctor cullFunctor, uint8_t tagBits, uint8_t tagMask) { cullFunctor = cullFunctor ? cullFunctor : [](const RenderArgs*, const AABox&){ return true; }; - PROFILE_RANGE(startup, "RenderFetchCullSortTask::build"); // CPU jobs: // Fetch and cull the items from the scene const ItemFilter filter = ItemFilter::Builder::visibleWorldItems().withoutLayered().withTagBits(tagBits, tagMask); diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 08df55dddd..7e4c8de51b 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -47,7 +47,7 @@ protected: bool _doAbortTask{ false }; }; -// JobContext class is the base calss for the context object which is passed through all the Job::run calls thoughout the graph of jobs +// JobContext class is the base class for the context object which is passed through all the Job::run calls thoughout the graph of jobs // It is used to communicate to the job::run its context and various state information the job relies on. // It specifically provide access to: // - The taskFlow object allowing for messaging control flow commands from within a Job::run @@ -73,19 +73,21 @@ class JobConcept { public: using Config = JobConfig; - JobConcept(QConfigPointer config) : _config(config) {} + JobConcept(const std::string& name, QConfigPointer config) : _name(name), _config(config) {} virtual ~JobConcept() = default; + + const std::string& getName() const { return _name; } virtual const Varying getInput() const { return Varying(); } virtual const Varying getOutput() const { return Varying(); } virtual QConfigPointer& getConfiguration() { return _config; } virtual void applyConfiguration() = 0; - void setCPURunTime(double mstime) { std::static_pointer_cast(_config)->setCPURunTime(mstime); } QConfigPointer _config; protected: + const std::string _name; }; @@ -122,7 +124,7 @@ public: class Concept : public JobConcept { public: - Concept(QConfigPointer config) : JobConcept(config) {} + Concept(const std::string& name, QConfigPointer config) : JobConcept(name, config) {} virtual ~Concept() = default; virtual void run(const ContextPointer& jobContext) = 0; @@ -143,8 +145,8 @@ public: const Varying getOutput() const override { return _output; } template - Model(const Varying& input, QConfigPointer config, A&&... args) : - Concept(config), + Model(const std::string& name, const Varying& input, QConfigPointer config, A&&... args) : + Concept(name, config), _data(Data(std::forward(args)...)), _input(input), _output(Output()) { @@ -152,12 +154,14 @@ public: } template - static std::shared_ptr create(const Varying& input, A&&... args) { - return std::make_shared(input, std::make_shared(), std::forward(args)...); + static std::shared_ptr create(const std::string& name, const Varying& input, A&&... args) { + return std::make_shared(name, input, std::make_shared(), std::forward(args)...); } void applyConfiguration() override { + Duration profileRange(trace_render(), ("configure::" + getName()).c_str()); + jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); } @@ -173,8 +177,9 @@ public: template using ModelO = Model; template using ModelIO = Model; - Job(std::string name, ConceptPointer concept) : _concept(concept), _name(name) {} + Job(ConceptPointer concept) : _concept(concept) {} + const std::string& getName() const { return _concept->getName(); } const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } @@ -193,9 +198,9 @@ public: } virtual void run(const ContextPointer& jobContext) { - PerformanceTimer perfTimer(_name.c_str()); + PerformanceTimer perfTimer(getName().c_str()); // NOTE: rather than use the PROFILE_RANGE macro, we create a Duration manually - Duration profileRange(jobContext->profileCategory, _name.c_str()); + Duration profileRange(jobContext->profileCategory, ("run::" + getName()).c_str()); auto start = usecTimestampNow(); _concept->run(jobContext); @@ -203,11 +208,8 @@ public: _concept->setCPURunTime((double)(usecTimestampNow() - start) / 1000.0); } - const std::string& getName() const { return _name; } - protected: ConceptPointer _concept; - std::string _name = ""; }; @@ -230,7 +232,7 @@ public: using ConceptPointer = typename JobType::ConceptPointer; using Jobs = std::vector; - Task(std::string name, ConceptPointer concept) : JobType(name, concept) {} + Task(ConceptPointer concept) : JobType(concept) {} class TaskConcept : public Concept { public: @@ -259,11 +261,11 @@ public: return jobIt; } - TaskConcept(const Varying& input, QConfigPointer config) : Concept(config), _input(input) {} + TaskConcept(const std::string& name, const Varying& input, QConfigPointer config) : Concept(name, config), _input(input) {} // Create a new job in the container's queue; returns the job's output template const Varying addJob(std::string name, const Varying& input, NA&&... args) { - _jobs.emplace_back(name, (NT::JobModel::create(input, std::forward(args)...))); + _jobs.emplace_back((NT::JobModel::create(name, input, std::forward(args)...))); // Conect the child config to this task's config std::static_pointer_cast(Concept::getConfiguration())->connectChildConfig(_jobs.back().getConfiguration(), name); @@ -284,16 +286,18 @@ public: Data _data; - TaskModel(const Varying& input, QConfigPointer config) : - TaskConcept(input, config), + TaskModel(const std::string& name, const Varying& input, QConfigPointer config) : + TaskConcept(name, input, config), _data(Data()) {} template - static std::shared_ptr create(const Varying& input, A&&... args) { - auto model = std::make_shared(input, std::make_shared()); - - model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); + static std::shared_ptr create(const std::string& name, const Varying& input, A&&... args) { + auto model = std::make_shared(name, input, std::make_shared()); + { + Duration profileRange(trace_render(), ("build::" + model->getName()).c_str()); + model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); + } // Recreate the Config to use the templated type model->createConfiguration(); model->applyConfiguration(); @@ -302,9 +306,9 @@ public: } template - static std::shared_ptr create(A&&... args) { + static std::shared_ptr create(const std::string& name, A&&... args) { const auto input = Varying(Input()); - return create(input, std::forward(args)...); + return create(name, input, std::forward(args)...); } void createConfiguration() { @@ -326,6 +330,7 @@ public: } void applyConfiguration() override { + Duration profileRange(trace_render(), ("configure::" + getName()).c_str()); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); for (auto& job : TaskConcept::_jobs) { job.applyConfiguration(); From 888fca2127531ae6901e4d1eeb1af54504f4d8a1 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Wed, 11 Apr 2018 18:31:09 -0700 Subject: [PATCH 12/15] Qualify getName in task template to satisfy gcc --- libraries/task/src/task/Task.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 7e4c8de51b..413a940f62 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -330,7 +330,7 @@ public: } void applyConfiguration() override { - Duration profileRange(trace_render(), ("configure::" + getName()).c_str()); + Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); for (auto& job : TaskConcept::_jobs) { job.applyConfiguration(); From 5c141aa5e99a8d9ae50c112fbef31c4a058f6d2d Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Thu, 12 Apr 2018 09:28:28 -0700 Subject: [PATCH 13/15] Add --disableWatchdog command-line option Watchdog still runs but doesn't abort on timeout. Also fixes for previous tracing improvements. --- interface/src/Application.cpp | 13 ++++++++++--- libraries/task/src/task/Task.h | 4 ++-- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 11427fb1e6..e882909a7c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -399,7 +399,8 @@ public: static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples // Set the heartbeat on launch - DeadlockWatchdogThread() { + DeadlockWatchdogThread(bool crashOnTrigger = true) + : _crashOnTrigger(crashOnTrigger) { setObjectName("Deadlock Watchdog"); // Give the heartbeat an initial value _heartbeat = usecTimestampNow(); @@ -490,7 +491,9 @@ public: // Don't actually crash in debug builds, in case this apparent deadlock is simply from // the developer actively debugging code #ifdef NDEBUG + if (_crashOnTrigger) { deadlockDetectionCrash(); + } #endif } } @@ -502,6 +505,8 @@ public: static std::atomic _maxElapsedAverage; static ThreadSafeMovingAverage _movingAverage; + const bool _crashOnTrigger; + bool _quit { false }; }; @@ -957,7 +962,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); - + bool watchdogCrashWhenTriggered = true; { const QString TEST_SCRIPT = "--testScript"; const QStringList args = arguments(); @@ -967,6 +972,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); } + } else if (args.at(i) == QStringLiteral("--disableWatchdog")) { + watchdogCrashWhenTriggered = false; } } } @@ -1014,7 +1021,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Set up a watchdog thread to intentionally crash the application on deadlocks if (!DISABLE_WATCHDOG) { - (new DeadlockWatchdogThread())->start(); + (new DeadlockWatchdogThread(watchdogCrashWhenTriggered))->start(); } // Set File Logger Session UUID diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 413a940f62..c07051fda1 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -73,7 +73,7 @@ class JobConcept { public: using Config = JobConfig; - JobConcept(const std::string& name, QConfigPointer config) : _name(name), _config(config) {} + JobConcept(const std::string& name, QConfigPointer config) : _config(config), _name(name) {} virtual ~JobConcept() = default; const std::string& getName() const { return _name; } @@ -330,7 +330,7 @@ public: } void applyConfiguration() override { - Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); + Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); for (auto& job : TaskConcept::_jobs) { job.applyConfiguration(); From a584d67acde3d39fd8cda702415529e0f2c2bfb9 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Thu, 12 Apr 2018 10:44:41 -0700 Subject: [PATCH 14/15] Tweaks for clang error and gcc warning --- interface/src/main.cpp | 2 +- libraries/task/src/task/Task.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 5f2afa9155..22db128f7e 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -264,7 +264,7 @@ int main(int argc, const char* argv[]) { QTimer exitTimer; - if (traceDuration > 0.0) { + if (traceDuration > 0.0f) { exitTimer.setSingleShot(true); QObject::connect(&exitTimer, &QTimer::timeout, &app, &Application::quit); exitTimer.start(int(1000 * traceDuration)); diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index c07051fda1..022dd99200 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -160,7 +160,7 @@ public: void applyConfiguration() override { - Duration profileRange(trace_render(), ("configure::" + getName()).c_str()); + Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); } From 76468f7f261184a96ee5967c973b22b3dad75d13 Mon Sep 17 00:00:00 2001 From: Simon Walton Date: Thu, 12 Apr 2018 16:58:13 -0700 Subject: [PATCH 15/15] Use existing DISABLE_WATCHDOG global to turn off thread entirely --- interface/src/Application.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e882909a7c..5b2b9b9ac6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -399,8 +399,7 @@ public: static const int HEARTBEAT_SAMPLES = 100000; // ~5 seconds worth of samples // Set the heartbeat on launch - DeadlockWatchdogThread(bool crashOnTrigger = true) - : _crashOnTrigger(crashOnTrigger) { + DeadlockWatchdogThread() { setObjectName("Deadlock Watchdog"); // Give the heartbeat an initial value _heartbeat = usecTimestampNow(); @@ -491,9 +490,7 @@ public: // Don't actually crash in debug builds, in case this apparent deadlock is simply from // the developer actively debugging code #ifdef NDEBUG - if (_crashOnTrigger) { - deadlockDetectionCrash(); - } + deadlockDetectionCrash(); #endif } } @@ -505,8 +502,6 @@ public: static std::atomic _maxElapsedAverage; static ThreadSafeMovingAverage _movingAverage; - const bool _crashOnTrigger; - bool _quit { false }; }; @@ -962,7 +957,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto steamClient = PluginManager::getInstance()->getSteamClientPlugin(); setProperty(hifi::properties::STEAM, (steamClient && steamClient->isRunning())); setProperty(hifi::properties::CRASHED, _previousSessionCrashed); - bool watchdogCrashWhenTriggered = true; { const QString TEST_SCRIPT = "--testScript"; const QStringList args = arguments(); @@ -972,8 +966,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo if (QFileInfo(testScriptPath).exists()) { setProperty(hifi::properties::TEST, QUrl::fromLocalFile(testScriptPath)); } - } else if (args.at(i) == QStringLiteral("--disableWatchdog")) { - watchdogCrashWhenTriggered = false; } } } @@ -1019,9 +1011,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo auto nodeList = DependencyManager::get(); nodeList->startThread(); + const char** constArgv = const_cast(argv); + if (cmdOptionExists(argc, constArgv, "--disableWatchdog")) { + DISABLE_WATCHDOG = true; + } // Set up a watchdog thread to intentionally crash the application on deadlocks if (!DISABLE_WATCHDOG) { - (new DeadlockWatchdogThread(watchdogCrashWhenTriggered))->start(); + (new DeadlockWatchdogThread())->start(); } // Set File Logger Session UUID @@ -1228,7 +1224,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo connect(&_entityEditSender, &EntityEditPacketSender::packetSent, this, &Application::packetSent); connect(&_entityEditSender, &EntityEditPacketSender::addingEntityWithCertificate, this, &Application::addingEntityWithCertificate); - const char** constArgv = const_cast(argv); QString concurrentDownloadsStr = getCmdOption(argc, constArgv, "--concurrent-downloads"); bool success; int concurrentDownloads = concurrentDownloadsStr.toInt(&success);