mirror of
https://github.com/overte-org/overte.git
synced 2025-08-05 20:39:55 +02:00
Merge and fix the bug!!!
This commit is contained in:
commit
9031e65aa5
34 changed files with 852 additions and 310 deletions
|
@ -17,6 +17,30 @@
|
||||||
|
|
||||||
class MenuItemProperties;
|
class MenuItemProperties;
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* The `Menu` provides access to the menu that is shown at the top of the window
|
||||||
|
* shown on a user's desktop and the right click menu that is accessible
|
||||||
|
* in both Desktop and HMD mode.
|
||||||
|
*
|
||||||
|
* <h3>Groupings</h3>
|
||||||
|
* A `grouping` is a way to group a set of menus and/or menu items together
|
||||||
|
* so that they can all be set visible or invisible as a group. There are
|
||||||
|
* 2 available groups: "Advanced" and "Developer"
|
||||||
|
* These groupings can be toggled in the "Settings" menu.
|
||||||
|
*
|
||||||
|
* @namespace Menu
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CURRENTLY NOT WORKING:
|
||||||
|
*
|
||||||
|
* <h3>Action groups</h3>
|
||||||
|
* When 1+ menu items are checkable and in the same action group, only 1 can be
|
||||||
|
* selected at any one time. If another item in the action group is selected, the
|
||||||
|
* previous will be deselected. This feature provides the ability to create
|
||||||
|
* "radio-button"-like menus.
|
||||||
|
*/
|
||||||
|
|
||||||
class MenuScriptingInterface : public QObject {
|
class MenuScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
MenuScriptingInterface() { };
|
MenuScriptingInterface() { };
|
||||||
|
@ -28,33 +52,142 @@ private slots:
|
||||||
void menuItemTriggered();
|
void menuItemTriggered();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
/**jsdoc
|
||||||
|
* Add a new top-level menu.
|
||||||
|
* @function Menu.addMenu
|
||||||
|
* @param {string} menuName Name that will be shown in the menu.
|
||||||
|
* @param {string} grouping Name of the grouping to add this menu to.
|
||||||
|
*/
|
||||||
void addMenu(const QString& menuName, const QString& grouping = QString());
|
void addMenu(const QString& menuName, const QString& grouping = QString());
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Remove a top-level menu.
|
||||||
|
* @function Menu.removeMenu
|
||||||
|
* @param {string} menuName Name of the menu to remove.
|
||||||
|
*/
|
||||||
void removeMenu(const QString& menuName);
|
void removeMenu(const QString& menuName);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Check whether a top-level menu exists.
|
||||||
|
* @function Menu.menuExists
|
||||||
|
* @param {string} menuName Name of the menu to check for existence.
|
||||||
|
* @return {bool} `true` if the menu exists, otherwise `false`.
|
||||||
|
*/
|
||||||
bool menuExists(const QString& menuName);
|
bool menuExists(const QString& menuName);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Add a separator with an unclickable label below it.
|
||||||
|
* The line will be placed at the bottom of the menu.
|
||||||
|
* @function Menu.addSeparator
|
||||||
|
* @param {string} menuName Name of the menu to add a separator to.
|
||||||
|
* @param {string} separatorName Name of the separator that will be shown (but unclickable) below the separator line.
|
||||||
|
*/
|
||||||
void addSeparator(const QString& menuName, const QString& separatorName);
|
void addSeparator(const QString& menuName, const QString& separatorName);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Remove a separator and its label from a menu.
|
||||||
|
* @function Menu.removeSeparator
|
||||||
|
* @param {string} menuName Name of the menu to remove a separator from.
|
||||||
|
* @param {string} separatorName Name of the separator to remove.
|
||||||
|
*/
|
||||||
void removeSeparator(const QString& menuName, const QString& separatorName);
|
void removeSeparator(const QString& menuName, const QString& separatorName);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Add a new menu item to a menu.
|
||||||
|
* @function Menu.addMenuItem
|
||||||
|
* @param {Menu.MenuItemProperties} properties
|
||||||
|
*/
|
||||||
void addMenuItem(const MenuItemProperties& properties);
|
void addMenuItem(const MenuItemProperties& properties);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Add a new menu item to a menu.
|
||||||
|
* @function Menu.addMenuItem
|
||||||
|
* @param {string} menuName Name of the menu to add a menu item to.
|
||||||
|
* @param {string} menuItem Name of the menu item. This is what will be displayed in the menu.
|
||||||
|
* @param {string} shortcutKey A shortcut key that can be used to trigger the menu item.
|
||||||
|
*/
|
||||||
void addMenuItem(const QString& menuName, const QString& menuitem, const QString& shortcutKey);
|
void addMenuItem(const QString& menuName, const QString& menuitem, const QString& shortcutKey);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Add a new menu item to a menu.
|
||||||
|
* @function Menu.addMenuItem
|
||||||
|
* @param {string} menuName Name of the menu to add a menu item to.
|
||||||
|
* @param {string} menuItem Name of the menu item. This is what will be displayed in the menu.
|
||||||
|
*/
|
||||||
void addMenuItem(const QString& menuName, const QString& menuitem);
|
void addMenuItem(const QString& menuName, const QString& menuitem);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Remove a menu item from a menu.
|
||||||
|
* @function Menu.removeMenuItem
|
||||||
|
* @param {string} menuName Name of the menu to remove a menu item from.
|
||||||
|
* @param {string} menuItem Name of the menu item to remove.
|
||||||
|
*/
|
||||||
void removeMenuItem(const QString& menuName, const QString& menuitem);
|
void removeMenuItem(const QString& menuName, const QString& menuitem);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Check if a menu item exists.
|
||||||
|
* @function Menu.menuItemExists
|
||||||
|
* @param {string} menuName Name of the menu that the menu item is in.
|
||||||
|
* @param {string} menuItem Name of the menu item to check for existence of.
|
||||||
|
* @return {bool} `true` if the menu item exists, otherwise `false`.
|
||||||
|
*/
|
||||||
bool menuItemExists(const QString& menuName, const QString& menuitem);
|
bool menuItemExists(const QString& menuName, const QString& menuitem);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Not working, will not document until fixed
|
||||||
|
*/
|
||||||
void addActionGroup(const QString& groupName, const QStringList& actionList,
|
void addActionGroup(const QString& groupName, const QStringList& actionList,
|
||||||
const QString& selected = QString());
|
const QString& selected = QString());
|
||||||
void removeActionGroup(const QString& groupName);
|
void removeActionGroup(const QString& groupName);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Check whether a checkable menu item is checked.
|
||||||
|
* @function Menu.isOptionChecked
|
||||||
|
* @param {string} menuOption The name of the menu item.
|
||||||
|
* @return `true` if the option is checked, otherwise false.
|
||||||
|
*/
|
||||||
bool isOptionChecked(const QString& menuOption);
|
bool isOptionChecked(const QString& menuOption);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Set a checkable menu item as checked or unchecked.
|
||||||
|
* @function Menu.setIsOptionChecked
|
||||||
|
* @param {string} menuOption The name of the menu item to modify.
|
||||||
|
* @param {bool} isChecked If `true`, the menu item will be checked, otherwise it will not be checked.
|
||||||
|
*/
|
||||||
void setIsOptionChecked(const QString& menuOption, bool isChecked);
|
void setIsOptionChecked(const QString& menuOption, bool isChecked);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Toggle the status of a checkable menu item. If it is checked, it will be unchecked.
|
||||||
|
* If it is unchecked, it will be checked.
|
||||||
|
* @function Menu.setIsOptionChecked
|
||||||
|
* @param {string} menuOption The name of the menu item to toggle.
|
||||||
|
*/
|
||||||
void triggerOption(const QString& menuOption);
|
void triggerOption(const QString& menuOption);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Check whether a menu is enabled. If a menu is disabled it will be greyed out
|
||||||
|
* and unselectable.
|
||||||
|
* Menus are enabled by default.
|
||||||
|
* @function Menu.isMenuEnabled
|
||||||
|
* @param {string} menuName The name of the menu to check.
|
||||||
|
* @return {bool} `true` if the menu is enabled, otherwise false.
|
||||||
|
*/
|
||||||
bool isMenuEnabled(const QString& menuName);
|
bool isMenuEnabled(const QString& menuName);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Set a menu to be enabled or disabled.
|
||||||
|
* @function Menu.setMenuEnabled
|
||||||
|
* @param {string} menuName The name of the menu to modify.
|
||||||
|
* @param {bool} isEnabled Whether the menu will be enabled or not.
|
||||||
|
*/
|
||||||
void setMenuEnabled(const QString& menuName, bool isEnabled);
|
void setMenuEnabled(const QString& menuName, bool isEnabled);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
/**jsdoc
|
||||||
|
* This is a signal that is emitted when a menu item is clicked.
|
||||||
|
* @function Menu.menuItemEvent
|
||||||
|
* @param {string} menuItem Name of the menu item that was triggered.
|
||||||
|
*/
|
||||||
void menuItemEvent(const QString& menuItem);
|
void menuItemEvent(const QString& menuItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,14 @@ Q_DECLARE_METATYPE(OverlayPropertyResult);
|
||||||
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value);
|
QScriptValue OverlayPropertyResultToScriptValue(QScriptEngine* engine, const OverlayPropertyResult& value);
|
||||||
void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value);
|
void OverlayPropertyResultFromScriptValue(const QScriptValue& object, OverlayPropertyResult& value);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @typedef Overlays.RayToOverlayIntersectionResult
|
||||||
|
* @property {bool} intersects True if the PickRay intersected with a 3D overlay.
|
||||||
|
* @property {Overlays.OverlayID} overlayID The ID of the overlay that was intersected with.
|
||||||
|
* @property {float} distance The distance from the PickRay origin to the intersection point.
|
||||||
|
* @property {Vec3} surfaceNormal The normal of the surface that was intersected with.
|
||||||
|
* @property {Vec3} intersection The point at which the PickRay intersected with the overlay.
|
||||||
|
*/
|
||||||
class RayToOverlayIntersectionResult {
|
class RayToOverlayIntersectionResult {
|
||||||
public:
|
public:
|
||||||
RayToOverlayIntersectionResult();
|
RayToOverlayIntersectionResult();
|
||||||
|
@ -57,6 +65,16 @@ Q_DECLARE_METATYPE(RayToOverlayIntersectionResult);
|
||||||
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value);
|
QScriptValue RayToOverlayIntersectionResultToScriptValue(QScriptEngine* engine, const RayToOverlayIntersectionResult& value);
|
||||||
void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, RayToOverlayIntersectionResult& value);
|
void RayToOverlayIntersectionResultFromScriptValue(const QScriptValue& object, RayToOverlayIntersectionResult& value);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @typedef {int} Overlays.OverlayID
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
*
|
||||||
|
* Overlays namespace...
|
||||||
|
* @namespace Overlays
|
||||||
|
*/
|
||||||
|
|
||||||
class Overlays : public QObject {
|
class Overlays : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -72,57 +90,137 @@ public:
|
||||||
Overlay::Pointer getOverlay(unsigned int id) const;
|
Overlay::Pointer getOverlay(unsigned int id) const;
|
||||||
OverlayPanel::Pointer getPanel(unsigned int id) const { return _panels[id]; }
|
OverlayPanel::Pointer getPanel(unsigned int id) const { return _panels[id]; }
|
||||||
|
|
||||||
void cleanupAllOverlays();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
/// adds an overlay with the specific properties
|
|
||||||
unsigned int addOverlay(const QString& type, const QVariant& properties);
|
|
||||||
|
|
||||||
/// adds an overlay that's already been created
|
/// adds an overlay that's already been created
|
||||||
unsigned int addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
unsigned int addOverlay(Overlay* overlay) { return addOverlay(Overlay::Pointer(overlay)); }
|
||||||
unsigned int addOverlay(Overlay::Pointer overlay);
|
unsigned int addOverlay(Overlay::Pointer overlay);
|
||||||
|
|
||||||
/// clones an existing overlay
|
void cleanupAllOverlays();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
/**jsdoc
|
||||||
|
* Add an overlays to the scene. The properties specified will depend
|
||||||
|
* on the type of overlay that is being created.
|
||||||
|
*
|
||||||
|
* @function Overlays.addOverlay
|
||||||
|
* @param {string} type The type of the overlay to add.
|
||||||
|
* @param {Overlays.OverlayProperties} The properties of the overlay that you want to add.
|
||||||
|
* @return {Overlays.OverlayID} The ID of the newly created overlay.
|
||||||
|
*/
|
||||||
|
unsigned int addOverlay(const QString& type, const QVariant& properties);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Create a clone of an existing overlay.
|
||||||
|
*
|
||||||
|
* @function Overlays.cloneOverlay
|
||||||
|
* @param {Overlays.OverlayID} overlayID The ID of the overlay to clone.
|
||||||
|
* @return {Overlays.OverlayID} The ID of the new overlay.
|
||||||
|
*/
|
||||||
unsigned int cloneOverlay(unsigned int id);
|
unsigned int cloneOverlay(unsigned int id);
|
||||||
|
|
||||||
/// edits an overlay updating only the included properties, will return the identified OverlayID in case of
|
/**jsdoc
|
||||||
/// successful edit, if the input id is for an unknown overlay this function will have no effect
|
* Edit an overlay's properties.
|
||||||
|
*
|
||||||
|
* @function Overlays.editOverlay
|
||||||
|
* @param {Overlays.OverlayID} overlayID The ID of the overlay to edit.
|
||||||
|
* @return {bool} `true` if the overlay was found and edited, otherwise false.
|
||||||
|
*/
|
||||||
bool editOverlay(unsigned int id, const QVariant& properties);
|
bool editOverlay(unsigned int id, const QVariant& properties);
|
||||||
|
|
||||||
/// edits an overlay updating only the included properties, will return the identified OverlayID in case of
|
/// edits an overlay updating only the included properties, will return the identified OverlayID in case of
|
||||||
/// successful edit, if the input id is for an unknown overlay this function will have no effect
|
/// successful edit, if the input id is for an unknown overlay this function will have no effect
|
||||||
bool editOverlays(const QVariant& propertiesById);
|
bool editOverlays(const QVariant& propertiesById);
|
||||||
|
|
||||||
/// deletes an overlay
|
/**jsdoc
|
||||||
|
* Delete an overlay.
|
||||||
|
*
|
||||||
|
* @function Overlays.deleteOverlay
|
||||||
|
* @param {Overlays.OverlayID} overlayID The ID of the overlay to delete.
|
||||||
|
*/
|
||||||
void deleteOverlay(unsigned int id);
|
void deleteOverlay(unsigned int id);
|
||||||
|
|
||||||
/// get the string type of the overlay used in addOverlay
|
/**jsdoc
|
||||||
|
* Get the type of an overlay.
|
||||||
|
*
|
||||||
|
* @function Overlays.getOverlayType
|
||||||
|
* @param {Overlays.OverlayID} overlayID The ID of the overlay to get the type of.
|
||||||
|
* @return {string} The type of the overlay if found, otherwise the empty string.
|
||||||
|
*/
|
||||||
QString getOverlayType(unsigned int overlayId) const;
|
QString getOverlayType(unsigned int overlayId) const;
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Get the ID of the overlay at a particular point on the HUD/screen.
|
||||||
|
*
|
||||||
|
* @function Overlays.getOverlayAtPoint
|
||||||
|
* @param {Vec2} point The point to check for an overlay.
|
||||||
|
* @return {Overlays.OverlayID} The ID of the overlay at the point specified.
|
||||||
|
* If no overlay is found, `0` will be returned.
|
||||||
|
*/
|
||||||
|
unsigned int getOverlayAtPoint(const glm::vec2& point);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Get the value of a an overlay's property.
|
||||||
|
*
|
||||||
|
* @function Overlays.getProperty
|
||||||
|
* @param {Overlays.OverlayID} The ID of the overlay to get the property of.
|
||||||
|
* @param {string} The name of the property to get the value of.
|
||||||
|
* @return {Object} The value of the property. If the overlay or the property could
|
||||||
|
* not be found, `undefined` will be returned.
|
||||||
|
*/
|
||||||
|
OverlayPropertyResult getProperty(unsigned int id, const QString& property);
|
||||||
|
|
||||||
|
/*jsdoc
|
||||||
|
* Find the closest 3D overlay hit by a pick ray.
|
||||||
|
*
|
||||||
|
* @function Overlays.findRayIntersection
|
||||||
|
* @param {PickRay} The PickRay to use for finding overlays.
|
||||||
|
* @return {Overlays.RayToOverlayIntersectionResult} The result of the ray cast.
|
||||||
|
*/
|
||||||
|
RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Check whether an overlay's assets have been loaded. For example, if the
|
||||||
|
* overlay is an "image" overlay, this will indicate whether the its image
|
||||||
|
* has loaded.
|
||||||
|
* @function Overlays.isLoaded
|
||||||
|
* @param {Overlays.OverlayID} The ID of the overlay to check.
|
||||||
|
* @return {bool} `true` if the overlay's assets have been loaded, otherwise `false`.
|
||||||
|
*/
|
||||||
|
bool isLoaded(unsigned int id);
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Calculates the size of the given text in the specified overlay if it is a text overlay.
|
||||||
|
* If it is a 2D text overlay, the size will be in pixels.
|
||||||
|
* If it is a 3D text overlay, the size will be in meters.
|
||||||
|
*
|
||||||
|
* @function Overlays.textSize
|
||||||
|
* @param {Overlays.OverlayID} The ID of the overlay to measure.
|
||||||
|
* @param {string} The string to measure.
|
||||||
|
* @return {Vec2} The size of the text.
|
||||||
|
*/
|
||||||
|
QSizeF textSize(unsigned int id, const QString& text) const;
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Get the width of the virtual 2D HUD.
|
||||||
|
*
|
||||||
|
* @function Overlays.width
|
||||||
|
* @return {float} The width of the 2D HUD.
|
||||||
|
*/
|
||||||
|
float width() const;
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* Get the height of the virtual 2D HUD.
|
||||||
|
*
|
||||||
|
* @function Overlays.height
|
||||||
|
* @return {float} The height of the 2D HUD.
|
||||||
|
*/
|
||||||
|
float height() const;
|
||||||
|
|
||||||
|
/// return true if there is an overlay with that id else false
|
||||||
|
bool isAddedOverlay(unsigned int id);
|
||||||
|
|
||||||
unsigned int getParentPanel(unsigned int childId) const;
|
unsigned int getParentPanel(unsigned int childId) const;
|
||||||
void setParentPanel(unsigned int childId, unsigned int panelId);
|
void setParentPanel(unsigned int childId, unsigned int panelId);
|
||||||
|
|
||||||
/// returns the top most 2D overlay at the screen point, or 0 if not overlay at that point
|
|
||||||
unsigned int getOverlayAtPoint(const glm::vec2& point);
|
|
||||||
|
|
||||||
/// returns the value of specified property, or null if there is no such property
|
|
||||||
OverlayPropertyResult getProperty(unsigned int id, const QString& property);
|
|
||||||
|
|
||||||
/// returns details about the closest 3D Overlay hit by the pick ray
|
|
||||||
RayToOverlayIntersectionResult findRayIntersection(const PickRay& ray);
|
|
||||||
|
|
||||||
/// returns whether the overlay's assets are loaded or not
|
|
||||||
bool isLoaded(unsigned int id);
|
|
||||||
|
|
||||||
/// returns the size of the given text in the specified overlay if it is a text overlay: in pixels if it is a 2D text
|
|
||||||
/// overlay; in meters if it is a 3D text overlay
|
|
||||||
QSizeF textSize(unsigned int id, const QString& text) const;
|
|
||||||
|
|
||||||
// Return the size of the virtual screen
|
|
||||||
float width() const;
|
|
||||||
float height() const;
|
|
||||||
|
|
||||||
|
|
||||||
/// adds a panel that has already been created
|
/// adds a panel that has already been created
|
||||||
unsigned int addPanel(OverlayPanel::Pointer panel);
|
unsigned int addPanel(OverlayPanel::Pointer panel);
|
||||||
|
|
||||||
|
@ -138,13 +236,16 @@ public slots:
|
||||||
/// deletes a panel and all child overlays
|
/// deletes a panel and all child overlays
|
||||||
void deletePanel(unsigned int panelId);
|
void deletePanel(unsigned int panelId);
|
||||||
|
|
||||||
/// return true if there is an overlay with that id else false
|
|
||||||
bool isAddedOverlay(unsigned int id);
|
|
||||||
|
|
||||||
/// return true if there is a panel with that id else false
|
/// return true if there is a panel with that id else false
|
||||||
bool isAddedPanel(unsigned int id) { return _panels.contains(id); }
|
bool isAddedPanel(unsigned int id) { return _panels.contains(id); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
/**jsdoc
|
||||||
|
* Emitted when an overlay is deleted
|
||||||
|
*
|
||||||
|
* @function Overlays.overlayDeleted
|
||||||
|
* @param {OverlayID} The ID of the overlay that was deleted.
|
||||||
|
*/
|
||||||
void overlayDeleted(unsigned int id);
|
void overlayDeleted(unsigned int id);
|
||||||
void panelDeleted(unsigned int id);
|
void panelDeleted(unsigned int id);
|
||||||
|
|
||||||
|
|
|
@ -438,6 +438,7 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unhookChildAvatar(entityID);
|
||||||
emit deletingEntity(entityID);
|
emit deletingEntity(entityID);
|
||||||
|
|
||||||
// NOTE: callers must lock the tree before using this method
|
// NOTE: callers must lock the tree before using this method
|
||||||
|
@ -447,6 +448,17 @@ void EntityTree::deleteEntity(const EntityItemID& entityID, bool force, bool ign
|
||||||
_isDirty = true;
|
_isDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntityTree::unhookChildAvatar(const EntityItemID entityID) {
|
||||||
|
|
||||||
|
EntityItemPointer entity = findEntityByEntityItemID(entityID);
|
||||||
|
|
||||||
|
entity->forEachDescendant([&](SpatiallyNestablePointer child) {
|
||||||
|
if (child->getNestableType() == NestableType::Avatar) {
|
||||||
|
child->setParentID(nullptr);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool ignoreWarnings) {
|
void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool ignoreWarnings) {
|
||||||
// NOTE: callers must lock the tree before using this method
|
// NOTE: callers must lock the tree before using this method
|
||||||
DeleteEntityOperator theOperator(getThisPointer());
|
DeleteEntityOperator theOperator(getThisPointer());
|
||||||
|
@ -476,6 +488,7 @@ void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool i
|
||||||
}
|
}
|
||||||
|
|
||||||
// tell our delete operator about this entityID
|
// tell our delete operator about this entityID
|
||||||
|
unhookChildAvatar(entityID);
|
||||||
theOperator.addEntityIDToDeleteList(entityID);
|
theOperator.addEntityIDToDeleteList(entityID);
|
||||||
emit deletingEntity(entityID);
|
emit deletingEntity(entityID);
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,6 +121,8 @@ public:
|
||||||
// use this method if you have a pointer to the entity (avoid an extra entity lookup)
|
// use this method if you have a pointer to the entity (avoid an extra entity lookup)
|
||||||
bool updateEntity(EntityItemPointer entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
bool updateEntity(EntityItemPointer entity, const EntityItemProperties& properties, const SharedNodePointer& senderNode = SharedNodePointer(nullptr));
|
||||||
|
|
||||||
|
// check if the avatar is a child of this entity, If so set the avatar parentID to null
|
||||||
|
void unhookChildAvatar(const EntityItemID entityID);
|
||||||
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = true);
|
void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = true);
|
||||||
void deleteEntities(QSet<EntityItemID> entityIDs, bool force = false, bool ignoreWarnings = true);
|
void deleteEntities(QSet<EntityItemID> entityIDs, bool force = false, bool ignoreWarnings = true);
|
||||||
|
|
||||||
|
|
|
@ -83,9 +83,7 @@ public:
|
||||||
const Vec4i& region, QImage& destImage) final override;
|
const Vec4i& region, QImage& destImage) final override;
|
||||||
|
|
||||||
|
|
||||||
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
|
// this is the maximum numeber of available input buffers
|
||||||
static const int MAX_NUM_INPUT_BUFFERS = 16;
|
|
||||||
|
|
||||||
size_t getNumInputBuffers() const { return _input._invalidBuffers.size(); }
|
size_t getNumInputBuffers() const { return _input._invalidBuffers.size(); }
|
||||||
|
|
||||||
// this is the maximum per shader stage on the low end apple
|
// this is the maximum per shader stage on the low end apple
|
||||||
|
@ -147,6 +145,10 @@ public:
|
||||||
virtual void do_startNamedCall(const Batch& batch, size_t paramOffset) final;
|
virtual void do_startNamedCall(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_stopNamedCall(const Batch& batch, size_t paramOffset) final;
|
virtual void do_stopNamedCall(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
|
static const int MAX_NUM_ATTRIBUTES = Stream::NUM_INPUT_SLOTS;
|
||||||
|
// The drawcall Info attribute channel is reserved and is the upper bound for the number of availables Input buffers
|
||||||
|
static const int MAX_NUM_INPUT_BUFFERS = Stream::DRAW_CALL_INFO;
|
||||||
|
|
||||||
virtual void do_pushProfileRange(const Batch& batch, size_t paramOffset) final;
|
virtual void do_pushProfileRange(const Batch& batch, size_t paramOffset) final;
|
||||||
virtual void do_popProfileRange(const Batch& batch, size_t paramOffset) final;
|
virtual void do_popProfileRange(const Batch& batch, size_t paramOffset) final;
|
||||||
|
|
||||||
|
@ -235,18 +237,21 @@ protected:
|
||||||
virtual void initInput() final;
|
virtual void initInput() final;
|
||||||
virtual void killInput() final;
|
virtual void killInput() final;
|
||||||
virtual void syncInputStateCache() final;
|
virtual void syncInputStateCache() final;
|
||||||
virtual void resetInputStage() final;
|
virtual void resetInputStage();
|
||||||
virtual void updateInput();
|
virtual void updateInput() = 0;
|
||||||
|
|
||||||
struct InputStageState {
|
struct InputStageState {
|
||||||
bool _invalidFormat { true };
|
bool _invalidFormat { true };
|
||||||
Stream::FormatPointer _format;
|
Stream::FormatPointer _format;
|
||||||
|
std::string _formatKey;
|
||||||
|
|
||||||
typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache;
|
typedef std::bitset<MAX_NUM_ATTRIBUTES> ActivationCache;
|
||||||
ActivationCache _attributeActivation { 0 };
|
ActivationCache _attributeActivation { 0 };
|
||||||
|
|
||||||
typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState;
|
typedef std::bitset<MAX_NUM_INPUT_BUFFERS> BuffersState;
|
||||||
BuffersState _invalidBuffers { 0 };
|
|
||||||
|
BuffersState _invalidBuffers{ 0 };
|
||||||
|
BuffersState _attribBindingBuffers{ 0 };
|
||||||
|
|
||||||
Buffers _buffers;
|
Buffers _buffers;
|
||||||
Offsets _bufferOffsets;
|
Offsets _bufferOffsets;
|
||||||
|
@ -266,7 +271,11 @@ protected:
|
||||||
GLuint _defaultVAO { 0 };
|
GLuint _defaultVAO { 0 };
|
||||||
|
|
||||||
InputStageState() :
|
InputStageState() :
|
||||||
_buffers(_invalidBuffers.size()),
|
_invalidFormat(true),
|
||||||
|
_format(0),
|
||||||
|
_formatKey(),
|
||||||
|
_attributeActivation(0),
|
||||||
|
_buffers(_invalidBuffers.size(), BufferPointer(0)),
|
||||||
_bufferOffsets(_invalidBuffers.size(), 0),
|
_bufferOffsets(_invalidBuffers.size(), 0),
|
||||||
_bufferStrides(_invalidBuffers.size(), 0),
|
_bufferStrides(_invalidBuffers.size(), 0),
|
||||||
_bufferVBOs(_invalidBuffers.size(), 0) {}
|
_bufferVBOs(_invalidBuffers.size(), 0) {}
|
||||||
|
@ -276,8 +285,8 @@ protected:
|
||||||
void killTransform();
|
void killTransform();
|
||||||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||||
void syncTransformStateCache();
|
void syncTransformStateCache();
|
||||||
void updateTransform(const Batch& batch);
|
virtual void updateTransform(const Batch& batch) = 0;
|
||||||
void resetTransformStage();
|
virtual void resetTransformStage();
|
||||||
|
|
||||||
// Allows for correction of the camera pose to account for changes
|
// Allows for correction of the camera pose to account for changes
|
||||||
// between the time when a was recorded and the time(s) when it is
|
// between the time when a was recorded and the time(s) when it is
|
||||||
|
@ -325,6 +334,8 @@ protected:
|
||||||
bool _invalidProj { false };
|
bool _invalidProj { false };
|
||||||
bool _invalidViewport { false };
|
bool _invalidViewport { false };
|
||||||
|
|
||||||
|
bool _enabledDrawcallInfoBuffer{ false };
|
||||||
|
|
||||||
using Pair = std::pair<size_t, size_t>;
|
using Pair = std::pair<size_t, size_t>;
|
||||||
using List = std::list<Pair>;
|
using List = std::list<Pair>;
|
||||||
List _cameraOffsets;
|
List _cameraOffsets;
|
||||||
|
@ -399,8 +410,8 @@ protected:
|
||||||
|
|
||||||
void resetQueryStage();
|
void resetQueryStage();
|
||||||
struct QueryStageState {
|
struct QueryStageState {
|
||||||
|
uint32_t _rangeQueryDepth { 0 };
|
||||||
};
|
} _queryStage;
|
||||||
|
|
||||||
void resetStages();
|
void resetStages();
|
||||||
|
|
||||||
|
|
|
@ -10,16 +10,26 @@
|
||||||
//
|
//
|
||||||
#include "GLBackend.h"
|
#include "GLBackend.h"
|
||||||
#include "GLShared.h"
|
#include "GLShared.h"
|
||||||
|
#include "GLInputFormat.h"
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
using namespace gpu::gl;
|
using namespace gpu::gl;
|
||||||
|
|
||||||
void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_setInputFormat(const Batch& batch, size_t paramOffset) {
|
||||||
Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint);
|
Stream::FormatPointer format = batch._streamFormats.get(batch._params[paramOffset]._uint);
|
||||||
|
|
||||||
if (format != _input._format) {
|
if (format != _input._format) {
|
||||||
_input._format = format;
|
_input._format = format;
|
||||||
_input._invalidFormat = true;
|
if (format) {
|
||||||
|
auto inputFormat = GLInputFormat::sync((*format));
|
||||||
|
assert(inputFormat);
|
||||||
|
if (_input._formatKey != inputFormat->key) {
|
||||||
|
_input._formatKey = inputFormat->key;
|
||||||
|
_input._invalidFormat = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_input._formatKey.clear();
|
||||||
|
_input._invalidFormat = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,16 +103,9 @@ void GLBackend::resetInputStage() {
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
(void) CHECK_GL_ERROR();
|
(void) CHECK_GL_ERROR();
|
||||||
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
||||||
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) {
|
|
||||||
glDisableVertexAttribArray(i);
|
|
||||||
glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset vertex buffer and format
|
// Reset vertex buffer and format
|
||||||
_input._format.reset();
|
_input._format.reset();
|
||||||
|
_input._formatKey.clear();
|
||||||
_input._invalidFormat = false;
|
_input._invalidFormat = false;
|
||||||
_input._attributeActivation.reset();
|
_input._attributeActivation.reset();
|
||||||
|
|
||||||
|
@ -114,6 +117,7 @@ void GLBackend::resetInputStage() {
|
||||||
}
|
}
|
||||||
_input._invalidBuffers.reset();
|
_input._invalidBuffers.reset();
|
||||||
|
|
||||||
|
// THe vertex array binding MUST be reset in the specific Backend versions as they use different techniques
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::do_setIndexBuffer(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_setIndexBuffer(const Batch& batch, size_t paramOffset) {
|
||||||
|
@ -151,183 +155,3 @@ void GLBackend::do_setIndirectBuffer(const Batch& batch, size_t paramOffset) {
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Core 41 doesn't expose the features to really separate the vertex format from the vertex buffers binding
|
|
||||||
// Core 43 does :)
|
|
||||||
// FIXME crashing problem with glVertexBindingDivisor / glVertexAttribFormat
|
|
||||||
// Once resolved, break this up into the GL 4.1 and 4.5 backends
|
|
||||||
#if 1 || (GPU_INPUT_PROFILE == GPU_CORE_41)
|
|
||||||
#define NO_SUPPORT_VERTEX_ATTRIB_FORMAT
|
|
||||||
#else
|
|
||||||
#define SUPPORT_VERTEX_ATTRIB_FORMAT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void GLBackend::updateInput() {
|
|
||||||
#if defined(SUPPORT_VERTEX_ATTRIB_FORMAT)
|
|
||||||
if (_input._invalidFormat) {
|
|
||||||
|
|
||||||
InputStageState::ActivationCache newActivation;
|
|
||||||
|
|
||||||
// Assign the vertex format required
|
|
||||||
if (_input._format) {
|
|
||||||
for (auto& it : _input._format->getAttributes()) {
|
|
||||||
const Stream::Attribute& attrib = (it).second;
|
|
||||||
|
|
||||||
GLuint slot = attrib._slot;
|
|
||||||
GLuint count = attrib._element.getLocationScalarCount();
|
|
||||||
uint8_t locationCount = attrib._element.getLocationCount();
|
|
||||||
GLenum type = _elementTypeToGL41Type[attrib._element.getType()];
|
|
||||||
GLuint offset = attrib._offset;;
|
|
||||||
GLboolean isNormalized = attrib._element.isNormalized();
|
|
||||||
|
|
||||||
GLenum perLocationSize = attrib._element.getLocationSize();
|
|
||||||
|
|
||||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
|
||||||
newActivation.set(slot + locNum);
|
|
||||||
glVertexAttribFormat(slot + locNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
|
||||||
glVertexAttribBinding(slot + locNum, attrib._channel);
|
|
||||||
}
|
|
||||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
|
||||||
glVertexBindingDivisor(attrib._channel, attrib._frequency * (isStereo() ? 2 : 1));
|
|
||||||
#else
|
|
||||||
glVertexBindingDivisor(attrib._channel, attrib._frequency);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manage Activation what was and what is expected now
|
|
||||||
for (size_t i = 0; i < newActivation.size(); i++) {
|
|
||||||
bool newState = newActivation[i];
|
|
||||||
if (newState != _input._attributeActivation[i]) {
|
|
||||||
if (newState) {
|
|
||||||
glEnableVertexAttribArray(i);
|
|
||||||
} else {
|
|
||||||
glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
_input._attributeActivation.flip(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
|
|
||||||
_input._invalidFormat = false;
|
|
||||||
_stats._ISNumFormatChanges++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_input._invalidBuffers.any()) {
|
|
||||||
int numBuffers = _input._buffers.size();
|
|
||||||
auto buffer = _input._buffers.data();
|
|
||||||
auto vbo = _input._bufferVBOs.data();
|
|
||||||
auto offset = _input._bufferOffsets.data();
|
|
||||||
auto stride = _input._bufferStrides.data();
|
|
||||||
|
|
||||||
for (int bufferNum = 0; bufferNum < numBuffers; bufferNum++) {
|
|
||||||
if (_input._invalidBuffers.test(bufferNum)) {
|
|
||||||
glBindVertexBuffer(bufferNum, (*vbo), (*offset), (*stride));
|
|
||||||
}
|
|
||||||
buffer++;
|
|
||||||
vbo++;
|
|
||||||
offset++;
|
|
||||||
stride++;
|
|
||||||
}
|
|
||||||
_input._invalidBuffers.reset();
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
|
||||||
|
|
||||||
if (_input._invalidFormat) {
|
|
||||||
InputStageState::ActivationCache newActivation;
|
|
||||||
|
|
||||||
_stats._ISNumFormatChanges++;
|
|
||||||
|
|
||||||
// Check expected activation
|
|
||||||
if (_input._format) {
|
|
||||||
for (auto& it : _input._format->getAttributes()) {
|
|
||||||
const Stream::Attribute& attrib = (it).second;
|
|
||||||
uint8_t locationCount = attrib._element.getLocationCount();
|
|
||||||
for (int i = 0; i < locationCount; ++i) {
|
|
||||||
newActivation.set(attrib._slot + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Manage Activation what was and what is expected now
|
|
||||||
for (unsigned int i = 0; i < newActivation.size(); i++) {
|
|
||||||
bool newState = newActivation[i];
|
|
||||||
if (newState != _input._attributeActivation[i]) {
|
|
||||||
|
|
||||||
if (newState) {
|
|
||||||
glEnableVertexAttribArray(i);
|
|
||||||
} else {
|
|
||||||
glDisableVertexAttribArray(i);
|
|
||||||
}
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
|
|
||||||
_input._attributeActivation.flip(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now we need to bind the buffers and assign the attrib pointers
|
|
||||||
if (_input._format) {
|
|
||||||
const Buffers& buffers = _input._buffers;
|
|
||||||
const Offsets& offsets = _input._bufferOffsets;
|
|
||||||
const Offsets& strides = _input._bufferStrides;
|
|
||||||
|
|
||||||
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
|
||||||
auto& inputChannels = _input._format->getChannels();
|
|
||||||
_stats._ISNumInputBufferChanges++;
|
|
||||||
|
|
||||||
GLuint boundVBO = 0;
|
|
||||||
for (auto& channelIt : inputChannels) {
|
|
||||||
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;
|
|
||||||
if ((channelIt).first < buffers.size()) {
|
|
||||||
int bufferNum = (channelIt).first;
|
|
||||||
|
|
||||||
if (_input._invalidBuffers.test(bufferNum) || _input._invalidFormat) {
|
|
||||||
// GLuint vbo = gpu::GL41Backend::getBufferID((*buffers[bufferNum]));
|
|
||||||
GLuint vbo = _input._bufferVBOs[bufferNum];
|
|
||||||
if (boundVBO != vbo) {
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
boundVBO = vbo;
|
|
||||||
}
|
|
||||||
_input._invalidBuffers[bufferNum] = false;
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < channel._slots.size(); i++) {
|
|
||||||
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
|
|
||||||
GLuint slot = attrib._slot;
|
|
||||||
GLuint count = attrib._element.getLocationScalarCount();
|
|
||||||
uint8_t locationCount = attrib._element.getLocationCount();
|
|
||||||
GLenum type = gl::ELEMENT_TYPE_TO_GL[attrib._element.getType()];
|
|
||||||
// GLenum perLocationStride = strides[bufferNum];
|
|
||||||
GLenum perLocationStride = attrib._element.getLocationSize();
|
|
||||||
GLuint stride = (GLuint)strides[bufferNum];
|
|
||||||
GLuint pointer = (GLuint)(attrib._offset + offsets[bufferNum]);
|
|
||||||
GLboolean isNormalized = attrib._element.isNormalized();
|
|
||||||
|
|
||||||
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
|
||||||
glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride,
|
|
||||||
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
|
||||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
|
||||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1));
|
|
||||||
#else
|
|
||||||
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Support properly the IAttrib version
|
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// everything format related should be in sync now
|
|
||||||
_input._invalidFormat = false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,10 @@ using namespace gpu::gl;
|
||||||
|
|
||||||
// Eventually, we want to test with TIME_ELAPSED instead of TIMESTAMP
|
// Eventually, we want to test with TIME_ELAPSED instead of TIMESTAMP
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
|
const uint32_t MAX_RANGE_QUERY_DEPTH = 1;
|
||||||
static bool timeElapsed = true;
|
static bool timeElapsed = true;
|
||||||
#else
|
#else
|
||||||
|
const uint32_t MAX_RANGE_QUERY_DEPTH = 10000;
|
||||||
static bool timeElapsed = false;
|
static bool timeElapsed = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -27,12 +29,17 @@ void GLBackend::do_beginQuery(const Batch& batch, size_t paramOffset) {
|
||||||
if (glquery) {
|
if (glquery) {
|
||||||
PROFILE_RANGE_BEGIN(glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00);
|
PROFILE_RANGE_BEGIN(glquery->_profileRangeId, query->getName().c_str(), 0xFFFF7F00);
|
||||||
|
|
||||||
glquery->_batchElapsedTime = usecTimestampNow() * 1000;
|
++_queryStage._rangeQueryDepth;
|
||||||
|
glGetInteger64v(GL_TIMESTAMP, (GLint64*)&glquery->_batchElapsedTime);
|
||||||
|
|
||||||
if (timeElapsed) {
|
if (timeElapsed) {
|
||||||
glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo);
|
if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) {
|
||||||
|
glBeginQuery(GL_TIME_ELAPSED, glquery->_endqo);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
glQueryCounter(glquery->_beginqo, GL_TIMESTAMP);
|
glQueryCounter(glquery->_beginqo, GL_TIMESTAMP);
|
||||||
}
|
}
|
||||||
|
glquery->_rangeQueryDepth = _queryStage._rangeQueryDepth;
|
||||||
(void)CHECK_GL_ERROR();
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,12 +49,16 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) {
|
||||||
GLQuery* glquery = syncGPUObject(*query);
|
GLQuery* glquery = syncGPUObject(*query);
|
||||||
if (glquery) {
|
if (glquery) {
|
||||||
if (timeElapsed) {
|
if (timeElapsed) {
|
||||||
glEndQuery(GL_TIME_ELAPSED);
|
if (_queryStage._rangeQueryDepth <= MAX_RANGE_QUERY_DEPTH) {
|
||||||
|
glEndQuery(GL_TIME_ELAPSED);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
glQueryCounter(glquery->_endqo, GL_TIMESTAMP);
|
glQueryCounter(glquery->_endqo, GL_TIMESTAMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLint64 now = usecTimestampNow() * 1000;
|
--_queryStage._rangeQueryDepth;
|
||||||
|
GLint64 now;
|
||||||
|
glGetInteger64v(GL_TIMESTAMP, &now);
|
||||||
glquery->_batchElapsedTime = now - glquery->_batchElapsedTime;
|
glquery->_batchElapsedTime = now - glquery->_batchElapsedTime;
|
||||||
|
|
||||||
PROFILE_RANGE_END(glquery->_profileRangeId);
|
PROFILE_RANGE_END(glquery->_profileRangeId);
|
||||||
|
@ -59,20 +70,24 @@ void GLBackend::do_endQuery(const Batch& batch, size_t paramOffset) {
|
||||||
void GLBackend::do_getQuery(const Batch& batch, size_t paramOffset) {
|
void GLBackend::do_getQuery(const Batch& batch, size_t paramOffset) {
|
||||||
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
auto query = batch._queries.get(batch._params[paramOffset]._uint);
|
||||||
GLQuery* glquery = syncGPUObject(*query);
|
GLQuery* glquery = syncGPUObject(*query);
|
||||||
if (glquery) {
|
if (glquery) {
|
||||||
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT_AVAILABLE, &glquery->_result);
|
if (glquery->_rangeQueryDepth > MAX_RANGE_QUERY_DEPTH) {
|
||||||
if (glquery->_result == GL_TRUE) {
|
|
||||||
if (timeElapsed) {
|
|
||||||
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &glquery->_result);
|
|
||||||
} else {
|
|
||||||
GLuint64 start, end;
|
|
||||||
glGetQueryObjectui64v(glquery->_beginqo, GL_QUERY_RESULT, &start);
|
|
||||||
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &end);
|
|
||||||
glquery->_result = end - start;
|
|
||||||
}
|
|
||||||
query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime);
|
query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime);
|
||||||
|
} else {
|
||||||
|
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT_AVAILABLE, &glquery->_result);
|
||||||
|
if (glquery->_result == GL_TRUE) {
|
||||||
|
if (timeElapsed) {
|
||||||
|
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &glquery->_result);
|
||||||
|
} else {
|
||||||
|
GLuint64 start, end;
|
||||||
|
glGetQueryObjectui64v(glquery->_beginqo, GL_QUERY_RESULT, &start);
|
||||||
|
glGetQueryObjectui64v(glquery->_endqo, GL_QUERY_RESULT, &end);
|
||||||
|
glquery->_result = end - start;
|
||||||
|
}
|
||||||
|
query->triggerReturnHandler(glquery->_result, glquery->_batchElapsedTime);
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
}
|
}
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,9 @@ void GLBackend::syncTransformStateCache() {
|
||||||
Mat4 modelView;
|
Mat4 modelView;
|
||||||
auto modelViewInv = glm::inverse(modelView);
|
auto modelViewInv = glm::inverse(modelView);
|
||||||
_transform._view.evalFromRawMatrix(modelViewInv);
|
_transform._view.evalFromRawMatrix(modelViewInv);
|
||||||
|
|
||||||
|
glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO);
|
||||||
|
_transform._enabledDrawcallInfoBuffer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) {
|
void GLBackend::TransformStageState::preUpdate(size_t commandIndex, const StereoState& stereo) {
|
||||||
|
@ -162,29 +165,7 @@ void GLBackend::TransformStageState::bindCurrentCamera(int eye) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLBackend::updateTransform(const Batch& batch) {
|
|
||||||
_transform.update(_commandIndex, _stereo);
|
|
||||||
|
|
||||||
auto& drawCallInfoBuffer = batch.getDrawCallInfoBuffer();
|
|
||||||
if (batch._currentNamedCall.empty()) {
|
|
||||||
auto& drawCallInfo = drawCallInfoBuffer[_currentDraw];
|
|
||||||
glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is disabled
|
|
||||||
glVertexAttribI2i(gpu::Stream::DRAW_CALL_INFO, drawCallInfo.index, drawCallInfo.unused);
|
|
||||||
} else {
|
|
||||||
glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled
|
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer);
|
|
||||||
glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0,
|
|
||||||
_transform._drawCallInfoOffsets[batch._currentNamedCall]);
|
|
||||||
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
|
||||||
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1));
|
|
||||||
#else
|
|
||||||
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
(void)CHECK_GL_ERROR();
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLBackend::resetTransformStage() {
|
void GLBackend::resetTransformStage() {
|
||||||
|
glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO);
|
||||||
|
_transform._enabledDrawcallInfoBuffer = false;
|
||||||
}
|
}
|
||||||
|
|
33
libraries/gpu-gl/src/gpu/gl/GLInputFormat.cpp
Normal file
33
libraries/gpu-gl/src/gpu/gl/GLInputFormat.cpp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 2016/07/21
|
||||||
|
// Copyright 2013-2016 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 "GLInputFormat.h"
|
||||||
|
#include "GLBackend.h"
|
||||||
|
|
||||||
|
using namespace gpu;
|
||||||
|
using namespace gpu::gl;
|
||||||
|
|
||||||
|
|
||||||
|
GLInputFormat::GLInputFormat() {
|
||||||
|
}
|
||||||
|
|
||||||
|
GLInputFormat:: ~GLInputFormat() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GLInputFormat* GLInputFormat::sync(const Stream::Format& inputFormat) {
|
||||||
|
GLInputFormat* object = Backend::getGPUObject<GLInputFormat>(inputFormat);
|
||||||
|
|
||||||
|
if (!object) {
|
||||||
|
object = new GLInputFormat();
|
||||||
|
object->key = inputFormat.getKey();
|
||||||
|
Backend::setGPUObject(inputFormat, object);
|
||||||
|
}
|
||||||
|
|
||||||
|
return object;
|
||||||
|
}
|
29
libraries/gpu-gl/src/gpu/gl/GLInputFormat.h
Normal file
29
libraries/gpu-gl/src/gpu/gl/GLInputFormat.h
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
//
|
||||||
|
// Created by Sam Gateau on 2016/07/21
|
||||||
|
// Copyright 2013-2016 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
|
||||||
|
//
|
||||||
|
#ifndef hifi_gpu_gl_GLInputFormat_h
|
||||||
|
#define hifi_gpu_gl_GLInputFormat_h
|
||||||
|
|
||||||
|
#include "GLShared.h"
|
||||||
|
|
||||||
|
namespace gpu {
|
||||||
|
namespace gl {
|
||||||
|
|
||||||
|
class GLInputFormat : public GPUObject {
|
||||||
|
public:
|
||||||
|
static GLInputFormat* sync(const Stream::Format& inputFormat);
|
||||||
|
|
||||||
|
GLInputFormat();
|
||||||
|
~GLInputFormat();
|
||||||
|
|
||||||
|
std::string key;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -50,6 +50,7 @@ public:
|
||||||
GLuint64 _result { (GLuint64)-1 };
|
GLuint64 _result { (GLuint64)-1 };
|
||||||
GLuint64 _batchElapsedTime { (GLuint64) 0 };
|
GLuint64 _batchElapsedTime { (GLuint64) 0 };
|
||||||
uint64_t _profileRangeId { 0 };
|
uint64_t _profileRangeId { 0 };
|
||||||
|
uint32_t _rangeQueryDepth { 0 };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GLQuery(const std::weak_ptr<GLBackend>& backend, const Query& query, GLuint endId, GLuint beginId) : Parent(backend, query, endId), _beginqo(beginId) {}
|
GLQuery(const std::weak_ptr<GLBackend>& backend, const Query& query, GLuint endId, GLuint beginId) : Parent(backend, query, endId), _beginqo(beginId) {}
|
||||||
|
|
|
@ -77,13 +77,13 @@ protected:
|
||||||
void do_multiDrawIndexedIndirect(const Batch& batch, size_t paramOffset) override;
|
void do_multiDrawIndexedIndirect(const Batch& batch, size_t paramOffset) override;
|
||||||
|
|
||||||
// Input Stage
|
// Input Stage
|
||||||
|
void resetInputStage() override;
|
||||||
void updateInput() override;
|
void updateInput() override;
|
||||||
|
|
||||||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||||
void transferTransformState(const Batch& batch) const override;
|
void transferTransformState(const Batch& batch) const override;
|
||||||
void initTransform() override;
|
void initTransform() override;
|
||||||
void updateTransform(const Batch& batch);
|
void updateTransform(const Batch& batch) override;
|
||||||
void resetTransformStage();
|
|
||||||
|
|
||||||
// Output stage
|
// Output stage
|
||||||
void do_blit(const Batch& batch, size_t paramOffset) override;
|
void do_blit(const Batch& batch, size_t paramOffset) override;
|
||||||
|
|
|
@ -13,7 +13,111 @@
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
using namespace gpu::gl41;
|
using namespace gpu::gl41;
|
||||||
|
|
||||||
void GL41Backend::updateInput() {
|
|
||||||
Parent::updateInput();
|
void GL41Backend::resetInputStage() {
|
||||||
|
Parent::resetInputStage();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) {
|
||||||
|
glDisableVertexAttribArray(i);
|
||||||
|
glVertexAttribPointer(i, 4, GL_FLOAT, GL_FALSE, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL41Backend::updateInput() {
|
||||||
|
if (_input._invalidFormat || _input._invalidBuffers.any()) {
|
||||||
|
|
||||||
|
if (_input._invalidFormat) {
|
||||||
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
_stats._ISNumFormatChanges++;
|
||||||
|
|
||||||
|
// Check expected activation
|
||||||
|
if (_input._format) {
|
||||||
|
for (auto& it : _input._format->getAttributes()) {
|
||||||
|
const Stream::Attribute& attrib = (it).second;
|
||||||
|
uint8_t locationCount = attrib._element.getLocationCount();
|
||||||
|
for (int i = 0; i < locationCount; ++i) {
|
||||||
|
newActivation.set(attrib._slot + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage Activation what was and what is expected now
|
||||||
|
for (unsigned int i = 0; i < newActivation.size(); i++) {
|
||||||
|
bool newState = newActivation[i];
|
||||||
|
if (newState != _input._attributeActivation[i]) {
|
||||||
|
|
||||||
|
if (newState) {
|
||||||
|
glEnableVertexAttribArray(i);
|
||||||
|
} else {
|
||||||
|
glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
|
||||||
|
_input._attributeActivation.flip(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// now we need to bind the buffers and assign the attrib pointers
|
||||||
|
if (_input._format) {
|
||||||
|
const Buffers& buffers = _input._buffers;
|
||||||
|
const Offsets& offsets = _input._bufferOffsets;
|
||||||
|
const Offsets& strides = _input._bufferStrides;
|
||||||
|
|
||||||
|
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
||||||
|
auto& inputChannels = _input._format->getChannels();
|
||||||
|
_stats._ISNumInputBufferChanges++;
|
||||||
|
|
||||||
|
GLuint boundVBO = 0;
|
||||||
|
for (auto& channelIt : inputChannels) {
|
||||||
|
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;
|
||||||
|
if ((channelIt).first < buffers.size()) {
|
||||||
|
int bufferNum = (channelIt).first;
|
||||||
|
|
||||||
|
if (_input._invalidBuffers.test(bufferNum) || _input._invalidFormat) {
|
||||||
|
// GLuint vbo = gpu::GL41Backend::getBufferID((*buffers[bufferNum]));
|
||||||
|
GLuint vbo = _input._bufferVBOs[bufferNum];
|
||||||
|
if (boundVBO != vbo) {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
boundVBO = vbo;
|
||||||
|
}
|
||||||
|
_input._invalidBuffers[bufferNum] = false;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < channel._slots.size(); i++) {
|
||||||
|
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
|
||||||
|
GLuint slot = attrib._slot;
|
||||||
|
GLuint count = attrib._element.getLocationScalarCount();
|
||||||
|
uint8_t locationCount = attrib._element.getLocationCount();
|
||||||
|
GLenum type = gl::ELEMENT_TYPE_TO_GL[attrib._element.getType()];
|
||||||
|
// GLenum perLocationStride = strides[bufferNum];
|
||||||
|
GLenum perLocationStride = attrib._element.getLocationSize();
|
||||||
|
GLuint stride = (GLuint)strides[bufferNum];
|
||||||
|
GLuint pointer = (GLuint)(attrib._offset + offsets[bufferNum]);
|
||||||
|
GLboolean isNormalized = attrib._element.isNormalized();
|
||||||
|
|
||||||
|
for (size_t locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
|
glVertexAttribPointer(slot + (GLuint)locNum, count, type, isNormalized, stride,
|
||||||
|
reinterpret_cast<GLvoid*>(pointer + perLocationStride * (GLuint)locNum));
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency * (isStereo() ? 2 : 1));
|
||||||
|
#else
|
||||||
|
glVertexAttribDivisor(slot + (GLuint)locNum, attrib._frequency);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Support properly the IAttrib version
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// everything format related should be in sync now
|
||||||
|
_input._invalidFormat = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,3 +79,32 @@ void GL41Backend::transferTransformState(const Batch& batch) const {
|
||||||
// Make sure the current Camera offset is unknown before render Draw
|
// Make sure the current Camera offset is unknown before render Draw
|
||||||
_transform._currentCameraOffset = INVALID_OFFSET;
|
_transform._currentCameraOffset = INVALID_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GL41Backend::updateTransform(const Batch& batch) {
|
||||||
|
_transform.update(_commandIndex, _stereo);
|
||||||
|
|
||||||
|
auto& drawCallInfoBuffer = batch.getDrawCallInfoBuffer();
|
||||||
|
if (batch._currentNamedCall.empty()) {
|
||||||
|
auto& drawCallInfo = drawCallInfoBuffer[_currentDraw];
|
||||||
|
if (_transform._enabledDrawcallInfoBuffer) {
|
||||||
|
glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is disabled
|
||||||
|
_transform._enabledDrawcallInfoBuffer = false;
|
||||||
|
}
|
||||||
|
glVertexAttribI2i(gpu::Stream::DRAW_CALL_INFO, drawCallInfo.index, drawCallInfo.unused);
|
||||||
|
} else {
|
||||||
|
if (!_transform._enabledDrawcallInfoBuffer) {
|
||||||
|
glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, _transform._drawCallInfoBuffer);
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1));
|
||||||
|
#else
|
||||||
|
glVertexAttribDivisor(gpu::Stream::DRAW_CALL_INFO, 1);
|
||||||
|
#endif
|
||||||
|
_transform._enabledDrawcallInfoBuffer = true;
|
||||||
|
}
|
||||||
|
glVertexAttribIPointer(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0, _transform._drawCallInfoOffsets[batch._currentNamedCall]);
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
|
@ -130,13 +130,13 @@ protected:
|
||||||
void do_multiDrawIndexedIndirect(const Batch& batch, size_t paramOffset) override;
|
void do_multiDrawIndexedIndirect(const Batch& batch, size_t paramOffset) override;
|
||||||
|
|
||||||
// Input Stage
|
// Input Stage
|
||||||
|
void resetInputStage() override;
|
||||||
void updateInput() override;
|
void updateInput() override;
|
||||||
|
|
||||||
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
// Synchronize the state cache of this Backend with the actual real state of the GL Context
|
||||||
void transferTransformState(const Batch& batch) const override;
|
void transferTransformState(const Batch& batch) const override;
|
||||||
void initTransform() override;
|
void initTransform() override;
|
||||||
void updateTransform(const Batch& batch);
|
void updateTransform(const Batch& batch) override;
|
||||||
void resetTransformStage();
|
|
||||||
|
|
||||||
// Output stage
|
// Output stage
|
||||||
void do_blit(const Batch& batch, size_t paramOffset) override;
|
void do_blit(const Batch& batch, size_t paramOffset) override;
|
||||||
|
|
|
@ -9,10 +9,112 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
#include "GL45Backend.h"
|
#include "GL45Backend.h"
|
||||||
|
#include "../gl/GLShared.h"
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
using namespace gpu::gl45;
|
using namespace gpu::gl45;
|
||||||
|
|
||||||
void GL45Backend::updateInput() {
|
void GL45Backend::resetInputStage() {
|
||||||
Parent::updateInput();
|
Parent::resetInputStage();
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
for (uint32_t i = 0; i < _input._attributeActivation.size(); i++) {
|
||||||
|
glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
for (uint32_t i = 0; i < _input._attribBindingBuffers.size(); i++) {
|
||||||
|
glBindVertexBuffer(i, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GL45Backend::updateInput() {
|
||||||
|
if (_input._invalidFormat) {
|
||||||
|
InputStageState::ActivationCache newActivation;
|
||||||
|
|
||||||
|
// Assign the vertex format required
|
||||||
|
if (_input._format) {
|
||||||
|
_input._attribBindingBuffers.reset();
|
||||||
|
|
||||||
|
const Stream::Format::AttributeMap& attributes = _input._format->getAttributes();
|
||||||
|
auto& inputChannels = _input._format->getChannels();
|
||||||
|
for (auto& channelIt : inputChannels) {
|
||||||
|
auto bufferChannelNum = (channelIt).first;
|
||||||
|
const Stream::Format::ChannelMap::value_type::second_type& channel = (channelIt).second;
|
||||||
|
_input._attribBindingBuffers.set(bufferChannelNum);
|
||||||
|
|
||||||
|
GLuint frequency = 0;
|
||||||
|
for (unsigned int i = 0; i < channel._slots.size(); i++) {
|
||||||
|
const Stream::Attribute& attrib = attributes.at(channel._slots[i]);
|
||||||
|
|
||||||
|
GLuint slot = attrib._slot;
|
||||||
|
GLuint count = attrib._element.getLocationScalarCount();
|
||||||
|
uint8_t locationCount = attrib._element.getLocationCount();
|
||||||
|
GLenum type = gl::ELEMENT_TYPE_TO_GL[attrib._element.getType()];
|
||||||
|
|
||||||
|
GLuint offset = (GLuint)attrib._offset;;
|
||||||
|
GLboolean isNormalized = attrib._element.isNormalized();
|
||||||
|
|
||||||
|
GLenum perLocationSize = attrib._element.getLocationSize();
|
||||||
|
for (GLuint locNum = 0; locNum < locationCount; ++locNum) {
|
||||||
|
GLuint attriNum = (GLuint)(slot + locNum);
|
||||||
|
newActivation.set(attriNum);
|
||||||
|
if (!_input._attributeActivation[attriNum]) {
|
||||||
|
_input._attributeActivation.set(attriNum);
|
||||||
|
glEnableVertexAttribArray(attriNum);
|
||||||
|
}
|
||||||
|
glVertexAttribFormat(attriNum, count, type, isNormalized, offset + locNum * perLocationSize);
|
||||||
|
// TODO: Support properly the IAttrib version
|
||||||
|
glVertexAttribBinding(attriNum, attrib._channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
frequency = attrib._frequency;
|
||||||
|
} else {
|
||||||
|
assert(frequency == attrib._frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glVertexBindingDivisor(bufferChannelNum, frequency * (isStereo() ? 2 : 1));
|
||||||
|
#else
|
||||||
|
glVertexBindingDivisor(bufferChannelNum, frequency);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Manage Activation what was and what is expected now
|
||||||
|
// This should only disable VertexAttribs since the one in use have been disabled above
|
||||||
|
for (GLuint i = 0; i < (GLuint)newActivation.size(); i++) {
|
||||||
|
bool newState = newActivation[i];
|
||||||
|
if (newState != _input._attributeActivation[i]) {
|
||||||
|
if (newState) {
|
||||||
|
glEnableVertexAttribArray(i);
|
||||||
|
} else {
|
||||||
|
glDisableVertexAttribArray(i);
|
||||||
|
}
|
||||||
|
_input._attributeActivation.flip(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
|
|
||||||
|
_input._invalidFormat = false;
|
||||||
|
_stats._ISNumFormatChanges++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_input._invalidBuffers.any()) {
|
||||||
|
auto vbo = _input._bufferVBOs.data();
|
||||||
|
auto offset = _input._bufferOffsets.data();
|
||||||
|
auto stride = _input._bufferStrides.data();
|
||||||
|
|
||||||
|
for (GLuint buffer = 0; buffer < _input._buffers.size(); buffer++, vbo++, offset++, stride++) {
|
||||||
|
if (_input._invalidBuffers.test(buffer)) {
|
||||||
|
glBindVertexBuffer(buffer, (*vbo), (*offset), (GLsizei)(*stride));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_input._invalidBuffers.reset();
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,3 +66,36 @@ void GL45Backend::transferTransformState(const Batch& batch) const {
|
||||||
// Make sure the current Camera offset is unknown before render Draw
|
// Make sure the current Camera offset is unknown before render Draw
|
||||||
_transform._currentCameraOffset = INVALID_OFFSET;
|
_transform._currentCameraOffset = INVALID_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GL45Backend::updateTransform(const Batch& batch) {
|
||||||
|
_transform.update(_commandIndex, _stereo);
|
||||||
|
|
||||||
|
auto& drawCallInfoBuffer = batch.getDrawCallInfoBuffer();
|
||||||
|
if (batch._currentNamedCall.empty()) {
|
||||||
|
auto& drawCallInfo = drawCallInfoBuffer[_currentDraw];
|
||||||
|
if (_transform._enabledDrawcallInfoBuffer) {
|
||||||
|
glDisableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is disabled
|
||||||
|
_transform._enabledDrawcallInfoBuffer = false;
|
||||||
|
}
|
||||||
|
glVertexAttribI2i(gpu::Stream::DRAW_CALL_INFO, drawCallInfo.index, drawCallInfo.unused);
|
||||||
|
} else {
|
||||||
|
if (!_transform._enabledDrawcallInfoBuffer) {
|
||||||
|
glEnableVertexAttribArray(gpu::Stream::DRAW_CALL_INFO); // Make sure attrib array is enabled
|
||||||
|
glVertexAttribIFormat(gpu::Stream::DRAW_CALL_INFO, 2, GL_UNSIGNED_SHORT, 0);
|
||||||
|
glVertexAttribBinding(gpu::Stream::DRAW_CALL_INFO, gpu::Stream::DRAW_CALL_INFO);
|
||||||
|
#ifdef GPU_STEREO_DRAWCALL_INSTANCED
|
||||||
|
glVertexBindingDivisor(gpu::Stream::DRAW_CALL_INFO, (isStereo() ? 2 : 1));
|
||||||
|
#else
|
||||||
|
glVertexBindingDivisor(gpu::Stream::DRAW_CALL_INFO, 1);
|
||||||
|
#endif
|
||||||
|
_transform._enabledDrawcallInfoBuffer = true;
|
||||||
|
}
|
||||||
|
// NOTE: A stride of zero in BindVertexBuffer signifies that all elements are sourced from the same location,
|
||||||
|
// so we must provide a stride.
|
||||||
|
// This is in contrast to VertexAttrib*Pointer, where a zero signifies tightly-packed elements.
|
||||||
|
glBindVertexBuffer(gpu::Stream::DRAW_CALL_INFO, _transform._drawCallInfoBuffer, (GLintptr)_transform._drawCallInfoOffsets[batch._currentNamedCall], 2 * sizeof(GLushort));
|
||||||
|
}
|
||||||
|
|
||||||
|
(void)CHECK_GL_ERROR();
|
||||||
|
}
|
|
@ -13,6 +13,23 @@
|
||||||
#include "GPULogging.h"
|
#include "GPULogging.h"
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
|
||||||
|
|
||||||
|
void ContextStats::evalDelta(const ContextStats& begin, const ContextStats& end) {
|
||||||
|
_ISNumFormatChanges = end._ISNumFormatChanges - begin._ISNumFormatChanges;
|
||||||
|
_ISNumInputBufferChanges = end._ISNumInputBufferChanges - begin._ISNumInputBufferChanges;
|
||||||
|
_ISNumIndexBufferChanges = end._ISNumIndexBufferChanges - begin._ISNumIndexBufferChanges;
|
||||||
|
|
||||||
|
_RSNumTextureBounded = end._RSNumTextureBounded - begin._RSNumTextureBounded;
|
||||||
|
_RSAmountTextureMemoryBounded = end._RSAmountTextureMemoryBounded - begin._RSAmountTextureMemoryBounded;
|
||||||
|
|
||||||
|
_DSNumAPIDrawcalls = end._DSNumAPIDrawcalls - begin._DSNumAPIDrawcalls;
|
||||||
|
_DSNumDrawcalls = end._DSNumDrawcalls - begin._DSNumDrawcalls;
|
||||||
|
_DSNumTriangles= end._DSNumTriangles - begin._DSNumTriangles;
|
||||||
|
|
||||||
|
_PSNumSetPipelines = end._PSNumSetPipelines - begin._PSNumSetPipelines;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Context::CreateBackend Context::_createBackendCallback = nullptr;
|
Context::CreateBackend Context::_createBackendCallback = nullptr;
|
||||||
Context::MakeProgram Context::_makeProgramCallback = nullptr;
|
Context::MakeProgram Context::_makeProgramCallback = nullptr;
|
||||||
std::once_flag Context::_initialized;
|
std::once_flag Context::_initialized;
|
||||||
|
@ -73,6 +90,10 @@ void Context::consumeFrameUpdates(const FramePointer& frame) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Context::executeFrame(const FramePointer& frame) const {
|
void Context::executeFrame(const FramePointer& frame) const {
|
||||||
|
// Grab the stats at the around the frame and delta to have a consistent sampling
|
||||||
|
ContextStats beginStats;
|
||||||
|
getStats(beginStats);
|
||||||
|
|
||||||
// FIXME? probably not necessary, but safe
|
// FIXME? probably not necessary, but safe
|
||||||
consumeFrameUpdates(frame);
|
consumeFrameUpdates(frame);
|
||||||
_backend->setStereoState(frame->stereoState);
|
_backend->setStereoState(frame->stereoState);
|
||||||
|
@ -90,6 +111,10 @@ void Context::executeFrame(const FramePointer& frame) const {
|
||||||
_frameRangeTimer->end(endBatch);
|
_frameRangeTimer->end(endBatch);
|
||||||
_backend->render(endBatch);
|
_backend->render(endBatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContextStats endStats;
|
||||||
|
getStats(endStats);
|
||||||
|
_frameStats.evalDelta(beginStats, endStats);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) {
|
bool Context::makeProgram(Shader& shader, const Shader::BindingSet& bindings) {
|
||||||
|
@ -135,10 +160,18 @@ void Context::downloadFramebuffer(const FramebufferPointer& srcFramebuffer, cons
|
||||||
_backend->downloadFramebuffer(srcFramebuffer, region, destImage);
|
_backend->downloadFramebuffer(srcFramebuffer, region, destImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::resetStats() const {
|
||||||
|
_backend->resetStats();
|
||||||
|
}
|
||||||
|
|
||||||
void Context::getStats(ContextStats& stats) const {
|
void Context::getStats(ContextStats& stats) const {
|
||||||
_backend->getStats(stats);
|
_backend->getStats(stats);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::getFrameStats(ContextStats& stats) const {
|
||||||
|
stats = _frameStats;
|
||||||
|
}
|
||||||
|
|
||||||
double Context::getFrameTimerGPUAverage() const {
|
double Context::getFrameTimerGPUAverage() const {
|
||||||
if (_frameRangeTimer) {
|
if (_frameRangeTimer) {
|
||||||
return _frameRangeTimer->getGPUAverage();
|
return _frameRangeTimer->getGPUAverage();
|
||||||
|
|
|
@ -45,6 +45,8 @@ public:
|
||||||
|
|
||||||
ContextStats() {}
|
ContextStats() {}
|
||||||
ContextStats(const ContextStats& stats) = default;
|
ContextStats(const ContextStats& stats) = default;
|
||||||
|
|
||||||
|
void evalDelta(const ContextStats& begin, const ContextStats& end);
|
||||||
};
|
};
|
||||||
|
|
||||||
class Backend {
|
class Backend {
|
||||||
|
@ -83,6 +85,7 @@ public:
|
||||||
return reinterpret_cast<T*>(object.gpuObject.getGPUObject());
|
return reinterpret_cast<T*>(object.gpuObject.getGPUObject());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resetStats() const { _stats = ContextStats(); }
|
||||||
void getStats(ContextStats& stats) const { stats = _stats; }
|
void getStats(ContextStats& stats) const { stats = _stats; }
|
||||||
|
|
||||||
virtual bool isTextureManagementSparseEnabled() const = 0;
|
virtual bool isTextureManagementSparseEnabled() const = 0;
|
||||||
|
@ -123,7 +126,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class Context;
|
friend class Context;
|
||||||
ContextStats _stats;
|
mutable ContextStats _stats;
|
||||||
StereoState _stereo;
|
StereoState _stereo;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -201,8 +204,11 @@ public:
|
||||||
void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage);
|
void downloadFramebuffer(const FramebufferPointer& srcFramebuffer, const Vec4i& region, QImage& destImage);
|
||||||
|
|
||||||
// Repporting stats of the context
|
// Repporting stats of the context
|
||||||
|
void resetStats() const;
|
||||||
void getStats(ContextStats& stats) const;
|
void getStats(ContextStats& stats) const;
|
||||||
|
|
||||||
|
// Same as above but grabbed at every end of a frame
|
||||||
|
void getFrameStats(ContextStats& stats) const;
|
||||||
|
|
||||||
double getFrameTimerGPUAverage() const;
|
double getFrameTimerGPUAverage() const;
|
||||||
double getFrameTimerBatchAverage() const;
|
double getFrameTimerBatchAverage() const;
|
||||||
|
@ -229,8 +235,8 @@ protected:
|
||||||
RangeTimerPointer _frameRangeTimer;
|
RangeTimerPointer _frameRangeTimer;
|
||||||
StereoState _stereo;
|
StereoState _stereo;
|
||||||
|
|
||||||
double getGPUAverage() const;
|
// Sampled at the end of every frame, the stats of all the counters
|
||||||
double getBatchAverage() const;
|
mutable ContextStats _frameStats;
|
||||||
|
|
||||||
// This function can only be called by "static Shader::makeProgram()"
|
// This function can only be called by "static Shader::makeProgram()"
|
||||||
// makeProgramShader(...) make a program shader ready to be used in a Batch.
|
// makeProgramShader(...) make a program shader ready to be used in a Batch.
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#include "Stream.h"
|
#include "Stream.h"
|
||||||
|
|
||||||
#include <algorithm> //min max and more
|
#include <algorithm> //min max and more
|
||||||
|
#include <sstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
using namespace gpu;
|
using namespace gpu;
|
||||||
|
|
||||||
|
@ -39,9 +41,21 @@ const ElementArray& getDefaultElements() {
|
||||||
return defaultElements;
|
return defaultElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Stream::Attribute::getKey() const {
|
||||||
|
std::stringstream skey;
|
||||||
|
|
||||||
|
skey << std::hex;
|
||||||
|
skey << std::setw(8) << std::setfill('0') << (uint32)((((uint32)_slot) << 24) | (((uint32)_channel) << 16) | ((uint32)_element.getRaw()));
|
||||||
|
skey << _offset;
|
||||||
|
skey << _frequency;
|
||||||
|
return skey.str();
|
||||||
|
}
|
||||||
|
|
||||||
void Stream::Format::evaluateCache() {
|
void Stream::Format::evaluateCache() {
|
||||||
|
_key.clear();
|
||||||
_channels.clear();
|
_channels.clear();
|
||||||
_elementTotalSize = 0;
|
_elementTotalSize = 0;
|
||||||
|
|
||||||
for(AttributeMap::iterator it = _attributes.begin(); it != _attributes.end(); it++) {
|
for(AttributeMap::iterator it = _attributes.begin(); it != _attributes.end(); it++) {
|
||||||
Attribute& attrib = (*it).second;
|
Attribute& attrib = (*it).second;
|
||||||
ChannelInfo& channel = _channels[attrib._channel];
|
ChannelInfo& channel = _channels[attrib._channel];
|
||||||
|
@ -49,6 +63,8 @@ void Stream::Format::evaluateCache() {
|
||||||
channel._stride = std::max(channel._stride, attrib.getSize() + attrib._offset);
|
channel._stride = std::max(channel._stride, attrib.getSize() + attrib._offset);
|
||||||
channel._netSize += attrib.getSize();
|
channel._netSize += attrib.getSize();
|
||||||
_elementTotalSize += attrib.getSize();
|
_elementTotalSize += attrib.getSize();
|
||||||
|
|
||||||
|
_key += attrib.getKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
@ -73,6 +74,9 @@ public:
|
||||||
|
|
||||||
// Size of the
|
// Size of the
|
||||||
uint32 getSize() const { return _element.getSize(); }
|
uint32 getSize() const { return _element.getSize(); }
|
||||||
|
|
||||||
|
// Generate a string key describing the attribute uniquely
|
||||||
|
std::string getKey() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Stream Format is describing how to feed a list of attributes from a bunch of stream buffer channels
|
// Stream Format is describing how to feed a list of attributes from a bunch of stream buffer channels
|
||||||
|
@ -106,10 +110,15 @@ public:
|
||||||
|
|
||||||
bool hasAttribute(Slot slot) const { return (_attributes.find(slot) != _attributes.end()); }
|
bool hasAttribute(Slot slot) const { return (_attributes.find(slot) != _attributes.end()); }
|
||||||
|
|
||||||
|
const std::string& getKey() const { return _key; }
|
||||||
|
|
||||||
|
const GPUObjectPointer gpuObject{};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AttributeMap _attributes;
|
AttributeMap _attributes;
|
||||||
ChannelMap _channels;
|
ChannelMap _channels;
|
||||||
uint32 _elementTotalSize { 0 };
|
uint32 _elementTotalSize { 0 };
|
||||||
|
std::string _key;
|
||||||
|
|
||||||
void evaluateCache();
|
void evaluateCache();
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,14 +35,24 @@ layout(std140) uniform transformCameraBuffer {
|
||||||
|
|
||||||
#ifdef GPU_VERTEX_SHADER
|
#ifdef GPU_VERTEX_SHADER
|
||||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
|
|
||||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA_ATTRIBUTED
|
||||||
layout(location=14) in int _inStereoSide;
|
layout(location=14) in int _inStereoSide;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
flat out int _stereoSide;
|
flat out int _stereoSide;
|
||||||
|
|
||||||
|
// In stereo drawcall mode Instances are drawn twice (left then right) hence the true InstanceID is the gl_InstanceID / 2
|
||||||
|
int gpu_InstanceID = gl_InstanceID >> 1;
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
int gpu_InstanceID = gl_InstanceID;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
#else
|
||||||
|
|
||||||
|
int gpu_InstanceID = gl_InstanceID;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -54,6 +64,7 @@ flat in int _stereoSide;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
TransformCamera getTransformCamera() {
|
TransformCamera getTransformCamera() {
|
||||||
#ifdef GPU_TRANSFORM_IS_STEREO
|
#ifdef GPU_TRANSFORM_IS_STEREO
|
||||||
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
#ifdef GPU_TRANSFORM_STEREO_CAMERA
|
||||||
|
@ -211,6 +222,8 @@ TransformObject getTransformObject() {
|
||||||
{ // transformWorldToClipPos
|
{ // transformWorldToClipPos
|
||||||
vec4 eyeWAPos = <$worldPos$> - vec4(<$cameraTransform$>._viewInverse[3].xyz, 0.0);
|
vec4 eyeWAPos = <$worldPos$> - vec4(<$cameraTransform$>._viewInverse[3].xyz, 0.0);
|
||||||
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
<$clipPos$> = <$cameraTransform$>._projectionViewUntranslated * eyeWAPos;
|
||||||
|
|
||||||
|
<$transformStereoClipsSpace($cameraTransform$, $clipPos$)$>
|
||||||
}
|
}
|
||||||
<@endfunc@>
|
<@endfunc@>
|
||||||
|
|
||||||
|
|
|
@ -179,6 +179,10 @@ void LightClusters::updateFrustum(const ViewFrustum& frustum) {
|
||||||
_frustum = frustum;
|
_frustum = frustum;
|
||||||
|
|
||||||
_frustumGridBuffer.edit().updateFrustum(frustum);
|
_frustumGridBuffer.edit().updateFrustum(frustum);
|
||||||
|
|
||||||
|
if (true) {
|
||||||
|
_frustumGridBuffer.edit().generateGridPlanes(_gridPlanes[0], _gridPlanes[1], _gridPlanes[2]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LightClusters::updateLightStage(const LightStagePointer& lightStage) {
|
void LightClusters::updateLightStage(const LightStagePointer& lightStage) {
|
||||||
|
|
|
@ -53,12 +53,12 @@ void main(void) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ivec3 cluster = clusterGrid_getCluster(gl_InstanceID);
|
ivec3 cluster = clusterGrid_getCluster(gpu_InstanceID);
|
||||||
int numLights = cluster.x + cluster.y;
|
int numLights = cluster.x + cluster.y;
|
||||||
|
|
||||||
float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0);
|
float numLightsScale = clamp(numLights * 0.1, 0.0, 1.0);
|
||||||
|
|
||||||
ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID);
|
ivec3 clusterPos = frustumGrid_indexToCluster(gpu_InstanceID);
|
||||||
|
|
||||||
float boxScale = 0.99;
|
float boxScale = 0.99;
|
||||||
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3((1.0 - boxScale) * 0.5 + (1.0 - numLightsScale) * boxScale * 0.5) + numLightsScale * boxScale * pos.xyz);
|
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3((1.0 - boxScale) * 0.5 + (1.0 - numLightsScale) * boxScale * 0.5) + numLightsScale * boxScale * pos.xyz);
|
||||||
|
@ -69,5 +69,5 @@ void main(void) {
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
|
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
|
||||||
|
|
||||||
varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), (numLights >0 ? 0.9 : 0.1));
|
varColor = vec4(colorWheel(fract(float(gpu_InstanceID) / float(frustumGrid_numClusters()))), (numLights >0 ? 0.9 : 0.1));
|
||||||
}
|
}
|
|
@ -53,7 +53,7 @@ void main(void) {
|
||||||
);
|
);
|
||||||
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
|
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
|
||||||
|
|
||||||
ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID);
|
ivec3 clusterPos = frustumGrid_indexToCluster(gpu_InstanceID);
|
||||||
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz);
|
vec3 eyePos = frustumGrid_clusterPosToEye(clusterPos, vec3(0.05) + 0.9 * pos.xyz);
|
||||||
vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0));
|
vec4 worldPos = frustumGrid_eyeToWorld(vec4(eyePos.xyz, 1.0));
|
||||||
|
|
||||||
|
@ -62,5 +62,5 @@ void main(void) {
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
|
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
|
||||||
|
|
||||||
varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), 0.9);
|
varColor = vec4(colorWheel(fract(float(gpu_InstanceID) / float(frustumGrid_numClusters()))), 0.9);
|
||||||
}
|
}
|
|
@ -54,10 +54,10 @@ void main(void) {
|
||||||
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
|
vec4 pos = UNIT_BOX[UNIT_BOX_LINE_INDICES[gl_VertexID]];
|
||||||
|
|
||||||
|
|
||||||
ivec3 cluster = clusterGrid_getCluster(gl_InstanceID);
|
ivec3 cluster = clusterGrid_getCluster(gpu_InstanceID);
|
||||||
int numLights = cluster.x + cluster.y;
|
int numLights = cluster.x + cluster.y;
|
||||||
|
|
||||||
ivec3 clusterPos = frustumGrid_indexToCluster(gl_InstanceID);
|
ivec3 clusterPos = frustumGrid_indexToCluster(gpu_InstanceID);
|
||||||
|
|
||||||
|
|
||||||
float boxScale = 1.0;
|
float boxScale = 1.0;
|
||||||
|
@ -69,5 +69,5 @@ void main(void) {
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
|
<$transformWorldToClipPos(cam, worldPos, gl_Position)$>
|
||||||
|
|
||||||
varColor = vec4(colorWheel(fract(float(gl_InstanceID) / float(frustumGrid_numClusters()))), (numLights > 0 ? 0.9 : 0.0));
|
varColor = vec4(colorWheel(fract(float(gpu_InstanceID) / float(frustumGrid_numClusters()))), (numLights > 0 ? 0.9 : 0.0));
|
||||||
}
|
}
|
|
@ -35,21 +35,21 @@ void EngineStats::run(const SceneContextPointer& sceneContext, const RenderConte
|
||||||
config->textureGPUVirtualMemoryUsage = gpu::Texture::getTextureGPUVirtualMemoryUsage();
|
config->textureGPUVirtualMemoryUsage = gpu::Texture::getTextureGPUVirtualMemoryUsage();
|
||||||
config->textureGPUTransferCount = gpu::Texture::getTextureGPUTransferCount();
|
config->textureGPUTransferCount = gpu::Texture::getTextureGPUTransferCount();
|
||||||
|
|
||||||
gpu::ContextStats gpuStats(_gpuStats);
|
renderContext->args->_context->getFrameStats(_gpuStats);
|
||||||
renderContext->args->_context->getStats(_gpuStats);
|
|
||||||
|
|
||||||
config->frameAPIDrawcallCount = _gpuStats._DSNumAPIDrawcalls - gpuStats._DSNumAPIDrawcalls;
|
config->frameAPIDrawcallCount = _gpuStats._DSNumAPIDrawcalls;
|
||||||
config->frameDrawcallCount = _gpuStats._DSNumDrawcalls - gpuStats._DSNumDrawcalls;
|
config->frameDrawcallCount = _gpuStats._DSNumDrawcalls;
|
||||||
config->frameDrawcallRate = config->frameDrawcallCount * frequency;
|
config->frameDrawcallRate = config->frameDrawcallCount * frequency;
|
||||||
|
|
||||||
config->frameTriangleCount = _gpuStats._DSNumTriangles - gpuStats._DSNumTriangles;
|
config->frameTriangleCount = _gpuStats._DSNumTriangles;
|
||||||
config->frameTriangleRate = config->frameTriangleCount * frequency;
|
config->frameTriangleRate = config->frameTriangleCount * frequency;
|
||||||
|
|
||||||
config->frameTextureCount = _gpuStats._RSNumTextureBounded - gpuStats._RSNumTextureBounded;
|
config->frameTextureCount = _gpuStats._RSNumTextureBounded;
|
||||||
config->frameTextureRate = config->frameTextureCount * frequency;
|
config->frameTextureRate = config->frameTextureCount * frequency;
|
||||||
config->frameTextureMemoryUsage = _gpuStats._RSAmountTextureMemoryBounded - gpuStats._RSAmountTextureMemoryBounded;
|
config->frameTextureMemoryUsage = _gpuStats._RSAmountTextureMemoryBounded;
|
||||||
|
|
||||||
config->frameSetPipelineCount = _gpuStats._PSNumSetPipelines - gpuStats._PSNumSetPipelines;
|
config->frameSetPipelineCount = _gpuStats._PSNumSetPipelines;
|
||||||
|
config->frameSetInputFormatCount = _gpuStats._ISNumFormatChanges;
|
||||||
|
|
||||||
config->emitDirty();
|
config->emitDirty();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ namespace render {
|
||||||
Q_PROPERTY(quint32 frameTextureMemoryUsage MEMBER frameTextureMemoryUsage NOTIFY dirty)
|
Q_PROPERTY(quint32 frameTextureMemoryUsage MEMBER frameTextureMemoryUsage NOTIFY dirty)
|
||||||
|
|
||||||
Q_PROPERTY(quint32 frameSetPipelineCount MEMBER frameSetPipelineCount NOTIFY dirty)
|
Q_PROPERTY(quint32 frameSetPipelineCount MEMBER frameSetPipelineCount NOTIFY dirty)
|
||||||
|
Q_PROPERTY(quint32 frameSetInputFormatCount MEMBER frameSetInputFormatCount NOTIFY dirty)
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -78,6 +79,8 @@ namespace render {
|
||||||
|
|
||||||
quint32 frameSetPipelineCount{ 0 };
|
quint32 frameSetPipelineCount{ 0 };
|
||||||
|
|
||||||
|
quint32 frameSetInputFormatCount{ 0 };
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void emitDirty() { emit dirty(); }
|
void emitDirty() { emit dirty(); }
|
||||||
|
|
|
@ -28,7 +28,7 @@ MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& m
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& menuItemName,
|
MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& menuItemName,
|
||||||
const KeyEvent& shortcutKeyEvent, bool checkable, bool checked, bool separator) :
|
const KeyEvent& shortcutKeyEvent, bool checkable, bool checked, bool separator) :
|
||||||
menuName(menuName),
|
menuName(menuName),
|
||||||
menuItemName(menuItemName),
|
menuItemName(menuItemName),
|
||||||
|
@ -50,13 +50,31 @@ QScriptValue menuItemPropertiesToScriptValue(QScriptEngine* engine, const MenuIt
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* `MenuItemProperties` is a list of properties that can be passed to Menu.addMenuItem
|
||||||
|
* to create a new menu item.
|
||||||
|
*
|
||||||
|
* If none of position, beforeItem, afterItem, or grouping are specified, the
|
||||||
|
* menu item will be placed in the last position.
|
||||||
|
*
|
||||||
|
* @typedef {Object} Menu.MenuItemProperties
|
||||||
|
* @property {string} menuName Name of the top-level menu
|
||||||
|
* @property {string} menuItemName Name of the menu item
|
||||||
|
* @property {bool} isCheckable Whether the menu item is checkable or not
|
||||||
|
* @property {bool} isChecked Where the menu item is checked or not
|
||||||
|
* @property {string} shortcutKey An optional shortcut key to trigger the menu item.
|
||||||
|
* @property {int} position The position to place the new menu item. `0` is the first menu item.
|
||||||
|
* @property {string} beforeItem The name of the menu item to place this menu item before.
|
||||||
|
* @property {string} afterItem The name of the menu item to place this menu item after.
|
||||||
|
* @property {string} grouping The name of grouping to add this menu item to.
|
||||||
|
*/
|
||||||
void menuItemPropertiesFromScriptValue(const QScriptValue& object, MenuItemProperties& properties) {
|
void menuItemPropertiesFromScriptValue(const QScriptValue& object, MenuItemProperties& properties) {
|
||||||
properties.menuName = object.property("menuName").toVariant().toString();
|
properties.menuName = object.property("menuName").toVariant().toString();
|
||||||
properties.menuItemName = object.property("menuItemName").toVariant().toString();
|
properties.menuItemName = object.property("menuItemName").toVariant().toString();
|
||||||
properties.isCheckable = object.property("isCheckable").toVariant().toBool();
|
properties.isCheckable = object.property("isCheckable").toVariant().toBool();
|
||||||
properties.isChecked = object.property("isChecked").toVariant().toBool();
|
properties.isChecked = object.property("isChecked").toVariant().toBool();
|
||||||
properties.isSeparator = object.property("isSeparator").toVariant().toBool();
|
properties.isSeparator = object.property("isSeparator").toVariant().toBool();
|
||||||
|
|
||||||
// handle the shortcut key options in order...
|
// handle the shortcut key options in order...
|
||||||
QScriptValue shortcutKeyValue = object.property("shortcutKey");
|
QScriptValue shortcutKeyValue = object.property("shortcutKey");
|
||||||
if (shortcutKeyValue.isValid()) {
|
if (shortcutKeyValue.isValid()) {
|
||||||
|
|
|
@ -20,6 +20,24 @@
|
||||||
|
|
||||||
#include "GLMHelpers.h"
|
#include "GLMHelpers.h"
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* A 2-dimensional vector.
|
||||||
|
*
|
||||||
|
* @typedef Vec2
|
||||||
|
* @property {float} x X-coordinate of the vector.
|
||||||
|
* @property {float} y Y-coordinate of the vector.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* A 3-dimensional vector.
|
||||||
|
*
|
||||||
|
* @typedef Vec3
|
||||||
|
* @property {float} x X-coordinate of the vector.
|
||||||
|
* @property {float} y Y-coordinate of the vector.
|
||||||
|
* @property {float} z Z-coordinate of the vector.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/// Scriptable interface a Vec3ernion helper class object. Used exclusively in the JavaScript API
|
/// Scriptable interface a Vec3ernion helper class object. Used exclusively in the JavaScript API
|
||||||
class Vec3 : public QObject {
|
class Vec3 : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
|
@ -197,7 +197,7 @@ GPUIdent* GPUIdent::ensureQuery(const QString& vendor, const QString& renderer)
|
||||||
|
|
||||||
ULONG uNumOfInstances = 0;
|
ULONG uNumOfInstances = 0;
|
||||||
CComPtr<IWbemClassObject> spInstance = NULL;
|
CComPtr<IWbemClassObject> spInstance = NULL;
|
||||||
hr = spEnumInst->Next(WBEM_INFINITE, 1, &spInstance, &uNumOfInstances);
|
hr = spEnumInst->Next(WBEM_INFINITE, 1, &spInstance.p, &uNumOfInstances);
|
||||||
while (hr == S_OK && spInstance && uNumOfInstances) {
|
while (hr == S_OK && spInstance && uNumOfInstances) {
|
||||||
// Get properties from the object
|
// Get properties from the object
|
||||||
CComVariant var;
|
CComVariant var;
|
||||||
|
|
|
@ -16,6 +16,11 @@
|
||||||
|
|
||||||
#include "DependencyManager.h"
|
#include "DependencyManager.h"
|
||||||
|
|
||||||
|
/**jsdoc
|
||||||
|
* @namespace Paths
|
||||||
|
* @readonly
|
||||||
|
* @property {string} resources The path to the resources directory.
|
||||||
|
*/
|
||||||
class PathUtils : public QObject, public Dependency {
|
class PathUtils : public QObject, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
SINGLETON_DEPENDENCY
|
SINGLETON_DEPENDENCY
|
||||||
|
|
|
@ -173,6 +173,11 @@ Item {
|
||||||
prop: "frameSetPipelineCount",
|
prop: "frameSetPipelineCount",
|
||||||
label: "Pipelines",
|
label: "Pipelines",
|
||||||
color: "#E2334D"
|
color: "#E2334D"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: "frameSetInputFormatCount",
|
||||||
|
label: "Input Formats",
|
||||||
|
color: "#1AC567"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ exports.handlers = {
|
||||||
var dirList = [
|
var dirList = [
|
||||||
'../../interface/src',
|
'../../interface/src',
|
||||||
'../../interface/src/scripting',
|
'../../interface/src/scripting',
|
||||||
|
'../../interface/src/ui/overlays',
|
||||||
'../../libraries/script-engine/src',
|
'../../libraries/script-engine/src',
|
||||||
'../../libraries/networking/src',
|
'../../libraries/networking/src',
|
||||||
'../../libraries/animation/src',
|
'../../libraries/animation/src',
|
||||||
|
|
Loading…
Reference in a new issue